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 1037 : libspdm_get_asym_get_public_key_from_x509(uint32_t base_asym_algo)
191 : {
192 1037 : 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 937 : 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 937 : 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 1037 : 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 1037 : get_public_key_from_x509_function = libspdm_get_asym_get_public_key_from_x509(base_asym_algo);
277 1037 : if (get_public_key_from_x509_function == NULL) {
278 0 : return false;
279 : }
280 1037 : 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 781 : 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 781 : f0_size = 64;
335 781 : t0_size = 64;
336 :
337 781 : status = libspdm_x509_set_date_time("19700101000000Z", f0, &f0_size);
338 781 : if (!status) {
339 0 : return false;
340 : }
341 :
342 781 : status = libspdm_x509_set_date_time("99991231235959Z", t0, &t0_size);
343 781 : if (!status) {
344 0 : return false;
345 : }
346 :
347 : /* from >= f0*/
348 781 : ret = libspdm_x509_compare_date_time(from, f0);
349 781 : if (ret < 0) {
350 0 : return false;
351 : }
352 :
353 : /* to <= t0*/
354 781 : ret = libspdm_x509_compare_date_time(t0, to);
355 781 : if (ret < 0) {
356 0 : return false;
357 : }
358 :
359 781 : 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 1554 : static uint32_t libspdm_get_public_key_algo_OID_len(
370 : uint32_t base_asym_algo, uint32_t pqc_asym_algo)
371 : {
372 1554 : if (base_asym_algo != 0) {
373 1554 : 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 1424 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
411 : #if LIBSPDM_ECDSA_P256_SUPPORT
412 1424 : 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 777 : 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 777 : oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
563 777 : if (oid_len == 0) {
564 0 : return false;
565 : }
566 :
567 777 : if (base_asym_algo != 0) {
568 777 : 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 712 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256: {
607 : #if LIBSPDM_ECDSA_P256_SUPPORT
608 712 : uint8_t encry_algo_oid_ecc256[] = KEY_ENCRY_ALGO_ECC256_OID;
609 712 : libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc256, oid_len);
610 712 : 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 777 : 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 777 : length = (int32_t)cert_size;
850 777 : ptr = (uint8_t*)(size_t)cert;
851 777 : obj_len = 0;
852 777 : end = ptr + length;
853 777 : ret = true;
854 :
855 : /* TBSCertificate have 5 sequence before subjectPublicKeyInfo*/
856 777 : sequence_time = 5;
857 :
858 : /*all cert sequence*/
859 777 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
860 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
861 777 : if (!ret) {
862 0 : return false;
863 : }
864 :
865 : /*TBSCertificate sequence*/
866 777 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
867 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
868 777 : if (!ret) {
869 0 : return false;
870 : }
871 :
872 777 : end = ptr + obj_len;
873 : /*version*/
874 777 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
875 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
876 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
877 777 : if (!ret) {
878 0 : return false;
879 : }
880 :
881 777 : ptr += obj_len;
882 : /*serialNumber*/
883 777 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
884 777 : 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 4662 : for (index = 0; index < sequence_time; index++) {
896 3885 : ptr += obj_len;
897 3885 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
898 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
899 3885 : if (!ret) {
900 0 : return false;
901 : }
902 : }
903 :
904 777 : if (base_asym_algo != 0) {
905 777 : 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 714 : 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 714 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
938 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
939 714 : if (!ret) {
940 0 : return false;
941 : }
942 714 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
943 714 : if (!ret) {
944 0 : return false;
945 : }
946 :
947 : /*get ecc second oid*/
948 714 : ptr +=obj_len;
949 714 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
950 714 : if (!ret) {
951 0 : return false;
952 : }
953 :
954 714 : if (oid_size != obj_len) {
955 0 : return false;
956 : }
957 :
958 714 : libspdm_copy_mem(oid, oid_size, ptr, obj_len);
959 714 : 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 776 : 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 776 : 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 777 : 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 777 : libspdm_zero_mem(libspdm_public_key_crypt_algo_oid, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
1053 777 : libspdm_zero_mem(libspdm_public_key_crypt_algo_oid_other, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
1054 :
1055 : /*work around: skip the sm2*/
1056 777 : if (base_asym_algo == SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256) {
1057 0 : return true;
1058 : }
1059 :
1060 777 : oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
1061 777 : if (oid_len == 0) {
1062 0 : return false;
1063 : }
1064 : /*get public key encrypt algo OID from libspdm stored*/
1065 777 : 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 777 : if (!status) {
1069 0 : return status;
1070 : }
1071 :
1072 : /*get public key encrypt algo OID from cert*/
1073 777 : 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 777 : 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 775 : 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 760 : 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 760 : uint8_t basic_constraints_false_case[] = BASIC_CONSTRAINTS_CA_FALSE;
1106 :
1107 760 : len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1108 :
1109 760 : status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1110 : cert_basic_constraints, &len);
1111 760 : if (!status) {
1112 0 : return false;
1113 760 : } 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 1514 : if ((len == sizeof(basic_constraints_false_case)) &&
1123 756 : (libspdm_consttime_is_mem_equal(cert_basic_constraints,
1124 : basic_constraints_false_case,
1125 : sizeof(basic_constraints_false_case)))) {
1126 756 : return true;
1127 : }
1128 :
1129 2 : 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 15 : 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 15 : const uint8_t basic_constraints_false_case[] = BASIC_CONSTRAINTS_CA_FALSE;
1162 15 : const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_CA_TRUE;
1163 :
1164 15 : len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1165 :
1166 15 : status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1167 : cert_basic_constraints, &len);
1168 15 : if (!status) {
1169 0 : return false;
1170 15 : } else if (need_basic_constraints && (len == 0)) {
1171 0 : return false;
1172 : }
1173 :
1174 15 : 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 6 : if (need_basic_constraints || (len != 0)) {
1187 : /* basicConstraints may include the pathLen field. Therefore do not check sequence
1188 : * length. */
1189 6 : if (len >= sizeof(basic_constraints_true_case)) {
1190 4 : if (cert_basic_constraints[0] != basic_constraints_true_case[0]) {
1191 0 : return false;
1192 : }
1193 4 : if (libspdm_consttime_is_mem_equal(&cert_basic_constraints[2],
1194 : &basic_constraints_true_case[2],
1195 : sizeof(basic_constraints_true_case) - 2)) {
1196 4 : 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 781 : 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 781 : uint8_t eku_requester_auth_oid[] = SPDM_OID_DMTF_EKU_REQUESTER_AUTH;
1231 781 : uint8_t eku_responder_auth_oid[] = SPDM_OID_DMTF_EKU_RESPONDER_AUTH;
1232 :
1233 781 : eku_size = sizeof(eku);
1234 781 : status = libspdm_x509_get_extended_key_usage(cert, cert_size, eku, &eku_size);
1235 781 : if (!status) {
1236 0 : return false;
1237 781 : } else if (eku_size == 0) {
1238 : /* eku is not present in cert */
1239 0 : return true;
1240 : }
1241 :
1242 781 : ptr = eku;
1243 781 : obj_len = 0;
1244 781 : req_auth_oid_find_success = false;
1245 781 : rsp_auth_oid_find_success = false;
1246 :
1247 781 : status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len,
1248 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1249 781 : if (!status) {
1250 0 : return false;
1251 : }
1252 :
1253 3127 : while(ptr < eku + eku_size) {
1254 2346 : status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1255 2346 : if (!status) {
1256 0 : return false;
1257 : }
1258 :
1259 2354 : 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 2354 : 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 2346 : ptr += obj_len;
1271 : }
1272 :
1273 781 : if (ptr != eku + eku_size) {
1274 0 : return false;
1275 : }
1276 :
1277 781 : 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 761 : 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 779 : return true;
1292 : }
1293 :
1294 : /**
1295 : * Verify leaf cert spdm defined extension
1296 : *
1297 : * @param[in] cert Pointer to the DER-encoded certificate data.
1298 : * @param[in] cert_size The size of certificate data in bytes.
1299 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1300 : *
1301 : * @retval true verify pass
1302 : * @retval false verify fail,two case: 1. Unable to get get or validate extension data.
1303 : * 2. hardware_identity_oid is found in AliasCert model;
1304 : **/
1305 773 : static bool libspdm_verify_leaf_cert_spdm_extension(const uint8_t *cert, size_t cert_size,
1306 : bool is_requester_cert,
1307 : uint8_t cert_model)
1308 : {
1309 : bool status;
1310 : bool find_successful;
1311 : uint8_t spdm_extension[LIBSPDM_MAX_EXTENSION_LEN];
1312 : size_t len;
1313 : uint8_t *ptr;
1314 : uint8_t *temptr;
1315 : size_t obj_len;
1316 :
1317 : /* SPDM defined OID */
1318 773 : uint8_t oid_spdm_extension[] = SPDM_OID_DMTF_SPDM_EXTENSION;
1319 773 : uint8_t hardware_identity_oid[] = SPDM_OID_DMTF_HARDWARE_IDENTITY;
1320 :
1321 773 : len = LIBSPDM_MAX_EXTENSION_LEN;
1322 :
1323 773 : if (cert == NULL || cert_size == 0) {
1324 0 : return false;
1325 : }
1326 :
1327 773 : status = libspdm_x509_get_extension_data(cert, cert_size,
1328 : (const uint8_t *)oid_spdm_extension,
1329 : sizeof(oid_spdm_extension),
1330 : spdm_extension,
1331 : &len);
1332 773 : if (!status) {
1333 0 : return false;
1334 773 : } else if (len == 0) {
1335 13 : return true;
1336 : }
1337 :
1338 : /*find the spdm hardware identity OID*/
1339 760 : find_successful = false;
1340 760 : ptr = spdm_extension;
1341 760 : obj_len = 0;
1342 :
1343 : /*id-spdm-cert-oids ::= SEQUENCE SIZE (1..MAX) OF id-spdm-cert-oid*/
1344 760 : status = libspdm_asn1_get_tag(
1345 : &ptr, spdm_extension + len, &obj_len,
1346 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1347 760 : if (!status) {
1348 0 : return false;
1349 : }
1350 :
1351 1520 : while(ptr < spdm_extension + len) {
1352 760 : status = libspdm_asn1_get_tag(
1353 : &ptr, spdm_extension + len, &obj_len,
1354 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1355 760 : if (!status) {
1356 0 : return false;
1357 : }
1358 :
1359 760 : temptr = ptr + obj_len;
1360 760 : status = libspdm_asn1_get_tag(
1361 : &ptr, spdm_extension + len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1362 760 : if (!status) {
1363 0 : return false;
1364 : }
1365 1520 : if ((obj_len == sizeof(hardware_identity_oid)) &&
1366 760 : (libspdm_consttime_is_mem_equal(ptr, hardware_identity_oid,
1367 : sizeof(hardware_identity_oid)))) {
1368 760 : find_successful = true;
1369 : }
1370 760 : ptr = temptr;
1371 : }
1372 :
1373 760 : if (ptr != spdm_extension + len) {
1374 0 : return false;
1375 : }
1376 :
1377 : /* Responder does not determine Requester's certificate model */
1378 760 : if (!is_requester_cert) {
1379 745 : if ((find_successful) && (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1380 : /* Hardware_identity_OID is found in alias cert model */
1381 4 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1382 : "Hardware identity OID present in alias leaf certificate.\n"));
1383 4 : return false;
1384 : }
1385 : }
1386 :
1387 756 : return true;
1388 : }
1389 :
1390 : /**
1391 : * Certificate common Check for SPDM leaf cert when get_cert and set_cert.
1392 : *
1393 : * @param[in] cert Pointer to the DER-encoded certificate data.
1394 : * @param[in] cert_size The size of certificate data in bytes.
1395 : * @param[in] base_asym_algo SPDM base_asym_algo
1396 : * @param[in] is_requester_cert Is the function verifying requester or responder cert.
1397 : * @param[in] cert_model One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
1398 : * @param[in] set_cert Is the function verifying a set certificate operation.
1399 : *
1400 : * @retval true Success.
1401 : * @retval false Certificate is not valid.
1402 : **/
1403 783 : static bool libspdm_x509_common_certificate_check(
1404 : const uint8_t *cert, size_t cert_size,
1405 : uint32_t base_asym_algo, uint32_t pqc_asym_algo,
1406 : bool is_requester_cert, uint8_t cert_model,
1407 : bool set_cert)
1408 : {
1409 : uint8_t end_cert_from[64];
1410 : size_t end_cert_from_len;
1411 : uint8_t end_cert_to[64];
1412 : size_t end_cert_to_len;
1413 : size_t asn1_buffer_len;
1414 : bool status;
1415 : size_t cert_version;
1416 : void *context;
1417 : size_t signature_algo_oid_size;
1418 :
1419 783 : if (cert == NULL || cert_size == 0) {
1420 0 : return false;
1421 : }
1422 :
1423 783 : status = true;
1424 783 : context = NULL;
1425 783 : end_cert_from_len = 64;
1426 783 : end_cert_to_len = 64;
1427 :
1428 : /* 1. Version */
1429 783 : cert_version = 0;
1430 783 : status = libspdm_x509_get_version(cert, cert_size, &cert_version);
1431 783 : if (!status) {
1432 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Version field is not present.\n"));
1433 0 : goto cleanup;
1434 : }
1435 783 : if (cert_version != 2) {
1436 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1437 : "Expected Version to be equal to 2 but it is actually %zu.\n", cert_version));
1438 0 : status = false;
1439 0 : goto cleanup;
1440 : }
1441 :
1442 : /* 2. Serial Number */
1443 783 : asn1_buffer_len = 0;
1444 783 : status = libspdm_x509_get_serial_number(cert, cert_size, NULL, &asn1_buffer_len);
1445 783 : if (asn1_buffer_len == 0) {
1446 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Serial Number field is not present.\n"));
1447 0 : status = false;
1448 0 : goto cleanup;
1449 : }
1450 :
1451 : /* 3. Signature Algorithm */
1452 783 : signature_algo_oid_size = 0;
1453 783 : status = libspdm_x509_get_signature_algorithm(cert, cert_size, NULL, &signature_algo_oid_size);
1454 783 : if (status) {
1455 0 : if ((signature_algo_oid_size == 0) &&
1456 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1457 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1458 : "The mandatory Signature Algorithm field is not present.\n"));
1459 0 : status = false;
1460 0 : goto cleanup;
1461 : }
1462 : } else {
1463 783 : if (signature_algo_oid_size == 0) {
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 : }
1470 :
1471 : /* 4. Verify public key algorithm.
1472 : * If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
1473 : * check should be skipped as the Device Certificate CA's public key does not have to use
1474 : * the same algorithms as the connection's negotiated algorithms. */
1475 783 : if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1476 777 : status = libspdm_verify_cert_subject_public_key_info(cert, cert_size, base_asym_algo,
1477 : pqc_asym_algo);
1478 777 : if (!status) {
1479 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1480 : "Error in verifying the Public Key Algorithm field.\n"));
1481 2 : goto cleanup;
1482 : }
1483 : }
1484 :
1485 : /* 5. Issuer */
1486 781 : asn1_buffer_len = 0;
1487 781 : status = libspdm_x509_get_issuer_name(cert, cert_size, NULL, &asn1_buffer_len);
1488 781 : if (status) {
1489 0 : if ((asn1_buffer_len == 0) &&
1490 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1491 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Issuer field is not present.\n"));
1492 0 : status = false;
1493 0 : goto cleanup;
1494 : }
1495 : } else {
1496 781 : if (asn1_buffer_len == 0) {
1497 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Issuer field is not present.\n"));
1498 0 : status = false;
1499 0 : goto cleanup;
1500 : }
1501 : }
1502 :
1503 : /* 6. subject_name*/
1504 781 : asn1_buffer_len = 0;
1505 781 : status = libspdm_x509_get_subject_name(cert, cert_size, NULL, &asn1_buffer_len);
1506 781 : if (status) {
1507 0 : if ((asn1_buffer_len == 0) &&
1508 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1509 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Subject field is not present.\n"));
1510 0 : status = false;
1511 0 : goto cleanup;
1512 : }
1513 : } else {
1514 781 : if (asn1_buffer_len == 0) {
1515 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Subject field is not present.\n"));
1516 0 : status = false;
1517 0 : goto cleanup;
1518 : }
1519 : }
1520 :
1521 : /* 7. Validity */
1522 781 : status = libspdm_x509_get_validity(cert, cert_size, end_cert_from,
1523 : &end_cert_from_len, end_cert_to,
1524 : &end_cert_to_len);
1525 781 : if (status) {
1526 781 : if ((end_cert_from_len == 0) &&
1527 : (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
1528 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Validity field is not present.\n"));
1529 0 : status = false;
1530 0 : goto cleanup;
1531 : }
1532 : } else {
1533 0 : if (end_cert_from_len == 0) {
1534 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Validity field is not present.\n"));
1535 0 : status = false;
1536 0 : goto cleanup;
1537 : }
1538 : }
1539 :
1540 781 : if (end_cert_from_len != 0) {
1541 781 : status = libspdm_internal_x509_date_time_check(
1542 : end_cert_from, end_cert_from_len, end_cert_to, end_cert_to_len);
1543 781 : if (!status) {
1544 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1545 : "The certificate is outside its validity period.\n"));
1546 0 : goto cleanup;
1547 : }
1548 : }
1549 :
1550 : /* 8. Subject Public Key Info */
1551 781 : if (base_asym_algo != 0) {
1552 781 : status = libspdm_asym_get_public_key_from_x509(base_asym_algo, cert, cert_size, &context);
1553 : }
1554 781 : if (pqc_asym_algo != 0) {
1555 0 : status = libspdm_pqc_asym_get_public_key_from_x509(pqc_asym_algo, cert, cert_size, &context);
1556 : }
1557 781 : if (!status) {
1558 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1559 : "The mandatory Subject Public Key Info field is not present.\n"));
1560 0 : goto cleanup;
1561 : }
1562 :
1563 : /* 9. Key Usage
1564 : * If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
1565 : * check should be skipped as the SPDM specification does not specify the presence or absence
1566 : * of the Device Certificate CA's keyUsage field. */
1567 781 : if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
1568 775 : size_t value = 0;
1569 :
1570 775 : status = libspdm_x509_get_key_usage(cert, cert_size, &value);
1571 775 : if (!status) {
1572 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Key Usage field is not present.\n"));
1573 0 : goto cleanup;
1574 : } else {
1575 775 : if (value == 0) {
1576 0 : if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
1577 0 : status = false;
1578 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1579 : "The mandatory Key Usage field is not present.\n"));
1580 0 : goto cleanup;
1581 : }
1582 : } else {
1583 775 : if ((LIBSPDM_CRYPTO_X509_KU_DIGITAL_SIGNATURE & value) == 0) {
1584 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1585 : "The Mandatory digital signature bit in Key Usage field is not set.\n"));
1586 0 : status = false;
1587 0 : goto cleanup;
1588 : }
1589 : }
1590 : }
1591 : }
1592 :
1593 : /* 10. Extended Key Usage */
1594 781 : status = libspdm_verify_leaf_cert_spdm_eku(cert, cert_size, is_requester_cert);
1595 781 : if (!status) {
1596 2 : goto cleanup;
1597 : }
1598 :
1599 779 : if ((!set_cert) || (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT)) {
1600 : /* 11. verify spdm defined extension*/
1601 773 : status = libspdm_verify_leaf_cert_spdm_extension(cert, cert_size,
1602 : is_requester_cert, cert_model);
1603 773 : if (!status) {
1604 4 : goto cleanup;
1605 : }
1606 : }
1607 :
1608 775 : cleanup:
1609 783 : if (base_asym_algo != 0) {
1610 783 : libspdm_asym_free(base_asym_algo, context);
1611 : }
1612 783 : if (pqc_asym_algo != 0) {
1613 0 : libspdm_pqc_asym_free(pqc_asym_algo, context);
1614 : }
1615 783 : return status;
1616 : }
1617 :
1618 768 : bool libspdm_x509_certificate_check(
1619 : uint8_t spdm_version,
1620 : const uint8_t *cert, size_t cert_size,
1621 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1622 : bool is_requester, uint8_t cert_model)
1623 : {
1624 : bool status;
1625 : bool need_basic_constraints;
1626 :
1627 768 : status = libspdm_x509_common_certificate_check(
1628 : cert, cert_size, base_asym_algo, pqc_asym_algo, is_requester, cert_model, false);
1629 768 : if (!status) {
1630 8 : return false;
1631 : }
1632 :
1633 760 : if (spdm_version >= SPDM_MESSAGE_VERSION_13) {
1634 : /* verify basic constraints: the leaf cert always is ca:false in get_cert
1635 : * basic_constraints is mandatory in SPDM 1.3*/
1636 14 : need_basic_constraints = true;
1637 : } else {
1638 : /* verify basic constraints: the leaf cert always is ca:false in get_cert*/
1639 746 : need_basic_constraints = false;
1640 : }
1641 760 : status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, need_basic_constraints);
1642 760 : return status;
1643 : }
1644 :
1645 15 : bool libspdm_x509_set_cert_certificate_check(
1646 : uint8_t spdm_version,
1647 : const uint8_t *cert, size_t cert_size,
1648 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1649 : bool is_requester, uint8_t cert_model)
1650 : {
1651 : bool status;
1652 : bool need_basic_constraints;
1653 :
1654 15 : status = libspdm_x509_common_certificate_check(
1655 : cert, cert_size, base_asym_algo, pqc_asym_algo, is_requester, cert_model, true);
1656 15 : if (!status) {
1657 0 : return false;
1658 : }
1659 :
1660 : /* verify basic constraints: need check with is_device_cert_model*/
1661 15 : if (spdm_version >= SPDM_MESSAGE_VERSION_13) {
1662 6 : need_basic_constraints = true;
1663 : } else {
1664 9 : need_basic_constraints = false;
1665 : }
1666 15 : status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
1667 : cert, cert_size, cert_model, need_basic_constraints);
1668 :
1669 15 : return status;
1670 : }
1671 :
1672 59 : bool libspdm_is_root_certificate(const uint8_t *cert, size_t cert_size)
1673 : {
1674 : uint8_t issuer_name[LIBSPDM_MAX_NAME_SIZE];
1675 : size_t issuer_name_len;
1676 : uint8_t subject_name[LIBSPDM_MAX_NAME_SIZE];
1677 : size_t subject_name_len;
1678 : bool result;
1679 : uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
1680 : size_t cert_basic_constraints_len;
1681 59 : const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_CA_TRUE;
1682 :
1683 59 : if (cert == NULL || cert_size == 0) {
1684 0 : return false;
1685 : }
1686 :
1687 : /* 1. issuer_name*/
1688 59 : issuer_name_len = sizeof(issuer_name);
1689 59 : result = libspdm_x509_get_issuer_name(cert, cert_size, issuer_name, &issuer_name_len);
1690 59 : if (!result) {
1691 0 : return false;
1692 : }
1693 :
1694 : /* 2. subject_name*/
1695 59 : subject_name_len = sizeof(subject_name);
1696 59 : result = libspdm_x509_get_subject_name(cert, cert_size, subject_name, &subject_name_len);
1697 59 : if (!result) {
1698 0 : return false;
1699 : }
1700 :
1701 59 : if (issuer_name_len != subject_name_len) {
1702 3 : return false;
1703 : }
1704 56 : if (!libspdm_consttime_is_mem_equal(issuer_name, subject_name, issuer_name_len)) {
1705 0 : return false;
1706 : }
1707 :
1708 : /* 3. cA must be present in Basic Constraints */
1709 56 : cert_basic_constraints_len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
1710 56 : result = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
1711 : cert_basic_constraints,
1712 : &cert_basic_constraints_len);
1713 56 : if (!result) {
1714 0 : return false;
1715 : }
1716 :
1717 56 : if ((cert_basic_constraints_len < sizeof(basic_constraints_true_case) ||
1718 56 : (cert_basic_constraints[0] != basic_constraints_true_case[0]))) {
1719 0 : return false;
1720 : }
1721 56 : if (!libspdm_consttime_is_mem_equal(&cert_basic_constraints[2],
1722 : &basic_constraints_true_case[2],
1723 : sizeof(basic_constraints_true_case) - 2)) {
1724 0 : return false;
1725 : }
1726 :
1727 : /* 4. certificate must be self-signed */
1728 56 : result = libspdm_x509_verify_cert(cert, cert_size, cert, cert_size);
1729 56 : if (!result) {
1730 1 : return false;
1731 : }
1732 :
1733 55 : return true;
1734 : }
1735 :
1736 9 : bool libspdm_get_dmtf_subject_alt_name_from_bytes(
1737 : uint8_t *buffer, size_t len, char *name_buffer,
1738 : size_t *name_buffer_size, uint8_t *oid,
1739 : size_t *oid_size)
1740 : {
1741 : uint8_t *ptr;
1742 : int32_t length;
1743 : size_t obj_len;
1744 : int32_t ret;
1745 :
1746 : /*copy mem variable*/
1747 : volatile uint8_t* dst;
1748 : const volatile uint8_t* src;
1749 : size_t dst_len;
1750 : size_t src_len;
1751 :
1752 9 : length = (int32_t)len;
1753 9 : ptr = buffer;
1754 9 : obj_len = 0;
1755 :
1756 : /* Sequence*/
1757 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + length, &obj_len,
1758 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1759 9 : if (!ret) {
1760 0 : return false;
1761 : }
1762 :
1763 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len,
1764 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1765 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1766 :
1767 9 : ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1768 9 : if (!ret) {
1769 0 : return false;
1770 : }
1771 : /* CopyData to OID*/
1772 9 : if (*oid_size < (size_t)obj_len) {
1773 0 : *oid_size = (size_t)obj_len;
1774 0 : return false;
1775 : }
1776 9 : if (oid != NULL) {
1777 9 : libspdm_copy_mem(oid, *oid_size, ptr, obj_len);
1778 9 : *oid_size = obj_len;
1779 : }
1780 :
1781 : /* Move to next element*/
1782 9 : ptr += obj_len;
1783 :
1784 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1785 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1786 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1787 9 : ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
1788 : LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
1789 9 : if (!ret) {
1790 0 : return false;
1791 : }
1792 :
1793 9 : if (*name_buffer_size < (size_t)obj_len + 1) {
1794 0 : *name_buffer_size = (size_t)obj_len + 1;
1795 0 : return false;
1796 : }
1797 :
1798 : /* the src and dst address are overlap,
1799 : * When the function is called by libspdm_get_dmtf_subject_alt_name.
1800 : * libspdm_copy_mem can not be used. */
1801 9 : if ((name_buffer != NULL) && (ptr != NULL)) {
1802 9 : dst = (volatile uint8_t*) name_buffer;
1803 9 : src = (const volatile uint8_t*) ptr;
1804 9 : dst_len = *name_buffer_size;
1805 9 : src_len = obj_len;
1806 :
1807 : /* Check for case where "dst_len" may be invalid. Do not zero "dst" in this case. */
1808 9 : if (dst_len > (SIZE_MAX >> 1)) {
1809 0 : LIBSPDM_ASSERT(0);
1810 0 : return false;
1811 : }
1812 :
1813 : /* Guard against invalid lengths. Zero "dst" in these cases. */
1814 9 : if (src_len > dst_len ||
1815 9 : src_len > (SIZE_MAX >> 1)) {
1816 0 : libspdm_zero_mem(name_buffer, dst_len);
1817 0 : LIBSPDM_ASSERT(0);
1818 0 : return false;
1819 : }
1820 :
1821 207 : while (src_len-- != 0) {
1822 198 : *(dst++) = *(src++);
1823 : }
1824 :
1825 : /*encode name buffer to string*/
1826 9 : *name_buffer_size = obj_len + 1;
1827 9 : name_buffer[obj_len] = 0;
1828 9 : return true;
1829 : }
1830 :
1831 0 : return false;
1832 : }
1833 :
1834 6 : bool libspdm_get_dmtf_subject_alt_name(const uint8_t *cert, size_t cert_size,
1835 : char *name_buffer,
1836 : size_t *name_buffer_size,
1837 : uint8_t *oid, size_t *oid_size)
1838 : {
1839 : bool status;
1840 : size_t extension_data_size;
1841 6 : uint8_t oid_subject_alt_name[] = { 0x55, 0x1D, 0x11 };
1842 :
1843 6 : extension_data_size = 0;
1844 6 : status = libspdm_x509_get_extension_data(cert, cert_size,
1845 : oid_subject_alt_name,
1846 : sizeof(oid_subject_alt_name), NULL,
1847 : &extension_data_size);
1848 6 : if (status || (extension_data_size == 0)) {
1849 0 : *name_buffer_size = 0;
1850 0 : return false;
1851 : }
1852 6 : if (extension_data_size > *name_buffer_size) {
1853 0 : *name_buffer_size = extension_data_size;
1854 0 : return false;
1855 : }
1856 : status =
1857 6 : libspdm_x509_get_extension_data(cert, cert_size,
1858 : oid_subject_alt_name,
1859 : sizeof(oid_subject_alt_name),
1860 : (uint8_t *)name_buffer, name_buffer_size);
1861 6 : if (!status) {
1862 0 : return status;
1863 : }
1864 :
1865 6 : return libspdm_get_dmtf_subject_alt_name_from_bytes(
1866 : (uint8_t *)name_buffer, *name_buffer_size, name_buffer,
1867 : name_buffer_size, oid, oid_size);
1868 : }
1869 :
1870 707 : bool libspdm_verify_cert_chain_data(
1871 : uint8_t spdm_version,
1872 : uint8_t *cert_chain_data, size_t cert_chain_data_size,
1873 : uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
1874 : bool is_requester_cert, uint8_t cert_model)
1875 : {
1876 : const uint8_t *root_cert_buffer;
1877 : size_t root_cert_buffer_size;
1878 : const uint8_t *leaf_cert_buffer;
1879 : size_t leaf_cert_buffer_size;
1880 :
1881 707 : if (cert_chain_data_size >
1882 : SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
1883 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1884 : "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
1885 0 : return false;
1886 : }
1887 :
1888 707 : if (!libspdm_x509_get_cert_from_cert_chain(
1889 : cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
1890 : &root_cert_buffer_size)) {
1891 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1892 : "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
1893 0 : return false;
1894 : }
1895 :
1896 707 : if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
1897 : cert_chain_data, cert_chain_data_size)) {
1898 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1899 : "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
1900 2 : return false;
1901 : }
1902 :
1903 705 : if (!libspdm_x509_get_cert_from_cert_chain(
1904 : cert_chain_data, cert_chain_data_size, -1,
1905 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
1906 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1907 : "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
1908 0 : return false;
1909 : }
1910 :
1911 705 : if (!libspdm_x509_certificate_check(spdm_version,
1912 : leaf_cert_buffer, leaf_cert_buffer_size,
1913 : base_asym_algo, pqc_asym_algo, base_hash_algo,
1914 : is_requester_cert, cert_model)) {
1915 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1916 : "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
1917 1 : return false;
1918 : }
1919 :
1920 704 : return true;
1921 : }
1922 :
1923 40 : bool libspdm_verify_certificate_chain_buffer(
1924 : uint8_t spdm_version,
1925 : uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
1926 : const void *cert_chain_buffer,
1927 : size_t cert_chain_buffer_size,
1928 : bool is_requester_cert, uint8_t cert_model)
1929 : {
1930 : const uint8_t *cert_chain_data;
1931 : size_t cert_chain_data_size;
1932 : const uint8_t *first_cert_buffer;
1933 : size_t first_cert_buffer_size;
1934 : size_t hash_size;
1935 : uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
1936 : const uint8_t *leaf_cert_buffer;
1937 : size_t leaf_cert_buffer_size;
1938 : bool result;
1939 : const spdm_cert_chain_t *cert_chain_header;
1940 :
1941 40 : hash_size = libspdm_get_hash_size(base_hash_algo);
1942 :
1943 40 : if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
1944 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1945 : "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
1946 0 : return false;
1947 : }
1948 :
1949 40 : cert_chain_header = cert_chain_buffer;
1950 40 : if (cert_chain_header->length != cert_chain_buffer_size) {
1951 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1952 : "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
1953 2 : return false;
1954 : }
1955 :
1956 38 : cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
1957 38 : cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
1958 38 : if (!libspdm_x509_get_cert_from_cert_chain(
1959 : cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
1960 : &first_cert_buffer_size)) {
1961 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1962 : "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
1963 0 : return false;
1964 : }
1965 :
1966 38 : if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
1967 35 : result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
1968 : calc_root_cert_hash);
1969 35 : if (!result) {
1970 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1971 : "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
1972 0 : return false;
1973 : }
1974 35 : if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
1975 : sizeof(spdm_cert_chain_t),
1976 : calc_root_cert_hash, hash_size)) {
1977 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1978 : "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
1979 0 : return false;
1980 : }
1981 35 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1982 : "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
1983 : }
1984 :
1985 : /*If the number of certificates in the certificate chain is more than 1,
1986 : * other certificates need to be verified.*/
1987 38 : if (cert_chain_data_size > first_cert_buffer_size) {
1988 38 : if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
1989 : cert_chain_data + first_cert_buffer_size,
1990 : cert_chain_data_size - first_cert_buffer_size)) {
1991 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
1992 : "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
1993 3 : return false;
1994 : }
1995 : }
1996 :
1997 35 : if (!libspdm_x509_get_cert_from_cert_chain(
1998 : cert_chain_data, cert_chain_data_size, -1,
1999 : &leaf_cert_buffer, &leaf_cert_buffer_size)) {
2000 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2001 : "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
2002 0 : return false;
2003 : }
2004 :
2005 35 : if (!libspdm_x509_certificate_check(spdm_version,
2006 : leaf_cert_buffer, leaf_cert_buffer_size,
2007 : base_asym_algo, pqc_asym_algo, base_hash_algo,
2008 : is_requester_cert, cert_model)) {
2009 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2010 : "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
2011 3 : return false;
2012 : }
2013 :
2014 32 : return true;
2015 : }
2016 :
2017 256 : bool libspdm_get_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2018 : uint32_t base_asym_alg,
2019 : uint8_t *cert_chain_data,
2020 : size_t cert_chain_data_size,
2021 : void **public_key)
2022 : {
2023 : size_t hash_size;
2024 : const uint8_t *cert_buffer;
2025 : size_t cert_buffer_size;
2026 : bool result;
2027 :
2028 256 : hash_size = libspdm_get_hash_size(base_hash_algo);
2029 :
2030 256 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2031 256 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2032 :
2033 : /* Get leaf cert from cert chain */
2034 256 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2035 : cert_chain_data_size, -1,
2036 : &cert_buffer, &cert_buffer_size);
2037 256 : if (!result) {
2038 0 : return false;
2039 : }
2040 :
2041 256 : result = libspdm_asym_get_public_key_from_x509(
2042 : base_asym_alg,
2043 : cert_buffer, cert_buffer_size, public_key);
2044 256 : if (!result) {
2045 4 : return false;
2046 : }
2047 :
2048 252 : return true;
2049 : }
2050 :
2051 0 : bool libspdm_get_pqc_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
2052 : uint32_t pqc_asym_alg,
2053 : uint8_t *cert_chain_data,
2054 : size_t cert_chain_data_size,
2055 : void **public_key)
2056 : {
2057 : size_t hash_size;
2058 : const uint8_t *cert_buffer;
2059 : size_t cert_buffer_size;
2060 : bool result;
2061 :
2062 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
2063 :
2064 0 : cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
2065 0 : cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
2066 :
2067 : /* Get leaf cert from cert chain */
2068 0 : result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
2069 : cert_chain_data_size, -1,
2070 : &cert_buffer, &cert_buffer_size);
2071 0 : if (!result) {
2072 0 : return false;
2073 : }
2074 :
2075 0 : result = libspdm_pqc_asym_get_public_key_from_x509(
2076 : pqc_asym_alg,
2077 : cert_buffer, cert_buffer_size, public_key);
2078 0 : if (!result) {
2079 0 : return false;
2080 : }
2081 :
2082 0 : return true;
2083 : }
2084 :
2085 29 : bool libspdm_verify_req_info(uint8_t *req_info, uint16_t req_info_len)
2086 : {
2087 : bool ret;
2088 : uint8_t *ptr;
2089 : int32_t length;
2090 : size_t obj_len;
2091 : uint8_t *end;
2092 :
2093 29 : length = (int32_t)req_info_len;
2094 29 : ptr = req_info;
2095 29 : obj_len = 0;
2096 29 : end = ptr + length;
2097 29 : ret = true;
2098 :
2099 29 : if (req_info_len == 0) {
2100 4 : return true;
2101 : }
2102 :
2103 : /*req_info sequence*/
2104 25 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2105 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2106 25 : if (!ret) {
2107 2 : return false;
2108 : }
2109 :
2110 : /*integer:version*/
2111 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
2112 23 : if (!ret) {
2113 0 : return false;
2114 : } else {
2115 23 : ptr += obj_len;
2116 : }
2117 :
2118 : /*sequence:subject name*/
2119 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2120 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2121 23 : if (!ret) {
2122 0 : return false;
2123 : } else {
2124 23 : ptr += obj_len;
2125 : }
2126 :
2127 : /*sequence:subject pkinfo*/
2128 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2129 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2130 23 : if (!ret) {
2131 0 : return false;
2132 : } else {
2133 23 : ptr += obj_len;
2134 : }
2135 :
2136 : /*[0]: attributes*/
2137 23 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2138 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
2139 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2140 : /*req_info format error, don't have attributes tag*/
2141 23 : if (!ret) {
2142 0 : return false;
2143 : }
2144 :
2145 : /*there is no attributes object*/
2146 23 : if (ptr == end) {
2147 0 : return true;
2148 : }
2149 :
2150 : /*there is some attributes object: 0,1,2 ...*/
2151 46 : while (ret)
2152 : {
2153 46 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
2154 : LIBSPDM_CRYPTO_ASN1_SEQUENCE |
2155 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
2156 46 : if (ret) {
2157 23 : ptr += obj_len;
2158 : } else {
2159 23 : break;
2160 : }
2161 : }
2162 :
2163 23 : if (ptr == end) {
2164 23 : return true;
2165 : } else {
2166 0 : return false;
2167 : }
2168 : }
2169 :
2170 : #endif
|