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