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