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 1022 : libspdm_get_asym_get_public_key_from_x509(uint32_t base_asym_algo)
192 : {
193 1022 : 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 922 : 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 922 : 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 1022 : 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 1022 : get_public_key_from_x509_function = libspdm_get_asym_get_public_key_from_x509(base_asym_algo);
291 1022 : if (get_public_key_from_x509_function == NULL) {
292 0 : return false;
293 : }
294 1022 : 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 768 : 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 768 : f0_size = 64;
362 768 : t0_size = 64;
363 :
364 768 : status = libspdm_x509_set_date_time("19700101000000Z", f0, &f0_size);
365 768 : if (!status) {
366 0 : return false;
367 : }
368 :
369 768 : status = libspdm_x509_set_date_time("99991231235959Z", t0, &t0_size);
370 768 : if (!status) {
371 0 : return false;
372 : }
373 :
374 : /* from >= f0*/
375 768 : ret = libspdm_x509_compare_date_time(from, f0);
376 768 : if (ret < 0) {
377 0 : return false;
378 : }
379 :
380 : /* to <= t0*/
381 768 : ret = libspdm_x509_compare_date_time(t0, to);
382 768 : if (ret < 0) {
383 0 : return false;
384 : }
385 :
386 768 : 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 1528 : static uint32_t libspdm_get_public_key_algo_OID_len(
397 : uint32_t base_asym_algo, uint32_t pqc_asym_algo)
398 : {
399 1528 : if (base_asym_algo != 0) {
400 1528 : 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 1398 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
438 : #if LIBSPDM_ECDSA_P256_SUPPORT
439 1398 : 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 764 : 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 764 : oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
590 764 : if(oid_len == 0) {
591 0 : return false;
592 : }
593 :
594 764 : if (base_asym_algo != 0) {
595 764 : 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 699 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256: {
634 : #if LIBSPDM_ECDSA_P256_SUPPORT
635 699 : uint8_t encry_algo_oid_ecc256[] = KEY_ENCRY_ALGO_ECC256_OID;
636 699 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc256, oid_len);
637 699 : 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 764 : 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 764 : length = (int32_t)cert_size;
877 764 : ptr = (uint8_t*)(size_t)cert;
878 764 : obj_len = 0;
879 764 : end = ptr + length;
880 764 : ret = true;
881 :
882 : /* TBSCertificate have 5 sequence before subjectPublicKeyInfo*/
883 764 : sequence_time = 5;
884 :
885 : /*all cert sequence*/
886 764 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
887 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
888 764 : if (!ret) {
889 0 : return false;
890 : }
891 :
892 : /*TBSCertificate sequence*/
893 764 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
894 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
895 764 : if (!ret) {
896 0 : return false;
897 : }
898 :
899 764 : end = ptr + obj_len;
900 : /*version*/
901 764 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
902 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
903 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
904 764 : if (!ret) {
905 0 : return false;
906 : }
907 :
908 764 : ptr += obj_len;
909 : /*serialNumber*/
910 764 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
911 764 : 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 4584 : for (index = 0; index < sequence_time; index++) {
923 3820 : ptr += obj_len;
924 3820 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
925 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
926 3820 : if (!ret) {
927 0 : return false;
928 : }
929 : }
930 :
931 764 : if (base_asym_algo != 0) {
932 764 : 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 701 : 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 701 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
965 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
966 701 : if (!ret) {
967 0 : return false;
968 : }
969 701 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
970 701 : if (!ret) {
971 0 : return false;
972 : }
973 :
974 : /*get ecc second oid*/
975 701 : ptr +=obj_len;
976 701 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
977 701 : if (!ret) {
978 0 : return false;
979 : }
980 :
981 701 : if (oid_size != obj_len) {
982 0 : return false;
983 : }
984 :
985 701 : libspdm_copy_mem(oid, oid_size, ptr, obj_len);
986 701 : 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 763 : 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 763 : 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 764 : 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 764 : libspdm_zero_mem(libspdm_public_key_crypt_algo_oid, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
1080 764 : libspdm_zero_mem(libspdm_public_key_crypt_algo_oid_other, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
1081 :
1082 : /*work around: skip the sm2*/
1083 764 : if (base_asym_algo == SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256) {
1084 0 : return true;
1085 : }
1086 :
1087 764 : oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
1088 764 : if(oid_len == 0) {
1089 0 : return false;
1090 : }
1091 : /*get public key encrypt algo OID from libspdm stored*/
1092 764 : 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 764 : if (!status) {
1096 0 : return status;
1097 : }
1098 :
1099 : /*get public key encrypt algo OID from cert*/
1100 764 : 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 764 : 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 762 : 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 748 : 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 748 : uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
1133 748 : uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
1134 :
1135 748 : len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1136 :
1137 748 : status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1138 : cert_basic_constraints, &len);
1139 748 : if (!status) {
1140 0 : return false;
1141 748 : } 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 1490 : if ((len == sizeof(basic_constraints_false_case1)) &&
1151 744 : (libspdm_consttime_is_mem_equal(cert_basic_constraints,
1152 : basic_constraints_false_case1,
1153 : sizeof(basic_constraints_false_case1)))) {
1154 744 : 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 14 : 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 14 : const uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
1197 14 : const uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
1198 14 : const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_STRING_TRUE_CASE;
1199 :
1200 14 : len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1201 :
1202 14 : status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1203 : cert_basic_constraints, &len);
1204 14 : if (!status) {
1205 0 : return false;
1206 14 : } else if (need_basic_constraints && (len == 0)) {
1207 0 : return false;
1208 : }
1209 :
1210 14 : if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT) ||
1211 : (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1212 8 : if (need_basic_constraints || (len != 0)) {
1213 16 : if ((len == sizeof(basic_constraints_false_case1)) &&
1214 8 : (libspdm_consttime_is_mem_equal(cert_basic_constraints,
1215 : basic_constraints_false_case1,
1216 : sizeof(basic_constraints_false_case1)))) {
1217 8 : 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 768 : 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 768 : uint8_t eku_requester_auth_oid[] = SPDM_OID_DMTF_EKU_REQUESTER_AUTH;
1274 768 : uint8_t eku_responder_auth_oid[] = SPDM_OID_DMTF_EKU_RESPONDER_AUTH;
1275 :
1276 768 : eku_size = sizeof(eku);
1277 768 : status = libspdm_x509_get_extended_key_usage(cert, cert_size, eku, &eku_size);
1278 768 : if (!status) {
1279 0 : return false;
1280 768 : } else if (eku_size == 0) {
1281 : /* eku is not present in cert */
1282 0 : return true;
1283 : }
1284 :
1285 768 : ptr = eku;
1286 768 : obj_len = 0;
1287 768 : req_auth_oid_find_success = false;
1288 768 : rsp_auth_oid_find_success = false;
1289 :
1290 768 : status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len,
1291 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1292 768 : if (!status) {
1293 0 : return false;
1294 : }
1295 :
1296 3075 : while(ptr < eku + eku_size) {
1297 2307 : status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1298 2307 : if (!status) {
1299 0 : return false;
1300 : }
1301 :
1302 2315 : 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 2315 : 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 2307 : ptr += obj_len;
1314 : }
1315 :
1316 768 : if (ptr != eku + eku_size) {
1317 0 : return false;
1318 : }
1319 :
1320 768 : 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 : return false;
1324 : }
1325 : } else {
1326 : /* it should not only contain requester auth oid */
1327 748 : if (req_auth_oid_find_success && !rsp_auth_oid_find_success) {
1328 1 : return false;
1329 : }
1330 : }
1331 :
1332 766 : return true;
1333 : }
1334 :
1335 : /**
1336 : * Verify leaf cert spdm defined extension
1337 : *
1338 : * @param[in] cert Pointer to the DER-encoded certificate data.
1339 : * @param[in] cert_size The size of certificate data in bytes.
1340 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1341 : *
1342 : * @retval true verify pass
1343 : * @retval false verify fail,two case: 1. return is not RETURN_SUCCESS or RETURN_NOT_FOUND;
1344 : * 2. hardware_identity_oid is found in AliasCert model;
1345 : **/
1346 760 : static bool libspdm_verify_leaf_cert_spdm_extension(const uint8_t *cert, size_t cert_size,
1347 : bool is_requester_cert,
1348 : uint8_t cert_model)
1349 : {
1350 : bool status;
1351 : bool find_sucessful;
1352 : uint8_t spdm_extension[LIBSPDM_MAX_EXTENSION_LEN];
1353 : size_t len;
1354 : uint8_t *ptr;
1355 : uint8_t *temptr;
1356 : size_t obj_len;
1357 :
1358 : /* SPDM defined OID */
1359 760 : uint8_t oid_spdm_extension[] = SPDM_OID_DMTF_SPDM_EXTENSION;
1360 760 : uint8_t hardware_identity_oid[] = SPDM_OID_DMTF_HARDWARE_IDENTITY;
1361 :
1362 760 : len = LIBSPDM_MAX_EXTENSION_LEN;
1363 :
1364 760 : if (cert == NULL || cert_size == 0) {
1365 0 : return false;
1366 : }
1367 :
1368 760 : status = libspdm_x509_get_extension_data(cert, cert_size,
1369 : (const uint8_t *)oid_spdm_extension,
1370 : sizeof(oid_spdm_extension),
1371 : spdm_extension,
1372 : &len);
1373 760 : if (!status) {
1374 0 : return false;
1375 760 : } else if(len == 0) {
1376 13 : return true;
1377 : }
1378 :
1379 : /*find the spdm hardware identity OID*/
1380 747 : find_sucessful = false;
1381 747 : ptr = spdm_extension;
1382 747 : obj_len = 0;
1383 :
1384 : /*id-spdm-cert-oids ::= SEQUENCE SIZE (1..MAX) OF id-spdm-cert-oid*/
1385 747 : status = libspdm_asn1_get_tag(
1386 : &ptr, spdm_extension + len, &obj_len,
1387 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1388 747 : if (!status) {
1389 0 : return false;
1390 : }
1391 :
1392 1494 : while(ptr < spdm_extension + len) {
1393 747 : status = libspdm_asn1_get_tag(
1394 : &ptr, spdm_extension + len, &obj_len,
1395 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1396 747 : if (!status) {
1397 0 : return false;
1398 : }
1399 :
1400 747 : temptr = ptr + obj_len;
1401 747 : status = libspdm_asn1_get_tag(
1402 : &ptr, spdm_extension + len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1403 747 : if (!status) {
1404 0 : return false;
1405 : }
1406 1494 : if ((obj_len == sizeof(hardware_identity_oid)) &&
1407 747 : (libspdm_consttime_is_mem_equal(ptr, hardware_identity_oid,
1408 : sizeof(hardware_identity_oid)))) {
1409 747 : find_sucessful = true;
1410 : }
1411 747 : ptr = temptr;
1412 : }
1413 :
1414 747 : if (ptr != spdm_extension + len) {
1415 0 : return false;
1416 : }
1417 :
1418 : /* Responder does not determine Requester's certificate model */
1419 747 : if (!is_requester_cert) {
1420 732 : if ((find_sucessful) && (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1421 : /* Hardware_identity_OID is found in alias cert model */
1422 4 : return false;
1423 : }
1424 : }
1425 :
1426 743 : return true;
1427 : }
1428 :
1429 : /**
1430 : * Certificate common Check for SPDM leaf cert when get_cert and set_cert.
1431 : *
1432 : * @param[in] cert Pointer to the DER-encoded certificate data.
1433 : * @param[in] cert_size The size of certificate data in bytes.
1434 : * @param[in] base_asym_algo SPDM base_asym_algo
1435 : * @param[in] base_hash_algo SPDM base_hash_algo
1436 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1437 : * @param[in] cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
1438 : * @param[in] set_cert Is the function verifying a set certificate operation.
1439 : *
1440 : * @retval true Success.
1441 : * @retval false Certificate is not valid.
1442 : **/
1443 770 : bool libspdm_x509_common_certificate_check(
1444 : const uint8_t *cert, size_t cert_size,
1445 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1446 : bool is_requester_cert, uint8_t cert_model,
1447 : bool set_cert)
1448 : {
1449 : uint8_t end_cert_from[64];
1450 : size_t end_cert_from_len;
1451 : uint8_t end_cert_to[64];
1452 : size_t end_cert_to_len;
1453 : size_t asn1_buffer_len;
1454 : bool status;
1455 : size_t cert_version;
1456 : void *context;
1457 : #if LIBSPDM_ADDITIONAL_CHECK_CERT
1458 : size_t signature_algo_oid_size;
1459 : #endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */
1460 :
1461 770 : if (cert == NULL || cert_size == 0) {
1462 0 : return false;
1463 : }
1464 :
1465 770 : status = true;
1466 770 : context = NULL;
1467 770 : end_cert_from_len = 64;
1468 770 : end_cert_to_len = 64;
1469 :
1470 : /* 1. version*/
1471 770 : cert_version = 0;
1472 770 : status = libspdm_x509_get_version(cert, cert_size, &cert_version);
1473 770 : if (!status) {
1474 0 : goto cleanup;
1475 : }
1476 770 : if (cert_version != 2) {
1477 0 : status = false;
1478 0 : goto cleanup;
1479 : }
1480 :
1481 : /* 2. serial_number*/
1482 770 : asn1_buffer_len = 0;
1483 770 : status = libspdm_x509_get_serial_number(cert, cert_size, NULL, &asn1_buffer_len);
1484 770 : if (asn1_buffer_len == 0) {
1485 0 : status = false;
1486 0 : goto cleanup;
1487 : }
1488 :
1489 : #if LIBSPDM_ADDITIONAL_CHECK_CERT
1490 : /* 3. Verify signature algorithm. */
1491 : signature_algo_oid_size = 0;
1492 : status = libspdm_x509_get_signature_algorithm(cert, cert_size, NULL, &signature_algo_oid_size);
1493 : if (status) {
1494 : if ((signature_algo_oid_size == 0) &&
1495 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1496 : status = false;
1497 : goto cleanup;
1498 : }
1499 : } else {
1500 : if (signature_algo_oid_size == 0) {
1501 : status = false;
1502 : goto cleanup;
1503 : }
1504 : }
1505 : #endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */
1506 :
1507 : /* 4. Verify public key algorithm.
1508 : * If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
1509 : * check should be skipped as the Device Certificate CA's public key does not have to use
1510 : * the same algorithms as the connection's negotiated algorithms. */
1511 770 : if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1512 764 : status = libspdm_verify_cert_subject_public_key_info(cert, cert_size, base_asym_algo, pqc_asym_algo);
1513 764 : if (!status) {
1514 2 : goto cleanup;
1515 : }
1516 : }
1517 :
1518 : /* 5. issuer_name*/
1519 768 : asn1_buffer_len = 0;
1520 768 : status = libspdm_x509_get_issuer_name(cert, cert_size, NULL, &asn1_buffer_len);
1521 768 : if (status) {
1522 0 : if ((asn1_buffer_len == 0) &&
1523 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1524 0 : status = false;
1525 0 : goto cleanup;
1526 : }
1527 : } else {
1528 768 : if (asn1_buffer_len == 0) {
1529 0 : status = false;
1530 0 : goto cleanup;
1531 : }
1532 : }
1533 :
1534 : /* 6. subject_name*/
1535 768 : asn1_buffer_len = 0;
1536 768 : status = libspdm_x509_get_subject_name(cert, cert_size, NULL, &asn1_buffer_len);
1537 768 : if (status) {
1538 0 : if ((asn1_buffer_len == 0) &&
1539 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1540 0 : status = false;
1541 0 : goto cleanup;
1542 : }
1543 : } else {
1544 768 : if (asn1_buffer_len == 0) {
1545 0 : status = false;
1546 0 : goto cleanup;
1547 : }
1548 : }
1549 :
1550 : /* 7. validity*/
1551 768 : status = libspdm_x509_get_validity(cert, cert_size, end_cert_from,
1552 : &end_cert_from_len, end_cert_to,
1553 : &end_cert_to_len);
1554 768 : if (status) {
1555 768 : if ((end_cert_from_len == 0) &&
1556 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1557 0 : status = false;
1558 0 : goto cleanup;
1559 : }
1560 : } else {
1561 0 : if (end_cert_from_len == 0) {
1562 0 : status = false;
1563 0 : goto cleanup;
1564 : }
1565 : }
1566 :
1567 768 : if (end_cert_from_len != 0) {
1568 768 : status = libspdm_internal_x509_date_time_check(
1569 : end_cert_from, end_cert_from_len, end_cert_to, end_cert_to_len);
1570 768 : if (!status) {
1571 0 : goto cleanup;
1572 : }
1573 : }
1574 :
1575 : /* 8. subject_public_key*/
1576 768 : if (base_asym_algo != 0) {
1577 768 : status = libspdm_asym_get_public_key_from_x509(base_asym_algo, cert, cert_size, &context);
1578 : }
1579 768 : if (pqc_asym_algo != 0) {
1580 0 : status = libspdm_pqc_asym_get_public_key_from_x509(pqc_asym_algo, cert, cert_size, &context);
1581 : }
1582 768 : if (!status) {
1583 0 : goto cleanup;
1584 : }
1585 :
1586 : /* 9. key_usage
1587 : * If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
1588 : * check should be skipped as the SPDM specification does not specify the presence or absence
1589 : * of the Device Certificate CA's keyUsage field. */
1590 768 : if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1591 762 : size_t value = 0;
1592 :
1593 762 : status = libspdm_x509_get_key_usage(cert, cert_size, &value);
1594 762 : if (!status) {
1595 0 : goto cleanup;
1596 : } else {
1597 762 : if (value == 0) {
1598 0 : if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
1599 0 : status = false;
1600 0 : goto cleanup;
1601 : }
1602 : } else {
1603 762 : if ((LIBSPDM_CRYPTO_X509_KU_DIGITAL_SIGNATURE & value) == 0) {
1604 0 : status = false;
1605 0 : goto cleanup;
1606 : }
1607 : }
1608 : }
1609 : }
1610 :
1611 : /* 10. verify spdm defined extended key usage*/
1612 768 : status = libspdm_verify_leaf_cert_spdm_eku(cert, cert_size, is_requester_cert);
1613 768 : if (!status) {
1614 2 : goto cleanup;
1615 : }
1616 :
1617 766 : if ((!set_cert) || (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT)) {
1618 : /* 11. verify spdm defined extension*/
1619 760 : status = libspdm_verify_leaf_cert_spdm_extension(cert, cert_size,
1620 : is_requester_cert, cert_model);
1621 760 : if (!status) {
1622 4 : goto cleanup;
1623 : }
1624 : }
1625 :
1626 762 : cleanup:
1627 770 : if (base_asym_algo != 0) {
1628 770 : libspdm_asym_free(base_asym_algo, context);
1629 : }
1630 770 : if (pqc_asym_algo != 0) {
1631 0 : libspdm_pqc_asym_free(pqc_asym_algo, context);
1632 : }
1633 770 : return status;
1634 : }
1635 :
1636 : /**
1637 : * Certificate Check for SPDM leaf cert when get_cert command
1638 : *
1639 : * @param[in] cert Pointer to the DER-encoded certificate data.
1640 : * @param[in] cert_size The size of certificate data in bytes.
1641 : * @param[in] base_asym_algo SPDM base_asym_algo
1642 : * @param[in] base_hash_algo SPDM base_hash_algo
1643 : * @param[in] is_requester Is the function verifying a cert as a requester or responder.
1644 : * @param[in] is_device_cert_model If true, the local endpoint uses the DeviceCert model.
1645 : * If false, the local endpoint uses the AliasCert model.
1646 : *
1647 : * @retval true Success.
1648 : * @retval false Certificate is not valid
1649 : **/
1650 54 : bool libspdm_x509_certificate_check(const uint8_t *cert, size_t cert_size,
1651 : uint32_t base_asym_algo,
1652 : uint32_t base_hash_algo,
1653 : bool is_requester,
1654 : bool is_device_cert_model)
1655 : {
1656 : bool status;
1657 : uint8_t cert_model;
1658 :
1659 54 : if (is_device_cert_model) {
1660 48 : cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
1661 : } else {
1662 6 : cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
1663 : }
1664 :
1665 54 : status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo, 0,
1666 : base_hash_algo, is_requester,
1667 : cert_model, false);
1668 54 : if (!status) {
1669 5 : return false;
1670 : }
1671 :
1672 : /* verify basic constraints: the leaf cert always is ca:false in get_cert*/
1673 49 : status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, false);
1674 49 : return status;
1675 : }
1676 :
1677 :
1678 : /**
1679 : * Certificate Check for SPDM leaf cert when get_cert command. It is used for SPDM 1.3.
1680 : *
1681 : * @param[in] cert Pointer to the DER-encoded certificate data.
1682 : * @param[in] cert_size The size of certificate data in bytes.
1683 : * @param[in] base_asym_algo SPDM base_asym_algo
1684 : * @param[in] base_hash_algo SPDM base_hash_algo
1685 : * @param[in] is_requester Is the function verifying a cert as a requester or responder.
1686 : * @param[in] cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
1687 : *
1688 : * @retval true Success.
1689 : * @retval false Certificate is not valid
1690 : **/
1691 702 : bool libspdm_x509_certificate_check_with_pqc(const uint8_t *cert, size_t cert_size,
1692 : uint32_t base_asym_algo, uint32_t pqc_asym_algo,
1693 : uint32_t base_hash_algo,
1694 : bool is_requester,
1695 : uint8_t cert_model)
1696 : {
1697 : bool status;
1698 :
1699 702 : status = libspdm_x509_common_certificate_check(
1700 : cert, cert_size, base_asym_algo, pqc_asym_algo,
1701 : base_hash_algo, is_requester,
1702 : cert_model, false);
1703 702 : if (!status) {
1704 3 : return false;
1705 : }
1706 :
1707 : /* verify basic constraints: the leaf cert always is ca:false in get_cert
1708 : * basic_constraints is mandatory in SPDM 1.3*/
1709 699 : status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, true);
1710 699 : return status;
1711 : }
1712 :
1713 9 : bool libspdm_x509_certificate_check_ex(const uint8_t *cert, size_t cert_size,
1714 : uint32_t base_asym_algo,
1715 : uint32_t base_hash_algo,
1716 : bool is_requester,
1717 : uint8_t cert_model)
1718 : {
1719 9 : return libspdm_x509_certificate_check_with_pqc (
1720 : cert, cert_size,
1721 : base_asym_algo, 0, base_hash_algo,
1722 : is_requester, cert_model);
1723 : }
1724 :
1725 8 : bool libspdm_x509_set_cert_certificate_check(const uint8_t *cert, size_t cert_size,
1726 : uint32_t base_asym_algo, uint32_t base_hash_algo,
1727 : bool is_requester, bool is_device_cert_model)
1728 : {
1729 : bool status;
1730 : uint8_t cert_model;
1731 :
1732 8 : if (is_device_cert_model) {
1733 5 : cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
1734 : } else {
1735 3 : cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
1736 : }
1737 :
1738 8 : status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo, 0,
1739 : base_hash_algo, is_requester,
1740 : cert_model, true);
1741 8 : if (!status) {
1742 0 : return false;
1743 : }
1744 :
1745 : /* verify basic constraints: need check with is_device_cert_model*/
1746 8 : status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
1747 : cert, cert_size, cert_model, false);
1748 8 : return status;
1749 : }
1750 :
1751 6 : bool libspdm_x509_set_cert_certificate_check_with_pqc(
1752 : const uint8_t *cert, size_t cert_size,
1753 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1754 : bool is_requester, uint8_t cert_model)
1755 : {
1756 : bool status;
1757 :
1758 6 : status = libspdm_x509_common_certificate_check(
1759 : cert, cert_size, base_asym_algo, pqc_asym_algo,
1760 : base_hash_algo, is_requester,
1761 : cert_model, true);
1762 6 : if (!status) {
1763 0 : return false;
1764 : }
1765 :
1766 : /* verify basic constraints: need check with is_device_cert_model*/
1767 6 : status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
1768 : cert, cert_size, cert_model, true);
1769 :
1770 6 : return status;
1771 : }
1772 :
1773 6 : bool libspdm_x509_set_cert_certificate_check_ex(const uint8_t *cert, size_t cert_size,
1774 : uint32_t base_asym_algo, uint32_t base_hash_algo,
1775 : bool is_requester, uint8_t cert_model)
1776 : {
1777 6 : return libspdm_x509_set_cert_certificate_check_with_pqc (
1778 : cert, cert_size,
1779 : base_asym_algo, 0, base_hash_algo,
1780 : is_requester, cert_model);
1781 : }
1782 :
1783 : /**
1784 : * Return certificate is root cert or not.
1785 : * Certificate is considered as a root certificate if the subjectname equal issuername.
1786 : *
1787 : * @param[in] cert Pointer to the DER-encoded certificate data.
1788 : * @param[in] cert_size The size of certificate data in bytes.
1789 : *
1790 : * @retval true Certificate is self-signed.
1791 : * @retval false Certificate is not self-signed.
1792 : **/
1793 59 : bool libspdm_is_root_certificate(const uint8_t *cert, size_t cert_size)
1794 : {
1795 : uint8_t issuer_name[LIBSPDM_MAX_NAME_SIZE];
1796 : size_t issuer_name_len;
1797 : uint8_t subject_name[LIBSPDM_MAX_NAME_SIZE];
1798 : size_t subject_name_len;
1799 : bool result;
1800 :
1801 59 : if (cert == NULL || cert_size == 0) {
1802 0 : return false;
1803 : }
1804 :
1805 : /* 1. issuer_name*/
1806 59 : issuer_name_len = sizeof(issuer_name);
1807 59 : result = libspdm_x509_get_issuer_name(cert, cert_size, issuer_name, &issuer_name_len);
1808 59 : if (!result) {
1809 0 : return false;
1810 : }
1811 :
1812 : /* 2. subject_name*/
1813 59 : subject_name_len = sizeof(subject_name);
1814 59 : result = libspdm_x509_get_subject_name(cert, cert_size, subject_name, &subject_name_len);
1815 59 : if (!result) {
1816 0 : return false;
1817 : }
1818 :
1819 59 : if (issuer_name_len != subject_name_len) {
1820 3 : return false;
1821 : }
1822 56 : if (!libspdm_consttime_is_mem_equal(issuer_name, subject_name, issuer_name_len)) {
1823 0 : return false;
1824 : }
1825 :
1826 56 : return true;
1827 : }
1828 :
1829 : /**
1830 : * Retrieve the SubjectAltName from SubjectAltName Bytes.
1831 : *
1832 : * @param[in] buffer Pointer to subjectAltName oct bytes.
1833 : * @param[in] len size of buffer in bytes.
1834 : * @param[out] name_buffer buffer to contain the retrieved certificate
1835 : * SubjectAltName. At most name_buffer_size bytes will be
1836 : * written. Maybe NULL in order to determine the size
1837 : * buffer needed.
1838 : * @param[in,out] name_buffer_size The size in bytes of the name buffer on input,
1839 : * and the size of buffer returned name on output.
1840 : * If name_buffer is NULL then the amount of space needed
1841 : * in buffer (including the final null) is returned.
1842 : * @param[out] oid OID of otherName
1843 : * @param[in,out] oid_size the buffersize for required OID
1844 : *
1845 : * @retval true get the subjectAltName string successfully
1846 : * @retval failed get the subjectAltName string failed
1847 : **/
1848 9 : bool libspdm_get_dmtf_subject_alt_name_from_bytes(
1849 : uint8_t *buffer, const size_t len, char *name_buffer,
1850 : size_t *name_buffer_size, uint8_t *oid,
1851 : size_t *oid_size)
1852 : {
1853 : uint8_t *ptr;
1854 : int32_t length;
1855 : size_t obj_len;
1856 : int32_t ret;
1857 :
1858 : /*copy mem variable*/
1859 : volatile uint8_t* dst;
1860 : const volatile uint8_t* src;
1861 : size_t dst_len;
1862 : size_t src_len;
1863 :
1864 9 : length = (int32_t)len;
1865 9 : ptr = buffer;
1866 9 : obj_len = 0;
1867 :
1868 : /* Sequence*/
1869 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + length, &obj_len,
1870 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1871 9 : if (!ret) {
1872 0 : return false;
1873 : }
1874 :
1875 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len,
1876 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1877 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1878 :
1879 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1880 9 : if (!ret) {
1881 0 : return false;
1882 : }
1883 : /* CopyData to OID*/
1884 9 : if (*oid_size < (size_t)obj_len) {
1885 0 : *oid_size = (size_t)obj_len;
1886 0 : return false;
1887 : }
1888 9 : if (oid != NULL) {
1889 9 : libspdm_copy_mem(oid, *oid_size, ptr, obj_len);
1890 9 : *oid_size = obj_len;
1891 : }
1892 :
1893 : /* Move to next element*/
1894 9 : ptr += obj_len;
1895 :
1896 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1897 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1898 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1899 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1900 : LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
1901 9 : if (!ret) {
1902 0 : return false;
1903 : }
1904 :
1905 9 : if (*name_buffer_size < (size_t)obj_len + 1) {
1906 0 : *name_buffer_size = (size_t)obj_len + 1;
1907 0 : return false;
1908 : }
1909 :
1910 : /* the src and dst address are overlap,
1911 : * When the function is called by libspdm_get_dmtf_subject_alt_name.
1912 : * libspdm_copy_mem can not be used. */
1913 9 : if ((name_buffer != NULL) && (ptr != NULL)) {
1914 9 : dst = (volatile uint8_t*) name_buffer;
1915 9 : src = (const volatile uint8_t*) ptr;
1916 9 : dst_len = *name_buffer_size;
1917 9 : src_len = obj_len;
1918 :
1919 : /* Check for case where "dst_len" may be invalid. Do not zero "dst" in this case. */
1920 9 : if (dst_len > (SIZE_MAX >> 1)) {
1921 0 : LIBSPDM_ASSERT(0);
1922 0 : return false;
1923 : }
1924 :
1925 : /* Guard against invalid lengths. Zero "dst" in these cases. */
1926 9 : if (src_len > dst_len ||
1927 9 : src_len > (SIZE_MAX >> 1)) {
1928 0 : libspdm_zero_mem(name_buffer, dst_len);
1929 0 : LIBSPDM_ASSERT(0);
1930 0 : return false;
1931 : }
1932 :
1933 207 : while (src_len-- != 0) {
1934 198 : *(dst++) = *(src++);
1935 : }
1936 :
1937 : /*encode name buffer to string*/
1938 9 : *name_buffer_size = obj_len + 1;
1939 9 : name_buffer[obj_len] = 0;
1940 9 : return true;
1941 : }
1942 :
1943 0 : return false;
1944 : }
1945 :
1946 : /**
1947 : * Retrieve the SubjectAltName from one X.509 certificate.
1948 : *
1949 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1950 : * @param[in] cert_size size of the X509 certificate in bytes.
1951 : * @param[out] name_buffer buffer to contain the retrieved certificate
1952 : * SubjectAltName. At most name_buffer_size bytes will be
1953 : * written. Maybe NULL in order to determine the size
1954 : * buffer needed.
1955 : * @param[in,out] name_buffer_size The size in bytes of the name buffer on input,
1956 : * and the size of buffer returned name on output.
1957 : * If name_buffer is NULL then the amount of space needed
1958 : * in buffer (including the final null) is returned.
1959 : * @param[out] oid OID of otherName
1960 : * @param[in,out] oid_size the buffersize for required OID
1961 : *
1962 : * @retval true get the subjectAltName string successfully
1963 : * @retval failed get the subjectAltName string failed
1964 : **/
1965 6 : bool libspdm_get_dmtf_subject_alt_name(const uint8_t *cert, const size_t cert_size,
1966 : char *name_buffer,
1967 : size_t *name_buffer_size,
1968 : uint8_t *oid, size_t *oid_size)
1969 : {
1970 : bool status;
1971 : size_t extension_data_size;
1972 6 : uint8_t oid_subject_alt_name[] = { 0x55, 0x1D, 0x11 };
1973 :
1974 6 : extension_data_size = 0;
1975 6 : status = libspdm_x509_get_extension_data(cert, cert_size,
1976 : oid_subject_alt_name,
1977 : sizeof(oid_subject_alt_name), NULL,
1978 : &extension_data_size);
1979 6 : if (status || (extension_data_size == 0)) {
1980 0 : *name_buffer_size = 0;
1981 0 : return false;
1982 : }
1983 6 : if (extension_data_size > *name_buffer_size) {
1984 0 : *name_buffer_size = extension_data_size;
1985 0 : return false;
1986 : }
1987 : status =
1988 6 : libspdm_x509_get_extension_data(cert, cert_size,
1989 : oid_subject_alt_name,
1990 : sizeof(oid_subject_alt_name),
1991 : (uint8_t *)name_buffer, name_buffer_size);
1992 6 : if (!status) {
1993 0 : return status;
1994 : }
1995 :
1996 6 : return libspdm_get_dmtf_subject_alt_name_from_bytes(
1997 : (uint8_t *)name_buffer, *name_buffer_size, name_buffer,
1998 : name_buffer_size, oid, oid_size);
1999 : }
2000 :
2001 : /**
2002 : * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
2003 : * It is used for SPDM 1.3.
2004 : *
2005 : * @param cert_chain_data The certificate chain data without spdm_cert_chain_t header.
2006 : * @param cert_chain_data_size Size in bytes of the certificate chain data.
2007 : * @param base_asym_algo SPDM base_asym_algo
2008 : * @param base_hash_algo SPDM base_hash_algo
2009 : * @param is_requester_cert Is the function verifying requester or responder cert.
2010 : * @param cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
2011 : *
2012 : * @retval true Certificate chain data integrity verification pass.
2013 : * @retval false Certificate chain data integrity verification fail.
2014 : **/
2015 6 : bool libspdm_verify_cert_chain_data_ex(uint8_t *cert_chain_data, size_t cert_chain_data_size,
2016 : uint32_t base_asym_algo, uint32_t base_hash_algo,
2017 : bool is_requester_cert, uint8_t cert_model)
2018 : {
2019 : const uint8_t *root_cert_buffer;
2020 : size_t root_cert_buffer_size;
2021 : const uint8_t *leaf_cert_buffer;
2022 : size_t leaf_cert_buffer_size;
2023 :
2024 6 : if (cert_chain_data_size >
2025 : SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
2026 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2027 : "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
2028 0 : return false;
2029 : }
2030 :
2031 6 : if (!libspdm_x509_get_cert_from_cert_chain(
2032 : cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
2033 : &root_cert_buffer_size)) {
2034 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2035 : "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
2036 0 : return false;
2037 : }
2038 :
2039 6 : if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
2040 : cert_chain_data, cert_chain_data_size)) {
2041 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2042 : "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
2043 2 : return false;
2044 : }
2045 :
2046 4 : if (!libspdm_x509_get_cert_from_cert_chain(
2047 : cert_chain_data, cert_chain_data_size, -1,
2048 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2049 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2050 : "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
2051 0 : return false;
2052 : }
2053 :
2054 4 : if (!libspdm_x509_certificate_check_ex(leaf_cert_buffer, leaf_cert_buffer_size,
2055 : base_asym_algo, base_hash_algo,
2056 : is_requester_cert, cert_model)) {
2057 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2058 : "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
2059 1 : return false;
2060 : }
2061 :
2062 3 : return true;
2063 : }
2064 : /**
2065 : * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
2066 : *
2067 : * @param cert_chain_data The certificate chain data without spdm_cert_chain_t header.
2068 : * @param cert_chain_data_size size in bytes of the certificate chain data.
2069 : * @param base_asym_algo SPDM base_asym_algo
2070 : * @param base_hash_algo SPDM base_hash_algo
2071 : * @param is_requester_cert Is the function verifying requester or responder cert.
2072 : * @param is_device_cert_model If true, the cert chain is DeviceCert model;
2073 : * If false, the cert chain is AliasCert model;
2074 : *
2075 : * @retval true certificate chain data integrity verification pass.
2076 : * @retval false certificate chain data integrity verification fail.
2077 : **/
2078 689 : bool libspdm_verify_cert_chain_data_with_pqc(
2079 : uint8_t *cert_chain_data, size_t cert_chain_data_size,
2080 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
2081 : bool is_requester_cert, bool is_device_cert_model)
2082 : {
2083 : const uint8_t *root_cert_buffer;
2084 : size_t root_cert_buffer_size;
2085 : const uint8_t *leaf_cert_buffer;
2086 : size_t leaf_cert_buffer_size;
2087 :
2088 689 : if (cert_chain_data_size >
2089 : SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
2090 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2091 : "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
2092 0 : return false;
2093 : }
2094 :
2095 689 : if (!libspdm_x509_get_cert_from_cert_chain(
2096 : cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
2097 : &root_cert_buffer_size)) {
2098 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2099 : "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
2100 0 : return false;
2101 : }
2102 :
2103 689 : if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
2104 : cert_chain_data, cert_chain_data_size)) {
2105 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2106 : "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
2107 0 : return false;
2108 : }
2109 :
2110 689 : if (!libspdm_x509_get_cert_from_cert_chain(
2111 : cert_chain_data, cert_chain_data_size, -1,
2112 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2113 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2114 : "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
2115 0 : return false;
2116 : }
2117 :
2118 689 : if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
2119 : base_asym_algo, pqc_asym_algo, base_hash_algo,
2120 : is_requester_cert, is_device_cert_model)) {
2121 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2122 : "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
2123 0 : return false;
2124 : }
2125 :
2126 689 : return true;
2127 : }
2128 :
2129 689 : bool libspdm_verify_cert_chain_data(uint8_t *cert_chain_data, size_t cert_chain_data_size,
2130 : uint32_t base_asym_algo, uint32_t base_hash_algo,
2131 : bool is_requester_cert, bool is_device_cert_model)
2132 : {
2133 689 : return libspdm_verify_cert_chain_data_with_pqc (
2134 : cert_chain_data, cert_chain_data_size,
2135 : base_asym_algo, 0, base_hash_algo,
2136 : is_requester_cert, is_device_cert_model);
2137 : }
2138 :
2139 : /**
2140 : * This function verifies the integrity of certificate chain buffer including
2141 : * spdm_cert_chain_t header. It is used for SPDM 1.3.
2142 : *
2143 : * @param base_hash_algo SPDM base_hash_algo
2144 : * @param base_asym_algo SPDM base_asym_algo
2145 : * @param cert_chain_buffer The certificate chain buffer including spdm_cert_chain_t header.
2146 : * @param cert_chain_buffer_size Size in bytes of the certificate chain buffer.
2147 : * @param is_requester_cert Is the function verifying requester or responder cert.
2148 : * @param cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
2149 : *
2150 : * @retval true Certificate chain buffer integrity verification pass.
2151 : * @retval false Certificate chain buffer integrity verification fail.
2152 : **/
2153 6 : bool libspdm_verify_certificate_chain_buffer_with_pqc(
2154 : uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
2155 : const void *cert_chain_buffer,
2156 : size_t cert_chain_buffer_size,
2157 : bool is_requester_cert, uint8_t cert_model)
2158 : {
2159 : const uint8_t *cert_chain_data;
2160 : size_t cert_chain_data_size;
2161 : const uint8_t *first_cert_buffer;
2162 : size_t first_cert_buffer_size;
2163 : size_t hash_size;
2164 : uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
2165 : const uint8_t *leaf_cert_buffer;
2166 : size_t leaf_cert_buffer_size;
2167 : bool result;
2168 : const spdm_cert_chain_t *cert_chain_header;
2169 :
2170 6 : hash_size = libspdm_get_hash_size(base_hash_algo);
2171 :
2172 6 : if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
2173 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2174 : "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
2175 0 : return false;
2176 : }
2177 :
2178 6 : cert_chain_header = cert_chain_buffer;
2179 6 : if (cert_chain_header->length != cert_chain_buffer_size) {
2180 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2181 : "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
2182 2 : return false;
2183 : }
2184 :
2185 4 : cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
2186 4 : cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
2187 4 : if (!libspdm_x509_get_cert_from_cert_chain(
2188 : cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
2189 : &first_cert_buffer_size)) {
2190 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2191 : "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
2192 0 : return false;
2193 : }
2194 :
2195 4 : if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
2196 4 : result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
2197 : calc_root_cert_hash);
2198 4 : if (!result) {
2199 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2200 : "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
2201 0 : return false;
2202 : }
2203 4 : if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
2204 : sizeof(spdm_cert_chain_t),
2205 : calc_root_cert_hash, hash_size)) {
2206 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2207 : "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
2208 0 : return false;
2209 : }
2210 4 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2211 : "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
2212 : }
2213 :
2214 : /*If the number of certificates in the certificate chain is more than 1,
2215 : * other certificates need to be verified.*/
2216 4 : if (cert_chain_data_size > first_cert_buffer_size) {
2217 4 : if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
2218 : cert_chain_data + first_cert_buffer_size,
2219 : cert_chain_data_size - first_cert_buffer_size)) {
2220 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2221 : "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
2222 0 : return false;
2223 : }
2224 : }
2225 :
2226 4 : if (!libspdm_x509_get_cert_from_cert_chain(
2227 : cert_chain_data, cert_chain_data_size, -1,
2228 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2229 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2230 : "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
2231 0 : return false;
2232 : }
2233 :
2234 4 : if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
2235 : base_asym_algo, pqc_asym_algo, base_hash_algo,
2236 : is_requester_cert, cert_model)) {
2237 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2238 : "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
2239 1 : return false;
2240 : }
2241 :
2242 3 : return true;
2243 : }
2244 :
2245 6 : bool libspdm_verify_certificate_chain_buffer_ex(uint32_t base_hash_algo, uint32_t base_asym_algo,
2246 : const void *cert_chain_buffer,
2247 : size_t cert_chain_buffer_size,
2248 : bool is_requester_cert, uint8_t cert_model)
2249 : {
2250 6 : return libspdm_verify_certificate_chain_buffer_with_pqc (
2251 : base_hash_algo, base_asym_algo, 0,
2252 : cert_chain_buffer, cert_chain_buffer_size,
2253 : is_requester_cert, cert_model);
2254 : }
2255 :
2256 34 : bool libspdm_verify_certificate_chain_buffer(uint32_t base_hash_algo, uint32_t base_asym_algo,
2257 : const void *cert_chain_buffer,
2258 : size_t cert_chain_buffer_size,
2259 : bool is_requester_cert,
2260 : bool is_device_cert_model)
2261 : {
2262 : const uint8_t *cert_chain_data;
2263 : size_t cert_chain_data_size;
2264 : const uint8_t *first_cert_buffer;
2265 : size_t first_cert_buffer_size;
2266 : size_t hash_size;
2267 : uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
2268 : const uint8_t *leaf_cert_buffer;
2269 : size_t leaf_cert_buffer_size;
2270 : bool result;
2271 : const spdm_cert_chain_t *cert_chain_header;
2272 :
2273 34 : hash_size = libspdm_get_hash_size(base_hash_algo);
2274 :
2275 34 : if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
2276 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2277 : "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
2278 0 : return false;
2279 : }
2280 :
2281 34 : cert_chain_header = cert_chain_buffer;
2282 34 : if (cert_chain_header->length != cert_chain_buffer_size) {
2283 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2284 : "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
2285 0 : return false;
2286 : }
2287 :
2288 34 : cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
2289 34 : cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
2290 34 : if (!libspdm_x509_get_cert_from_cert_chain(
2291 : cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
2292 : &first_cert_buffer_size)) {
2293 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2294 : "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
2295 0 : return false;
2296 : }
2297 :
2298 34 : if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
2299 32 : result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
2300 : calc_root_cert_hash);
2301 32 : if (!result) {
2302 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2303 : "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
2304 0 : return false;
2305 : }
2306 32 : if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
2307 : sizeof(spdm_cert_chain_t),
2308 : calc_root_cert_hash, hash_size)) {
2309 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2310 : "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
2311 0 : return false;
2312 : }
2313 32 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2314 : "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
2315 : }
2316 :
2317 : /*If the number of certificates in the certificate chain is more than 1,
2318 : * other certificates need to be verified.*/
2319 34 : if (cert_chain_data_size > first_cert_buffer_size) {
2320 34 : if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
2321 : cert_chain_data + first_cert_buffer_size,
2322 : cert_chain_data_size - first_cert_buffer_size)) {
2323 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2324 : "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
2325 3 : return false;
2326 : }
2327 : }
2328 :
2329 31 : if (!libspdm_x509_get_cert_from_cert_chain(
2330 : cert_chain_data, cert_chain_data_size, -1,
2331 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2332 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2333 : "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
2334 0 : return false;
2335 : }
2336 :
2337 31 : if (!libspdm_x509_certificate_check(leaf_cert_buffer, leaf_cert_buffer_size,
2338 : base_asym_algo, base_hash_algo,
2339 : is_requester_cert, is_device_cert_model)) {
2340 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2341 : "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
2342 2 : return false;
2343 : }
2344 :
2345 29 : return true;
2346 : }
2347 :
2348 254 : bool libspdm_get_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2349 : uint32_t base_asym_alg,
2350 : uint8_t *cert_chain_data,
2351 : size_t cert_chain_data_size,
2352 : void **public_key)
2353 : {
2354 : size_t hash_size;
2355 : const uint8_t *cert_buffer;
2356 : size_t cert_buffer_size;
2357 : bool result;
2358 :
2359 254 : hash_size = libspdm_get_hash_size(base_hash_algo);
2360 :
2361 254 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2362 254 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2363 :
2364 : /* Get leaf cert from cert chain */
2365 254 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2366 : cert_chain_data_size, -1,
2367 : &cert_buffer, &cert_buffer_size);
2368 254 : if (!result) {
2369 0 : return false;
2370 : }
2371 :
2372 254 : result = libspdm_asym_get_public_key_from_x509(
2373 : base_asym_alg,
2374 : cert_buffer, cert_buffer_size, public_key);
2375 254 : if (!result) {
2376 4 : return false;
2377 : }
2378 :
2379 250 : return true;
2380 : }
2381 :
2382 : /**
2383 : * Retrieve the asymmetric public key from one DER-encoded X509 certificate,
2384 : * based upon negotiated asymmetric or requester asymmetric algorithm.
2385 : *
2386 : * @param base_hash_algo SPDM base_hash_algo.
2387 : * @param pqc_asym_alg SPDM pqc_asym_algo or req_pqc_asym_alg.
2388 : * @param cert_chain_data Certificate chain data with spdm_cert_chain_t header.
2389 : * @param cert_chain_data_size Size in bytes of the certificate chain data.
2390 : * @param public_key Pointer to newly generated asymmetric context which contain the
2391 : * retrieved public key component.
2392 : *
2393 : * @retval true Public key was retrieved successfully.
2394 : * @retval false Fail to retrieve public key from X509 certificate.
2395 : **/
2396 0 : bool libspdm_get_pqc_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2397 : uint32_t pqc_asym_alg,
2398 : uint8_t *cert_chain_data,
2399 : size_t cert_chain_data_size,
2400 : void **public_key)
2401 : {
2402 : size_t hash_size;
2403 : const uint8_t *cert_buffer;
2404 : size_t cert_buffer_size;
2405 : bool result;
2406 :
2407 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
2408 :
2409 0 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2410 0 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2411 :
2412 : /* Get leaf cert from cert chain */
2413 0 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2414 : cert_chain_data_size, -1,
2415 : &cert_buffer, &cert_buffer_size);
2416 0 : if (!result) {
2417 0 : return false;
2418 : }
2419 :
2420 0 : result = libspdm_pqc_asym_get_public_key_from_x509(
2421 : pqc_asym_alg,
2422 : cert_buffer, cert_buffer_size, public_key);
2423 0 : if (!result) {
2424 0 : return false;
2425 : }
2426 :
2427 0 : return true;
2428 : }
2429 :
2430 29 : bool libspdm_verify_req_info(uint8_t *req_info, uint16_t req_info_len)
2431 : {
2432 : bool ret;
2433 : uint8_t *ptr;
2434 : int32_t length;
2435 : size_t obj_len;
2436 : uint8_t *end;
2437 :
2438 29 : length = (int32_t)req_info_len;
2439 29 : ptr = req_info;
2440 29 : obj_len = 0;
2441 29 : end = ptr + length;
2442 29 : ret = true;
2443 :
2444 29 : if (req_info_len == 0) {
2445 4 : return true;
2446 : }
2447 :
2448 : /*req_info sequence*/
2449 25 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2450 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2451 25 : if (!ret) {
2452 2 : return false;
2453 : }
2454 :
2455 : /*integer:version*/
2456 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
2457 23 : if (!ret) {
2458 0 : return false;
2459 : } else {
2460 23 : ptr += obj_len;
2461 : }
2462 :
2463 : /*sequence:subject name*/
2464 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2465 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2466 23 : if (!ret) {
2467 0 : return false;
2468 : } else {
2469 23 : ptr += obj_len;
2470 : }
2471 :
2472 : /*sequence:subject pkinfo*/
2473 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2474 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2475 23 : if (!ret) {
2476 0 : return false;
2477 : } else {
2478 23 : ptr += obj_len;
2479 : }
2480 :
2481 : /*[0]: attributes*/
2482 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2483 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
2484 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2485 : /*req_info format error, don't have attributes tag*/
2486 23 : if (!ret) {
2487 0 : return false;
2488 : }
2489 :
2490 : /*there is no attributes object*/
2491 23 : if (ptr == end) {
2492 0 : return true;
2493 : }
2494 :
2495 : /*there is some attributes object: 0,1,2 ...*/
2496 46 : while (ret)
2497 : {
2498 46 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2499 : LIBSPDM_CRYPTO_ASN1_SEQUENCE |
2500 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2501 46 : if (ret) {
2502 23 : ptr += obj_len;
2503 : } else {
2504 23 : break;
2505 : }
2506 : }
2507 :
2508 23 : if (ptr == end) {
2509 23 : return true;
2510 : } else {
2511 0 : return false;
2512 : }
2513 : }
2514 :
2515 : #endif
|