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 59 : bool libspdm_is_root_certificate(const uint8_t *cert, size_t cert_size)
1810 : {
1811 : uint8_t issuer_name[LIBSPDM_MAX_NAME_SIZE];
1812 : size_t issuer_name_len;
1813 : uint8_t subject_name[LIBSPDM_MAX_NAME_SIZE];
1814 : size_t subject_name_len;
1815 : bool result;
1816 : uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
1817 : size_t cert_basic_constraints_len;
1818 59 : const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_STRING_TRUE_CASE;
1819 :
1820 59 : if (cert == NULL || cert_size == 0) {
1821 0 : return false;
1822 : }
1823 :
1824 : /* 1. issuer_name*/
1825 59 : issuer_name_len = sizeof(issuer_name);
1826 59 : result = libspdm_x509_get_issuer_name(cert, cert_size, issuer_name, &issuer_name_len);
1827 59 : if (!result) {
1828 0 : return false;
1829 : }
1830 :
1831 : /* 2. subject_name*/
1832 59 : subject_name_len = sizeof(subject_name);
1833 59 : result = libspdm_x509_get_subject_name(cert, cert_size, subject_name, &subject_name_len);
1834 59 : if (!result) {
1835 0 : return false;
1836 : }
1837 :
1838 59 : if (issuer_name_len != subject_name_len) {
1839 3 : return false;
1840 : }
1841 56 : if (!libspdm_consttime_is_mem_equal(issuer_name, subject_name, issuer_name_len)) {
1842 0 : return false;
1843 : }
1844 :
1845 : /* 3. cA must be present in Basic Constraints */
1846 56 : cert_basic_constraints_len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1847 56 : result = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1848 : cert_basic_constraints, &cert_basic_constraints_len);
1849 56 : if (!result || cert_basic_constraints_len == 0) {
1850 0 : return false;
1851 : }
1852 56 : if (cert_basic_constraints_len >= sizeof(basic_constraints_true_case)) {
1853 56 : if (cert_basic_constraints[0] != basic_constraints_true_case[0]) {
1854 0 : return false;
1855 : }
1856 56 : if (!libspdm_consttime_is_mem_equal(&cert_basic_constraints[2],
1857 : &basic_constraints_true_case[2],
1858 : sizeof(basic_constraints_true_case) - 2)) {
1859 0 : return false;
1860 : }
1861 : }
1862 :
1863 : /* 4. certificate must be self-signed */
1864 56 : result = libspdm_x509_verify_cert(cert, cert_size, cert, cert_size);
1865 56 : if (!result) {
1866 1 : return false;
1867 : }
1868 :
1869 55 : return true;
1870 : }
1871 :
1872 : /**
1873 : * Retrieve the SubjectAltName from SubjectAltName Bytes.
1874 : *
1875 : * @param[in] buffer Pointer to subjectAltName oct bytes.
1876 : * @param[in] len size of buffer in bytes.
1877 : * @param[out] name_buffer buffer to contain the retrieved certificate
1878 : * SubjectAltName. At most name_buffer_size bytes will be
1879 : * written. Maybe NULL in order to determine the size
1880 : * buffer needed.
1881 : * @param[in,out] name_buffer_size The size in bytes of the name buffer on input,
1882 : * and the size of buffer returned name on output.
1883 : * If name_buffer is NULL then the amount of space needed
1884 : * in buffer (including the final null) is returned.
1885 : * @param[out] oid OID of otherName
1886 : * @param[in,out] oid_size the buffersize for required OID
1887 : *
1888 : * @retval true get the subjectAltName string successfully
1889 : * @retval failed get the subjectAltName string failed
1890 : **/
1891 9 : bool libspdm_get_dmtf_subject_alt_name_from_bytes(
1892 : uint8_t *buffer, const size_t len, char *name_buffer,
1893 : size_t *name_buffer_size, uint8_t *oid,
1894 : size_t *oid_size)
1895 : {
1896 : uint8_t *ptr;
1897 : int32_t length;
1898 : size_t obj_len;
1899 : int32_t ret;
1900 :
1901 : /*copy mem variable*/
1902 : volatile uint8_t* dst;
1903 : const volatile uint8_t* src;
1904 : size_t dst_len;
1905 : size_t src_len;
1906 :
1907 9 : length = (int32_t)len;
1908 9 : ptr = buffer;
1909 9 : obj_len = 0;
1910 :
1911 : /* Sequence*/
1912 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + length, &obj_len,
1913 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1914 9 : if (!ret) {
1915 0 : return false;
1916 : }
1917 :
1918 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len,
1919 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1920 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1921 :
1922 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1923 9 : if (!ret) {
1924 0 : return false;
1925 : }
1926 : /* CopyData to OID*/
1927 9 : if (*oid_size < (size_t)obj_len) {
1928 0 : *oid_size = (size_t)obj_len;
1929 0 : return false;
1930 : }
1931 9 : if (oid != NULL) {
1932 9 : libspdm_copy_mem(oid, *oid_size, ptr, obj_len);
1933 9 : *oid_size = obj_len;
1934 : }
1935 :
1936 : /* Move to next element*/
1937 9 : ptr += obj_len;
1938 :
1939 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1940 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1941 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1942 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1943 : LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
1944 9 : if (!ret) {
1945 0 : return false;
1946 : }
1947 :
1948 9 : if (*name_buffer_size < (size_t)obj_len + 1) {
1949 0 : *name_buffer_size = (size_t)obj_len + 1;
1950 0 : return false;
1951 : }
1952 :
1953 : /* the src and dst address are overlap,
1954 : * When the function is called by libspdm_get_dmtf_subject_alt_name.
1955 : * libspdm_copy_mem can not be used. */
1956 9 : if ((name_buffer != NULL) && (ptr != NULL)) {
1957 9 : dst = (volatile uint8_t*) name_buffer;
1958 9 : src = (const volatile uint8_t*) ptr;
1959 9 : dst_len = *name_buffer_size;
1960 9 : src_len = obj_len;
1961 :
1962 : /* Check for case where "dst_len" may be invalid. Do not zero "dst" in this case. */
1963 9 : if (dst_len > (SIZE_MAX >> 1)) {
1964 0 : LIBSPDM_ASSERT(0);
1965 0 : return false;
1966 : }
1967 :
1968 : /* Guard against invalid lengths. Zero "dst" in these cases. */
1969 9 : if (src_len > dst_len ||
1970 9 : src_len > (SIZE_MAX >> 1)) {
1971 0 : libspdm_zero_mem(name_buffer, dst_len);
1972 0 : LIBSPDM_ASSERT(0);
1973 0 : return false;
1974 : }
1975 :
1976 207 : while (src_len-- != 0) {
1977 198 : *(dst++) = *(src++);
1978 : }
1979 :
1980 : /*encode name buffer to string*/
1981 9 : *name_buffer_size = obj_len + 1;
1982 9 : name_buffer[obj_len] = 0;
1983 9 : return true;
1984 : }
1985 :
1986 0 : return false;
1987 : }
1988 :
1989 : /**
1990 : * Retrieve the SubjectAltName from one X.509 certificate.
1991 : *
1992 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1993 : * @param[in] cert_size size of the X509 certificate in bytes.
1994 : * @param[out] name_buffer buffer to contain the retrieved certificate
1995 : * SubjectAltName. At most name_buffer_size bytes will be
1996 : * written. Maybe NULL in order to determine the size
1997 : * buffer needed.
1998 : * @param[in,out] name_buffer_size The size in bytes of the name buffer on input,
1999 : * and the size of buffer returned name on output.
2000 : * If name_buffer is NULL then the amount of space needed
2001 : * in buffer (including the final null) is returned.
2002 : * @param[out] oid OID of otherName
2003 : * @param[in,out] oid_size the buffersize for required OID
2004 : *
2005 : * @retval true get the subjectAltName string successfully
2006 : * @retval failed get the subjectAltName string failed
2007 : **/
2008 6 : bool libspdm_get_dmtf_subject_alt_name(const uint8_t *cert, const size_t cert_size,
2009 : char *name_buffer,
2010 : size_t *name_buffer_size,
2011 : uint8_t *oid, size_t *oid_size)
2012 : {
2013 : bool status;
2014 : size_t extension_data_size;
2015 6 : uint8_t oid_subject_alt_name[] = { 0x55, 0x1D, 0x11 };
2016 :
2017 6 : extension_data_size = 0;
2018 6 : status = libspdm_x509_get_extension_data(cert, cert_size,
2019 : oid_subject_alt_name,
2020 : sizeof(oid_subject_alt_name), NULL,
2021 : &extension_data_size);
2022 6 : if (status || (extension_data_size == 0)) {
2023 0 : *name_buffer_size = 0;
2024 0 : return false;
2025 : }
2026 6 : if (extension_data_size > *name_buffer_size) {
2027 0 : *name_buffer_size = extension_data_size;
2028 0 : return false;
2029 : }
2030 : status =
2031 6 : libspdm_x509_get_extension_data(cert, cert_size,
2032 : oid_subject_alt_name,
2033 : sizeof(oid_subject_alt_name),
2034 : (uint8_t *)name_buffer, name_buffer_size);
2035 6 : if (!status) {
2036 0 : return status;
2037 : }
2038 :
2039 6 : return libspdm_get_dmtf_subject_alt_name_from_bytes(
2040 : (uint8_t *)name_buffer, *name_buffer_size, name_buffer,
2041 : name_buffer_size, oid, oid_size);
2042 : }
2043 :
2044 : /**
2045 : * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
2046 : * It is used for SPDM 1.3.
2047 : *
2048 : * @param cert_chain_data The certificate chain data without spdm_cert_chain_t header.
2049 : * @param cert_chain_data_size Size in bytes of the certificate chain data.
2050 : * @param base_asym_algo SPDM base_asym_algo
2051 : * @param base_hash_algo SPDM base_hash_algo
2052 : * @param is_requester_cert Is the function verifying requester or responder cert.
2053 : * @param cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
2054 : *
2055 : * @retval true Certificate chain data integrity verification pass.
2056 : * @retval false Certificate chain data integrity verification fail.
2057 : **/
2058 6 : bool libspdm_verify_cert_chain_data_ex(uint8_t *cert_chain_data, size_t cert_chain_data_size,
2059 : uint32_t base_asym_algo, uint32_t base_hash_algo,
2060 : bool is_requester_cert, uint8_t cert_model)
2061 : {
2062 : const uint8_t *root_cert_buffer;
2063 : size_t root_cert_buffer_size;
2064 : const uint8_t *leaf_cert_buffer;
2065 : size_t leaf_cert_buffer_size;
2066 :
2067 6 : if (cert_chain_data_size >
2068 : SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
2069 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2070 : "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
2071 0 : return false;
2072 : }
2073 :
2074 6 : if (!libspdm_x509_get_cert_from_cert_chain(
2075 : cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
2076 : &root_cert_buffer_size)) {
2077 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2078 : "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
2079 0 : return false;
2080 : }
2081 :
2082 6 : if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
2083 : cert_chain_data, cert_chain_data_size)) {
2084 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2085 : "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
2086 2 : return false;
2087 : }
2088 :
2089 4 : if (!libspdm_x509_get_cert_from_cert_chain(
2090 : cert_chain_data, cert_chain_data_size, -1,
2091 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2092 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2093 : "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
2094 0 : return false;
2095 : }
2096 :
2097 4 : if (!libspdm_x509_certificate_check_ex(leaf_cert_buffer, leaf_cert_buffer_size,
2098 : base_asym_algo, base_hash_algo,
2099 : is_requester_cert, cert_model)) {
2100 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2101 : "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
2102 1 : return false;
2103 : }
2104 :
2105 3 : return true;
2106 : }
2107 : /**
2108 : * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
2109 : *
2110 : * @param cert_chain_data The certificate chain data without spdm_cert_chain_t header.
2111 : * @param cert_chain_data_size size in bytes of the certificate chain data.
2112 : * @param base_asym_algo SPDM base_asym_algo
2113 : * @param base_hash_algo SPDM base_hash_algo
2114 : * @param is_requester_cert Is the function verifying requester or responder cert.
2115 : * @param is_device_cert_model If true, the cert chain is DeviceCert model;
2116 : * If false, the cert chain is AliasCert model;
2117 : *
2118 : * @retval true certificate chain data integrity verification pass.
2119 : * @retval false certificate chain data integrity verification fail.
2120 : **/
2121 702 : bool libspdm_verify_cert_chain_data_with_pqc(
2122 : uint8_t *cert_chain_data, size_t cert_chain_data_size,
2123 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
2124 : bool is_requester_cert, bool is_device_cert_model)
2125 : {
2126 : const uint8_t *root_cert_buffer;
2127 : size_t root_cert_buffer_size;
2128 : const uint8_t *leaf_cert_buffer;
2129 : size_t leaf_cert_buffer_size;
2130 :
2131 702 : if (cert_chain_data_size >
2132 : SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
2133 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2134 : "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
2135 0 : return false;
2136 : }
2137 :
2138 702 : if (!libspdm_x509_get_cert_from_cert_chain(
2139 : cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
2140 : &root_cert_buffer_size)) {
2141 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2142 : "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
2143 0 : return false;
2144 : }
2145 :
2146 702 : if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
2147 : cert_chain_data, cert_chain_data_size)) {
2148 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2149 : "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
2150 0 : return false;
2151 : }
2152 :
2153 702 : if (!libspdm_x509_get_cert_from_cert_chain(
2154 : cert_chain_data, cert_chain_data_size, -1,
2155 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2156 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2157 : "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
2158 0 : return false;
2159 : }
2160 :
2161 702 : if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
2162 : base_asym_algo, pqc_asym_algo, base_hash_algo,
2163 : is_requester_cert, is_device_cert_model)) {
2164 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2165 : "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
2166 0 : return false;
2167 : }
2168 :
2169 702 : return true;
2170 : }
2171 :
2172 702 : bool libspdm_verify_cert_chain_data(uint8_t *cert_chain_data, size_t cert_chain_data_size,
2173 : uint32_t base_asym_algo, uint32_t base_hash_algo,
2174 : bool is_requester_cert, bool is_device_cert_model)
2175 : {
2176 702 : return libspdm_verify_cert_chain_data_with_pqc (
2177 : cert_chain_data, cert_chain_data_size,
2178 : base_asym_algo, 0, base_hash_algo,
2179 : is_requester_cert, is_device_cert_model);
2180 : }
2181 :
2182 : /**
2183 : * This function verifies the integrity of certificate chain buffer including
2184 : * spdm_cert_chain_t header. It is used for SPDM 1.3.
2185 : *
2186 : * @param base_hash_algo SPDM base_hash_algo
2187 : * @param base_asym_algo SPDM base_asym_algo
2188 : * @param cert_chain_buffer The certificate chain buffer including spdm_cert_chain_t header.
2189 : * @param cert_chain_buffer_size Size in bytes of the certificate chain buffer.
2190 : * @param is_requester_cert Is the function verifying requester or responder cert.
2191 : * @param cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
2192 : *
2193 : * @retval true Certificate chain buffer integrity verification pass.
2194 : * @retval false Certificate chain buffer integrity verification fail.
2195 : **/
2196 40 : bool libspdm_verify_certificate_chain_buffer_with_pqc(
2197 : uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
2198 : const void *cert_chain_buffer,
2199 : size_t cert_chain_buffer_size,
2200 : bool is_requester_cert, uint8_t cert_model)
2201 : {
2202 : const uint8_t *cert_chain_data;
2203 : size_t cert_chain_data_size;
2204 : const uint8_t *first_cert_buffer;
2205 : size_t first_cert_buffer_size;
2206 : size_t hash_size;
2207 : uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
2208 : const uint8_t *leaf_cert_buffer;
2209 : size_t leaf_cert_buffer_size;
2210 : bool result;
2211 : const spdm_cert_chain_t *cert_chain_header;
2212 :
2213 40 : hash_size = libspdm_get_hash_size(base_hash_algo);
2214 :
2215 40 : if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
2216 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2217 : "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
2218 0 : return false;
2219 : }
2220 :
2221 40 : cert_chain_header = cert_chain_buffer;
2222 40 : if (cert_chain_header->length != cert_chain_buffer_size) {
2223 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2224 : "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
2225 2 : return false;
2226 : }
2227 :
2228 38 : cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
2229 38 : cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
2230 38 : if (!libspdm_x509_get_cert_from_cert_chain(
2231 : cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
2232 : &first_cert_buffer_size)) {
2233 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2234 : "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
2235 0 : return false;
2236 : }
2237 :
2238 38 : if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
2239 35 : result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
2240 : calc_root_cert_hash);
2241 35 : if (!result) {
2242 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2243 : "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
2244 0 : return false;
2245 : }
2246 35 : if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
2247 : sizeof(spdm_cert_chain_t),
2248 : calc_root_cert_hash, hash_size)) {
2249 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2250 : "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
2251 0 : return false;
2252 : }
2253 35 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2254 : "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
2255 : }
2256 :
2257 : /*If the number of certificates in the certificate chain is more than 1,
2258 : * other certificates need to be verified.*/
2259 38 : if (cert_chain_data_size > first_cert_buffer_size) {
2260 38 : if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
2261 : cert_chain_data + first_cert_buffer_size,
2262 : cert_chain_data_size - first_cert_buffer_size)) {
2263 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2264 : "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
2265 3 : return false;
2266 : }
2267 : }
2268 :
2269 35 : if (!libspdm_x509_get_cert_from_cert_chain(
2270 : cert_chain_data, cert_chain_data_size, -1,
2271 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2272 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2273 : "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
2274 0 : return false;
2275 : }
2276 :
2277 35 : if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
2278 : base_asym_algo, pqc_asym_algo, base_hash_algo,
2279 : is_requester_cert, cert_model)) {
2280 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2281 : "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
2282 3 : return false;
2283 : }
2284 :
2285 32 : return true;
2286 : }
2287 :
2288 6 : bool libspdm_verify_certificate_chain_buffer_ex(uint32_t base_hash_algo, uint32_t base_asym_algo,
2289 : const void *cert_chain_buffer,
2290 : size_t cert_chain_buffer_size,
2291 : bool is_requester_cert, uint8_t cert_model)
2292 : {
2293 6 : return libspdm_verify_certificate_chain_buffer_with_pqc (
2294 : base_hash_algo, base_asym_algo, 0,
2295 : cert_chain_buffer, cert_chain_buffer_size,
2296 : is_requester_cert, cert_model);
2297 : }
2298 :
2299 0 : bool libspdm_verify_certificate_chain_buffer(uint32_t base_hash_algo, uint32_t base_asym_algo,
2300 : const void *cert_chain_buffer,
2301 : size_t cert_chain_buffer_size,
2302 : bool is_requester_cert,
2303 : bool is_device_cert_model)
2304 : {
2305 : const uint8_t *cert_chain_data;
2306 : size_t cert_chain_data_size;
2307 : const uint8_t *first_cert_buffer;
2308 : size_t first_cert_buffer_size;
2309 : size_t hash_size;
2310 : uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
2311 : const uint8_t *leaf_cert_buffer;
2312 : size_t leaf_cert_buffer_size;
2313 : bool result;
2314 : const spdm_cert_chain_t *cert_chain_header;
2315 :
2316 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
2317 :
2318 0 : if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
2319 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2320 : "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
2321 0 : return false;
2322 : }
2323 :
2324 0 : cert_chain_header = cert_chain_buffer;
2325 0 : if (cert_chain_header->length != cert_chain_buffer_size) {
2326 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2327 : "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
2328 0 : return false;
2329 : }
2330 :
2331 0 : cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
2332 0 : cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
2333 0 : if (!libspdm_x509_get_cert_from_cert_chain(
2334 : cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
2335 : &first_cert_buffer_size)) {
2336 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2337 : "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
2338 0 : return false;
2339 : }
2340 :
2341 0 : if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
2342 0 : result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
2343 : calc_root_cert_hash);
2344 0 : if (!result) {
2345 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2346 : "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
2347 0 : return false;
2348 : }
2349 0 : if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
2350 : sizeof(spdm_cert_chain_t),
2351 : calc_root_cert_hash, hash_size)) {
2352 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2353 : "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
2354 0 : return false;
2355 : }
2356 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2357 : "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
2358 : }
2359 :
2360 : /*If the number of certificates in the certificate chain is more than 1,
2361 : * other certificates need to be verified.*/
2362 0 : if (cert_chain_data_size > first_cert_buffer_size) {
2363 0 : if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
2364 : cert_chain_data + first_cert_buffer_size,
2365 : cert_chain_data_size - first_cert_buffer_size)) {
2366 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2367 : "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
2368 0 : return false;
2369 : }
2370 : }
2371 :
2372 0 : if (!libspdm_x509_get_cert_from_cert_chain(
2373 : cert_chain_data, cert_chain_data_size, -1,
2374 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2375 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2376 : "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
2377 0 : return false;
2378 : }
2379 :
2380 0 : if (!libspdm_x509_certificate_check(leaf_cert_buffer, leaf_cert_buffer_size,
2381 : base_asym_algo, base_hash_algo,
2382 : is_requester_cert, is_device_cert_model)) {
2383 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2384 : "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
2385 0 : return false;
2386 : }
2387 :
2388 0 : return true;
2389 : }
2390 :
2391 256 : bool libspdm_get_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2392 : uint32_t base_asym_alg,
2393 : uint8_t *cert_chain_data,
2394 : size_t cert_chain_data_size,
2395 : void **public_key)
2396 : {
2397 : size_t hash_size;
2398 : const uint8_t *cert_buffer;
2399 : size_t cert_buffer_size;
2400 : bool result;
2401 :
2402 256 : hash_size = libspdm_get_hash_size(base_hash_algo);
2403 :
2404 256 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2405 256 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2406 :
2407 : /* Get leaf cert from cert chain */
2408 256 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2409 : cert_chain_data_size, -1,
2410 : &cert_buffer, &cert_buffer_size);
2411 256 : if (!result) {
2412 0 : return false;
2413 : }
2414 :
2415 256 : result = libspdm_asym_get_public_key_from_x509(
2416 : base_asym_alg,
2417 : cert_buffer, cert_buffer_size, public_key);
2418 256 : if (!result) {
2419 4 : return false;
2420 : }
2421 :
2422 252 : return true;
2423 : }
2424 :
2425 : /**
2426 : * Retrieve the asymmetric public key from one DER-encoded X509 certificate,
2427 : * based upon negotiated asymmetric or requester asymmetric algorithm.
2428 : *
2429 : * @param base_hash_algo SPDM base_hash_algo.
2430 : * @param pqc_asym_alg SPDM pqc_asym_algo or req_pqc_asym_alg.
2431 : * @param cert_chain_data Certificate chain data with spdm_cert_chain_t header.
2432 : * @param cert_chain_data_size Size in bytes of the certificate chain data.
2433 : * @param public_key Pointer to newly generated asymmetric context which contain the
2434 : * retrieved public key component.
2435 : *
2436 : * @retval true Public key was retrieved successfully.
2437 : * @retval false Fail to retrieve public key from X509 certificate.
2438 : **/
2439 0 : bool libspdm_get_pqc_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2440 : uint32_t pqc_asym_alg,
2441 : uint8_t *cert_chain_data,
2442 : size_t cert_chain_data_size,
2443 : void **public_key)
2444 : {
2445 : size_t hash_size;
2446 : const uint8_t *cert_buffer;
2447 : size_t cert_buffer_size;
2448 : bool result;
2449 :
2450 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
2451 :
2452 0 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2453 0 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2454 :
2455 : /* Get leaf cert from cert chain */
2456 0 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2457 : cert_chain_data_size, -1,
2458 : &cert_buffer, &cert_buffer_size);
2459 0 : if (!result) {
2460 0 : return false;
2461 : }
2462 :
2463 0 : result = libspdm_pqc_asym_get_public_key_from_x509(
2464 : pqc_asym_alg,
2465 : cert_buffer, cert_buffer_size, public_key);
2466 0 : if (!result) {
2467 0 : return false;
2468 : }
2469 :
2470 0 : return true;
2471 : }
2472 :
2473 29 : bool libspdm_verify_req_info(uint8_t *req_info, uint16_t req_info_len)
2474 : {
2475 : bool ret;
2476 : uint8_t *ptr;
2477 : int32_t length;
2478 : size_t obj_len;
2479 : uint8_t *end;
2480 :
2481 29 : length = (int32_t)req_info_len;
2482 29 : ptr = req_info;
2483 29 : obj_len = 0;
2484 29 : end = ptr + length;
2485 29 : ret = true;
2486 :
2487 29 : if (req_info_len == 0) {
2488 4 : return true;
2489 : }
2490 :
2491 : /*req_info sequence*/
2492 25 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2493 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2494 25 : if (!ret) {
2495 2 : return false;
2496 : }
2497 :
2498 : /*integer:version*/
2499 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
2500 23 : if (!ret) {
2501 0 : return false;
2502 : } else {
2503 23 : ptr += obj_len;
2504 : }
2505 :
2506 : /*sequence:subject name*/
2507 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2508 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2509 23 : if (!ret) {
2510 0 : return false;
2511 : } else {
2512 23 : ptr += obj_len;
2513 : }
2514 :
2515 : /*sequence:subject pkinfo*/
2516 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2517 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2518 23 : if (!ret) {
2519 0 : return false;
2520 : } else {
2521 23 : ptr += obj_len;
2522 : }
2523 :
2524 : /*[0]: attributes*/
2525 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2526 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
2527 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2528 : /*req_info format error, don't have attributes tag*/
2529 23 : if (!ret) {
2530 0 : return false;
2531 : }
2532 :
2533 : /*there is no attributes object*/
2534 23 : if (ptr == end) {
2535 0 : return true;
2536 : }
2537 :
2538 : /*there is some attributes object: 0,1,2 ...*/
2539 46 : while (ret)
2540 : {
2541 46 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2542 : LIBSPDM_CRYPTO_ASN1_SEQUENCE |
2543 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2544 46 : if (ret) {
2545 23 : ptr += obj_len;
2546 : } else {
2547 23 : break;
2548 : }
2549 : }
2550 :
2551 23 : if (ptr == end) {
2552 23 : return true;
2553 : } else {
2554 0 : return false;
2555 : }
2556 : }
2557 :
2558 : #endif
|