Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2026 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: RFC9881
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: RFC9909
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 certificate basic constraints with cA field set to false. According to RFC5280, false is the
160 : * default value, and according to DER encoding a sequence item with a default value must not be
161 : * encoded. */
162 : #define BASIC_CONSTRAINTS_CA_FALSE {0x30, 0x00}
163 :
164 : /* Leaf certificate basic constraints with cA field set to true. */
165 : #define BASIC_CONSTRAINTS_CA_TRUE {0x30, 0x03, 0x01, 0x01, 0xFF}
166 :
167 : /**
168 : * Retrieve the asymmetric public key from one DER-encoded X509 certificate.
169 : *
170 : * @param cert Pointer to the DER-encoded X509 certificate.
171 : * @param cert_size Size of the X509 certificate in bytes.
172 : * @param context Pointer to newly generated asymmetric context which contain the retrieved public
173 : * key component. Use libspdm_asym_free() function to free the resource.
174 : *
175 : * @retval true public key was retrieved successfully.
176 : * @retval false Fail to retrieve public key from X509 certificate.
177 : **/
178 : typedef bool (*libspdm_asym_get_public_key_from_x509_func)(const uint8_t *cert,
179 : size_t cert_size,
180 : void **context);
181 :
182 : /**
183 : * Return asymmetric GET_PUBLIC_KEY_FROM_X509 function, based upon the negotiated asymmetric algorithm.
184 : *
185 : * @param base_asym_algo SPDM base_asym_algo
186 : *
187 : * @return asymmetric GET_PUBLIC_KEY_FROM_X509 function
188 : **/
189 : static libspdm_asym_get_public_key_from_x509_func
190 1048 : libspdm_get_asym_get_public_key_from_x509(uint32_t base_asym_algo)
191 : {
192 1048 : switch (base_asym_algo) {
193 100 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
194 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
195 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
196 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
197 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
198 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
199 : #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
200 : #if !LIBSPDM_RSA_SSA_2048_SUPPORT
201 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048);
202 : #endif
203 : #if !LIBSPDM_RSA_SSA_3072_SUPPORT
204 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072);
205 : #endif
206 : #if !LIBSPDM_RSA_SSA_4096_SUPPORT
207 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096);
208 : #endif
209 : #if !LIBSPDM_RSA_PSS_2048_SUPPORT
210 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048);
211 : #endif
212 : #if !LIBSPDM_RSA_PSS_3072_SUPPORT
213 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072);
214 : #endif
215 : #if !LIBSPDM_RSA_PSS_4096_SUPPORT
216 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096);
217 : #endif
218 100 : return libspdm_rsa_get_public_key_from_x509;
219 : #else
220 : LIBSPDM_ASSERT(false);
221 : break;
222 : #endif
223 948 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
224 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
225 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
226 : #if LIBSPDM_ECDSA_SUPPORT
227 : #if !LIBSPDM_ECDSA_P256_SUPPORT
228 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256);
229 : #endif
230 : #if !LIBSPDM_ECDSA_P384_SUPPORT
231 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384);
232 : #endif
233 : #if !LIBSPDM_ECDSA_P521_SUPPORT
234 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521);
235 : #endif
236 948 : return libspdm_ec_get_public_key_from_x509;
237 : #else
238 : LIBSPDM_ASSERT(false);
239 : break;
240 : #endif
241 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
242 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
243 : #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
244 : #if !LIBSPDM_EDDSA_ED25519_SUPPORT
245 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519);
246 : #endif
247 : #if !LIBSPDM_EDDSA_ED448_SUPPORT
248 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448);
249 : #endif
250 : return libspdm_ecd_get_public_key_from_x509;
251 : #else
252 0 : LIBSPDM_ASSERT(false);
253 0 : break;
254 : #endif
255 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
256 : #if LIBSPDM_SM2_DSA_SUPPORT
257 : return libspdm_sm2_get_public_key_from_x509;
258 : #else
259 0 : LIBSPDM_ASSERT(false);
260 0 : break;
261 : #endif
262 0 : default:
263 0 : LIBSPDM_ASSERT(false);
264 0 : break;
265 : }
266 :
267 0 : return NULL;
268 : }
269 :
270 1048 : bool libspdm_asym_get_public_key_from_x509(uint32_t base_asym_algo,
271 : const uint8_t *cert,
272 : size_t cert_size,
273 : void **context)
274 : {
275 : libspdm_asym_get_public_key_from_x509_func get_public_key_from_x509_function;
276 1048 : get_public_key_from_x509_function = libspdm_get_asym_get_public_key_from_x509(base_asym_algo);
277 1048 : if (get_public_key_from_x509_function == NULL) {
278 0 : return false;
279 : }
280 1048 : return get_public_key_from_x509_function(cert, cert_size, context);
281 : }
282 :
283 : /**
284 : * Return requester asymmetric GET_PUBLIC_KEY_FROM_X509 function, based upon the negotiated requester asymmetric algorithm.
285 : *
286 : * @param req_base_asym_alg SPDM req_base_asym_alg
287 : *
288 : * @return requester asymmetric GET_PUBLIC_KEY_FROM_X509 function
289 : **/
290 : static libspdm_asym_get_public_key_from_x509_func
291 0 : libspdm_get_req_asym_get_public_key_from_x509(uint16_t req_base_asym_alg)
292 : {
293 0 : return libspdm_get_asym_get_public_key_from_x509(req_base_asym_alg);
294 : }
295 :
296 0 : bool libspdm_req_asym_get_public_key_from_x509(uint16_t req_base_asym_alg,
297 : const uint8_t *cert,
298 : size_t cert_size,
299 : void **context)
300 : {
301 : libspdm_asym_get_public_key_from_x509_func get_public_key_from_x509_function;
302 : get_public_key_from_x509_function =
303 0 : libspdm_get_req_asym_get_public_key_from_x509(req_base_asym_alg);
304 0 : if (get_public_key_from_x509_function == NULL) {
305 0 : return false;
306 : }
307 0 : return get_public_key_from_x509_function(cert, cert_size, context);
308 : }
309 :
310 : /**
311 : * Check the X509 DataTime is within a valid range.
312 : *
313 : * @param spdm_context A pointer to the SPDM context.
314 : * @param from notBefore Pointer to date_time object.
315 : * @param from_size notBefore date_time object size.
316 : * @param to notAfter Pointer to date_time object.
317 : * @param to_size notAfter date_time object size.
318 : *
319 : * @retval true verification pass.
320 : * @retval false verification fail.
321 : **/
322 792 : static bool libspdm_internal_x509_date_time_check(const uint8_t *from,
323 : size_t from_size,
324 : const uint8_t *to,
325 : size_t to_size)
326 : {
327 : int32_t ret;
328 : bool status;
329 : uint8_t f0[64];
330 : uint8_t t0[64];
331 : size_t f0_size;
332 : size_t t0_size;
333 :
334 792 : f0_size = 64;
335 792 : t0_size = 64;
336 :
337 792 : status = libspdm_x509_set_date_time("19700101000000Z", f0, &f0_size);
338 792 : if (!status) {
339 0 : return false;
340 : }
341 :
342 792 : status = libspdm_x509_set_date_time("99991231235959Z", t0, &t0_size);
343 792 : if (!status) {
344 0 : return false;
345 : }
346 :
347 : /* from >= f0*/
348 792 : ret = libspdm_x509_compare_date_time(from, f0);
349 792 : if (ret < 0) {
350 0 : return false;
351 : }
352 :
353 : /* to <= t0*/
354 792 : ret = libspdm_x509_compare_date_time(t0, to);
355 792 : if (ret < 0) {
356 0 : return false;
357 : }
358 :
359 792 : return true;
360 : }
361 :
362 : /**
363 : * This function returns the SPDM public key encryption algorithm OID len.
364 : *
365 : * @param[in] base_asym_algo SPDM base_asym_algo
366 : *
367 : * @return SPDM public key encryption algorithms OID len.
368 : **/
369 1574 : static uint32_t libspdm_get_public_key_algo_OID_len(
370 : uint32_t base_asym_algo, uint32_t pqc_asym_algo)
371 : {
372 1574 : if (base_asym_algo != 0) {
373 1574 : switch (base_asym_algo) {
374 116 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
375 : #if LIBSPDM_RSA_SSA_2048_SUPPORT
376 116 : return 4;
377 : #else
378 : return 0;
379 : #endif
380 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
381 : #if LIBSPDM_RSA_PSS_2048_SUPPORT
382 0 : return 4;
383 : #else
384 : return 0;
385 : #endif
386 6 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
387 : #if LIBSPDM_RSA_SSA_3072_SUPPORT
388 6 : return 4;
389 : #else
390 : return 0;
391 : #endif
392 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
393 : #if LIBSPDM_RSA_PSS_3072_SUPPORT
394 0 : return 4;
395 : #else
396 : return 0;
397 : #endif
398 4 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
399 : #if LIBSPDM_RSA_SSA_4096_SUPPORT
400 4 : return 4;
401 : #else
402 : return 0;
403 : #endif
404 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
405 : #if LIBSPDM_RSA_PSS_4096_SUPPORT
406 0 : return 4;
407 : #else
408 : return 0;
409 : #endif
410 1444 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
411 : #if LIBSPDM_ECDSA_P256_SUPPORT
412 1444 : return 8;
413 : #else
414 : return 0;
415 : #endif
416 2 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
417 : #if LIBSPDM_ECDSA_P384_SUPPORT
418 2 : return 5;
419 : #else
420 : return 0;
421 : #endif
422 2 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
423 : #if LIBSPDM_ECDSA_P521_SUPPORT
424 2 : return 5;
425 : #else
426 : return 0;
427 : #endif
428 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
429 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
430 : return 3;
431 : #else
432 0 : return 0;
433 : #endif
434 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
435 : #if LIBSPDM_EDDSA_ED448_SUPPORT
436 : return 3;
437 : #else
438 0 : return 0;
439 : #endif
440 0 : default:
441 0 : LIBSPDM_ASSERT(false);
442 0 : return 0;
443 : }
444 : }
445 0 : if (pqc_asym_algo != 0) {
446 0 : switch (pqc_asym_algo) {
447 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_44:
448 : #if LIBSPDM_ML_DSA_44_SUPPORT
449 : return 9;
450 : #else
451 0 : return 0;
452 : #endif
453 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_65:
454 : #if LIBSPDM_ML_DSA_65_SUPPORT
455 : return 9;
456 : #else
457 0 : return 0;
458 : #endif
459 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_87:
460 : #if LIBSPDM_ML_DSA_87_SUPPORT
461 : return 9;
462 : #else
463 0 : return 0;
464 : #endif
465 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128S:
466 : #if LIBSPDM_SLH_DSA_SHA2_128S_SUPPORT
467 : return 9;
468 : #else
469 0 : return 0;
470 : #endif
471 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128S:
472 : #if LIBSPDM_SLH_DSA_SHAKE_128S_SUPPORT
473 : return 9;
474 : #else
475 0 : return 0;
476 : #endif
477 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128F:
478 : #if LIBSPDM_SLH_DSA_SHA2_128F_SUPPORT
479 : return 9;
480 : #else
481 0 : return 0;
482 : #endif
483 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128F:
484 : #if LIBSPDM_SLH_DSA_SHAKE_128F_SUPPORT
485 : return 9;
486 : #else
487 0 : return 0;
488 : #endif
489 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192S:
490 : #if LIBSPDM_SLH_DSA_SHA2_192S_SUPPORT
491 : return 9;
492 : #else
493 0 : return 0;
494 : #endif
495 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192S:
496 : #if LIBSPDM_SLH_DSA_SHAKE_192S_SUPPORT
497 : return 9;
498 : #else
499 0 : return 0;
500 : #endif
501 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192F:
502 : #if LIBSPDM_SLH_DSA_SHA2_192F_SUPPORT
503 : return 9;
504 : #else
505 0 : return 0;
506 : #endif
507 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192F:
508 : #if LIBSPDM_SLH_DSA_SHAKE_192F_SUPPORT
509 : return 9;
510 : #else
511 0 : return 0;
512 : #endif
513 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256S:
514 : #if LIBSPDM_SLH_DSA_SHA2_256S_SUPPORT
515 : return 9;
516 : #else
517 0 : return 0;
518 : #endif
519 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256S:
520 : #if LIBSPDM_SLH_DSA_SHAKE_256S_SUPPORT
521 : return 9;
522 : #else
523 0 : return 0;
524 : #endif
525 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256F:
526 : #if LIBSPDM_SLH_DSA_SHA2_256F_SUPPORT
527 : return 9;
528 : #else
529 0 : return 0;
530 : #endif
531 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256F:
532 : #if LIBSPDM_SLH_DSA_SHAKE_256F_SUPPORT
533 : return 9;
534 : #else
535 0 : return 0;
536 : #endif
537 0 : default:
538 0 : LIBSPDM_ASSERT(false);
539 0 : return 0;
540 : }
541 : }
542 0 : LIBSPDM_ASSERT(false);
543 0 : return 0;
544 : }
545 :
546 : /**
547 : * This function get the SPDM public key encryption algorithm OID.
548 : *
549 : * @param[in] base_asym_algo SPDM base_asym_algo
550 : * @param[in,out] oid SPDM public key encryption algorithm OID
551 : * @param[in,out] oid_other Other SPDM public key encryption algorithm OID
552 : * because of ASN1 code for integer
553 : *
554 : * @retval true get OID successful.
555 : * @retval false get OID fail.
556 : **/
557 787 : static bool libspdm_get_public_key_algo_OID(
558 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint8_t *oid,
559 : uint8_t *oid_other)
560 : {
561 : uint32_t oid_len;
562 787 : oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
563 787 : if (oid_len == 0) {
564 0 : return false;
565 : }
566 :
567 787 : if (base_asym_algo != 0) {
568 787 : switch (base_asym_algo) {
569 58 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
570 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048: {
571 : #if (LIBSPDM_RSA_SSA_2048_SUPPORT) || (LIBSPDM_RSA_PSS_2048_SUPPORT)
572 58 : uint8_t encry_algo_oid_rsa2048[] = KEY_ENCRY_ALGO_RSA2048_FLAG;
573 58 : uint8_t encry_algo_oid_rsa2048_other[] = KEY_ENCRY_ALGO_RSA2048_FLAG_OTHER;
574 58 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_rsa2048, oid_len);
575 58 : libspdm_copy_mem(oid_other, oid_len, encry_algo_oid_rsa2048_other, oid_len);
576 58 : return true;
577 : #else
578 : return false;
579 : #endif
580 : }
581 3 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
582 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072: {
583 : #if (LIBSPDM_RSA_SSA_3072_SUPPORT) || (LIBSPDM_RSA_PSS_3072_SUPPORT)
584 3 : uint8_t encry_algo_oid_rsa3072[] = KEY_ENCRY_ALGO_RSA3072_FLAG;
585 3 : uint8_t encry_algo_oid_rsa3072_other[] = KEY_ENCRY_ALGO_RSA3072_FLAG_OTHER;
586 3 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_rsa3072, oid_len);
587 3 : libspdm_copy_mem(oid_other, oid_len, encry_algo_oid_rsa3072_other, oid_len);
588 3 : return true;
589 : #else
590 : return false;
591 : #endif
592 : }
593 2 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
594 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096: {
595 : #if (LIBSPDM_RSA_SSA_4096_SUPPORT) || (LIBSPDM_RSA_PSS_4096_SUPPORT)
596 2 : uint8_t encry_algo_oid_rsa4096[] = KEY_ENCRY_ALGO_RSA4096_FLAG;
597 2 : uint8_t encry_algo_oid_rsa4096_other[] = KEY_ENCRY_ALGO_RSA4096_FLAG_OTHER;
598 2 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_rsa4096, oid_len);
599 2 : libspdm_copy_mem(oid_other, oid_len, encry_algo_oid_rsa4096_other, oid_len);
600 2 : return true;
601 : #else
602 : return false;
603 : #endif
604 : }
605 :
606 722 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256: {
607 : #if LIBSPDM_ECDSA_P256_SUPPORT
608 722 : uint8_t encry_algo_oid_ecc256[] = KEY_ENCRY_ALGO_ECC256_OID;
609 722 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc256, oid_len);
610 722 : return true;
611 : #else
612 : return false;
613 : #endif
614 : }
615 1 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384: {
616 : #if LIBSPDM_ECDSA_P384_SUPPORT
617 1 : uint8_t encry_algo_oid_ecc384[] = KEY_ENCRY_ALGO_ECC384_OID;
618 1 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc384, oid_len);
619 1 : return true;
620 : #else
621 : return false;
622 : #endif
623 : }
624 1 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521: {
625 : #if LIBSPDM_ECDSA_P521_SUPPORT
626 1 : uint8_t encry_algo_oid_ecc521[] = KEY_ENCRY_ALGO_ECC521_OID;
627 1 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc521, oid_len);
628 1 : return true;
629 : #else
630 : return false;
631 : #endif
632 : }
633 :
634 : /*sm2 oid TBD*/
635 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
636 0 : return true;
637 :
638 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519: {
639 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
640 : uint8_t encry_algo_oid_ed25519[] = ENCRY_ALGO_ED25519_OID;
641 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ed25519, oid_len);
642 : return true;
643 : #else
644 0 : return false;
645 : #endif
646 : break;
647 : }
648 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448: {
649 : #if LIBSPDM_EDDSA_ED448_SUPPORT
650 : uint8_t encry_algo_oid_ed448[] = ENCRY_ALGO_ED448_OID;
651 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ed448, oid_len);
652 : return true;
653 : #else
654 0 : return false;
655 : #endif
656 : break;
657 : }
658 :
659 0 : default:
660 0 : LIBSPDM_ASSERT(false);
661 0 : return false;
662 : }
663 : }
664 0 : if (pqc_asym_algo != 0) {
665 0 : switch (pqc_asym_algo) {
666 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_44: {
667 : #if LIBSPDM_ML_DSA_44_SUPPORT
668 : uint8_t algo_oid_mldsa44[] = ALGO_MLDSA44_OID;
669 : libspdm_copy_mem(oid, oid_len, algo_oid_mldsa44, oid_len);
670 : return true;
671 : #else
672 0 : return false;
673 : #endif
674 : break;
675 : }
676 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_65: {
677 : #if LIBSPDM_ML_DSA_65_SUPPORT
678 : uint8_t algo_oid_mldsa65[] = ALGO_MLDSA65_OID;
679 : libspdm_copy_mem(oid, oid_len, algo_oid_mldsa65, oid_len);
680 : return true;
681 : #else
682 0 : return false;
683 : #endif
684 : break;
685 : }
686 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_87: {
687 : #if LIBSPDM_ML_DSA_87_SUPPORT
688 : uint8_t algo_oid_mldsa87[] = ALGO_MLDSA87_OID;
689 : libspdm_copy_mem(oid, oid_len, algo_oid_mldsa87, oid_len);
690 : return true;
691 : #else
692 0 : return false;
693 : #endif
694 : break;
695 : }
696 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128S: {
697 : #if LIBSPDM_SLH_DSA_SHA2_128S_SUPPORT
698 : uint8_t algo_oid_slhdsa_sha2_128s[] = ALGO_SLHDSA_SHA2_128S_OID;
699 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_128s, oid_len);
700 : return true;
701 : #else
702 0 : return false;
703 : #endif
704 : break;
705 : }
706 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128S: {
707 : #if LIBSPDM_SLH_DSA_SHAKE_128S_SUPPORT
708 : uint8_t algo_oid_slhdsa_shake_128s[] = ALGO_SLHDSA_SHAKE_128S_OID;
709 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_128s, oid_len);
710 : return true;
711 : #else
712 0 : return false;
713 : #endif
714 : break;
715 : }
716 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128F: {
717 : #if LIBSPDM_SLH_DSA_SHA2_128F_SUPPORT
718 : uint8_t algo_oid_slhdsa_sha2_128f[] = ALGO_SLHDSA_SHA2_128F_OID;
719 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_128f, oid_len);
720 : return true;
721 : #else
722 0 : return false;
723 : #endif
724 : break;
725 : }
726 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128F: {
727 : #if LIBSPDM_SLH_DSA_SHAKE_128F_SUPPORT
728 : uint8_t algo_oid_slhdsa_shake_128f[] = ALGO_SLHDSA_SHAKE_128F_OID;
729 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_128f, oid_len);
730 : return true;
731 : #else
732 0 : return false;
733 : #endif
734 : break;
735 : }
736 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192S: {
737 : #if LIBSPDM_SLH_DSA_SHA2_192S_SUPPORT
738 : uint8_t algo_oid_slhdsa_sha2_192s[] = ALGO_SLHDSA_SHA2_192S_OID;
739 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_192s, oid_len);
740 : return true;
741 : #else
742 0 : return false;
743 : #endif
744 : break;
745 : }
746 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192S: {
747 : #if LIBSPDM_SLH_DSA_SHAKE_192S_SUPPORT
748 : uint8_t algo_oid_slhdsa_shake_192s[] = ALGO_SLHDSA_SHAKE_192S_OID;
749 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_192s, oid_len);
750 : return true;
751 : #else
752 0 : return false;
753 : #endif
754 : break;
755 : }
756 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192F: {
757 : #if LIBSPDM_SLH_DSA_SHA2_192F_SUPPORT
758 : uint8_t algo_oid_slhdsa_sha2_192f[] = ALGO_SLHDSA_SHA2_192F_OID;
759 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_192f, oid_len);
760 : return true;
761 : #else
762 0 : return false;
763 : #endif
764 : break;
765 : }
766 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192F: {
767 : #if LIBSPDM_SLH_DSA_SHAKE_192F_SUPPORT
768 : uint8_t algo_oid_slhdsa_shake_192f[] = ALGO_SLHDSA_SHAKE_192F_OID;
769 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_192f, oid_len);
770 : return true;
771 : #else
772 0 : return false;
773 : #endif
774 : break;
775 : }
776 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256S: {
777 : #if LIBSPDM_SLH_DSA_SHA2_256S_SUPPORT
778 : uint8_t algo_oid_slhdsa_sha2_256s[] = ALGO_SLHDSA_SHA2_256S_OID;
779 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_256s, oid_len);
780 : return true;
781 : #else
782 0 : return false;
783 : #endif
784 : break;
785 : }
786 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256S: {
787 : #if LIBSPDM_SLH_DSA_SHAKE_256S_SUPPORT
788 : uint8_t algo_oid_slhdsa_shake_256s[] = ALGO_SLHDSA_SHAKE_256S_OID;
789 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_256s, oid_len);
790 : return true;
791 : #else
792 0 : return false;
793 : #endif
794 : break;
795 : }
796 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256F: {
797 : #if LIBSPDM_SLH_DSA_SHA2_256F_SUPPORT
798 : uint8_t algo_oid_slhdsa_sha2_256f[] = ALGO_SLHDSA_SHA2_256F_OID;
799 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_sha2_256f, oid_len);
800 : return true;
801 : #else
802 0 : return false;
803 : #endif
804 : break;
805 : }
806 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256F: {
807 : #if LIBSPDM_SLH_DSA_SHAKE_256F_SUPPORT
808 : uint8_t algo_oid_slhdsa_shake_256f[] = ALGO_SLHDSA_SHAKE_256F_OID;
809 : libspdm_copy_mem(oid, oid_len, algo_oid_slhdsa_shake_256f, oid_len);
810 : return true;
811 : #else
812 0 : return false;
813 : #endif
814 : break;
815 : }
816 0 : default:
817 0 : LIBSPDM_ASSERT(false);
818 0 : return false;
819 : }
820 : }
821 0 : LIBSPDM_ASSERT(false);
822 0 : return false;
823 : }
824 :
825 : /**
826 : * Verify cert public key encryption algorithm is matched to negotiated base_aysm algo
827 : *
828 : * @param[in] cert Pointer to the DER-encoded certificate data.
829 : * @param[in] cert_size The size of certificate data in bytes.
830 : * @param[in] base_asym_algo SPDM base_asym_algo
831 : * @param[out] oid cert public key encryption algorithm OID
832 : * @param[in] oid_size the buffer size for required OID
833 : *
834 : * @retval true get public key oid from cert successfully
835 : * @retval false get public key oid from cert fail
836 : **/
837 787 : static bool libspdm_get_public_key_oid(
838 : const uint8_t *cert, size_t cert_size,
839 : uint8_t *oid, size_t oid_size, uint32_t base_asym_algo, uint32_t pqc_asym_algo)
840 : {
841 : bool ret;
842 : uint8_t *ptr;
843 : int32_t length;
844 : size_t obj_len;
845 : uint8_t *end;
846 : uint8_t index;
847 : uint8_t sequence_time;
848 :
849 787 : length = (int32_t)cert_size;
850 787 : ptr = (uint8_t*)(size_t)cert;
851 787 : obj_len = 0;
852 787 : end = ptr + length;
853 787 : ret = true;
854 :
855 : /* TBSCertificate have 5 sequence before subjectPublicKeyInfo*/
856 787 : sequence_time = 5;
857 :
858 : /*all cert sequence*/
859 787 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
860 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
861 787 : if (!ret) {
862 0 : return false;
863 : }
864 :
865 : /*TBSCertificate sequence*/
866 787 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
867 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
868 787 : if (!ret) {
869 0 : return false;
870 : }
871 :
872 787 : end = ptr + obj_len;
873 : /*version*/
874 787 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
875 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
876 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
877 787 : if (!ret) {
878 0 : return false;
879 : }
880 :
881 787 : ptr += obj_len;
882 : /*serialNumber*/
883 787 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
884 787 : if (!ret) {
885 0 : return false;
886 : }
887 :
888 : /**
889 : * signature AlgorithmIdentifier,
890 : * issuer Name,
891 : * validity Validity,
892 : * subject Name,
893 : * subjectPublicKeyInfo
894 : **/
895 4722 : for (index = 0; index < sequence_time; index++) {
896 3935 : ptr += obj_len;
897 3935 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
898 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
899 3935 : if (!ret) {
900 0 : return false;
901 : }
902 : }
903 :
904 787 : if (base_asym_algo != 0) {
905 787 : switch (base_asym_algo)
906 : {
907 63 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
908 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
909 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
910 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
911 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
912 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
913 63 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
914 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
915 63 : if (!ret) {
916 0 : return false;
917 : }
918 :
919 63 : ptr += obj_len;
920 63 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_BIT_STRING);
921 63 : if (!ret) {
922 0 : return false;
923 : }
924 :
925 : /*get rsa key len*/
926 63 : ptr++;
927 63 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
928 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
929 63 : if (!ret) {
930 1 : return false;
931 : }
932 62 : libspdm_copy_mem(oid, oid_size, ptr, oid_size);
933 62 : break;
934 724 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
935 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
936 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
937 724 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
938 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
939 724 : if (!ret) {
940 0 : return false;
941 : }
942 724 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
943 724 : if (!ret) {
944 0 : return false;
945 : }
946 :
947 : /*get ecc second oid*/
948 724 : ptr +=obj_len;
949 724 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
950 724 : if (!ret) {
951 0 : return false;
952 : }
953 :
954 724 : if (oid_size != obj_len) {
955 0 : return false;
956 : }
957 :
958 724 : libspdm_copy_mem(oid, oid_size, ptr, obj_len);
959 724 : break;
960 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
961 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
962 0 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
963 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
964 0 : if (!ret) {
965 0 : return false;
966 : }
967 :
968 : /*get eddsa oid*/
969 0 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
970 0 : if (!ret) {
971 0 : return false;
972 : }
973 :
974 0 : if (oid_size != obj_len) {
975 0 : return false;
976 : }
977 :
978 0 : libspdm_copy_mem(oid, oid_size, ptr, obj_len);
979 0 : break;
980 0 : default:
981 0 : LIBSPDM_ASSERT(false);
982 0 : return false;
983 : }
984 : }
985 786 : if (pqc_asym_algo != 0) {
986 0 : switch (pqc_asym_algo)
987 : {
988 0 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_44:
989 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_65:
990 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_87:
991 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128S:
992 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128S:
993 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128F:
994 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128F:
995 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192S:
996 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192S:
997 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192F:
998 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192F:
999 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256S:
1000 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256S:
1001 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256F:
1002 : case SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256F:
1003 : /* algorithm AlgorithmIdentifier SEQUENCE */
1004 0 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
1005 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1006 0 : if (!ret) {
1007 0 : return false;
1008 : }
1009 :
1010 : /* OID */
1011 0 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1012 0 : if (!ret) {
1013 0 : return false;
1014 : }
1015 :
1016 0 : if (oid_size != obj_len) {
1017 0 : return false;
1018 : }
1019 :
1020 0 : libspdm_copy_mem(oid, oid_size, ptr, obj_len);
1021 0 : break;
1022 0 : default:
1023 0 : LIBSPDM_ASSERT(false);
1024 0 : return false;
1025 : }
1026 : }
1027 786 : return true;
1028 : }
1029 :
1030 : /**
1031 : * Verify cert public key encryption algorithm is matched to negotiated base_aysm algo
1032 : *
1033 : * @param[in] cert Pointer to the DER-encoded certificate data.
1034 : * @param[in] cert_size The size of certificate data in bytes.
1035 : * @param[in] base_asym_algo SPDM base_asym_algo
1036 : *
1037 : * @retval true verify pass
1038 : * @retval false verify fail
1039 : **/
1040 787 : static bool libspdm_verify_cert_subject_public_key_info(const uint8_t *cert, size_t cert_size,
1041 : uint32_t base_asym_algo, uint32_t pqc_asym_algo)
1042 : {
1043 : size_t oid_len;
1044 : bool status;
1045 :
1046 : /*public key encrypt algo OID from cert*/
1047 : uint8_t cert_public_key_crypt_algo_oid[LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN];
1048 : /*public key encrypt algo OID from libspdm stored*/
1049 : uint8_t libspdm_public_key_crypt_algo_oid[LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN];
1050 : uint8_t libspdm_public_key_crypt_algo_oid_other[LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN];
1051 :
1052 787 : libspdm_zero_mem(libspdm_public_key_crypt_algo_oid, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
1053 787 : libspdm_zero_mem(libspdm_public_key_crypt_algo_oid_other, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
1054 :
1055 : /*work around: skip the sm2*/
1056 787 : if (base_asym_algo == SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256) {
1057 0 : return true;
1058 : }
1059 :
1060 787 : oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
1061 787 : if (oid_len == 0) {
1062 0 : return false;
1063 : }
1064 : /*get public key encrypt algo OID from libspdm stored*/
1065 787 : status = libspdm_get_public_key_algo_OID(base_asym_algo, pqc_asym_algo,
1066 : libspdm_public_key_crypt_algo_oid,
1067 : libspdm_public_key_crypt_algo_oid_other);
1068 787 : if (!status) {
1069 0 : return status;
1070 : }
1071 :
1072 : /*get public key encrypt algo OID from cert*/
1073 787 : status = libspdm_get_public_key_oid(cert, cert_size, cert_public_key_crypt_algo_oid, oid_len,
1074 : base_asym_algo, pqc_asym_algo);
1075 787 : if (!status || (!libspdm_consttime_is_mem_equal(cert_public_key_crypt_algo_oid,
1076 1 : libspdm_public_key_crypt_algo_oid, oid_len) &&
1077 1 : !libspdm_consttime_is_mem_equal(cert_public_key_crypt_algo_oid,
1078 : libspdm_public_key_crypt_algo_oid_other,
1079 : oid_len))) {
1080 2 : return false;
1081 : }
1082 :
1083 785 : return status;
1084 : }
1085 :
1086 : /**
1087 : * Verify leaf cert basic_constraints CA is false
1088 : *
1089 : * @param[in] cert Pointer to the DER-encoded certificate data.
1090 : * @param[in] cert_size The size of certificate data in bytes.
1091 : * @param[in] need_basic_constraints This value indicates whether basic_constraints must be present in the Cert
1092 : *
1093 : * @retval true verify pass,two case: 1.basic constraints is not present in cert, when need_basic_constraints is false;
1094 : * 2. cert basic_constraints CA is false;
1095 : * @retval false verify fail
1096 : **/
1097 769 : static bool libspdm_verify_leaf_cert_basic_constraints(const uint8_t *cert, size_t cert_size,
1098 : bool need_basic_constraints)
1099 : {
1100 : bool status;
1101 : /*basic_constraints from cert*/
1102 : uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
1103 : size_t len;
1104 :
1105 769 : uint8_t basic_constraints_false_case[] = BASIC_CONSTRAINTS_CA_FALSE;
1106 :
1107 769 : len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1108 :
1109 769 : status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1110 : cert_basic_constraints, &len);
1111 769 : if (!status) {
1112 0 : return false;
1113 769 : } else if (len == 0) {
1114 : /* basic constraints is not present in cert */
1115 2 : if (need_basic_constraints) {
1116 1 : return false;
1117 : } else {
1118 1 : return true;
1119 : }
1120 : }
1121 :
1122 1533 : if ((len == sizeof(basic_constraints_false_case)) &&
1123 766 : (libspdm_consttime_is_mem_equal(cert_basic_constraints,
1124 : basic_constraints_false_case,
1125 : sizeof(basic_constraints_false_case)))) {
1126 766 : return true;
1127 : }
1128 :
1129 1 : return false;
1130 : }
1131 :
1132 : /**
1133 : * Verify leaf certificate basic_constraints CA is correct for set certificate.
1134 : *
1135 : * For SPDM 1.2
1136 : * - If certificate model is DeviceCert and CA is present then CA must be false.
1137 : * - If certificate model is AliasCert and CA is present then CA must be true.
1138 : *
1139 : * For SPDM 1.3 and up, CA must be present and
1140 : * - If certificate model is DeviceCert or GenericCert then CA must be false.
1141 : * - If certificate model is AliasCert then CA must be true.
1142 : *
1143 : * @param[in] cert Pointer to the DER-encoded certificate data.
1144 : * @param[in] cert_size The size of certificate data in bytes.
1145 : * @param[in] cert_model The certificate model.
1146 : * @param[in] need_basic_constraints This value indicates whether basic_constraints must be present
1147 : * in the certificate.
1148 : *
1149 : * @retval true verify pass 1. basic_constraints is not present when allowed.
1150 : * 2. basic_constraints is present and correct.
1151 : * @retval false verify fail
1152 : **/
1153 16 : static bool libspdm_verify_set_cert_leaf_cert_basic_constraints(
1154 : const uint8_t *cert, size_t cert_size, uint8_t cert_model, bool need_basic_constraints)
1155 : {
1156 : bool status;
1157 : /* basic_constraints from certificate. */
1158 : uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
1159 : size_t len;
1160 :
1161 16 : const uint8_t basic_constraints_false_case[] = BASIC_CONSTRAINTS_CA_FALSE;
1162 16 : const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_CA_TRUE;
1163 :
1164 16 : len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1165 :
1166 16 : status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1167 : cert_basic_constraints, &len);
1168 16 : if (!status) {
1169 0 : return false;
1170 16 : } else if (need_basic_constraints && (len == 0)) {
1171 0 : return false;
1172 : }
1173 :
1174 16 : if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT) ||
1175 : (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1176 9 : if (need_basic_constraints || (len != 0)) {
1177 18 : if ((len == sizeof(basic_constraints_false_case)) &&
1178 9 : (libspdm_consttime_is_mem_equal(cert_basic_constraints,
1179 : basic_constraints_false_case,
1180 : sizeof(basic_constraints_false_case)))) {
1181 9 : return true;
1182 : }
1183 : }
1184 : } else {
1185 : /* Alias certificate model. */
1186 7 : if (need_basic_constraints || (len != 0)) {
1187 : /* basicConstraints may include the pathLen field. Therefore do not check sequence
1188 : * length. */
1189 7 : if (len >= sizeof(basic_constraints_true_case)) {
1190 5 : if (cert_basic_constraints[0] != basic_constraints_true_case[0]) {
1191 0 : return false;
1192 : }
1193 5 : if (libspdm_consttime_is_mem_equal(&cert_basic_constraints[2],
1194 : &basic_constraints_true_case[2],
1195 : sizeof(basic_constraints_true_case) - 2)) {
1196 5 : return true;
1197 : }
1198 : }
1199 : }
1200 : }
1201 2 : return false;
1202 : }
1203 :
1204 : /**
1205 : * Verify leaf cert spdm defined extended key usage
1206 : *
1207 : * @param[in] cert Pointer to the DER-encoded certificate data.
1208 : * @param[in] cert_size The size of certificate data in bytes.
1209 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1210 : *
1211 : * @retval true verify pass, two cases:
1212 : * 1. spdm defined eku is not present in cert;
1213 : * 2. spdm defined eku is compliant with requester/responder identity;
1214 : * @retval false verify fail, two cases:
1215 : * 1. requester's cert has only responder auth oid in eku;
1216 : * 2. responder's cert has only requester auth oid in eku;
1217 : **/
1218 792 : static bool libspdm_verify_leaf_cert_spdm_eku(const uint8_t *cert, size_t cert_size,
1219 : bool is_requester_cert)
1220 : {
1221 : bool status;
1222 : uint8_t eku[256];
1223 : size_t eku_size;
1224 : bool req_auth_oid_find_success;
1225 : bool rsp_auth_oid_find_success;
1226 : uint8_t *ptr;
1227 : size_t obj_len;
1228 :
1229 : /* SPDM defined OID */
1230 792 : uint8_t eku_requester_auth_oid[] = SPDM_OID_DMTF_EKU_REQUESTER_AUTH;
1231 792 : uint8_t eku_responder_auth_oid[] = SPDM_OID_DMTF_EKU_RESPONDER_AUTH;
1232 :
1233 792 : eku_size = sizeof(eku);
1234 792 : status = libspdm_x509_get_extended_key_usage(cert, cert_size, eku, &eku_size);
1235 792 : if (!status) {
1236 0 : return false;
1237 792 : } else if (eku_size == 0) {
1238 : /* eku is not present in cert */
1239 0 : return true;
1240 : }
1241 :
1242 792 : ptr = eku;
1243 792 : obj_len = 0;
1244 792 : req_auth_oid_find_success = false;
1245 792 : rsp_auth_oid_find_success = false;
1246 :
1247 792 : status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len,
1248 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1249 792 : if (!status) {
1250 0 : return false;
1251 : }
1252 :
1253 3171 : while(ptr < eku + eku_size) {
1254 2379 : status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1255 2379 : if (!status) {
1256 0 : return false;
1257 : }
1258 :
1259 2387 : if ((obj_len == sizeof(eku_requester_auth_oid)) &&
1260 8 : (libspdm_consttime_is_mem_equal(ptr, eku_requester_auth_oid,
1261 : sizeof(eku_requester_auth_oid)))) {
1262 4 : req_auth_oid_find_success = true;
1263 : }
1264 2387 : if ((obj_len == sizeof(eku_responder_auth_oid)) &&
1265 8 : (libspdm_consttime_is_mem_equal(ptr, eku_responder_auth_oid,
1266 : sizeof(eku_responder_auth_oid)))) {
1267 4 : rsp_auth_oid_find_success = true;
1268 : }
1269 :
1270 2379 : ptr += obj_len;
1271 : }
1272 :
1273 792 : if (ptr != eku + eku_size) {
1274 0 : return false;
1275 : }
1276 :
1277 792 : if (is_requester_cert) {
1278 : /* it should not only contain responder auth oid */
1279 20 : if (!req_auth_oid_find_success && rsp_auth_oid_find_success) {
1280 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Requester certificate contains Responder OID.\n"));
1281 1 : return false;
1282 : }
1283 : } else {
1284 : /* it should not only contain requester auth oid */
1285 772 : if (req_auth_oid_find_success && !rsp_auth_oid_find_success) {
1286 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Responder certificate contains Requester OID.\n"));
1287 1 : return false;
1288 : }
1289 : }
1290 :
1291 790 : return true;
1292 : }
1293 :
1294 789 : bool libspdm_contains_hardware_id_oid(const uint8_t *cert, size_t cert_size)
1295 : {
1296 : bool status;
1297 : bool find_successful;
1298 : uint8_t spdm_extension[LIBSPDM_MAX_EXTENSION_LEN];
1299 : size_t len;
1300 : uint8_t *ptr;
1301 : uint8_t *temptr;
1302 : size_t obj_len;
1303 :
1304 : /* SPDM defined OID */
1305 789 : uint8_t oid_spdm_extension[] = SPDM_OID_DMTF_SPDM_EXTENSION;
1306 789 : uint8_t hardware_identity_oid[] = SPDM_OID_DMTF_HARDWARE_IDENTITY;
1307 :
1308 789 : len = LIBSPDM_MAX_EXTENSION_LEN;
1309 :
1310 789 : if (cert == NULL || cert_size == 0) {
1311 0 : return false;
1312 : }
1313 :
1314 789 : status = libspdm_x509_get_extension_data(cert, cert_size,
1315 : (const uint8_t *)oid_spdm_extension,
1316 : sizeof(oid_spdm_extension),
1317 : spdm_extension,
1318 : &len);
1319 789 : if (!status) {
1320 0 : return false;
1321 789 : } else if (len == 0) {
1322 17 : return false;
1323 : }
1324 :
1325 : /*find the spdm hardware identity OID*/
1326 772 : find_successful = false;
1327 772 : ptr = spdm_extension;
1328 772 : obj_len = 0;
1329 :
1330 : /*id-spdm-cert-oids ::= SEQUENCE SIZE (1..MAX) OF id-spdm-cert-oid*/
1331 772 : status = libspdm_asn1_get_tag(
1332 : &ptr, spdm_extension + len, &obj_len,
1333 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1334 772 : if (!status) {
1335 0 : return false;
1336 : }
1337 :
1338 1544 : while(ptr < spdm_extension + len) {
1339 772 : status = libspdm_asn1_get_tag(
1340 : &ptr, spdm_extension + len, &obj_len,
1341 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1342 772 : if (!status) {
1343 0 : return false;
1344 : }
1345 :
1346 772 : temptr = ptr + obj_len;
1347 772 : status = libspdm_asn1_get_tag(
1348 : &ptr, spdm_extension + len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1349 772 : if (!status) {
1350 0 : return false;
1351 : }
1352 1544 : if ((obj_len == sizeof(hardware_identity_oid)) &&
1353 772 : (libspdm_consttime_is_mem_equal(ptr, hardware_identity_oid,
1354 : sizeof(hardware_identity_oid)))) {
1355 772 : find_successful = true;
1356 : }
1357 772 : ptr = temptr;
1358 : }
1359 :
1360 772 : if (ptr != spdm_extension + len) {
1361 0 : return false;
1362 : }
1363 :
1364 772 : return find_successful;
1365 : }
1366 :
1367 : /**
1368 : * Verify leaf cert spdm defined extension
1369 : *
1370 : * @param[in] cert Pointer to the DER-encoded certificate data.
1371 : * @param[in] cert_size The size of certificate data in bytes.
1372 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1373 : *
1374 : * @retval true verify pass
1375 : * @retval false verify fail,two case: 1. Unable to get get or validate extension data.
1376 : * 2. hardware_identity_oid is found in AliasCert model;
1377 : **/
1378 783 : static bool libspdm_verify_leaf_cert_spdm_extension(const uint8_t *cert, size_t cert_size,
1379 : bool is_requester_cert,
1380 : uint8_t cert_model)
1381 : {
1382 783 : bool find_successful = libspdm_contains_hardware_id_oid(cert, cert_size);
1383 :
1384 : /* Responder does not determine Requester's certificate model */
1385 783 : if (!is_requester_cert) {
1386 766 : if ((find_successful) && (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1387 : /* Hardware_identity_OID is found in alias cert model */
1388 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1389 : "Hardware identity OID present in alias leaf certificate.\n"));
1390 5 : return false;
1391 : }
1392 : }
1393 :
1394 778 : return true;
1395 : }
1396 :
1397 : /**
1398 : * Certificate common Check for SPDM leaf cert when get_cert and set_cert.
1399 : *
1400 : * @param[in] cert Pointer to the DER-encoded certificate data.
1401 : * @param[in] cert_size The size of certificate data in bytes.
1402 : * @param[in] base_asym_algo SPDM base_asym_algo
1403 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1404 : * @param[in] cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
1405 : * @param[in] set_cert Is the function verifying a set certificate operation.
1406 : *
1407 : * @retval true Success.
1408 : * @retval false Certificate is not valid.
1409 : **/
1410 794 : static bool libspdm_x509_common_certificate_check(
1411 : const uint8_t *cert, size_t cert_size,
1412 : uint32_t base_asym_algo, uint32_t pqc_asym_algo,
1413 : bool is_requester_cert, uint8_t cert_model,
1414 : bool set_cert)
1415 : {
1416 : uint8_t end_cert_from[64];
1417 : size_t end_cert_from_len;
1418 : uint8_t end_cert_to[64];
1419 : size_t end_cert_to_len;
1420 : size_t asn1_buffer_len;
1421 : bool status;
1422 : size_t cert_version;
1423 : void *context;
1424 : size_t signature_algo_oid_size;
1425 :
1426 794 : if (cert == NULL || cert_size == 0) {
1427 0 : return false;
1428 : }
1429 :
1430 794 : status = true;
1431 794 : context = NULL;
1432 794 : end_cert_from_len = 64;
1433 794 : end_cert_to_len = 64;
1434 :
1435 : /* 1. Version */
1436 794 : cert_version = 0;
1437 794 : status = libspdm_x509_get_version(cert, cert_size, &cert_version);
1438 794 : if (!status) {
1439 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Version field is not present.\n"));
1440 0 : goto cleanup;
1441 : }
1442 794 : if (cert_version != 2) {
1443 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1444 : "Expected Version to be equal to 2 but it is actually %zu.\n", cert_version));
1445 0 : status = false;
1446 0 : goto cleanup;
1447 : }
1448 :
1449 : /* 2. Serial Number */
1450 794 : asn1_buffer_len = 0;
1451 794 : status = libspdm_x509_get_serial_number(cert, cert_size, NULL, &asn1_buffer_len);
1452 794 : if (asn1_buffer_len == 0) {
1453 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Serial Number field is not present.\n"));
1454 0 : status = false;
1455 0 : goto cleanup;
1456 : }
1457 :
1458 : /* 3. Signature Algorithm */
1459 794 : signature_algo_oid_size = 0;
1460 794 : status = libspdm_x509_get_signature_algorithm(cert, cert_size, NULL, &signature_algo_oid_size);
1461 794 : if (status) {
1462 0 : if ((signature_algo_oid_size == 0) &&
1463 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1464 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1465 : "The mandatory Signature Algorithm field is not present.\n"));
1466 0 : status = false;
1467 0 : goto cleanup;
1468 : }
1469 : } else {
1470 794 : if (signature_algo_oid_size == 0) {
1471 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1472 : "The mandatory Signature Algorithm field is not present.\n"));
1473 0 : status = false;
1474 0 : goto cleanup;
1475 : }
1476 : }
1477 :
1478 : /* 4. Verify public key algorithm.
1479 : * If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
1480 : * check should be skipped as the Device Certificate CA's public key does not have to use
1481 : * the same algorithms as the connection's negotiated algorithms. */
1482 794 : if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1483 787 : status = libspdm_verify_cert_subject_public_key_info(cert, cert_size, base_asym_algo,
1484 : pqc_asym_algo);
1485 787 : if (!status) {
1486 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1487 : "Error in verifying the Public Key Algorithm field.\n"));
1488 2 : goto cleanup;
1489 : }
1490 : }
1491 :
1492 : /* 5. Issuer */
1493 792 : asn1_buffer_len = 0;
1494 792 : status = libspdm_x509_get_issuer_name(cert, cert_size, NULL, &asn1_buffer_len);
1495 792 : if (status) {
1496 0 : if ((asn1_buffer_len == 0) &&
1497 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1498 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Issuer field is not present.\n"));
1499 0 : status = false;
1500 0 : goto cleanup;
1501 : }
1502 : } else {
1503 792 : if (asn1_buffer_len == 0) {
1504 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Issuer field is not present.\n"));
1505 0 : status = false;
1506 0 : goto cleanup;
1507 : }
1508 : }
1509 :
1510 : /* 6. subject_name*/
1511 792 : asn1_buffer_len = 0;
1512 792 : status = libspdm_x509_get_subject_name(cert, cert_size, NULL, &asn1_buffer_len);
1513 792 : if (status) {
1514 0 : if ((asn1_buffer_len == 0) &&
1515 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1516 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Subject field is not present.\n"));
1517 0 : status = false;
1518 0 : goto cleanup;
1519 : }
1520 : } else {
1521 792 : if (asn1_buffer_len == 0) {
1522 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Subject field is not present.\n"));
1523 0 : status = false;
1524 0 : goto cleanup;
1525 : }
1526 : }
1527 :
1528 : /* 7. Validity */
1529 792 : status = libspdm_x509_get_validity(cert, cert_size, end_cert_from,
1530 : &end_cert_from_len, end_cert_to,
1531 : &end_cert_to_len);
1532 792 : if (status) {
1533 792 : if ((end_cert_from_len == 0) &&
1534 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1535 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Validity field is not present.\n"));
1536 0 : status = false;
1537 0 : goto cleanup;
1538 : }
1539 : } else {
1540 0 : if (end_cert_from_len == 0) {
1541 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Validity field is not present.\n"));
1542 0 : status = false;
1543 0 : goto cleanup;
1544 : }
1545 : }
1546 :
1547 792 : if (end_cert_from_len != 0) {
1548 792 : status = libspdm_internal_x509_date_time_check(
1549 : end_cert_from, end_cert_from_len, end_cert_to, end_cert_to_len);
1550 792 : if (!status) {
1551 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1552 : "The certificate is outside its validity period.\n"));
1553 0 : goto cleanup;
1554 : }
1555 : }
1556 :
1557 : /* 8. Subject Public Key Info */
1558 792 : if (base_asym_algo != 0) {
1559 792 : status = libspdm_asym_get_public_key_from_x509(base_asym_algo, cert, cert_size, &context);
1560 : }
1561 792 : if (pqc_asym_algo != 0) {
1562 0 : status = libspdm_pqc_asym_get_public_key_from_x509(pqc_asym_algo, cert, cert_size, &context);
1563 : }
1564 792 : if (!status) {
1565 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1566 : "The mandatory Subject Public Key Info field is not present.\n"));
1567 0 : goto cleanup;
1568 : }
1569 :
1570 : /* 9. Key Usage
1571 : * If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
1572 : * check should be skipped as the SPDM specification does not specify the presence or absence
1573 : * of the Device Certificate CA's keyUsage field. */
1574 792 : if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1575 785 : size_t value = 0;
1576 :
1577 785 : status = libspdm_x509_get_key_usage(cert, cert_size, &value);
1578 785 : if (!status) {
1579 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Key Usage field is not present.\n"));
1580 0 : goto cleanup;
1581 : } else {
1582 785 : if (value == 0) {
1583 0 : if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
1584 0 : status = false;
1585 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1586 : "The mandatory Key Usage field is not present.\n"));
1587 0 : goto cleanup;
1588 : }
1589 : } else {
1590 785 : if ((LIBSPDM_CRYPTO_X509_KU_DIGITAL_SIGNATURE & value) == 0) {
1591 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1592 : "The Mandatory digital signature bit in Key Usage field is not set.\n"));
1593 0 : status = false;
1594 0 : goto cleanup;
1595 : }
1596 : }
1597 : }
1598 : }
1599 :
1600 : /* 10. Extended Key Usage */
1601 792 : status = libspdm_verify_leaf_cert_spdm_eku(cert, cert_size, is_requester_cert);
1602 792 : if (!status) {
1603 2 : goto cleanup;
1604 : }
1605 :
1606 790 : if ((!set_cert) || (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT)) {
1607 : /* 11. verify spdm defined extension*/
1608 783 : status = libspdm_verify_leaf_cert_spdm_extension(cert, cert_size,
1609 : is_requester_cert, cert_model);
1610 783 : if (!status) {
1611 5 : goto cleanup;
1612 : }
1613 : }
1614 :
1615 785 : cleanup:
1616 794 : if (base_asym_algo != 0) {
1617 794 : libspdm_asym_free(base_asym_algo, context);
1618 : }
1619 794 : if (pqc_asym_algo != 0) {
1620 0 : libspdm_pqc_asym_free(pqc_asym_algo, context);
1621 : }
1622 794 : return status;
1623 : }
1624 :
1625 778 : bool libspdm_x509_certificate_check(
1626 : uint8_t spdm_version,
1627 : const uint8_t *cert, size_t cert_size,
1628 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1629 : bool is_requester, uint8_t cert_model)
1630 : {
1631 : bool status;
1632 : bool need_basic_constraints;
1633 :
1634 778 : status = libspdm_x509_common_certificate_check(
1635 : cert, cert_size, base_asym_algo, pqc_asym_algo, is_requester, cert_model, false);
1636 778 : if (!status) {
1637 9 : return false;
1638 : }
1639 :
1640 769 : if (spdm_version >= SPDM_MESSAGE_VERSION_13) {
1641 : /* verify basic constraints: the leaf cert always is ca:false in get_cert
1642 : * basic_constraints is mandatory in SPDM 1.3*/
1643 14 : need_basic_constraints = true;
1644 : } else {
1645 : /* verify basic constraints: the leaf cert always is ca:false in get_cert*/
1646 755 : need_basic_constraints = false;
1647 : }
1648 769 : status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, need_basic_constraints);
1649 769 : return status;
1650 : }
1651 :
1652 16 : bool libspdm_x509_set_cert_certificate_check(
1653 : uint8_t spdm_version,
1654 : const uint8_t *cert, size_t cert_size,
1655 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1656 : bool is_requester, uint8_t cert_model)
1657 : {
1658 : bool status;
1659 : bool need_basic_constraints;
1660 :
1661 16 : status = libspdm_x509_common_certificate_check(
1662 : cert, cert_size, base_asym_algo, pqc_asym_algo, is_requester, cert_model, true);
1663 16 : if (!status) {
1664 0 : return false;
1665 : }
1666 :
1667 : /* verify basic constraints: need check with is_device_cert_model*/
1668 16 : if (spdm_version >= SPDM_MESSAGE_VERSION_13) {
1669 6 : need_basic_constraints = true;
1670 : } else {
1671 10 : need_basic_constraints = false;
1672 : }
1673 16 : status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
1674 : cert, cert_size, cert_model, need_basic_constraints);
1675 :
1676 16 : return status;
1677 : }
1678 :
1679 59 : bool libspdm_is_root_certificate(const uint8_t *cert, size_t cert_size)
1680 : {
1681 : uint8_t issuer_name[LIBSPDM_MAX_NAME_SIZE];
1682 : size_t issuer_name_len;
1683 : uint8_t subject_name[LIBSPDM_MAX_NAME_SIZE];
1684 : size_t subject_name_len;
1685 : bool result;
1686 : uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
1687 : size_t cert_basic_constraints_len;
1688 59 : const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_CA_TRUE;
1689 :
1690 59 : if (cert == NULL || cert_size == 0) {
1691 0 : return false;
1692 : }
1693 :
1694 : /* 1. issuer_name*/
1695 59 : issuer_name_len = sizeof(issuer_name);
1696 59 : result = libspdm_x509_get_issuer_name(cert, cert_size, issuer_name, &issuer_name_len);
1697 59 : if (!result) {
1698 0 : return false;
1699 : }
1700 :
1701 : /* 2. subject_name*/
1702 59 : subject_name_len = sizeof(subject_name);
1703 59 : result = libspdm_x509_get_subject_name(cert, cert_size, subject_name, &subject_name_len);
1704 59 : if (!result) {
1705 0 : return false;
1706 : }
1707 :
1708 59 : if (issuer_name_len != subject_name_len) {
1709 3 : return false;
1710 : }
1711 56 : if (!libspdm_consttime_is_mem_equal(issuer_name, subject_name, issuer_name_len)) {
1712 0 : return false;
1713 : }
1714 :
1715 : /* 3. cA must be present in Basic Constraints */
1716 56 : cert_basic_constraints_len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1717 56 : result = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1718 : cert_basic_constraints,
1719 : &cert_basic_constraints_len);
1720 56 : if (!result) {
1721 0 : return false;
1722 : }
1723 :
1724 56 : if ((cert_basic_constraints_len < sizeof(basic_constraints_true_case) ||
1725 56 : (cert_basic_constraints[0] != basic_constraints_true_case[0]))) {
1726 0 : return false;
1727 : }
1728 56 : if (!libspdm_consttime_is_mem_equal(&cert_basic_constraints[2],
1729 : &basic_constraints_true_case[2],
1730 : sizeof(basic_constraints_true_case) - 2)) {
1731 0 : return false;
1732 : }
1733 :
1734 : /* 4. certificate must be self-signed */
1735 56 : result = libspdm_x509_verify_cert(cert, cert_size, cert, cert_size);
1736 56 : if (!result) {
1737 1 : return false;
1738 : }
1739 :
1740 55 : return true;
1741 : }
1742 :
1743 9 : bool libspdm_get_dmtf_subject_alt_name_from_bytes(
1744 : uint8_t *buffer, size_t len, char *name_buffer,
1745 : size_t *name_buffer_size, uint8_t *oid,
1746 : size_t *oid_size)
1747 : {
1748 : uint8_t *ptr;
1749 : int32_t length;
1750 : size_t obj_len;
1751 : int32_t ret;
1752 :
1753 : /*copy mem variable*/
1754 : volatile uint8_t* dst;
1755 : const volatile uint8_t* src;
1756 : size_t dst_len;
1757 : size_t src_len;
1758 :
1759 9 : length = (int32_t)len;
1760 9 : ptr = buffer;
1761 9 : obj_len = 0;
1762 :
1763 : /* Sequence*/
1764 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + length, &obj_len,
1765 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1766 9 : if (!ret) {
1767 0 : return false;
1768 : }
1769 :
1770 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len,
1771 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1772 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1773 :
1774 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1775 9 : if (!ret) {
1776 0 : return false;
1777 : }
1778 : /* CopyData to OID*/
1779 9 : if (*oid_size < (size_t)obj_len) {
1780 0 : *oid_size = (size_t)obj_len;
1781 0 : return false;
1782 : }
1783 9 : if (oid != NULL) {
1784 9 : libspdm_copy_mem(oid, *oid_size, ptr, obj_len);
1785 9 : *oid_size = obj_len;
1786 : }
1787 :
1788 : /* Move to next element*/
1789 9 : ptr += obj_len;
1790 :
1791 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1792 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1793 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1794 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1795 : LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
1796 9 : if (!ret) {
1797 0 : return false;
1798 : }
1799 :
1800 9 : if (*name_buffer_size < (size_t)obj_len + 1) {
1801 0 : *name_buffer_size = (size_t)obj_len + 1;
1802 0 : return false;
1803 : }
1804 :
1805 : /* the src and dst address are overlap,
1806 : * When the function is called by libspdm_get_dmtf_subject_alt_name.
1807 : * libspdm_copy_mem can not be used. */
1808 9 : if ((name_buffer != NULL) && (ptr != NULL)) {
1809 9 : dst = (volatile uint8_t*) name_buffer;
1810 9 : src = (const volatile uint8_t*) ptr;
1811 9 : dst_len = *name_buffer_size;
1812 9 : src_len = obj_len;
1813 :
1814 : /* Check for case where "dst_len" may be invalid. Do not zero "dst" in this case. */
1815 9 : if (dst_len > (SIZE_MAX >> 1)) {
1816 0 : LIBSPDM_ASSERT(0);
1817 0 : return false;
1818 : }
1819 :
1820 : /* Guard against invalid lengths. Zero "dst" in these cases. */
1821 9 : if (src_len > dst_len ||
1822 9 : src_len > (SIZE_MAX >> 1)) {
1823 0 : libspdm_zero_mem(name_buffer, dst_len);
1824 0 : LIBSPDM_ASSERT(0);
1825 0 : return false;
1826 : }
1827 :
1828 207 : while (src_len-- != 0) {
1829 198 : *(dst++) = *(src++);
1830 : }
1831 :
1832 : /*encode name buffer to string*/
1833 9 : *name_buffer_size = obj_len + 1;
1834 9 : name_buffer[obj_len] = 0;
1835 9 : return true;
1836 : }
1837 :
1838 0 : return false;
1839 : }
1840 :
1841 6 : bool libspdm_get_dmtf_subject_alt_name(const uint8_t *cert, size_t cert_size,
1842 : char *name_buffer,
1843 : size_t *name_buffer_size,
1844 : uint8_t *oid, size_t *oid_size)
1845 : {
1846 : bool status;
1847 : size_t extension_data_size;
1848 6 : uint8_t oid_subject_alt_name[] = { 0x55, 0x1D, 0x11 };
1849 :
1850 6 : extension_data_size = 0;
1851 6 : status = libspdm_x509_get_extension_data(cert, cert_size,
1852 : oid_subject_alt_name,
1853 : sizeof(oid_subject_alt_name), NULL,
1854 : &extension_data_size);
1855 6 : if (status || (extension_data_size == 0)) {
1856 0 : *name_buffer_size = 0;
1857 0 : return false;
1858 : }
1859 6 : if (extension_data_size > *name_buffer_size) {
1860 0 : *name_buffer_size = extension_data_size;
1861 0 : return false;
1862 : }
1863 : status =
1864 6 : libspdm_x509_get_extension_data(cert, cert_size,
1865 : oid_subject_alt_name,
1866 : sizeof(oid_subject_alt_name),
1867 : (uint8_t *)name_buffer, name_buffer_size);
1868 6 : if (!status) {
1869 0 : return status;
1870 : }
1871 :
1872 6 : return libspdm_get_dmtf_subject_alt_name_from_bytes(
1873 : (uint8_t *)name_buffer, *name_buffer_size, name_buffer,
1874 : name_buffer_size, oid, oid_size);
1875 : }
1876 :
1877 716 : bool libspdm_verify_cert_chain_data(
1878 : uint8_t spdm_version,
1879 : uint8_t *cert_chain_data, size_t cert_chain_data_size,
1880 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1881 : bool is_requester_cert, uint8_t cert_model)
1882 : {
1883 : const uint8_t *root_cert_buffer;
1884 : size_t root_cert_buffer_size;
1885 : const uint8_t *leaf_cert_buffer;
1886 : size_t leaf_cert_buffer_size;
1887 :
1888 716 : if (cert_chain_data_size >
1889 : SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
1890 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1891 : "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
1892 0 : return false;
1893 : }
1894 :
1895 716 : if (!libspdm_x509_get_cert_from_cert_chain(
1896 : cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
1897 : &root_cert_buffer_size)) {
1898 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1899 : "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
1900 0 : return false;
1901 : }
1902 :
1903 716 : if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
1904 : cert_chain_data, cert_chain_data_size)) {
1905 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1906 : "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
1907 2 : return false;
1908 : }
1909 :
1910 714 : if (!libspdm_x509_get_cert_from_cert_chain(
1911 : cert_chain_data, cert_chain_data_size, -1,
1912 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
1913 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1914 : "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
1915 0 : return false;
1916 : }
1917 :
1918 714 : if (!libspdm_x509_certificate_check(spdm_version,
1919 : leaf_cert_buffer, leaf_cert_buffer_size,
1920 : base_asym_algo, pqc_asym_algo, base_hash_algo,
1921 : is_requester_cert, cert_model)) {
1922 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1923 : "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
1924 1 : return false;
1925 : }
1926 :
1927 713 : return true;
1928 : }
1929 :
1930 40 : bool libspdm_verify_certificate_chain_buffer(
1931 : uint8_t spdm_version,
1932 : uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
1933 : const void *cert_chain_buffer,
1934 : size_t cert_chain_buffer_size,
1935 : bool is_requester_cert, uint8_t cert_model)
1936 : {
1937 : const uint8_t *cert_chain_data;
1938 : size_t cert_chain_data_size;
1939 : const uint8_t *first_cert_buffer;
1940 : size_t first_cert_buffer_size;
1941 : size_t hash_size;
1942 : uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
1943 : const uint8_t *leaf_cert_buffer;
1944 : size_t leaf_cert_buffer_size;
1945 : bool result;
1946 : const spdm_cert_chain_t *cert_chain_header;
1947 :
1948 40 : hash_size = libspdm_get_hash_size(base_hash_algo);
1949 :
1950 40 : if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
1951 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1952 : "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
1953 0 : return false;
1954 : }
1955 :
1956 40 : cert_chain_header = cert_chain_buffer;
1957 40 : if (cert_chain_header->length != cert_chain_buffer_size) {
1958 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1959 : "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
1960 2 : return false;
1961 : }
1962 :
1963 38 : cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
1964 38 : cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
1965 38 : if (!libspdm_x509_get_cert_from_cert_chain(
1966 : cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
1967 : &first_cert_buffer_size)) {
1968 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1969 : "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
1970 0 : return false;
1971 : }
1972 :
1973 38 : if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
1974 35 : result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
1975 : calc_root_cert_hash);
1976 35 : if (!result) {
1977 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1978 : "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
1979 0 : return false;
1980 : }
1981 35 : if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
1982 : sizeof(spdm_cert_chain_t),
1983 : calc_root_cert_hash, hash_size)) {
1984 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1985 : "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
1986 0 : return false;
1987 : }
1988 35 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1989 : "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
1990 : }
1991 :
1992 : /*If the number of certificates in the certificate chain is more than 1,
1993 : * other certificates need to be verified.*/
1994 38 : if (cert_chain_data_size > first_cert_buffer_size) {
1995 38 : if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
1996 : cert_chain_data + first_cert_buffer_size,
1997 : cert_chain_data_size - first_cert_buffer_size)) {
1998 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1999 : "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
2000 3 : return false;
2001 : }
2002 : }
2003 :
2004 35 : if (!libspdm_x509_get_cert_from_cert_chain(
2005 : cert_chain_data, cert_chain_data_size, -1,
2006 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2007 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2008 : "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
2009 0 : return false;
2010 : }
2011 :
2012 35 : if (!libspdm_x509_certificate_check(spdm_version,
2013 : leaf_cert_buffer, leaf_cert_buffer_size,
2014 : base_asym_algo, pqc_asym_algo, base_hash_algo,
2015 : is_requester_cert, cert_model)) {
2016 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2017 : "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
2018 3 : return false;
2019 : }
2020 :
2021 32 : return true;
2022 : }
2023 :
2024 256 : bool libspdm_get_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2025 : uint32_t base_asym_alg,
2026 : uint8_t *cert_chain_data,
2027 : size_t cert_chain_data_size,
2028 : void **public_key)
2029 : {
2030 : size_t hash_size;
2031 : const uint8_t *cert_buffer;
2032 : size_t cert_buffer_size;
2033 : bool result;
2034 :
2035 256 : hash_size = libspdm_get_hash_size(base_hash_algo);
2036 :
2037 256 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2038 256 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2039 :
2040 : /* Get leaf cert from cert chain */
2041 256 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2042 : cert_chain_data_size, -1,
2043 : &cert_buffer, &cert_buffer_size);
2044 256 : if (!result) {
2045 0 : return false;
2046 : }
2047 :
2048 256 : result = libspdm_asym_get_public_key_from_x509(
2049 : base_asym_alg,
2050 : cert_buffer, cert_buffer_size, public_key);
2051 256 : if (!result) {
2052 4 : return false;
2053 : }
2054 :
2055 252 : return true;
2056 : }
2057 :
2058 0 : bool libspdm_get_pqc_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2059 : uint32_t pqc_asym_alg,
2060 : uint8_t *cert_chain_data,
2061 : size_t cert_chain_data_size,
2062 : void **public_key)
2063 : {
2064 : size_t hash_size;
2065 : const uint8_t *cert_buffer;
2066 : size_t cert_buffer_size;
2067 : bool result;
2068 :
2069 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
2070 :
2071 0 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2072 0 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2073 :
2074 : /* Get leaf cert from cert chain */
2075 0 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2076 : cert_chain_data_size, -1,
2077 : &cert_buffer, &cert_buffer_size);
2078 0 : if (!result) {
2079 0 : return false;
2080 : }
2081 :
2082 0 : result = libspdm_pqc_asym_get_public_key_from_x509(
2083 : pqc_asym_alg,
2084 : cert_buffer, cert_buffer_size, public_key);
2085 0 : if (!result) {
2086 0 : return false;
2087 : }
2088 :
2089 0 : return true;
2090 : }
2091 :
2092 29 : bool libspdm_verify_req_info(uint8_t *req_info, uint16_t req_info_len)
2093 : {
2094 : bool ret;
2095 : uint8_t *ptr;
2096 : int32_t length;
2097 : size_t obj_len;
2098 : uint8_t *end;
2099 :
2100 29 : length = (int32_t)req_info_len;
2101 29 : ptr = req_info;
2102 29 : obj_len = 0;
2103 29 : end = ptr + length;
2104 29 : ret = true;
2105 :
2106 29 : if (req_info_len == 0) {
2107 4 : return true;
2108 : }
2109 :
2110 : /*req_info sequence*/
2111 25 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2112 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2113 25 : if (!ret) {
2114 2 : return false;
2115 : }
2116 :
2117 : /*integer:version*/
2118 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
2119 23 : if (!ret) {
2120 0 : return false;
2121 : } else {
2122 23 : ptr += obj_len;
2123 : }
2124 :
2125 : /*sequence:subject name*/
2126 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2127 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2128 23 : if (!ret) {
2129 0 : return false;
2130 : } else {
2131 23 : ptr += obj_len;
2132 : }
2133 :
2134 : /*sequence:subject pkinfo*/
2135 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2136 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2137 23 : if (!ret) {
2138 0 : return false;
2139 : } else {
2140 23 : ptr += obj_len;
2141 : }
2142 :
2143 : /*[0]: attributes*/
2144 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2145 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
2146 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2147 : /*req_info format error, don't have attributes tag*/
2148 23 : if (!ret) {
2149 0 : return false;
2150 : }
2151 :
2152 : /*there is no attributes object*/
2153 23 : if (ptr == end) {
2154 0 : return true;
2155 : }
2156 :
2157 : /*there is some attributes object: 0,1,2 ...*/
2158 46 : while (ret)
2159 : {
2160 46 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2161 : LIBSPDM_CRYPTO_ASN1_SEQUENCE |
2162 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2163 46 : if (ret) {
2164 23 : ptr += obj_len;
2165 : } else {
2166 23 : break;
2167 : }
2168 : }
2169 :
2170 23 : if (ptr == end) {
2171 23 : return true;
2172 : } else {
2173 0 : return false;
2174 : }
2175 : }
2176 :
2177 : #endif
|