Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2025 DMTF. All rights reserved.
4 : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : **/
6 :
7 : #include "internal/libspdm_crypt_lib.h"
8 :
9 : #if LIBSPDM_CERT_PARSE_SUPPORT
10 :
11 : /**pathLenConstraint is optional.
12 : * In https://www.pkisolutions.com/basic-constraints-certificate-extension/:
13 : * pathLenConstraint: How many CAs are allowed in the chain below current CA certificate.
14 : * This setting has no meaning for end entity certificates.
15 : **/
16 :
17 : /**
18 : * leaf cert spdm extension len
19 : * len > 2 * (spdm id-DMTF-spdm size + 2)
20 : **/
21 :
22 : #ifndef LIBSPDM_MAX_EXTENSION_LEN
23 : #define LIBSPDM_MAX_EXTENSION_LEN 30
24 : #endif
25 :
26 : #ifndef LIBSPDM_MAX_NAME_SIZE
27 : #define LIBSPDM_MAX_NAME_SIZE 100
28 : #endif
29 :
30 : /*max public key encryption algo oid len*/
31 : #ifndef LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN
32 : #define LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN 10
33 : #endif
34 :
35 : /* Maximum size of basicConstraints. This includes space for both cA and pathLen. */
36 : #ifndef LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN
37 : #define LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN 10
38 : #endif
39 :
40 : /**
41 : * 0x02 is integer;
42 : * 0x82 indicates that the length is expressed in two bytes;
43 : * 0x01 and 0x01 are rsa key len;
44 : **/
45 : #if (LIBSPDM_RSA_SSA_2048_SUPPORT) || (LIBSPDM_RSA_PSS_2048_SUPPORT)
46 : #define KEY_ENCRY_ALGO_RSA2048_FLAG {0x02, 0x82, 0x01, 0x01}
47 : /* the other case is ASN1 code different when integer is 1 on highest position*/
48 : #define KEY_ENCRY_ALGO_RSA2048_FLAG_OTHER {0x02, 0x82, 0x01, 0x00}
49 : #endif
50 : #if (LIBSPDM_RSA_SSA_3072_SUPPORT) || (LIBSPDM_RSA_PSS_3072_SUPPORT)
51 : #define KEY_ENCRY_ALGO_RSA3072_FLAG {0x02, 0x82, 0x01, 0x81}
52 : /* the other case is ASN1 code different when integer is 1 on highest position*/
53 : #define KEY_ENCRY_ALGO_RSA3072_FLAG_OTHER {0x02, 0x82, 0x01, 0x80}
54 : #endif
55 : #if (LIBSPDM_RSA_SSA_4096_SUPPORT) || (LIBSPDM_RSA_PSS_4096_SUPPORT)
56 : #define KEY_ENCRY_ALGO_RSA4096_FLAG {0x02, 0x82, 0x02, 0x01}
57 : /* the other case is ASN1 code different when integer is 1 on highest position*/
58 : #define KEY_ENCRY_ALGO_RSA4096_FLAG_OTHER {0x02, 0x82, 0x02, 0x00}
59 : #endif
60 :
61 : /**
62 : * https://oidref.com/1.2.840.10045.3.1.7
63 : * ECC256 curve OID: 1.2.840.10045.3.1.7
64 : * https://oidref.com/1.3.132.0.34
65 : * ECC384 curve OID: 1.3.132.0.34
66 : * https://oidref.com/1.3.132.0.35
67 : * ECC521 curve OID: 1.3.132.0.35
68 : **/
69 : #if LIBSPDM_ECDSA_P256_SUPPORT
70 : #define KEY_ENCRY_ALGO_ECC256_OID {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
71 : #endif
72 : #if LIBSPDM_ECDSA_P384_SUPPORT
73 : #define KEY_ENCRY_ALGO_ECC384_OID {0x2B, 0x81, 0x04, 0x00, 0x22}
74 : #endif
75 : #if LIBSPDM_ECDSA_P521_SUPPORT
76 : #define KEY_ENCRY_ALGO_ECC521_OID {0x2B, 0x81, 0x04, 0x00, 0x23}
77 : #endif
78 :
79 : /**
80 : * EDxxx OID: https://datatracker.ietf.org/doc/html/rfc8420
81 : * ED448 OID: 1.3.101.113
82 : * ED25519 OID: 1.3.101.112
83 : **/
84 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
85 : #define ENCRY_ALGO_ED25519_OID {0x2B, 0x65, 0x70}
86 : #endif
87 : #if LIBSPDM_EDDSA_ED448_SUPPORT
88 : #define ENCRY_ALGO_ED448_OID {0x2B, 0x65, 0x71}
89 : #endif
90 :
91 : /**
92 : * MLDSA OID: https://datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates
93 : * MLDSA44 OID: 2.16.840.1.101.3.4.3.17
94 : * MLDSA65 OID: 2.16.840.1.101.3.4.3.18
95 : * MLDSA87 OID: 2.16.840.1.101.3.4.3.19
96 : **/
97 : #if LIBSPDM_ML_DSA_44_SUPPORT
98 : #define ALGO_MLDSA44_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x11}
99 : #endif
100 : #if LIBSPDM_ML_DSA_65_SUPPORT
101 : #define ALGO_MLDSA65_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x12}
102 : #endif
103 : #if LIBSPDM_ML_DSA_87_SUPPORT
104 : #define ALGO_MLDSA87_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x13}
105 : #endif
106 :
107 : /**
108 : * SLHDSA OID: https://datatracker.ietf.org/doc/draft-ietf-lamps-x509-slhdsa
109 : * SLHDSA_SHA2_128S OID: 2.16.840.1.101.3.4.3.20
110 : * SLHDSA_SHA2_128F OID: 2.16.840.1.101.3.4.3.21
111 : * SLHDSA_SHA2_192S OID: 2.16.840.1.101.3.4.3.22
112 : * SLHDSA_SHA2_192F OID: 2.16.840.1.101.3.4.3.23
113 : * SLHDSA_SHA2_256S OID: 2.16.840.1.101.3.4.3.24
114 : * SLHDSA_SHA2_256F OID: 2.16.840.1.101.3.4.3.25
115 : * SLHDSA_SHAKE_128S OID: 2.16.840.1.101.3.4.3.26
116 : * SLHDSA_SHAKE_128F OID: 2.16.840.1.101.3.4.3.27
117 : * SLHDSA_SHAKE_192S OID: 2.16.840.1.101.3.4.3.28
118 : * SLHDSA_SHAKE_192F OID: 2.16.840.1.101.3.4.3.29
119 : * SLHDSA_SHAKE_256S OID: 2.16.840.1.101.3.4.3.30
120 : * SLHDSA_SHAKE_256F OID: 2.16.840.1.101.3.4.3.31
121 : **/
122 : #if LIBSPDM_SLH_DSA_SHA2_128S_SUPPORT
123 : #define ALGO_SLHDSA_SHA2_128S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x14}
124 : #endif
125 : #if LIBSPDM_SLH_DSA_SHA2_128F_SUPPORT
126 : #define ALGO_SLHDSA_SHA2_128F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x15}
127 : #endif
128 : #if LIBSPDM_SLH_DSA_SHA2_192S_SUPPORT
129 : #define ALGO_SLHDSA_SHA2_192S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x16}
130 : #endif
131 : #if LIBSPDM_SLH_DSA_SHA2_192F_SUPPORT
132 : #define ALGO_SLHDSA_SHA2_192F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x17}
133 : #endif
134 : #if LIBSPDM_SLH_DSA_SHA2_256S_SUPPORT
135 : #define ALGO_SLHDSA_SHA2_256S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x18}
136 : #endif
137 : #if LIBSPDM_SLH_DSA_SHA2_256F_SUPPORT
138 : #define ALGO_SLHDSA_SHA2_256F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x19}
139 : #endif
140 : #if LIBSPDM_SLH_DSA_SHAKE_128S_SUPPORT
141 : #define ALGO_SLHDSA_SHAKE_128S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1A}
142 : #endif
143 : #if LIBSPDM_SLH_DSA_SHAKE_128F_SUPPORT
144 : #define ALGO_SLHDSA_SHAKE_128F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1B}
145 : #endif
146 : #if LIBSPDM_SLH_DSA_SHAKE_192S_SUPPORT
147 : #define ALGO_SLHDSA_SHAKE_192S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1C}
148 : #endif
149 : #if LIBSPDM_SLH_DSA_SHAKE_192F_SUPPORT
150 : #define ALGO_SLHDSA_SHAKE_192F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1D}
151 : #endif
152 : #if LIBSPDM_SLH_DSA_SHAKE_256S_SUPPORT
153 : #define ALGO_SLHDSA_SHAKE_256S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1E}
154 : #endif
155 : #if LIBSPDM_SLH_DSA_SHAKE_256F_SUPPORT
156 : #define ALGO_SLHDSA_SHAKE_256F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1F}
157 : #endif
158 :
159 : /*leaf cert basic_constraints false case1: CA: false and CA object is excluded */
160 : #define BASIC_CONSTRAINTS_STRING_FALSE_CASE1 {0x30, 0x00}
161 :
162 : /*leaf cert basic_constraints false case2: CA: false */
163 : #define BASIC_CONSTRAINTS_STRING_FALSE_CASE2 {0x30, 0x03, 0x01, 0x01, 0x00}
164 :
165 : /*leaf cert basic_constraints true case: CA: true */
166 : #define BASIC_CONSTRAINTS_STRING_TRUE_CASE {0x30, 0x03, 0x01, 0x01, 0xFF}
167 :
168 : /**
169 : * Retrieve the asymmetric public key from one DER-encoded X509 certificate.
170 : *
171 : * @param cert Pointer to the DER-encoded X509 certificate.
172 : * @param cert_size Size of the X509 certificate in bytes.
173 : * @param context Pointer to newly generated asymmetric context which contain the retrieved public
174 : * key component. Use libspdm_asym_free() function to free the resource.
175 : *
176 : * @retval true public key was retrieved successfully.
177 : * @retval false Fail to retrieve public key from X509 certificate.
178 : **/
179 : typedef bool (*libspdm_asym_get_public_key_from_x509_func)(const uint8_t *cert,
180 : size_t cert_size,
181 : void **context);
182 :
183 : /**
184 : * Return asymmetric GET_PUBLIC_KEY_FROM_X509 function, based upon the negotiated asymmetric algorithm.
185 : *
186 : * @param base_asym_algo SPDM base_asym_algo
187 : *
188 : * @return asymmetric GET_PUBLIC_KEY_FROM_X509 function
189 : **/
190 : static libspdm_asym_get_public_key_from_x509_func
191 1038 : libspdm_get_asym_get_public_key_from_x509(uint32_t base_asym_algo)
192 : {
193 1038 : switch (base_asym_algo) {
194 100 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
195 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
196 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
197 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
198 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
199 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
200 : #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
201 : #if !LIBSPDM_RSA_SSA_2048_SUPPORT
202 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048);
203 : #endif
204 : #if !LIBSPDM_RSA_SSA_3072_SUPPORT
205 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072);
206 : #endif
207 : #if !LIBSPDM_RSA_SSA_4096_SUPPORT
208 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096);
209 : #endif
210 : #if !LIBSPDM_RSA_PSS_2048_SUPPORT
211 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048);
212 : #endif
213 : #if !LIBSPDM_RSA_PSS_3072_SUPPORT
214 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072);
215 : #endif
216 : #if !LIBSPDM_RSA_PSS_4096_SUPPORT
217 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096);
218 : #endif
219 100 : return libspdm_rsa_get_public_key_from_x509;
220 : #else
221 : LIBSPDM_ASSERT(false);
222 : break;
223 : #endif
224 938 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
225 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
226 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
227 : #if LIBSPDM_ECDSA_SUPPORT
228 : #if !LIBSPDM_ECDSA_P256_SUPPORT
229 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256);
230 : #endif
231 : #if !LIBSPDM_ECDSA_P384_SUPPORT
232 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384);
233 : #endif
234 : #if !LIBSPDM_ECDSA_P521_SUPPORT
235 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521);
236 : #endif
237 938 : return libspdm_ec_get_public_key_from_x509;
238 : #else
239 : LIBSPDM_ASSERT(false);
240 : break;
241 : #endif
242 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
243 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
244 : #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
245 : #if !LIBSPDM_EDDSA_ED25519_SUPPORT
246 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519);
247 : #endif
248 : #if !LIBSPDM_EDDSA_ED448_SUPPORT
249 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448);
250 : #endif
251 : return libspdm_ecd_get_public_key_from_x509;
252 : #else
253 0 : LIBSPDM_ASSERT(false);
254 0 : break;
255 : #endif
256 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
257 : #if LIBSPDM_SM2_DSA_SUPPORT
258 : return libspdm_sm2_get_public_key_from_x509;
259 : #else
260 0 : LIBSPDM_ASSERT(false);
261 0 : break;
262 : #endif
263 0 : default:
264 0 : LIBSPDM_ASSERT(false);
265 0 : break;
266 : }
267 :
268 0 : return NULL;
269 : }
270 :
271 : /**
272 : * Retrieve the asymmetric public key from one DER-encoded X509 certificate,
273 : * based upon negotiated asymmetric algorithm.
274 : *
275 : * @param base_asym_algo SPDM base_asym_algo
276 : * @param cert Pointer to the DER-encoded X509 certificate.
277 : * @param cert_size size of the X509 certificate in bytes.
278 : * @param context Pointer to newly generated asymmetric context which contain the retrieved public key component.
279 : * Use libspdm_asym_free() function to free the resource.
280 : *
281 : * @retval true public key was retrieved successfully.
282 : * @retval false Fail to retrieve public key from X509 certificate.
283 : **/
284 1038 : bool libspdm_asym_get_public_key_from_x509(uint32_t base_asym_algo,
285 : const uint8_t *cert,
286 : size_t cert_size,
287 : void **context)
288 : {
289 : libspdm_asym_get_public_key_from_x509_func get_public_key_from_x509_function;
290 1038 : get_public_key_from_x509_function = libspdm_get_asym_get_public_key_from_x509(base_asym_algo);
291 1038 : if (get_public_key_from_x509_function == NULL) {
292 0 : return false;
293 : }
294 1038 : return get_public_key_from_x509_function(cert, cert_size, context);
295 : }
296 :
297 : /**
298 : * Return requester asymmetric GET_PUBLIC_KEY_FROM_X509 function, based upon the negotiated requester asymmetric algorithm.
299 : *
300 : * @param req_base_asym_alg SPDM req_base_asym_alg
301 : *
302 : * @return requester asymmetric GET_PUBLIC_KEY_FROM_X509 function
303 : **/
304 : static libspdm_asym_get_public_key_from_x509_func
305 0 : libspdm_get_req_asym_get_public_key_from_x509(uint16_t req_base_asym_alg)
306 : {
307 0 : return libspdm_get_asym_get_public_key_from_x509(req_base_asym_alg);
308 : }
309 :
310 : /**
311 : * Retrieve the asymmetric public key from one DER-encoded X509 certificate,
312 : * based upon negotiated requester asymmetric algorithm.
313 : *
314 : * @param req_base_asym_alg SPDM req_base_asym_alg
315 : * @param cert Pointer to the DER-encoded X509 certificate.
316 : * @param cert_size size of the X509 certificate in bytes.
317 : * @param context Pointer to newly generated asymmetric context which contain the retrieved public key component.
318 : * Use libspdm_asym_free() function to free the resource.
319 : *
320 : * @retval true public key was retrieved successfully.
321 : * @retval false Fail to retrieve public key from X509 certificate.
322 : **/
323 0 : bool libspdm_req_asym_get_public_key_from_x509(uint16_t req_base_asym_alg,
324 : const uint8_t *cert,
325 : size_t cert_size,
326 : void **context)
327 : {
328 : libspdm_asym_get_public_key_from_x509_func get_public_key_from_x509_function;
329 : get_public_key_from_x509_function =
330 0 : libspdm_get_req_asym_get_public_key_from_x509(req_base_asym_alg);
331 0 : if (get_public_key_from_x509_function == NULL) {
332 0 : return false;
333 : }
334 0 : return get_public_key_from_x509_function(cert, cert_size, context);
335 : }
336 :
337 : /**
338 : * Check the X509 DataTime is within a valid range.
339 : *
340 : * @param spdm_context A pointer to the SPDM context.
341 : * @param from notBefore Pointer to date_time object.
342 : * @param from_size notBefore date_time object size.
343 : * @param to notAfter Pointer to date_time object.
344 : * @param to_size notAfter date_time object size.
345 : *
346 : * @retval true verification pass.
347 : * @retval false verification fail.
348 : **/
349 782 : static bool libspdm_internal_x509_date_time_check(const uint8_t *from,
350 : size_t from_size,
351 : const uint8_t *to,
352 : size_t to_size)
353 : {
354 : int32_t ret;
355 : bool status;
356 : uint8_t f0[64];
357 : uint8_t t0[64];
358 : size_t f0_size;
359 : size_t t0_size;
360 :
361 782 : f0_size = 64;
362 782 : t0_size = 64;
363 :
364 782 : status = libspdm_x509_set_date_time("19700101000000Z", f0, &f0_size);
365 782 : if (!status) {
366 0 : return false;
367 : }
368 :
369 782 : status = libspdm_x509_set_date_time("99991231235959Z", t0, &t0_size);
370 782 : if (!status) {
371 0 : return false;
372 : }
373 :
374 : /* from >= f0*/
375 782 : ret = libspdm_x509_compare_date_time(from, f0);
376 782 : if (ret < 0) {
377 0 : return false;
378 : }
379 :
380 : /* to <= t0*/
381 782 : ret = libspdm_x509_compare_date_time(t0, to);
382 782 : if (ret < 0) {
383 0 : return false;
384 : }
385 :
386 782 : return true;
387 : }
388 :
389 : /**
390 : * This function returns the SPDM public key encryption algorithm OID len.
391 : *
392 : * @param[in] base_asym_algo SPDM base_asym_algo
393 : *
394 : * @return SPDM public key encryption algorithms OID len.
395 : **/
396 1556 : static uint32_t libspdm_get_public_key_algo_OID_len(
397 : uint32_t base_asym_algo, uint32_t pqc_asym_algo)
398 : {
399 1556 : if (base_asym_algo != 0) {
400 1556 : switch (base_asym_algo) {
401 116 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
402 : #if LIBSPDM_RSA_SSA_2048_SUPPORT
403 116 : return 4;
404 : #else
405 : return 0;
406 : #endif
407 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
408 : #if LIBSPDM_RSA_PSS_2048_SUPPORT
409 0 : return 4;
410 : #else
411 : return 0;
412 : #endif
413 6 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
414 : #if LIBSPDM_RSA_SSA_3072_SUPPORT
415 6 : return 4;
416 : #else
417 : return 0;
418 : #endif
419 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
420 : #if LIBSPDM_RSA_PSS_3072_SUPPORT
421 0 : return 4;
422 : #else
423 : return 0;
424 : #endif
425 4 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
426 : #if LIBSPDM_RSA_SSA_4096_SUPPORT
427 4 : return 4;
428 : #else
429 : return 0;
430 : #endif
431 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
432 : #if LIBSPDM_RSA_PSS_4096_SUPPORT
433 0 : return 4;
434 : #else
435 : return 0;
436 : #endif
437 1426 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
438 : #if LIBSPDM_ECDSA_P256_SUPPORT
439 1426 : return 8;
440 : #else
441 : return 0;
442 : #endif
443 2 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
444 : #if LIBSPDM_ECDSA_P384_SUPPORT
445 2 : return 5;
446 : #else
447 : return 0;
448 : #endif
449 2 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
450 : #if LIBSPDM_ECDSA_P521_SUPPORT
451 2 : return 5;
452 : #else
453 : return 0;
454 : #endif
455 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
456 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
457 : return 3;
458 : #else
459 0 : return 0;
460 : #endif
461 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
462 : #if LIBSPDM_EDDSA_ED448_SUPPORT
463 : return 3;
464 : #else
465 0 : return 0;
466 : #endif
467 0 : default:
468 0 : LIBSPDM_ASSERT(false);
469 0 : return 0;
470 : }
471 : }
472 0 : if (pqc_asym_algo != 0) {
473 0 : switch (pqc_asym_algo) {
474 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_44:
475 : #if LIBSPDM_ML_DSA_44_SUPPORT
476 : return 9;
477 : #else
478 0 : return 0;
479 : #endif
480 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_65:
481 : #if LIBSPDM_ML_DSA_65_SUPPORT
482 : return 9;
483 : #else
484 0 : return 0;
485 : #endif
486 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_87:
487 : #if LIBSPDM_ML_DSA_87_SUPPORT
488 : return 9;
489 : #else
490 0 : return 0;
491 : #endif
492 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128S:
493 : #if LIBSPDM_SLH_DSA_SHA2_128S_SUPPORT
494 : return 9;
495 : #else
496 0 : return 0;
497 : #endif
498 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128S:
499 : #if LIBSPDM_SLH_DSA_SHAKE_128S_SUPPORT
500 : return 9;
501 : #else
502 0 : return 0;
503 : #endif
504 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128F:
505 : #if LIBSPDM_SLH_DSA_SHA2_128F_SUPPORT
506 : return 9;
507 : #else
508 0 : return 0;
509 : #endif
510 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128F:
511 : #if LIBSPDM_SLH_DSA_SHAKE_128F_SUPPORT
512 : return 9;
513 : #else
514 0 : return 0;
515 : #endif
516 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192S:
517 : #if LIBSPDM_SLH_DSA_SHA2_192S_SUPPORT
518 : return 9;
519 : #else
520 0 : return 0;
521 : #endif
522 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192S:
523 : #if LIBSPDM_SLH_DSA_SHAKE_192S_SUPPORT
524 : return 9;
525 : #else
526 0 : return 0;
527 : #endif
528 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192F:
529 : #if LIBSPDM_SLH_DSA_SHA2_192F_SUPPORT
530 : return 9;
531 : #else
532 0 : return 0;
533 : #endif
534 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192F:
535 : #if LIBSPDM_SLH_DSA_SHAKE_192F_SUPPORT
536 : return 9;
537 : #else
538 0 : return 0;
539 : #endif
540 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256S:
541 : #if LIBSPDM_SLH_DSA_SHA2_256S_SUPPORT
542 : return 9;
543 : #else
544 0 : return 0;
545 : #endif
546 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256S:
547 : #if LIBSPDM_SLH_DSA_SHAKE_256S_SUPPORT
548 : return 9;
549 : #else
550 0 : return 0;
551 : #endif
552 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256F:
553 : #if LIBSPDM_SLH_DSA_SHA2_256F_SUPPORT
554 : return 9;
555 : #else
556 0 : return 0;
557 : #endif
558 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256F:
559 : #if LIBSPDM_SLH_DSA_SHAKE_256F_SUPPORT
560 : return 9;
561 : #else
562 0 : return 0;
563 : #endif
564 0 : default:
565 0 : LIBSPDM_ASSERT(false);
566 0 : return 0;
567 : }
568 : }
569 0 : LIBSPDM_ASSERT(false);
570 0 : return 0;
571 : }
572 :
573 : /**
574 : * This function get the SPDM public key encryption algorithm OID.
575 : *
576 : * @param[in] base_asym_algo SPDM base_asym_algo
577 : * @param[in,out] oid SPDM public key encryption algorithm OID
578 : * @param[in,out] oid_other Other SPDM public key encryption algorithm OID
579 : * because of ASN1 code for integer
580 : *
581 : * @retval true get OID successful.
582 : * @retval false get OID fail.
583 : **/
584 778 : static bool libspdm_get_public_key_algo_OID(
585 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint8_t *oid,
586 : uint8_t *oid_other)
587 : {
588 : uint32_t oid_len;
589 778 : oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
590 778 : if (oid_len == 0) {
591 0 : return false;
592 : }
593 :
594 778 : if (base_asym_algo != 0) {
595 778 : switch (base_asym_algo) {
596 58 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
597 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048: {
598 : #if (LIBSPDM_RSA_SSA_2048_SUPPORT) || (LIBSPDM_RSA_PSS_2048_SUPPORT)
599 58 : uint8_t encry_algo_oid_rsa2048[] = KEY_ENCRY_ALGO_RSA2048_FLAG;
600 58 : uint8_t encry_algo_oid_rsa2048_ohter[] = KEY_ENCRY_ALGO_RSA2048_FLAG_OTHER;
601 58 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_rsa2048, oid_len);
602 58 : libspdm_copy_mem(oid_other, oid_len, encry_algo_oid_rsa2048_ohter, oid_len);
603 58 : return true;
604 : #else
605 : return false;
606 : #endif
607 : }
608 3 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
609 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072: {
610 : #if (LIBSPDM_RSA_SSA_3072_SUPPORT) || (LIBSPDM_RSA_PSS_3072_SUPPORT)
611 3 : uint8_t encry_algo_oid_rsa3072[] = KEY_ENCRY_ALGO_RSA3072_FLAG;
612 3 : uint8_t encry_algo_oid_rsa3072_ohter[] = KEY_ENCRY_ALGO_RSA3072_FLAG_OTHER;
613 3 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_rsa3072, oid_len);
614 3 : libspdm_copy_mem(oid_other, oid_len, encry_algo_oid_rsa3072_ohter, oid_len);
615 3 : return true;
616 : #else
617 : return false;
618 : #endif
619 : }
620 2 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
621 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096: {
622 : #if (LIBSPDM_RSA_SSA_4096_SUPPORT) || (LIBSPDM_RSA_PSS_4096_SUPPORT)
623 2 : uint8_t encry_algo_oid_rsa4096[] = KEY_ENCRY_ALGO_RSA4096_FLAG;
624 2 : uint8_t encry_algo_oid_rsa4096_ohter[] = KEY_ENCRY_ALGO_RSA4096_FLAG_OTHER;
625 2 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_rsa4096, oid_len);
626 2 : libspdm_copy_mem(oid_other, oid_len, encry_algo_oid_rsa4096_ohter, oid_len);
627 2 : return true;
628 : #else
629 : return false;
630 : #endif
631 : }
632 :
633 713 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256: {
634 : #if LIBSPDM_ECDSA_P256_SUPPORT
635 713 : uint8_t encry_algo_oid_ecc256[] = KEY_ENCRY_ALGO_ECC256_OID;
636 713 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc256, oid_len);
637 713 : return true;
638 : #else
639 : return false;
640 : #endif
641 : }
642 1 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384: {
643 : #if LIBSPDM_ECDSA_P384_SUPPORT
644 1 : uint8_t encry_algo_oid_ecc384[] = KEY_ENCRY_ALGO_ECC384_OID;
645 1 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc384, oid_len);
646 1 : return true;
647 : #else
648 : return false;
649 : #endif
650 : }
651 1 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521: {
652 : #if LIBSPDM_ECDSA_P521_SUPPORT
653 1 : uint8_t encry_algo_oid_ecc521[] = KEY_ENCRY_ALGO_ECC521_OID;
654 1 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc521, oid_len);
655 1 : return true;
656 : #else
657 : return false;
658 : #endif
659 : }
660 :
661 : /*sm2 oid TBD*/
662 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
663 0 : return true;
664 :
665 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519: {
666 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
667 : uint8_t encry_algo_oid_ed25519[] = ENCRY_ALGO_ED25519_OID;
668 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ed25519, oid_len);
669 : return true;
670 : #else
671 0 : return false;
672 : #endif
673 : break;
674 : }
675 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448: {
676 : #if LIBSPDM_EDDSA_ED448_SUPPORT
677 : uint8_t encry_algo_oid_ed448[] = ENCRY_ALGO_ED448_OID;
678 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ed448, oid_len);
679 : return true;
680 : #else
681 0 : return false;
682 : #endif
683 : break;
684 : }
685 :
686 0 : default:
687 0 : LIBSPDM_ASSERT(false);
688 0 : return false;
689 : }
690 : }
691 0 : if (pqc_asym_algo != 0) {
692 0 : switch (pqc_asym_algo) {
693 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_44: {
694 : #if LIBSPDM_ML_DSA_44_SUPPORT
695 : uint8_t algo_oid_mldsa44[] = ALGO_MLDSA44_OID;
696 : libspdm_copy_mem(oid, oid_len, algo_oid_mldsa44, oid_len);
697 : return true;
698 : #else
699 0 : return false;
700 : #endif
701 : break;
702 : }
703 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_65: {
704 : #if LIBSPDM_ML_DSA_65_SUPPORT
705 : uint8_t algo_oid_mldsa65[] = ALGO_MLDSA65_OID;
706 : libspdm_copy_mem(oid, oid_len, algo_oid_mldsa65, oid_len);
707 : return true;
708 : #else
709 0 : return false;
710 : #endif
711 : break;
712 : }
713 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_87: {
714 : #if LIBSPDM_ML_DSA_87_SUPPORT
715 : uint8_t algo_oid_mldsa87[] = ALGO_MLDSA87_OID;
716 : libspdm_copy_mem(oid, oid_len, algo_oid_mldsa87, oid_len);
717 : return true;
718 : #else
719 0 : return false;
720 : #endif
721 : break;
722 : }
723 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128S: {
724 : #if LIBSPDM_SLH_DSA_SHA2_128S_SUPPORT
725 : uint8_t algo_oid_slhdsa_sha2_128s[] = ALGO_SLHDSA_SHA2_128S_OID;
726 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_128s, oid_len);
727 : return true;
728 : #else
729 0 : return false;
730 : #endif
731 : break;
732 : }
733 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128S: {
734 : #if LIBSPDM_SLH_DSA_SHAKE_128S_SUPPORT
735 : uint8_t algo_oid_slhdsa_shake_128s[] = ALGO_SLHDSA_SHAKE_128S_OID;
736 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_128s, oid_len);
737 : return true;
738 : #else
739 0 : return false;
740 : #endif
741 : break;
742 : }
743 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128F: {
744 : #if LIBSPDM_SLH_DSA_SHA2_128F_SUPPORT
745 : uint8_t algo_oid_slhdsa_sha2_128f[] = ALGO_SLHDSA_SHA2_128F_OID;
746 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_128f, oid_len);
747 : return true;
748 : #else
749 0 : return false;
750 : #endif
751 : break;
752 : }
753 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128F: {
754 : #if LIBSPDM_SLH_DSA_SHAKE_128F_SUPPORT
755 : uint8_t algo_oid_slhdsa_shake_128f[] = ALGO_SLHDSA_SHAKE_128F_OID;
756 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_128f, oid_len);
757 : return true;
758 : #else
759 0 : return false;
760 : #endif
761 : break;
762 : }
763 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192S: {
764 : #if LIBSPDM_SLH_DSA_SHA2_192S_SUPPORT
765 : uint8_t algo_oid_slhdsa_sha2_192s[] = ALGO_SLHDSA_SHA2_192S_OID;
766 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_192s, oid_len);
767 : return true;
768 : #else
769 0 : return false;
770 : #endif
771 : break;
772 : }
773 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192S: {
774 : #if LIBSPDM_SLH_DSA_SHAKE_192S_SUPPORT
775 : uint8_t algo_oid_slhdsa_shake_192s[] = ALGO_SLHDSA_SHAKE_192S_OID;
776 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_192s, oid_len);
777 : return true;
778 : #else
779 0 : return false;
780 : #endif
781 : break;
782 : }
783 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192F: {
784 : #if LIBSPDM_SLH_DSA_SHA2_192F_SUPPORT
785 : uint8_t algo_oid_slhdsa_sha2_192f[] = ALGO_SLHDSA_SHA2_192F_OID;
786 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_192f, oid_len);
787 : return true;
788 : #else
789 0 : return false;
790 : #endif
791 : break;
792 : }
793 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192F: {
794 : #if LIBSPDM_SLH_DSA_SHAKE_192F_SUPPORT
795 : uint8_t algo_oid_slhdsa_shake_192f[] = ALGO_SLHDSA_SHAKE_192F_OID;
796 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_192f, oid_len);
797 : return true;
798 : #else
799 0 : return false;
800 : #endif
801 : break;
802 : }
803 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256S: {
804 : #if LIBSPDM_SLH_DSA_SHA2_256S_SUPPORT
805 : uint8_t algo_oid_slhdsa_sha2_256s[] = ALGO_SLHDSA_SHA2_256S_OID;
806 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_256s, oid_len);
807 : return true;
808 : #else
809 0 : return false;
810 : #endif
811 : break;
812 : }
813 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256S: {
814 : #if LIBSPDM_SLH_DSA_SHAKE_256S_SUPPORT
815 : uint8_t algo_oid_slhdsa_shake_256s[] = ALGO_SLHDSA_SHAKE_256S_OID;
816 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_256s, oid_len);
817 : return true;
818 : #else
819 0 : return false;
820 : #endif
821 : break;
822 : }
823 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256F: {
824 : #if LIBSPDM_SLH_DSA_SHA2_256F_SUPPORT
825 : uint8_t algo_oid_slhdsa_sha2_256f[] = ALGO_SLHDSA_SHA2_256F_OID;
826 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_256f, oid_len);
827 : return true;
828 : #else
829 0 : return false;
830 : #endif
831 : break;
832 : }
833 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256F: {
834 : #if LIBSPDM_SLH_DSA_SHAKE_256F_SUPPORT
835 : uint8_t algo_oid_slhdsa_shake_256f[] = ALGO_SLHDSA_SHAKE_256F_OID;
836 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_256f, oid_len);
837 : return true;
838 : #else
839 0 : return false;
840 : #endif
841 : break;
842 : }
843 0 : default:
844 0 : LIBSPDM_ASSERT(false);
845 0 : return false;
846 : }
847 : }
848 0 : LIBSPDM_ASSERT(false);
849 0 : return false;
850 : }
851 :
852 : /**
853 : * Verify cert public key encryption algorithm is matched to negotiated base_aysm algo
854 : *
855 : * @param[in] cert Pointer to the DER-encoded certificate data.
856 : * @param[in] cert_size The size of certificate data in bytes.
857 : * @param[in] base_asym_algo SPDM base_asym_algo
858 : * @param[out] oid cert public key encryption algorithm OID
859 : * @param[in] oid_size the buffer size for required OID
860 : *
861 : * @retval true get public key oid from cert successfully
862 : * @retval false get public key oid from cert fail
863 : **/
864 778 : static bool libspdm_get_public_key_oid(
865 : const uint8_t *cert, size_t cert_size,
866 : uint8_t *oid, size_t oid_size, uint32_t base_asym_algo, uint32_t pqc_asym_algo)
867 : {
868 : bool ret;
869 : uint8_t *ptr;
870 : int32_t length;
871 : size_t obj_len;
872 : uint8_t *end;
873 : uint8_t index;
874 : uint8_t sequence_time;
875 :
876 778 : length = (int32_t)cert_size;
877 778 : ptr = (uint8_t*)(size_t)cert;
878 778 : obj_len = 0;
879 778 : end = ptr + length;
880 778 : ret = true;
881 :
882 : /* TBSCertificate have 5 sequence before subjectPublicKeyInfo*/
883 778 : sequence_time = 5;
884 :
885 : /*all cert sequence*/
886 778 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
887 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
888 778 : if (!ret) {
889 0 : return false;
890 : }
891 :
892 : /*TBSCertificate sequence*/
893 778 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
894 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
895 778 : if (!ret) {
896 0 : return false;
897 : }
898 :
899 778 : end = ptr + obj_len;
900 : /*version*/
901 778 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
902 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
903 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
904 778 : if (!ret) {
905 0 : return false;
906 : }
907 :
908 778 : ptr += obj_len;
909 : /*serialNumber*/
910 778 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
911 778 : if (!ret) {
912 0 : return false;
913 : }
914 :
915 : /**
916 : * signature AlgorithmIdentifier,
917 : * issuer Name,
918 : * validity Validity,
919 : * subject Name,
920 : * subjectPublicKeyInfo
921 : **/
922 4668 : for (index = 0; index < sequence_time; index++) {
923 3890 : ptr += obj_len;
924 3890 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
925 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
926 3890 : if (!ret) {
927 0 : return false;
928 : }
929 : }
930 :
931 778 : if (base_asym_algo != 0) {
932 778 : switch (base_asym_algo)
933 : {
934 63 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
935 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
936 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
937 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
938 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
939 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
940 63 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
941 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
942 63 : if (!ret) {
943 0 : return false;
944 : }
945 :
946 63 : ptr += obj_len;
947 63 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_BIT_STRING);
948 63 : if (!ret) {
949 0 : return false;
950 : }
951 :
952 : /*get rsa key len*/
953 63 : ptr++;
954 63 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
955 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
956 63 : if (!ret) {
957 1 : return false;
958 : }
959 62 : libspdm_copy_mem(oid, oid_size, ptr, oid_size);
960 62 : break;
961 715 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
962 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
963 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
964 715 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
965 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
966 715 : if (!ret) {
967 0 : return false;
968 : }
969 715 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
970 715 : if (!ret) {
971 0 : return false;
972 : }
973 :
974 : /*get ecc second oid*/
975 715 : ptr +=obj_len;
976 715 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
977 715 : if (!ret) {
978 0 : return false;
979 : }
980 :
981 715 : if (oid_size != obj_len) {
982 0 : return false;
983 : }
984 :
985 715 : libspdm_copy_mem(oid, oid_size, ptr, obj_len);
986 715 : break;
987 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
988 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
989 0 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
990 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
991 0 : if (!ret) {
992 0 : return false;
993 : }
994 :
995 : /*get eddsa oid*/
996 0 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
997 0 : if (!ret) {
998 0 : return false;
999 : }
1000 :
1001 0 : if (oid_size != obj_len) {
1002 0 : return false;
1003 : }
1004 :
1005 0 : libspdm_copy_mem(oid, oid_size, ptr, obj_len);
1006 0 : break;
1007 0 : default:
1008 0 : LIBSPDM_ASSERT(false);
1009 0 : return false;
1010 : }
1011 : }
1012 777 : if (pqc_asym_algo != 0) {
1013 0 : switch (pqc_asym_algo)
1014 : {
1015 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_44:
1016 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_65:
1017 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_87:
1018 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128S:
1019 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128S:
1020 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128F:
1021 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128F:
1022 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192S:
1023 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192S:
1024 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192F:
1025 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192F:
1026 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256S:
1027 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256S:
1028 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256F:
1029 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256F:
1030 : /* algorithm AlgorithmIdentifier SEQUENCE */
1031 0 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
1032 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1033 0 : if (!ret) {
1034 0 : return false;
1035 : }
1036 :
1037 : /* OID */
1038 0 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1039 0 : if (!ret) {
1040 0 : return false;
1041 : }
1042 :
1043 0 : if (oid_size != obj_len) {
1044 0 : return false;
1045 : }
1046 :
1047 0 : libspdm_copy_mem(oid, oid_size, ptr, obj_len);
1048 0 : break;
1049 0 : default:
1050 0 : LIBSPDM_ASSERT(false);
1051 0 : return false;
1052 : }
1053 : }
1054 777 : return true;
1055 : }
1056 :
1057 : /**
1058 : * Verify cert public key encryption algorithm is matched to negotiated base_aysm algo
1059 : *
1060 : * @param[in] cert Pointer to the DER-encoded certificate data.
1061 : * @param[in] cert_size The size of certificate data in bytes.
1062 : * @param[in] base_asym_algo SPDM base_asym_algo
1063 : *
1064 : * @retval true verify pass
1065 : * @retval false verify fail
1066 : **/
1067 778 : static bool libspdm_verify_cert_subject_public_key_info(const uint8_t *cert, size_t cert_size,
1068 : uint32_t base_asym_algo, uint32_t pqc_asym_algo)
1069 : {
1070 : size_t oid_len;
1071 : bool status;
1072 :
1073 : /*public key encrypt algo OID from cert*/
1074 : uint8_t cert_public_key_crypt_algo_oid[LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN];
1075 : /*public key encrypt algo OID from libspdm stored*/
1076 : uint8_t libspdm_public_key_crypt_algo_oid[LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN];
1077 : uint8_t libspdm_public_key_crypt_algo_oid_other[LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN];
1078 :
1079 778 : libspdm_zero_mem(libspdm_public_key_crypt_algo_oid, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
1080 778 : libspdm_zero_mem(libspdm_public_key_crypt_algo_oid_other, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
1081 :
1082 : /*work around: skip the sm2*/
1083 778 : if (base_asym_algo == SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256) {
1084 0 : return true;
1085 : }
1086 :
1087 778 : oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
1088 778 : if (oid_len == 0) {
1089 0 : return false;
1090 : }
1091 : /*get public key encrypt algo OID from libspdm stored*/
1092 778 : status = libspdm_get_public_key_algo_OID(base_asym_algo, pqc_asym_algo,
1093 : libspdm_public_key_crypt_algo_oid,
1094 : libspdm_public_key_crypt_algo_oid_other);
1095 778 : if (!status) {
1096 0 : return status;
1097 : }
1098 :
1099 : /*get public key encrypt algo OID from cert*/
1100 778 : status = libspdm_get_public_key_oid(cert, cert_size, cert_public_key_crypt_algo_oid, oid_len,
1101 : base_asym_algo, pqc_asym_algo);
1102 778 : if (!status || (!libspdm_consttime_is_mem_equal(cert_public_key_crypt_algo_oid,
1103 1 : libspdm_public_key_crypt_algo_oid, oid_len) &&
1104 1 : !libspdm_consttime_is_mem_equal(cert_public_key_crypt_algo_oid,
1105 : libspdm_public_key_crypt_algo_oid_other,
1106 : oid_len))) {
1107 2 : return false;
1108 : }
1109 :
1110 776 : return status;
1111 : }
1112 :
1113 : /**
1114 : * Verify leaf cert basic_constraints CA is false
1115 : *
1116 : * @param[in] cert Pointer to the DER-encoded certificate data.
1117 : * @param[in] cert_size The size of certificate data in bytes.
1118 : * @param[in] need_basic_constraints This value indicates whether basic_constraints must be present in the Cert
1119 : *
1120 : * @retval true verify pass,two case: 1.basic constraints is not present in cert, when need_basic_constraints is false;
1121 : * 2. cert basic_constraints CA is false;
1122 : * @retval false verify fail
1123 : **/
1124 761 : static bool libspdm_verify_leaf_cert_basic_constraints(const uint8_t *cert, size_t cert_size,
1125 : bool need_basic_constraints)
1126 : {
1127 : bool status;
1128 : /*basic_constraints from cert*/
1129 : uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
1130 : size_t len;
1131 :
1132 761 : uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
1133 761 : uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
1134 :
1135 761 : len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1136 :
1137 761 : status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1138 : cert_basic_constraints, &len);
1139 761 : if (!status) {
1140 0 : return false;
1141 761 : } else if (len == 0) {
1142 : /* basic constraints is not present in cert */
1143 2 : if (need_basic_constraints) {
1144 1 : return false;
1145 : } else {
1146 1 : return true;
1147 : }
1148 : }
1149 :
1150 1516 : if ((len == sizeof(basic_constraints_false_case1)) &&
1151 757 : (libspdm_consttime_is_mem_equal(cert_basic_constraints,
1152 : basic_constraints_false_case1,
1153 : sizeof(basic_constraints_false_case1)))) {
1154 757 : return true;
1155 : }
1156 :
1157 4 : if ((len == sizeof(basic_constraints_false_case2)) &&
1158 2 : (libspdm_consttime_is_mem_equal(cert_basic_constraints,
1159 : basic_constraints_false_case2,
1160 : sizeof(basic_constraints_false_case2)))) {
1161 0 : return true;
1162 : }
1163 :
1164 2 : return false;
1165 : }
1166 :
1167 : /**
1168 : * Verify leaf certificate basic_constraints CA is correct for set certificate.
1169 : *
1170 : * For SPDM 1.2
1171 : * - If certificate model is DeviceCert and CA is present then CA must be false.
1172 : * - If certificate model is AliasCert and CA is present then CA must be true.
1173 : *
1174 : * For SPDM 1.3 and up, CA must be present and
1175 : * - If certificate model is DeviceCert or GenericCert then CA must be false.
1176 : * - If certificate model is AliasCert then CA must be true.
1177 : *
1178 : * @param[in] cert Pointer to the DER-encoded certificate data.
1179 : * @param[in] cert_size The size of certificate data in bytes.
1180 : * @param[in] cert_model The certificate model.
1181 : * @param[in] need_basic_constraints This value indicates whether basic_constraints must be present
1182 : * in the certificate.
1183 : *
1184 : * @retval true verify pass 1. basic_constraints is not present when allowed.
1185 : * 2. basic_constraints is present and correct.
1186 : * @retval false verify fail
1187 : **/
1188 15 : static bool libspdm_verify_set_cert_leaf_cert_basic_constraints(
1189 : const uint8_t *cert, size_t cert_size, uint8_t cert_model, bool need_basic_constraints)
1190 : {
1191 : bool status;
1192 : /* basic_constraints from certificate. */
1193 : uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
1194 : size_t len;
1195 :
1196 15 : const uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
1197 15 : const uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
1198 15 : const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_STRING_TRUE_CASE;
1199 :
1200 15 : len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1201 :
1202 15 : status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1203 : cert_basic_constraints, &len);
1204 15 : if (!status) {
1205 0 : return false;
1206 15 : } else if (need_basic_constraints && (len == 0)) {
1207 0 : return false;
1208 : }
1209 :
1210 15 : if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT) ||
1211 : (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1212 9 : if (need_basic_constraints || (len != 0)) {
1213 18 : if ((len == sizeof(basic_constraints_false_case1)) &&
1214 9 : (libspdm_consttime_is_mem_equal(cert_basic_constraints,
1215 : basic_constraints_false_case1,
1216 : sizeof(basic_constraints_false_case1)))) {
1217 9 : return true;
1218 : }
1219 :
1220 0 : if ((len == sizeof(basic_constraints_false_case2)) &&
1221 0 : (libspdm_consttime_is_mem_equal(cert_basic_constraints,
1222 : basic_constraints_false_case2,
1223 : sizeof(basic_constraints_false_case2)))) {
1224 0 : return true;
1225 : }
1226 : }
1227 : } else {
1228 : /* Alias certificate model. */
1229 6 : if (need_basic_constraints || (len != 0)) {
1230 : /* basicConstraints may include the pathLen field. Therefore do not check sequence
1231 : * length. */
1232 6 : if (len >= sizeof(basic_constraints_true_case)) {
1233 4 : if (cert_basic_constraints[0] != basic_constraints_true_case[0]) {
1234 0 : return false;
1235 : }
1236 4 : if (libspdm_consttime_is_mem_equal(&cert_basic_constraints[2],
1237 : &basic_constraints_true_case[2],
1238 : sizeof(basic_constraints_true_case) - 2)) {
1239 4 : return true;
1240 : }
1241 : }
1242 : }
1243 : }
1244 2 : return false;
1245 : }
1246 :
1247 : /**
1248 : * Verify leaf cert spdm defined extended key usage
1249 : *
1250 : * @param[in] cert Pointer to the DER-encoded certificate data.
1251 : * @param[in] cert_size The size of certificate data in bytes.
1252 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1253 : *
1254 : * @retval true verify pass, two cases:
1255 : * 1. spdm defined eku is not present in cert;
1256 : * 2. spdm defined eku is compliant with requester/responder identity;
1257 : * @retval false verify fail, two cases:
1258 : * 1. requester's cert has only responder auth oid in eku;
1259 : * 2. responder's cert has only requester auth oid in eku;
1260 : **/
1261 782 : static bool libspdm_verify_leaf_cert_spdm_eku(const uint8_t *cert, size_t cert_size,
1262 : bool is_requester_cert)
1263 : {
1264 : bool status;
1265 : uint8_t eku[256];
1266 : size_t eku_size;
1267 : bool req_auth_oid_find_success;
1268 : bool rsp_auth_oid_find_success;
1269 : uint8_t *ptr;
1270 : size_t obj_len;
1271 :
1272 : /* SPDM defined OID */
1273 782 : uint8_t eku_requester_auth_oid[] = SPDM_OID_DMTF_EKU_REQUESTER_AUTH;
1274 782 : uint8_t eku_responder_auth_oid[] = SPDM_OID_DMTF_EKU_RESPONDER_AUTH;
1275 :
1276 782 : eku_size = sizeof(eku);
1277 782 : status = libspdm_x509_get_extended_key_usage(cert, cert_size, eku, &eku_size);
1278 782 : if (!status) {
1279 0 : return false;
1280 782 : } else if (eku_size == 0) {
1281 : /* eku is not present in cert */
1282 0 : return true;
1283 : }
1284 :
1285 782 : ptr = eku;
1286 782 : obj_len = 0;
1287 782 : req_auth_oid_find_success = false;
1288 782 : rsp_auth_oid_find_success = false;
1289 :
1290 782 : status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len,
1291 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1292 782 : if (!status) {
1293 0 : return false;
1294 : }
1295 :
1296 3131 : while(ptr < eku + eku_size) {
1297 2349 : status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1298 2349 : if (!status) {
1299 0 : return false;
1300 : }
1301 :
1302 2357 : if ((obj_len == sizeof(eku_requester_auth_oid)) &&
1303 8 : (libspdm_consttime_is_mem_equal(ptr, eku_requester_auth_oid,
1304 : sizeof(eku_requester_auth_oid)))) {
1305 4 : req_auth_oid_find_success = true;
1306 : }
1307 2357 : if ((obj_len == sizeof(eku_responder_auth_oid)) &&
1308 8 : (libspdm_consttime_is_mem_equal(ptr, eku_responder_auth_oid,
1309 : sizeof(eku_responder_auth_oid)))) {
1310 4 : rsp_auth_oid_find_success = true;
1311 : }
1312 :
1313 2349 : ptr += obj_len;
1314 : }
1315 :
1316 782 : if (ptr != eku + eku_size) {
1317 0 : return false;
1318 : }
1319 :
1320 782 : if (is_requester_cert) {
1321 : /* it should not only contain responder auth oid */
1322 20 : if (!req_auth_oid_find_success && rsp_auth_oid_find_success) {
1323 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Requester certificate contains Responder OID.\n"));
1324 1 : return false;
1325 : }
1326 : } else {
1327 : /* it should not only contain requester auth oid */
1328 762 : if (req_auth_oid_find_success && !rsp_auth_oid_find_success) {
1329 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Responder certificate contains Requester OID.\n"));
1330 1 : return false;
1331 : }
1332 : }
1333 :
1334 780 : return true;
1335 : }
1336 :
1337 : /**
1338 : * Verify leaf cert spdm defined extension
1339 : *
1340 : * @param[in] cert Pointer to the DER-encoded certificate data.
1341 : * @param[in] cert_size The size of certificate data in bytes.
1342 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1343 : *
1344 : * @retval true verify pass
1345 : * @retval false verify fail,two case: 1. Unable to get get or validate extension data.
1346 : * 2. hardware_identity_oid is found in AliasCert model;
1347 : **/
1348 774 : static bool libspdm_verify_leaf_cert_spdm_extension(const uint8_t *cert, size_t cert_size,
1349 : bool is_requester_cert,
1350 : uint8_t cert_model)
1351 : {
1352 : bool status;
1353 : bool find_sucessful;
1354 : uint8_t spdm_extension[LIBSPDM_MAX_EXTENSION_LEN];
1355 : size_t len;
1356 : uint8_t *ptr;
1357 : uint8_t *temptr;
1358 : size_t obj_len;
1359 :
1360 : /* SPDM defined OID */
1361 774 : uint8_t oid_spdm_extension[] = SPDM_OID_DMTF_SPDM_EXTENSION;
1362 774 : uint8_t hardware_identity_oid[] = SPDM_OID_DMTF_HARDWARE_IDENTITY;
1363 :
1364 774 : len = LIBSPDM_MAX_EXTENSION_LEN;
1365 :
1366 774 : if (cert == NULL || cert_size == 0) {
1367 0 : return false;
1368 : }
1369 :
1370 774 : status = libspdm_x509_get_extension_data(cert, cert_size,
1371 : (const uint8_t *)oid_spdm_extension,
1372 : sizeof(oid_spdm_extension),
1373 : spdm_extension,
1374 : &len);
1375 774 : if (!status) {
1376 0 : return false;
1377 774 : } else if (len == 0) {
1378 13 : return true;
1379 : }
1380 :
1381 : /*find the spdm hardware identity OID*/
1382 761 : find_sucessful = false;
1383 761 : ptr = spdm_extension;
1384 761 : obj_len = 0;
1385 :
1386 : /*id-spdm-cert-oids ::= SEQUENCE SIZE (1..MAX) OF id-spdm-cert-oid*/
1387 761 : status = libspdm_asn1_get_tag(
1388 : &ptr, spdm_extension + len, &obj_len,
1389 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1390 761 : if (!status) {
1391 0 : return false;
1392 : }
1393 :
1394 1522 : while(ptr < spdm_extension + len) {
1395 761 : status = libspdm_asn1_get_tag(
1396 : &ptr, spdm_extension + len, &obj_len,
1397 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1398 761 : if (!status) {
1399 0 : return false;
1400 : }
1401 :
1402 761 : temptr = ptr + obj_len;
1403 761 : status = libspdm_asn1_get_tag(
1404 : &ptr, spdm_extension + len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1405 761 : if (!status) {
1406 0 : return false;
1407 : }
1408 1522 : if ((obj_len == sizeof(hardware_identity_oid)) &&
1409 761 : (libspdm_consttime_is_mem_equal(ptr, hardware_identity_oid,
1410 : sizeof(hardware_identity_oid)))) {
1411 761 : find_sucessful = true;
1412 : }
1413 761 : ptr = temptr;
1414 : }
1415 :
1416 761 : if (ptr != spdm_extension + len) {
1417 0 : return false;
1418 : }
1419 :
1420 : /* Responder does not determine Requester's certificate model */
1421 761 : if (!is_requester_cert) {
1422 746 : if ((find_sucessful) && (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1423 : /* Hardware_identity_OID is found in alias cert model */
1424 4 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1425 : "Hardware identity OID present in alias leaf certificate.\n"));
1426 4 : return false;
1427 : }
1428 : }
1429 :
1430 757 : return true;
1431 : }
1432 :
1433 : /**
1434 : * Certificate common Check for SPDM leaf cert when get_cert and set_cert.
1435 : *
1436 : * @param[in] cert Pointer to the DER-encoded certificate data.
1437 : * @param[in] cert_size The size of certificate data in bytes.
1438 : * @param[in] base_asym_algo SPDM base_asym_algo
1439 : * @param[in] base_hash_algo SPDM base_hash_algo
1440 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1441 : * @param[in] cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
1442 : * @param[in] set_cert Is the function verifying a set certificate operation.
1443 : *
1444 : * @retval true Success.
1445 : * @retval false Certificate is not valid.
1446 : **/
1447 784 : bool libspdm_x509_common_certificate_check(
1448 : const uint8_t *cert, size_t cert_size,
1449 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1450 : bool is_requester_cert, uint8_t cert_model,
1451 : bool set_cert)
1452 : {
1453 : uint8_t end_cert_from[64];
1454 : size_t end_cert_from_len;
1455 : uint8_t end_cert_to[64];
1456 : size_t end_cert_to_len;
1457 : size_t asn1_buffer_len;
1458 : bool status;
1459 : size_t cert_version;
1460 : void *context;
1461 : size_t signature_algo_oid_size;
1462 :
1463 784 : if (cert == NULL || cert_size == 0) {
1464 0 : return false;
1465 : }
1466 :
1467 784 : status = true;
1468 784 : context = NULL;
1469 784 : end_cert_from_len = 64;
1470 784 : end_cert_to_len = 64;
1471 :
1472 : /* 1. Version */
1473 784 : cert_version = 0;
1474 784 : status = libspdm_x509_get_version(cert, cert_size, &cert_version);
1475 784 : if (!status) {
1476 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Version field is not present.\n"));
1477 0 : goto cleanup;
1478 : }
1479 784 : if (cert_version != 2) {
1480 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1481 : "Expected Version to be equal to 2 but it is actually %zu.\n", cert_version));
1482 0 : status = false;
1483 0 : goto cleanup;
1484 : }
1485 :
1486 : /* 2. Serial Number */
1487 784 : asn1_buffer_len = 0;
1488 784 : status = libspdm_x509_get_serial_number(cert, cert_size, NULL, &asn1_buffer_len);
1489 784 : if (asn1_buffer_len == 0) {
1490 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Serial Number field is not present.\n"));
1491 0 : status = false;
1492 0 : goto cleanup;
1493 : }
1494 :
1495 : /* 3. Signature Algorithm */
1496 784 : signature_algo_oid_size = 0;
1497 784 : status = libspdm_x509_get_signature_algorithm(cert, cert_size, NULL, &signature_algo_oid_size);
1498 784 : if (status) {
1499 0 : if ((signature_algo_oid_size == 0) &&
1500 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1501 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1502 : "The mandatory Signature Algorithm field is not present.\n"));
1503 0 : status = false;
1504 0 : goto cleanup;
1505 : }
1506 : } else {
1507 784 : if (signature_algo_oid_size == 0) {
1508 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1509 : "The mandatory Signature Algorithm field is not present.\n"));
1510 0 : status = false;
1511 0 : goto cleanup;
1512 : }
1513 : }
1514 :
1515 : /* 4. Verify public key algorithm.
1516 : * If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
1517 : * check should be skipped as the Device Certificate CA's public key does not have to use
1518 : * the same algorithms as the connection's negotiated algorithms. */
1519 784 : if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1520 778 : status = libspdm_verify_cert_subject_public_key_info(cert, cert_size, base_asym_algo,
1521 : pqc_asym_algo);
1522 778 : if (!status) {
1523 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1524 : "Error in verifying the Public Key Algorithm field.\n"));
1525 2 : goto cleanup;
1526 : }
1527 : }
1528 :
1529 : /* 5. Issuer */
1530 782 : asn1_buffer_len = 0;
1531 782 : status = libspdm_x509_get_issuer_name(cert, cert_size, NULL, &asn1_buffer_len);
1532 782 : if (status) {
1533 0 : if ((asn1_buffer_len == 0) &&
1534 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1535 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Issuer field is not present.\n"));
1536 0 : status = false;
1537 0 : goto cleanup;
1538 : }
1539 : } else {
1540 782 : if (asn1_buffer_len == 0) {
1541 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Issuer field is not present.\n"));
1542 0 : status = false;
1543 0 : goto cleanup;
1544 : }
1545 : }
1546 :
1547 : /* 6. subject_name*/
1548 782 : asn1_buffer_len = 0;
1549 782 : status = libspdm_x509_get_subject_name(cert, cert_size, NULL, &asn1_buffer_len);
1550 782 : if (status) {
1551 0 : if ((asn1_buffer_len == 0) &&
1552 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1553 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Subject field is not present.\n"));
1554 0 : status = false;
1555 0 : goto cleanup;
1556 : }
1557 : } else {
1558 782 : if (asn1_buffer_len == 0) {
1559 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Subject field is not present.\n"));
1560 0 : status = false;
1561 0 : goto cleanup;
1562 : }
1563 : }
1564 :
1565 : /* 7. Validity */
1566 782 : status = libspdm_x509_get_validity(cert, cert_size, end_cert_from,
1567 : &end_cert_from_len, end_cert_to,
1568 : &end_cert_to_len);
1569 782 : if (status) {
1570 782 : if ((end_cert_from_len == 0) &&
1571 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1572 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Validity field is not present.\n"));
1573 0 : status = false;
1574 0 : goto cleanup;
1575 : }
1576 : } else {
1577 0 : if (end_cert_from_len == 0) {
1578 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Validity field is not present.\n"));
1579 0 : status = false;
1580 0 : goto cleanup;
1581 : }
1582 : }
1583 :
1584 782 : if (end_cert_from_len != 0) {
1585 782 : status = libspdm_internal_x509_date_time_check(
1586 : end_cert_from, end_cert_from_len, end_cert_to, end_cert_to_len);
1587 782 : if (!status) {
1588 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1589 : "The certificate is outside its validity period.\n"));
1590 0 : goto cleanup;
1591 : }
1592 : }
1593 :
1594 : /* 8. Subject Public Key Info */
1595 782 : if (base_asym_algo != 0) {
1596 782 : status = libspdm_asym_get_public_key_from_x509(base_asym_algo, cert, cert_size, &context);
1597 : }
1598 782 : if (pqc_asym_algo != 0) {
1599 0 : status = libspdm_pqc_asym_get_public_key_from_x509(pqc_asym_algo, cert, cert_size, &context);
1600 : }
1601 782 : if (!status) {
1602 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1603 : "The mandatory Subject Public Key Info field is not present.\n"));
1604 0 : goto cleanup;
1605 : }
1606 :
1607 : /* 9. Key Usage
1608 : * If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
1609 : * check should be skipped as the SPDM specification does not specify the presence or absence
1610 : * of the Device Certificate CA's keyUsage field. */
1611 782 : if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1612 776 : size_t value = 0;
1613 :
1614 776 : status = libspdm_x509_get_key_usage(cert, cert_size, &value);
1615 776 : if (!status) {
1616 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Key Usage field is not present.\n"));
1617 0 : goto cleanup;
1618 : } else {
1619 776 : if (value == 0) {
1620 0 : if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
1621 0 : status = false;
1622 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1623 : "The mandatory Key Usage field is not present.\n"));
1624 0 : goto cleanup;
1625 : }
1626 : } else {
1627 776 : if ((LIBSPDM_CRYPTO_X509_KU_DIGITAL_SIGNATURE & value) == 0) {
1628 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1629 : "The Mandatory digital signature bit in Key Usage field is not set.\n"));
1630 0 : status = false;
1631 0 : goto cleanup;
1632 : }
1633 : }
1634 : }
1635 : }
1636 :
1637 : /* 10. Extended Key Usage */
1638 782 : status = libspdm_verify_leaf_cert_spdm_eku(cert, cert_size, is_requester_cert);
1639 782 : if (!status) {
1640 2 : goto cleanup;
1641 : }
1642 :
1643 780 : if ((!set_cert) || (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT)) {
1644 : /* 11. verify spdm defined extension*/
1645 774 : status = libspdm_verify_leaf_cert_spdm_extension(cert, cert_size,
1646 : is_requester_cert, cert_model);
1647 774 : if (!status) {
1648 4 : goto cleanup;
1649 : }
1650 : }
1651 :
1652 776 : cleanup:
1653 784 : if (base_asym_algo != 0) {
1654 784 : libspdm_asym_free(base_asym_algo, context);
1655 : }
1656 784 : if (pqc_asym_algo != 0) {
1657 0 : libspdm_pqc_asym_free(pqc_asym_algo, context);
1658 : }
1659 784 : return status;
1660 : }
1661 :
1662 : /**
1663 : * Certificate Check for SPDM leaf cert when get_cert command
1664 : *
1665 : * @param[in] cert Pointer to the DER-encoded certificate data.
1666 : * @param[in] cert_size The size of certificate data in bytes.
1667 : * @param[in] base_asym_algo SPDM base_asym_algo
1668 : * @param[in] base_hash_algo SPDM base_hash_algo
1669 : * @param[in] is_requester Is the function verifying a cert as a requester or responder.
1670 : * @param[in] is_device_cert_model If true, the local endpoint uses the DeviceCert model.
1671 : * If false, the local endpoint uses the AliasCert model.
1672 : *
1673 : * @retval true Success.
1674 : * @retval false Certificate is not valid
1675 : **/
1676 23 : bool libspdm_x509_certificate_check(const uint8_t *cert, size_t cert_size,
1677 : uint32_t base_asym_algo,
1678 : uint32_t base_hash_algo,
1679 : bool is_requester,
1680 : bool is_device_cert_model)
1681 : {
1682 : bool status;
1683 : uint8_t cert_model;
1684 :
1685 23 : if (is_device_cert_model) {
1686 20 : cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
1687 : } else {
1688 3 : cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
1689 : }
1690 :
1691 23 : status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo, 0,
1692 : base_hash_algo, is_requester,
1693 : cert_model, false);
1694 23 : if (!status) {
1695 4 : return false;
1696 : }
1697 :
1698 : /* verify basic constraints: the leaf cert always is ca:false in get_cert*/
1699 19 : status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, false);
1700 19 : return status;
1701 : }
1702 :
1703 :
1704 : /**
1705 : * Certificate Check for SPDM leaf cert when get_cert command. It is used for SPDM 1.3.
1706 : *
1707 : * @param[in] cert Pointer to the DER-encoded certificate data.
1708 : * @param[in] cert_size The size of certificate data in bytes.
1709 : * @param[in] base_asym_algo SPDM base_asym_algo
1710 : * @param[in] base_hash_algo SPDM base_hash_algo
1711 : * @param[in] is_requester Is the function verifying a cert as a requester or responder.
1712 : * @param[in] cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
1713 : *
1714 : * @retval true Success.
1715 : * @retval false Certificate is not valid
1716 : **/
1717 746 : bool libspdm_x509_certificate_check_with_pqc(const uint8_t *cert, size_t cert_size,
1718 : uint32_t base_asym_algo, uint32_t pqc_asym_algo,
1719 : uint32_t base_hash_algo,
1720 : bool is_requester,
1721 : uint8_t cert_model)
1722 : {
1723 : bool status;
1724 :
1725 746 : status = libspdm_x509_common_certificate_check(
1726 : cert, cert_size, base_asym_algo, pqc_asym_algo,
1727 : base_hash_algo, is_requester,
1728 : cert_model, false);
1729 746 : if (!status) {
1730 4 : return false;
1731 : }
1732 :
1733 : /* verify basic constraints: the leaf cert always is ca:false in get_cert
1734 : * basic_constraints is mandatory in SPDM 1.3*/
1735 742 : status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, true);
1736 742 : return status;
1737 : }
1738 :
1739 9 : bool libspdm_x509_certificate_check_ex(const uint8_t *cert, size_t cert_size,
1740 : uint32_t base_asym_algo,
1741 : uint32_t base_hash_algo,
1742 : bool is_requester,
1743 : uint8_t cert_model)
1744 : {
1745 9 : return libspdm_x509_certificate_check_with_pqc (
1746 : cert, cert_size,
1747 : base_asym_algo, 0, base_hash_algo,
1748 : is_requester, cert_model);
1749 : }
1750 :
1751 9 : bool libspdm_x509_set_cert_certificate_check(const uint8_t *cert, size_t cert_size,
1752 : uint32_t base_asym_algo, uint32_t base_hash_algo,
1753 : bool is_requester, bool is_device_cert_model)
1754 : {
1755 : bool status;
1756 : uint8_t cert_model;
1757 :
1758 9 : if (is_device_cert_model) {
1759 6 : cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
1760 : } else {
1761 3 : cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
1762 : }
1763 :
1764 9 : status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo, 0,
1765 : base_hash_algo, is_requester,
1766 : cert_model, true);
1767 9 : if (!status) {
1768 0 : return false;
1769 : }
1770 :
1771 : /* verify basic constraints: need check with is_device_cert_model*/
1772 9 : status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
1773 : cert, cert_size, cert_model, false);
1774 9 : return status;
1775 : }
1776 :
1777 6 : bool libspdm_x509_set_cert_certificate_check_with_pqc(
1778 : const uint8_t *cert, size_t cert_size,
1779 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1780 : bool is_requester, uint8_t cert_model)
1781 : {
1782 : bool status;
1783 :
1784 6 : status = libspdm_x509_common_certificate_check(
1785 : cert, cert_size, base_asym_algo, pqc_asym_algo,
1786 : base_hash_algo, is_requester,
1787 : cert_model, true);
1788 6 : if (!status) {
1789 0 : return false;
1790 : }
1791 :
1792 : /* verify basic constraints: need check with is_device_cert_model*/
1793 6 : status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
1794 : cert, cert_size, cert_model, true);
1795 :
1796 6 : return status;
1797 : }
1798 :
1799 5 : bool libspdm_x509_set_cert_certificate_check_ex(const uint8_t *cert, size_t cert_size,
1800 : uint32_t base_asym_algo, uint32_t base_hash_algo,
1801 : bool is_requester, uint8_t cert_model)
1802 : {
1803 5 : return libspdm_x509_set_cert_certificate_check_with_pqc (
1804 : cert, cert_size,
1805 : base_asym_algo, 0, base_hash_algo,
1806 : is_requester, cert_model);
1807 : }
1808 :
1809 : /**
1810 : * Return certificate is root cert or not.
1811 : * Certificate is considered as a root certificate if the subjectname equal issuername.
1812 : *
1813 : * @param[in] cert Pointer to the DER-encoded certificate data.
1814 : * @param[in] cert_size The size of certificate data in bytes.
1815 : *
1816 : * @retval true Certificate is self-signed.
1817 : * @retval false Certificate is not self-signed.
1818 : **/
1819 59 : bool libspdm_is_root_certificate(const uint8_t *cert, size_t cert_size)
1820 : {
1821 : uint8_t issuer_name[LIBSPDM_MAX_NAME_SIZE];
1822 : size_t issuer_name_len;
1823 : uint8_t subject_name[LIBSPDM_MAX_NAME_SIZE];
1824 : size_t subject_name_len;
1825 : bool result;
1826 :
1827 59 : if (cert == NULL || cert_size == 0) {
1828 0 : return false;
1829 : }
1830 :
1831 : /* 1. issuer_name*/
1832 59 : issuer_name_len = sizeof(issuer_name);
1833 59 : result = libspdm_x509_get_issuer_name(cert, cert_size, issuer_name, &issuer_name_len);
1834 59 : if (!result) {
1835 0 : return false;
1836 : }
1837 :
1838 : /* 2. subject_name*/
1839 59 : subject_name_len = sizeof(subject_name);
1840 59 : result = libspdm_x509_get_subject_name(cert, cert_size, subject_name, &subject_name_len);
1841 59 : if (!result) {
1842 0 : return false;
1843 : }
1844 :
1845 59 : if (issuer_name_len != subject_name_len) {
1846 3 : return false;
1847 : }
1848 56 : if (!libspdm_consttime_is_mem_equal(issuer_name, subject_name, issuer_name_len)) {
1849 0 : return false;
1850 : }
1851 :
1852 56 : return true;
1853 : }
1854 :
1855 : /**
1856 : * Retrieve the SubjectAltName from SubjectAltName Bytes.
1857 : *
1858 : * @param[in] buffer Pointer to subjectAltName oct bytes.
1859 : * @param[in] len size of buffer in bytes.
1860 : * @param[out] name_buffer buffer to contain the retrieved certificate
1861 : * SubjectAltName. At most name_buffer_size bytes will be
1862 : * written. Maybe NULL in order to determine the size
1863 : * buffer needed.
1864 : * @param[in,out] name_buffer_size The size in bytes of the name buffer on input,
1865 : * and the size of buffer returned name on output.
1866 : * If name_buffer is NULL then the amount of space needed
1867 : * in buffer (including the final null) is returned.
1868 : * @param[out] oid OID of otherName
1869 : * @param[in,out] oid_size the buffersize for required OID
1870 : *
1871 : * @retval true get the subjectAltName string successfully
1872 : * @retval failed get the subjectAltName string failed
1873 : **/
1874 9 : bool libspdm_get_dmtf_subject_alt_name_from_bytes(
1875 : uint8_t *buffer, const size_t len, char *name_buffer,
1876 : size_t *name_buffer_size, uint8_t *oid,
1877 : size_t *oid_size)
1878 : {
1879 : uint8_t *ptr;
1880 : int32_t length;
1881 : size_t obj_len;
1882 : int32_t ret;
1883 :
1884 : /*copy mem variable*/
1885 : volatile uint8_t* dst;
1886 : const volatile uint8_t* src;
1887 : size_t dst_len;
1888 : size_t src_len;
1889 :
1890 9 : length = (int32_t)len;
1891 9 : ptr = buffer;
1892 9 : obj_len = 0;
1893 :
1894 : /* Sequence*/
1895 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + length, &obj_len,
1896 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1897 9 : if (!ret) {
1898 0 : return false;
1899 : }
1900 :
1901 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len,
1902 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1903 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1904 :
1905 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1906 9 : if (!ret) {
1907 0 : return false;
1908 : }
1909 : /* CopyData to OID*/
1910 9 : if (*oid_size < (size_t)obj_len) {
1911 0 : *oid_size = (size_t)obj_len;
1912 0 : return false;
1913 : }
1914 9 : if (oid != NULL) {
1915 9 : libspdm_copy_mem(oid, *oid_size, ptr, obj_len);
1916 9 : *oid_size = obj_len;
1917 : }
1918 :
1919 : /* Move to next element*/
1920 9 : ptr += obj_len;
1921 :
1922 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1923 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1924 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1925 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1926 : LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
1927 9 : if (!ret) {
1928 0 : return false;
1929 : }
1930 :
1931 9 : if (*name_buffer_size < (size_t)obj_len + 1) {
1932 0 : *name_buffer_size = (size_t)obj_len + 1;
1933 0 : return false;
1934 : }
1935 :
1936 : /* the src and dst address are overlap,
1937 : * When the function is called by libspdm_get_dmtf_subject_alt_name.
1938 : * libspdm_copy_mem can not be used. */
1939 9 : if ((name_buffer != NULL) && (ptr != NULL)) {
1940 9 : dst = (volatile uint8_t*) name_buffer;
1941 9 : src = (const volatile uint8_t*) ptr;
1942 9 : dst_len = *name_buffer_size;
1943 9 : src_len = obj_len;
1944 :
1945 : /* Check for case where "dst_len" may be invalid. Do not zero "dst" in this case. */
1946 9 : if (dst_len > (SIZE_MAX >> 1)) {
1947 0 : LIBSPDM_ASSERT(0);
1948 0 : return false;
1949 : }
1950 :
1951 : /* Guard against invalid lengths. Zero "dst" in these cases. */
1952 9 : if (src_len > dst_len ||
1953 9 : src_len > (SIZE_MAX >> 1)) {
1954 0 : libspdm_zero_mem(name_buffer, dst_len);
1955 0 : LIBSPDM_ASSERT(0);
1956 0 : return false;
1957 : }
1958 :
1959 207 : while (src_len-- != 0) {
1960 198 : *(dst++) = *(src++);
1961 : }
1962 :
1963 : /*encode name buffer to string*/
1964 9 : *name_buffer_size = obj_len + 1;
1965 9 : name_buffer[obj_len] = 0;
1966 9 : return true;
1967 : }
1968 :
1969 0 : return false;
1970 : }
1971 :
1972 : /**
1973 : * Retrieve the SubjectAltName from one X.509 certificate.
1974 : *
1975 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1976 : * @param[in] cert_size size of the X509 certificate in bytes.
1977 : * @param[out] name_buffer buffer to contain the retrieved certificate
1978 : * SubjectAltName. At most name_buffer_size bytes will be
1979 : * written. Maybe NULL in order to determine the size
1980 : * buffer needed.
1981 : * @param[in,out] name_buffer_size The size in bytes of the name buffer on input,
1982 : * and the size of buffer returned name on output.
1983 : * If name_buffer is NULL then the amount of space needed
1984 : * in buffer (including the final null) is returned.
1985 : * @param[out] oid OID of otherName
1986 : * @param[in,out] oid_size the buffersize for required OID
1987 : *
1988 : * @retval true get the subjectAltName string successfully
1989 : * @retval failed get the subjectAltName string failed
1990 : **/
1991 6 : bool libspdm_get_dmtf_subject_alt_name(const uint8_t *cert, const size_t cert_size,
1992 : char *name_buffer,
1993 : size_t *name_buffer_size,
1994 : uint8_t *oid, size_t *oid_size)
1995 : {
1996 : bool status;
1997 : size_t extension_data_size;
1998 6 : uint8_t oid_subject_alt_name[] = { 0x55, 0x1D, 0x11 };
1999 :
2000 6 : extension_data_size = 0;
2001 6 : status = libspdm_x509_get_extension_data(cert, cert_size,
2002 : oid_subject_alt_name,
2003 : sizeof(oid_subject_alt_name), NULL,
2004 : &extension_data_size);
2005 6 : if (status || (extension_data_size == 0)) {
2006 0 : *name_buffer_size = 0;
2007 0 : return false;
2008 : }
2009 6 : if (extension_data_size > *name_buffer_size) {
2010 0 : *name_buffer_size = extension_data_size;
2011 0 : return false;
2012 : }
2013 : status =
2014 6 : libspdm_x509_get_extension_data(cert, cert_size,
2015 : oid_subject_alt_name,
2016 : sizeof(oid_subject_alt_name),
2017 : (uint8_t *)name_buffer, name_buffer_size);
2018 6 : if (!status) {
2019 0 : return status;
2020 : }
2021 :
2022 6 : return libspdm_get_dmtf_subject_alt_name_from_bytes(
2023 : (uint8_t *)name_buffer, *name_buffer_size, name_buffer,
2024 : name_buffer_size, oid, oid_size);
2025 : }
2026 :
2027 : /**
2028 : * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
2029 : * It is used for SPDM 1.3.
2030 : *
2031 : * @param cert_chain_data The certificate chain data without spdm_cert_chain_t header.
2032 : * @param cert_chain_data_size Size in bytes of the certificate chain data.
2033 : * @param base_asym_algo SPDM base_asym_algo
2034 : * @param base_hash_algo SPDM base_hash_algo
2035 : * @param is_requester_cert Is the function verifying requester or responder cert.
2036 : * @param cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
2037 : *
2038 : * @retval true Certificate chain data integrity verification pass.
2039 : * @retval false Certificate chain data integrity verification fail.
2040 : **/
2041 6 : bool libspdm_verify_cert_chain_data_ex(uint8_t *cert_chain_data, size_t cert_chain_data_size,
2042 : uint32_t base_asym_algo, uint32_t base_hash_algo,
2043 : bool is_requester_cert, uint8_t cert_model)
2044 : {
2045 : const uint8_t *root_cert_buffer;
2046 : size_t root_cert_buffer_size;
2047 : const uint8_t *leaf_cert_buffer;
2048 : size_t leaf_cert_buffer_size;
2049 :
2050 6 : if (cert_chain_data_size >
2051 : SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
2052 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2053 : "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
2054 0 : return false;
2055 : }
2056 :
2057 6 : if (!libspdm_x509_get_cert_from_cert_chain(
2058 : cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
2059 : &root_cert_buffer_size)) {
2060 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2061 : "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
2062 0 : return false;
2063 : }
2064 :
2065 6 : if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
2066 : cert_chain_data, cert_chain_data_size)) {
2067 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2068 : "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
2069 2 : return false;
2070 : }
2071 :
2072 4 : if (!libspdm_x509_get_cert_from_cert_chain(
2073 : cert_chain_data, cert_chain_data_size, -1,
2074 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2075 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2076 : "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
2077 0 : return false;
2078 : }
2079 :
2080 4 : if (!libspdm_x509_certificate_check_ex(leaf_cert_buffer, leaf_cert_buffer_size,
2081 : base_asym_algo, base_hash_algo,
2082 : is_requester_cert, cert_model)) {
2083 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2084 : "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
2085 1 : return false;
2086 : }
2087 :
2088 3 : return true;
2089 : }
2090 : /**
2091 : * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
2092 : *
2093 : * @param cert_chain_data The certificate chain data without spdm_cert_chain_t header.
2094 : * @param cert_chain_data_size size in bytes of the certificate chain data.
2095 : * @param base_asym_algo SPDM base_asym_algo
2096 : * @param base_hash_algo SPDM base_hash_algo
2097 : * @param is_requester_cert Is the function verifying requester or responder cert.
2098 : * @param is_device_cert_model If true, the cert chain is DeviceCert model;
2099 : * If false, the cert chain is AliasCert model;
2100 : *
2101 : * @retval true certificate chain data integrity verification pass.
2102 : * @retval false certificate chain data integrity verification fail.
2103 : **/
2104 702 : bool libspdm_verify_cert_chain_data_with_pqc(
2105 : uint8_t *cert_chain_data, size_t cert_chain_data_size,
2106 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
2107 : bool is_requester_cert, bool is_device_cert_model)
2108 : {
2109 : const uint8_t *root_cert_buffer;
2110 : size_t root_cert_buffer_size;
2111 : const uint8_t *leaf_cert_buffer;
2112 : size_t leaf_cert_buffer_size;
2113 :
2114 702 : if (cert_chain_data_size >
2115 : SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
2116 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2117 : "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
2118 0 : return false;
2119 : }
2120 :
2121 702 : if (!libspdm_x509_get_cert_from_cert_chain(
2122 : cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
2123 : &root_cert_buffer_size)) {
2124 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2125 : "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
2126 0 : return false;
2127 : }
2128 :
2129 702 : if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
2130 : cert_chain_data, cert_chain_data_size)) {
2131 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2132 : "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
2133 0 : return false;
2134 : }
2135 :
2136 702 : if (!libspdm_x509_get_cert_from_cert_chain(
2137 : cert_chain_data, cert_chain_data_size, -1,
2138 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2139 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2140 : "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
2141 0 : return false;
2142 : }
2143 :
2144 702 : if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
2145 : base_asym_algo, pqc_asym_algo, base_hash_algo,
2146 : is_requester_cert, is_device_cert_model)) {
2147 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2148 : "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
2149 0 : return false;
2150 : }
2151 :
2152 702 : return true;
2153 : }
2154 :
2155 702 : bool libspdm_verify_cert_chain_data(uint8_t *cert_chain_data, size_t cert_chain_data_size,
2156 : uint32_t base_asym_algo, uint32_t base_hash_algo,
2157 : bool is_requester_cert, bool is_device_cert_model)
2158 : {
2159 702 : return libspdm_verify_cert_chain_data_with_pqc (
2160 : cert_chain_data, cert_chain_data_size,
2161 : base_asym_algo, 0, base_hash_algo,
2162 : is_requester_cert, is_device_cert_model);
2163 : }
2164 :
2165 : /**
2166 : * This function verifies the integrity of certificate chain buffer including
2167 : * spdm_cert_chain_t header. It is used for SPDM 1.3.
2168 : *
2169 : * @param base_hash_algo SPDM base_hash_algo
2170 : * @param base_asym_algo SPDM base_asym_algo
2171 : * @param cert_chain_buffer The certificate chain buffer including spdm_cert_chain_t header.
2172 : * @param cert_chain_buffer_size Size in bytes of the certificate chain buffer.
2173 : * @param is_requester_cert Is the function verifying requester or responder cert.
2174 : * @param cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
2175 : *
2176 : * @retval true Certificate chain buffer integrity verification pass.
2177 : * @retval false Certificate chain buffer integrity verification fail.
2178 : **/
2179 40 : bool libspdm_verify_certificate_chain_buffer_with_pqc(
2180 : uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
2181 : const void *cert_chain_buffer,
2182 : size_t cert_chain_buffer_size,
2183 : bool is_requester_cert, uint8_t cert_model)
2184 : {
2185 : const uint8_t *cert_chain_data;
2186 : size_t cert_chain_data_size;
2187 : const uint8_t *first_cert_buffer;
2188 : size_t first_cert_buffer_size;
2189 : size_t hash_size;
2190 : uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
2191 : const uint8_t *leaf_cert_buffer;
2192 : size_t leaf_cert_buffer_size;
2193 : bool result;
2194 : const spdm_cert_chain_t *cert_chain_header;
2195 :
2196 40 : hash_size = libspdm_get_hash_size(base_hash_algo);
2197 :
2198 40 : if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
2199 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2200 : "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
2201 0 : return false;
2202 : }
2203 :
2204 40 : cert_chain_header = cert_chain_buffer;
2205 40 : if (cert_chain_header->length != cert_chain_buffer_size) {
2206 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2207 : "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
2208 2 : return false;
2209 : }
2210 :
2211 38 : cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
2212 38 : cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
2213 38 : if (!libspdm_x509_get_cert_from_cert_chain(
2214 : cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
2215 : &first_cert_buffer_size)) {
2216 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2217 : "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
2218 0 : return false;
2219 : }
2220 :
2221 38 : if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
2222 36 : result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
2223 : calc_root_cert_hash);
2224 36 : if (!result) {
2225 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2226 : "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
2227 0 : return false;
2228 : }
2229 36 : if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
2230 : sizeof(spdm_cert_chain_t),
2231 : calc_root_cert_hash, hash_size)) {
2232 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2233 : "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
2234 0 : return false;
2235 : }
2236 36 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2237 : "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
2238 : }
2239 :
2240 : /*If the number of certificates in the certificate chain is more than 1,
2241 : * other certificates need to be verified.*/
2242 38 : if (cert_chain_data_size > first_cert_buffer_size) {
2243 38 : if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
2244 : cert_chain_data + first_cert_buffer_size,
2245 : cert_chain_data_size - first_cert_buffer_size)) {
2246 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2247 : "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
2248 3 : return false;
2249 : }
2250 : }
2251 :
2252 35 : if (!libspdm_x509_get_cert_from_cert_chain(
2253 : cert_chain_data, cert_chain_data_size, -1,
2254 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2255 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2256 : "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
2257 0 : return false;
2258 : }
2259 :
2260 35 : if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
2261 : base_asym_algo, pqc_asym_algo, base_hash_algo,
2262 : is_requester_cert, cert_model)) {
2263 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2264 : "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
2265 3 : return false;
2266 : }
2267 :
2268 32 : return true;
2269 : }
2270 :
2271 6 : bool libspdm_verify_certificate_chain_buffer_ex(uint32_t base_hash_algo, uint32_t base_asym_algo,
2272 : const void *cert_chain_buffer,
2273 : size_t cert_chain_buffer_size,
2274 : bool is_requester_cert, uint8_t cert_model)
2275 : {
2276 6 : return libspdm_verify_certificate_chain_buffer_with_pqc (
2277 : base_hash_algo, base_asym_algo, 0,
2278 : cert_chain_buffer, cert_chain_buffer_size,
2279 : is_requester_cert, cert_model);
2280 : }
2281 :
2282 0 : bool libspdm_verify_certificate_chain_buffer(uint32_t base_hash_algo, uint32_t base_asym_algo,
2283 : const void *cert_chain_buffer,
2284 : size_t cert_chain_buffer_size,
2285 : bool is_requester_cert,
2286 : bool is_device_cert_model)
2287 : {
2288 : const uint8_t *cert_chain_data;
2289 : size_t cert_chain_data_size;
2290 : const uint8_t *first_cert_buffer;
2291 : size_t first_cert_buffer_size;
2292 : size_t hash_size;
2293 : uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
2294 : const uint8_t *leaf_cert_buffer;
2295 : size_t leaf_cert_buffer_size;
2296 : bool result;
2297 : const spdm_cert_chain_t *cert_chain_header;
2298 :
2299 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
2300 :
2301 0 : if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
2302 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2303 : "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
2304 0 : return false;
2305 : }
2306 :
2307 0 : cert_chain_header = cert_chain_buffer;
2308 0 : if (cert_chain_header->length != cert_chain_buffer_size) {
2309 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2310 : "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
2311 0 : return false;
2312 : }
2313 :
2314 0 : cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
2315 0 : cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
2316 0 : if (!libspdm_x509_get_cert_from_cert_chain(
2317 : cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
2318 : &first_cert_buffer_size)) {
2319 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2320 : "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
2321 0 : return false;
2322 : }
2323 :
2324 0 : if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
2325 0 : result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
2326 : calc_root_cert_hash);
2327 0 : if (!result) {
2328 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2329 : "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
2330 0 : return false;
2331 : }
2332 0 : if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
2333 : sizeof(spdm_cert_chain_t),
2334 : calc_root_cert_hash, hash_size)) {
2335 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2336 : "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
2337 0 : return false;
2338 : }
2339 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2340 : "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
2341 : }
2342 :
2343 : /*If the number of certificates in the certificate chain is more than 1,
2344 : * other certificates need to be verified.*/
2345 0 : if (cert_chain_data_size > first_cert_buffer_size) {
2346 0 : if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
2347 : cert_chain_data + first_cert_buffer_size,
2348 : cert_chain_data_size - first_cert_buffer_size)) {
2349 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2350 : "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
2351 0 : return false;
2352 : }
2353 : }
2354 :
2355 0 : if (!libspdm_x509_get_cert_from_cert_chain(
2356 : cert_chain_data, cert_chain_data_size, -1,
2357 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2358 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2359 : "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
2360 0 : return false;
2361 : }
2362 :
2363 0 : if (!libspdm_x509_certificate_check(leaf_cert_buffer, leaf_cert_buffer_size,
2364 : base_asym_algo, base_hash_algo,
2365 : is_requester_cert, is_device_cert_model)) {
2366 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2367 : "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
2368 0 : return false;
2369 : }
2370 :
2371 0 : return true;
2372 : }
2373 :
2374 256 : bool libspdm_get_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2375 : uint32_t base_asym_alg,
2376 : uint8_t *cert_chain_data,
2377 : size_t cert_chain_data_size,
2378 : void **public_key)
2379 : {
2380 : size_t hash_size;
2381 : const uint8_t *cert_buffer;
2382 : size_t cert_buffer_size;
2383 : bool result;
2384 :
2385 256 : hash_size = libspdm_get_hash_size(base_hash_algo);
2386 :
2387 256 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2388 256 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2389 :
2390 : /* Get leaf cert from cert chain */
2391 256 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2392 : cert_chain_data_size, -1,
2393 : &cert_buffer, &cert_buffer_size);
2394 256 : if (!result) {
2395 0 : return false;
2396 : }
2397 :
2398 256 : result = libspdm_asym_get_public_key_from_x509(
2399 : base_asym_alg,
2400 : cert_buffer, cert_buffer_size, public_key);
2401 256 : if (!result) {
2402 4 : return false;
2403 : }
2404 :
2405 252 : return true;
2406 : }
2407 :
2408 : /**
2409 : * Retrieve the asymmetric public key from one DER-encoded X509 certificate,
2410 : * based upon negotiated asymmetric or requester asymmetric algorithm.
2411 : *
2412 : * @param base_hash_algo SPDM base_hash_algo.
2413 : * @param pqc_asym_alg SPDM pqc_asym_algo or req_pqc_asym_alg.
2414 : * @param cert_chain_data Certificate chain data with spdm_cert_chain_t header.
2415 : * @param cert_chain_data_size Size in bytes of the certificate chain data.
2416 : * @param public_key Pointer to newly generated asymmetric context which contain the
2417 : * retrieved public key component.
2418 : *
2419 : * @retval true Public key was retrieved successfully.
2420 : * @retval false Fail to retrieve public key from X509 certificate.
2421 : **/
2422 0 : bool libspdm_get_pqc_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2423 : uint32_t pqc_asym_alg,
2424 : uint8_t *cert_chain_data,
2425 : size_t cert_chain_data_size,
2426 : void **public_key)
2427 : {
2428 : size_t hash_size;
2429 : const uint8_t *cert_buffer;
2430 : size_t cert_buffer_size;
2431 : bool result;
2432 :
2433 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
2434 :
2435 0 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2436 0 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2437 :
2438 : /* Get leaf cert from cert chain */
2439 0 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2440 : cert_chain_data_size, -1,
2441 : &cert_buffer, &cert_buffer_size);
2442 0 : if (!result) {
2443 0 : return false;
2444 : }
2445 :
2446 0 : result = libspdm_pqc_asym_get_public_key_from_x509(
2447 : pqc_asym_alg,
2448 : cert_buffer, cert_buffer_size, public_key);
2449 0 : if (!result) {
2450 0 : return false;
2451 : }
2452 :
2453 0 : return true;
2454 : }
2455 :
2456 29 : bool libspdm_verify_req_info(uint8_t *req_info, uint16_t req_info_len)
2457 : {
2458 : bool ret;
2459 : uint8_t *ptr;
2460 : int32_t length;
2461 : size_t obj_len;
2462 : uint8_t *end;
2463 :
2464 29 : length = (int32_t)req_info_len;
2465 29 : ptr = req_info;
2466 29 : obj_len = 0;
2467 29 : end = ptr + length;
2468 29 : ret = true;
2469 :
2470 29 : if (req_info_len == 0) {
2471 4 : return true;
2472 : }
2473 :
2474 : /*req_info sequence*/
2475 25 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2476 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2477 25 : if (!ret) {
2478 2 : return false;
2479 : }
2480 :
2481 : /*integer:version*/
2482 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
2483 23 : if (!ret) {
2484 0 : return false;
2485 : } else {
2486 23 : ptr += obj_len;
2487 : }
2488 :
2489 : /*sequence:subject name*/
2490 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2491 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2492 23 : if (!ret) {
2493 0 : return false;
2494 : } else {
2495 23 : ptr += obj_len;
2496 : }
2497 :
2498 : /*sequence:subject pkinfo*/
2499 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2500 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2501 23 : if (!ret) {
2502 0 : return false;
2503 : } else {
2504 23 : ptr += obj_len;
2505 : }
2506 :
2507 : /*[0]: attributes*/
2508 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2509 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
2510 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2511 : /*req_info format error, don't have attributes tag*/
2512 23 : if (!ret) {
2513 0 : return false;
2514 : }
2515 :
2516 : /*there is no attributes object*/
2517 23 : if (ptr == end) {
2518 0 : return true;
2519 : }
2520 :
2521 : /*there is some attributes object: 0,1,2 ...*/
2522 46 : while (ret)
2523 : {
2524 46 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2525 : LIBSPDM_CRYPTO_ASN1_SEQUENCE |
2526 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2527 46 : if (ret) {
2528 23 : ptr += obj_len;
2529 : } else {
2530 23 : break;
2531 : }
2532 : }
2533 :
2534 23 : if (ptr == end) {
2535 23 : return true;
2536 : } else {
2537 0 : return false;
2538 : }
2539 : }
2540 :
2541 : #endif
|