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