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