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