Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2025 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 : /** @file
8 : * X.509 Certificate Handler Wrapper Implementation.
9 : **/
10 :
11 : #include <stdarg.h>
12 : #include "internal_crypt_lib.h"
13 : #include <mbedtls/x509.h>
14 : #include <mbedtls/x509_crt.h>
15 : #include <mbedtls/rsa.h>
16 : #include <mbedtls/ecp.h>
17 : #include <mbedtls/ecdh.h>
18 : #include <mbedtls/ecdsa.h>
19 : #include <mbedtls/x509_csr.h>
20 : #include <mbedtls/entropy.h>
21 : #include <mbedtls/ctr_drbg.h>
22 : #include <mbedtls/oid.h>
23 : #include <mbedtls/bignum.h>
24 : #include <string.h>
25 :
26 : #if LIBSPDM_CERT_PARSE_SUPPORT
27 :
28 : /* OID*/
29 :
30 : #define OID_COMMON_NAME { 0x55, 0x04, 0x03 }
31 : #define OID_ORGANIZATION_NAME { 0x55, 0x04, 0x0A }
32 : #define OID_EXT_KEY_USAGE { 0x55, 0x1D, 0x25 }
33 : #define OID_BASIC_CONSTRAINTS { 0x55, 0x1D, 0x13 }
34 :
35 : static const uint8_t m_libspdm_oid_common_name[] = OID_COMMON_NAME;
36 : static const uint8_t m_libspdm_oid_organization_name[] = OID_ORGANIZATION_NAME;
37 : static const uint8_t m_libspdm_oid_ext_key_usage[] = OID_EXT_KEY_USAGE;
38 : static const uint8_t m_libspdm_oid_basic_constraints[] = OID_BASIC_CONSTRAINTS;
39 :
40 : typedef struct {
41 : const char *name; /* String representation of AttributeType, e.g.
42 : * "CN" or "emailAddress". */
43 : size_t name_len; /* Length of 'name', without trailing 0 byte. */
44 : const char *oid; /* String representation of OID of AttributeType,
45 : * as per RFC 5280, Appendix A.1. */
46 : size_t oid_len;
47 : int default_tag; /* The default character encoding used for the
48 : * given attribute type, e.g.
49 : * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */
50 : } libspdm_x509_subject_descriptor_t;
51 :
52 : #define LIBSPDM_ADD_STRLEN( s ) s, sizeof( s ) - 1
53 :
54 : /*
55 : * EC public keys:
56 : * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2
57 : * algorithm AlgorithmIdentifier, 1 + 1 (sequence)
58 : * + 1 + 1 + 7 (ec oid)
59 : * + 1 + 1 + 9 (namedCurve oid)
60 : * subjectPublicKey BIT STRING 1 + 2 + 1 [1]
61 : * + 1 (point format) [1]
62 : * + 2 * ECP_MAX (coords) [1]
63 : * }
64 : */
65 : #define LIBSPDM_ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
66 :
67 : /*
68 : * RSA public keys:
69 : * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3
70 : * algorithm AlgorithmIdentifier, 1 + 1 (sequence)
71 : * + 1 + 1 + 9 (rsa oid)
72 : * + 1 + 1 (params null)
73 : * subjectPublicKey BIT STRING } 1 + 3 + (1 + below)
74 : * RSAPublicKey ::= SEQUENCE { 1 + 3
75 : * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1
76 : * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1
77 : * }
78 : */
79 : #define LIBSPDM_RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
80 :
81 : #define LIBSPDM_MAX_PUBKEY_DER_BUFFER_SIZE (LIBSPDM_RSA_PUB_DER_MAX_BYTES > \
82 : LIBSPDM_ECP_PUB_DER_MAX_BYTES ? \
83 : LIBSPDM_RSA_PUB_DER_MAX_BYTES : \
84 : LIBSPDM_ECP_PUB_DER_MAX_BYTES )
85 :
86 : #define LIBSPDM_MAX_SUBJECT_BUFFER_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE
87 :
88 : #ifdef LIBSPDM_MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
89 : int wrapper_mbedtls_x509_crt_ext_cb(void *p_ctx,
90 : mbedtls_x509_crt const *crt,
91 : mbedtls_x509_buf const *oid,
92 : int critical,
93 : const unsigned char *p,
94 : const unsigned char *end)
95 : {
96 : return 0;
97 : }
98 : #endif
99 :
100 13820 : int wrapper_mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain,
101 : const unsigned char *buf,
102 : size_t buflen)
103 : {
104 : #ifdef LIBSPDM_MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
105 : return mbedtls_x509_crt_parse_der_with_ext_cb(chain, buf, buflen, 1, wrapper_mbedtls_x509_crt_ext_cb, NULL);
106 : #else
107 13820 : return mbedtls_x509_crt_parse_der(chain, buf, buflen);
108 : #endif
109 : }
110 :
111 : /**
112 : * Construct a X509 object from DER-encoded certificate data.
113 : *
114 : * If cert is NULL, then return false.
115 : * If single_x509_cert is NULL, then return false.
116 : *
117 : * @param[in] cert Pointer to the DER-encoded certificate data.
118 : * @param[in] cert_size The size of certificate data in bytes.
119 : * @param[out] single_x509_cert The generated X509 object.
120 : *
121 : * @retval true The X509 object generation succeeded.
122 : * @retval false The operation failed.
123 : *
124 : **/
125 6 : bool libspdm_x509_construct_certificate(const uint8_t *cert, size_t cert_size,
126 : uint8_t **single_x509_cert)
127 : {
128 : mbedtls_x509_crt *mbedtls_cert;
129 : int ret;
130 :
131 6 : if (cert == NULL || single_x509_cert == NULL || cert_size == 0) {
132 0 : return false;
133 : }
134 :
135 6 : mbedtls_cert = allocate_pool(sizeof(mbedtls_x509_crt));
136 6 : if (mbedtls_cert == NULL) {
137 0 : return false;
138 : }
139 :
140 6 : mbedtls_x509_crt_init(mbedtls_cert);
141 :
142 6 : *single_x509_cert = (uint8_t *)(void *)mbedtls_cert;
143 6 : ret = wrapper_mbedtls_x509_crt_parse_der(mbedtls_cert, cert, cert_size);
144 :
145 6 : if (ret != 0){
146 0 : libspdm_x509_free(mbedtls_cert);
147 0 : *single_x509_cert = NULL;
148 : }
149 :
150 6 : return ret == 0;
151 : }
152 :
153 0 : static bool libspdm_x509_construct_certificate_stack_v(uint8_t **x509_stack,
154 : va_list args)
155 : {
156 : uint8_t *cert;
157 : size_t cert_size;
158 : int ret;
159 :
160 0 : if (x509_stack == NULL) {
161 0 : return false;
162 : }
163 :
164 0 : ret = 0;
165 0 : mbedtls_x509_crt *crt = (mbedtls_x509_crt *)*x509_stack;
166 0 : if (crt == NULL) {
167 0 : crt = allocate_pool(sizeof(mbedtls_x509_crt));
168 0 : if (crt == NULL) {
169 0 : return false;
170 : }
171 0 : mbedtls_x509_crt_init(crt);
172 0 : *x509_stack = (uint8_t *)crt;
173 : }
174 :
175 : for (;;) {
176 :
177 : /* If cert is NULL, then it is the end of the list.*/
178 :
179 0 : cert = va_arg(args, uint8_t *);
180 0 : if (cert == NULL) {
181 0 : break;
182 : }
183 :
184 0 : cert_size = va_arg(args, size_t);
185 0 : if (cert_size == 0) {
186 0 : break;
187 : }
188 :
189 0 : ret = wrapper_mbedtls_x509_crt_parse_der(crt, cert, cert_size);
190 :
191 0 : if (ret != 0) {
192 0 : break;
193 : }
194 : }
195 0 : return ret == 0;
196 : }
197 :
198 : /**
199 : * Construct a X509 stack object from a list of DER-encoded certificate data.
200 : *
201 : * If x509_stack is NULL, then return false.
202 : *
203 : * @param[in, out] x509_stack On input, pointer to an existing or NULL X509 stack object.
204 : * On output, pointer to the X509 stack object with new
205 : * inserted X509 certificate.
206 : * @param ... A list of DER-encoded single certificate data followed
207 : * by certificate size. A NULL terminates the list. The
208 : * pairs are the arguments to libspdm_x509_construct_certificate().
209 : *
210 : * @retval true The X509 stack construction succeeded.
211 : * @retval false The construction operation failed.
212 : *
213 : **/
214 0 : bool libspdm_x509_construct_certificate_stack(uint8_t **x509_stack, ...)
215 : {
216 : va_list args;
217 : bool result;
218 :
219 0 : va_start(args, x509_stack);
220 0 : result = libspdm_x509_construct_certificate_stack_v(x509_stack, args);
221 0 : va_end(args);
222 0 : return result;
223 : }
224 :
225 : /**
226 : * Release the specified X509 object.
227 : *
228 : * If x509_cert is NULL, then return early.
229 : *
230 : * @param[in] x509_cert Pointer to the X509 object to be released.
231 : *
232 : **/
233 6 : void libspdm_x509_free(void *x509_cert)
234 : {
235 6 : if (x509_cert == NULL) {
236 0 : return;
237 : }
238 :
239 6 : mbedtls_x509_crt_free(x509_cert);
240 6 : free_pool(x509_cert);
241 : }
242 :
243 : /**
244 : * Release the specified X509 stack object.
245 : *
246 : * If x509_stack is NULL, then return early.
247 : *
248 : * @param[in] x509_stack Pointer to the X509 stack object to be released.
249 : *
250 : **/
251 0 : void libspdm_x509_stack_free(void *x509_stack)
252 : {
253 0 : if (x509_stack == NULL) {
254 0 : return;
255 : }
256 :
257 0 : mbedtls_x509_crt_free(x509_stack);
258 : }
259 :
260 : /**
261 : * Retrieve the tag and length of the tag.
262 : *
263 : * @param ptr The position in the ASN.1 data
264 : * @param end end of data
265 : * @param length The variable that will receive the length
266 : * @param tag The expected tag
267 : *
268 : * @retval true Get tag successful
269 : * @retval false Failed to get tag or tag not match
270 : **/
271 15026 : bool libspdm_asn1_get_tag(uint8_t **ptr, const uint8_t *end, size_t *length,
272 : uint32_t tag)
273 : {
274 15026 : if (mbedtls_asn1_get_tag(ptr, end, length, (int32_t)tag) == 0) {
275 14997 : return true;
276 : } else {
277 29 : return false;
278 : }
279 : }
280 :
281 : /**
282 : * Retrieve the subject bytes from one X.509 certificate.
283 : *
284 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
285 : * @param[in] cert_size size of the X509 certificate in bytes.
286 : * @param[out] cert_subject Pointer to the retrieved certificate subject bytes.
287 : * @param[in, out] subject_size The size in bytes of the cert_subject buffer on input,
288 : * and the size of buffer returned cert_subject on output.
289 : *
290 : * If cert is NULL, then return false.
291 : * If subject_size is NULL, then return false.
292 : *
293 : * @retval true If the subject_size is not equal 0. The certificate subject retrieved successfully.
294 : * @retval true If the subject_size is equal 0. The certificate parse successful. But the cert doesn't have subject.
295 : * @retval false If the subject_size is not equal 0. The certificate subject retrieved successfully.But the subject_size is too small for the result.
296 : * @retval false If the subject_size is equal 0. Invalid certificate.
297 : **/
298 841 : bool libspdm_x509_get_subject_name(const uint8_t *cert, size_t cert_size,
299 : uint8_t *cert_subject,
300 : size_t *subject_size)
301 : {
302 : mbedtls_x509_crt crt;
303 : int ret;
304 : bool status;
305 :
306 : /* Check input parameters.*/
307 841 : if (cert == NULL || cert == 0 || subject_size == NULL) {
308 0 : if (subject_size != NULL) {
309 0 : *subject_size = 0;
310 : }
311 0 : return false;
312 : }
313 :
314 841 : status = false;
315 :
316 841 : mbedtls_x509_crt_init(&crt);
317 :
318 841 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
319 :
320 841 : if (ret == 0) {
321 841 : if (*subject_size < crt.subject_raw.len) {
322 782 : *subject_size = crt.subject_raw.len;
323 782 : status = false;
324 782 : goto cleanup;
325 : }
326 59 : if (cert_subject != NULL) {
327 59 : libspdm_copy_mem(cert_subject, *subject_size,
328 59 : crt.subject_raw.p, crt.subject_raw.len);
329 : }
330 59 : *subject_size = crt.subject_raw.len;
331 59 : status = true;
332 : } else {
333 0 : *subject_size = 0;
334 : }
335 :
336 841 : cleanup:
337 841 : mbedtls_x509_crt_free(&crt);
338 :
339 841 : return status;
340 : }
341 :
342 : bool
343 0 : libspdm_internal_x509_get_nid_name(mbedtls_x509_name *name, const uint8_t *oid,
344 : size_t oid_size, char *common_name,
345 : size_t *common_name_size)
346 : {
347 : const mbedtls_asn1_named_data *data;
348 :
349 0 : data = mbedtls_asn1_find_named_data(name, (const char *)oid, oid_size);
350 0 : if (data != NULL) {
351 0 : if (*common_name_size <= data->val.len) {
352 0 : *common_name_size = data->val.len + 1;
353 0 : return false;
354 : }
355 0 : if (common_name != NULL) {
356 0 : libspdm_copy_mem(common_name, *common_name_size, data->val.p, data->val.len);
357 0 : common_name[data->val.len] = '\0';
358 : }
359 0 : *common_name_size = data->val.len + 1;
360 0 : return true;
361 : } else {
362 0 : *common_name_size = 0;
363 0 : return false;
364 : }
365 : }
366 :
367 : bool
368 0 : libspdm_internal_x509_get_subject_nid_name(const uint8_t *cert, size_t cert_size,
369 : const uint8_t *oid, size_t oid_size,
370 : char *common_name,
371 : size_t *common_name_size)
372 : {
373 : mbedtls_x509_crt crt;
374 : int ret;
375 : mbedtls_x509_name *name;
376 : bool status;
377 :
378 0 : if (cert == NULL) {
379 0 : return false;
380 : }
381 :
382 0 : status = false;
383 :
384 0 : mbedtls_x509_crt_init(&crt);
385 :
386 0 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
387 :
388 0 : if (ret == 0) {
389 0 : name = &(crt.subject);
390 0 : status = libspdm_internal_x509_get_nid_name(
391 : name, oid, oid_size, common_name, common_name_size);
392 : }
393 :
394 0 : mbedtls_x509_crt_free(&crt);
395 :
396 0 : return status;
397 : }
398 :
399 : bool
400 0 : libspdm_internal_x509_get_issuer_nid_name(const uint8_t *cert, size_t cert_size,
401 : const uint8_t *oid, size_t oid_size,
402 : char *common_name,
403 : size_t *common_name_size)
404 : {
405 : mbedtls_x509_crt crt;
406 : int ret;
407 : mbedtls_x509_name *name;
408 : bool status;
409 :
410 0 : if (cert == NULL) {
411 0 : return false;
412 : }
413 :
414 0 : status = false;
415 :
416 0 : mbedtls_x509_crt_init(&crt);
417 :
418 0 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
419 :
420 0 : if (ret == 0) {
421 0 : name = &(crt.issuer);
422 0 : status = libspdm_internal_x509_get_nid_name(
423 : name, oid, oid_size, common_name, common_name_size);
424 : }
425 :
426 0 : mbedtls_x509_crt_free(&crt);
427 :
428 0 : return status;
429 : }
430 :
431 : /**
432 : * Retrieve the common name (CN) string from one X.509 certificate.
433 : *
434 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
435 : * @param[in] cert_size size of the X509 certificate in bytes.
436 : * @param[out] common_name buffer to contain the retrieved certificate common
437 : * name string. At most common_name_size bytes will be
438 : * written and the string will be null terminated. May be
439 : * NULL in order to determine the size buffer needed.
440 : * @param[in,out] common_name_size The size in bytes of the common_name buffer on input,
441 : * and the size of buffer returned common_name on output.
442 : * If common_name is NULL then the amount of space needed
443 : * in buffer (including the final null) is returned.
444 : *
445 : * @retval RETURN_SUCCESS The certificate common_name retrieved successfully.
446 : * @retval RETURN_INVALID_PARAMETER If cert is NULL.
447 : * If common_name_size is NULL.
448 : * If common_name is not NULL and *common_name_size is 0.
449 : * If Certificate is invalid.
450 : * @retval RETURN_NOT_FOUND If no common_name entry exists.
451 : * @retval RETURN_BUFFER_TOO_SMALL If the common_name is NULL. The required buffer size
452 : * (including the final null) is returned in the
453 : * common_name_size parameter.
454 : * @retval RETURN_UNSUPPORTED The operation is not supported.
455 : *
456 : **/
457 0 : bool libspdm_x509_get_common_name(const uint8_t *cert, size_t cert_size,
458 : char *common_name,
459 : size_t *common_name_size)
460 : {
461 0 : return libspdm_internal_x509_get_subject_nid_name(
462 : cert, cert_size, (const uint8_t *)m_libspdm_oid_common_name,
463 : sizeof(m_libspdm_oid_common_name), common_name, common_name_size);
464 : }
465 :
466 : /**
467 : * Retrieve the organization name (O) string from one X.509 certificate.
468 : *
469 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
470 : * @param[in] cert_size size of the X509 certificate in bytes.
471 : * @param[out] name_buffer buffer to contain the retrieved certificate organization
472 : * name string. At most name_buffer_size bytes will be
473 : * written and the string will be null terminated. May be
474 : * NULL in order to determine the size buffer needed.
475 : * @param[in,out] name_buffer_size The size in bytes of the name buffer on input,
476 : * and the size of buffer returned name on output.
477 : * If name_buffer is NULL then the amount of space needed
478 : * in buffer (including the final null) is returned.
479 : *
480 : * @retval RETURN_SUCCESS The certificate Organization name retrieved successfully.
481 : * @retval RETURN_INVALID_PARAMETER If cert is NULL.
482 : * If name_buffer_size is NULL.
483 : * If name_buffer is not NULL and *common_name_size is 0.
484 : * If Certificate is invalid.
485 : * @retval RETURN_NOT_FOUND If no Organization name entry exists.
486 : * @retval RETURN_BUFFER_TOO_SMALL If the name_buffer is NULL. The required buffer size
487 : * (including the final null) is returned in the
488 : * common_name_size parameter.
489 : * @retval RETURN_UNSUPPORTED The operation is not supported.
490 : *
491 : **/
492 : bool
493 0 : libspdm_x509_get_organization_name(const uint8_t *cert, size_t cert_size,
494 : char *name_buffer,
495 : size_t *name_buffer_size)
496 : {
497 0 : return libspdm_internal_x509_get_subject_nid_name(
498 : cert, cert_size, m_libspdm_oid_organization_name,
499 : sizeof(m_libspdm_oid_organization_name), name_buffer, name_buffer_size);
500 : }
501 :
502 : #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
503 : /**
504 : * Retrieve the RSA public key from one DER-encoded X509 certificate.
505 : *
506 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
507 : * @param[in] cert_size size of the X509 certificate in bytes.
508 : * @param[out] rsa_context Pointer to newly generated RSA context which contain the retrieved
509 : * RSA public key component. Use libspdm_rsa_free() function to free the
510 : * resource.
511 : *
512 : * If cert is NULL, then return false.
513 : * If rsa_context is NULL, then return false.
514 : *
515 : * @retval true RSA public key was retrieved successfully.
516 : * @retval false Fail to retrieve RSA public key from X509 certificate.
517 : *
518 : **/
519 103 : bool libspdm_rsa_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
520 : void **rsa_context)
521 : {
522 : mbedtls_x509_crt crt;
523 : mbedtls_rsa_context *rsa;
524 : int ret;
525 :
526 103 : mbedtls_x509_crt_init(&crt);
527 :
528 103 : if (wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size) != 0) {
529 0 : return false;
530 : }
531 :
532 103 : if (mbedtls_pk_get_type(&crt.pk) != MBEDTLS_PK_RSA) {
533 6 : mbedtls_x509_crt_free(&crt);
534 6 : return false;
535 : }
536 :
537 97 : rsa = libspdm_rsa_new();
538 97 : if (rsa == NULL) {
539 0 : mbedtls_x509_crt_free(&crt);
540 0 : return false;
541 : }
542 97 : ret = mbedtls_rsa_copy(rsa, mbedtls_pk_rsa(crt.pk));
543 97 : if (ret != 0) {
544 0 : libspdm_rsa_free(rsa);
545 0 : mbedtls_x509_crt_free(&crt);
546 0 : return false;
547 : }
548 97 : mbedtls_x509_crt_free(&crt);
549 :
550 97 : *rsa_context = rsa;
551 97 : return true;
552 : }
553 : #endif /* (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT) */
554 :
555 : /**
556 : * Retrieve the EC public key from one DER-encoded X509 certificate.
557 : *
558 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
559 : * @param[in] cert_size size of the X509 certificate in bytes.
560 : * @param[out] ec_context Pointer to newly generated EC DSA context which contain the retrieved
561 : * EC public key component. Use libspdm_ec_free() function to free the
562 : * resource.
563 : *
564 : * If cert is NULL, then return false.
565 : * If ec_context is NULL, then return false.
566 : *
567 : * @retval true EC public key was retrieved successfully.
568 : * @retval false Fail to retrieve EC public key from X509 certificate.
569 : *
570 : **/
571 941 : bool libspdm_ec_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
572 : void **ec_context)
573 : {
574 : mbedtls_x509_crt crt;
575 : mbedtls_ecdh_context *ecdh;
576 : int ret;
577 :
578 941 : mbedtls_x509_crt_init(&crt);
579 :
580 941 : if (wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size) != 0) {
581 0 : return false;
582 : }
583 :
584 941 : if (mbedtls_pk_get_type(&crt.pk) != MBEDTLS_PK_ECKEY) {
585 1 : mbedtls_x509_crt_free(&crt);
586 1 : return false;
587 : }
588 :
589 940 : ecdh = allocate_zero_pool(sizeof(mbedtls_ecdh_context));
590 940 : if (ecdh == NULL) {
591 0 : mbedtls_x509_crt_free(&crt);
592 0 : return false;
593 : }
594 940 : mbedtls_ecdh_init(ecdh);
595 :
596 940 : ret = mbedtls_ecdh_get_params(ecdh, mbedtls_pk_ec(crt.pk),
597 : MBEDTLS_ECDH_OURS);
598 940 : if (ret != 0) {
599 0 : mbedtls_ecdh_free(ecdh);
600 0 : free_pool(ecdh);
601 0 : mbedtls_x509_crt_free(&crt);
602 0 : return false;
603 : }
604 940 : mbedtls_x509_crt_free(&crt);
605 :
606 940 : *ec_context = ecdh;
607 940 : return true;
608 : }
609 :
610 : /**
611 : * Retrieve the Ed public key from one DER-encoded X509 certificate.
612 : *
613 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
614 : * @param[in] cert_size size of the X509 certificate in bytes.
615 : * @param[out] ecd_context Pointer to newly generated Ed DSA context which contain the retrieved
616 : * Ed public key component. Use libspdm_ecd_free() function to free the
617 : * resource.
618 : *
619 : * If cert is NULL, then return false.
620 : * If ecd_context is NULL, then return false.
621 : *
622 : * @retval true Ed public key was retrieved successfully.
623 : * @retval false Fail to retrieve Ed public key from X509 certificate.
624 : *
625 : **/
626 0 : bool libspdm_ecd_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
627 : void **ecd_context)
628 : {
629 0 : return false;
630 : }
631 :
632 : /**
633 : * Retrieve the sm2 public key from one DER-encoded X509 certificate.
634 : *
635 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
636 : * @param[in] cert_size size of the X509 certificate in bytes.
637 : * @param[out] sm2_context Pointer to newly generated sm2 context which contain the retrieved
638 : * sm2 public key component. Use sm2_free() function to free the
639 : * resource.
640 : *
641 : * If cert is NULL, then return false.
642 : * If ecd_context is NULL, then return false.
643 : *
644 : * @retval true sm2 public key was retrieved successfully.
645 : * @retval false Fail to retrieve sm2 public key from X509 certificate.
646 : *
647 : **/
648 0 : bool libspdm_sm2_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
649 : void **sm2_context)
650 : {
651 0 : return false;
652 : }
653 :
654 : /**
655 : * Verify one X509 certificate was issued by the trusted CA.
656 : *
657 : * @param[in] cert Pointer to the DER-encoded X509 certificate to be verified.
658 : * @param[in] cert_size size of the X509 certificate in bytes.
659 : * @param[in] ca_cert Pointer to the DER-encoded trusted CA certificate.
660 : * @param[in] ca_cert_size size of the CA Certificate in bytes.
661 : *
662 : * If cert is NULL, then return false.
663 : * If ca_cert is NULL, then return false.
664 : *
665 : * @retval true The certificate was issued by the trusted CA.
666 : * @retval false Invalid certificate or the certificate was not issued by the given
667 : * trusted CA.
668 : *
669 : **/
670 2417 : bool libspdm_x509_verify_cert(const uint8_t *cert, size_t cert_size,
671 : const uint8_t *ca_cert, size_t ca_cert_size)
672 : {
673 : int ret;
674 : mbedtls_x509_crt ca, end;
675 2417 : uint32_t v_flag = 0;
676 2417 : mbedtls_x509_crt_profile profile = { 0 };
677 :
678 2417 : if (cert == NULL || ca_cert == NULL) {
679 0 : return false;
680 : }
681 :
682 2417 : libspdm_copy_mem(&profile, sizeof(profile),
683 : &mbedtls_x509_crt_profile_default,
684 : sizeof(mbedtls_x509_crt_profile));
685 :
686 2417 : mbedtls_x509_crt_init(&ca);
687 2417 : mbedtls_x509_crt_init(&end);
688 :
689 2417 : ret = wrapper_mbedtls_x509_crt_parse_der(&ca, ca_cert, ca_cert_size);
690 :
691 2417 : if (ret == 0) {
692 2417 : ret = wrapper_mbedtls_x509_crt_parse_der(&end, cert, cert_size);
693 : }
694 :
695 2417 : if (ret == 0) {
696 2417 : ret = mbedtls_x509_crt_verify_with_profile(
697 : &end, &ca, NULL, &profile, NULL, &v_flag, NULL, NULL);
698 : }
699 :
700 2417 : mbedtls_x509_crt_free(&ca);
701 2417 : mbedtls_x509_crt_free(&end);
702 :
703 2417 : return ret == 0;
704 : }
705 :
706 : /**
707 : * Verify one X509 certificate was issued by the trusted CA.
708 : *
709 : * @param[in] cert_chain One or more ASN.1 DER-encoded X.509 certificates
710 : * where the first certificate is signed by the Root
711 : * Certificate or is the Root Certificate itself. and
712 : * subsequent certificate is signed by the preceding
713 : * certificate.
714 : * @param[in] cert_chain_length Total length of the certificate chain, in bytes.
715 : *
716 : * @param[in] root_cert Trusted Root Certificate buffer
717 : *
718 : * @param[in] root_cert_length Trusted Root Certificate buffer length
719 : *
720 : * @retval true All certificates were issued by the first certificate in X509Certchain.
721 : * @retval false Invalid certificate or the certificate was not issued by the given
722 : * trusted CA.
723 : **/
724 759 : bool libspdm_x509_verify_cert_chain(const uint8_t *root_cert, size_t root_cert_length,
725 : const uint8_t *cert_chain, size_t cert_chain_length)
726 : {
727 : size_t asn1_len;
728 : size_t preceding_cert_len;
729 : const uint8_t *preceding_cert;
730 : size_t current_cert_len;
731 : const unsigned char *current_cert;
732 : const unsigned char *tmp_ptr;
733 : int ret;
734 : bool verify_flag;
735 :
736 759 : verify_flag = false;
737 759 : preceding_cert = root_cert;
738 759 : preceding_cert_len = root_cert_length;
739 :
740 759 : current_cert = (const unsigned char *)cert_chain;
741 :
742 :
743 : /* Get Current certificate from certificates buffer and Verify with preceding cert*/
744 :
745 : do {
746 3172 : tmp_ptr = current_cert;
747 3172 : ret = mbedtls_asn1_get_tag(
748 3172 : &tmp_ptr, cert_chain + cert_chain_length, &asn1_len,
749 : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
750 3172 : if (ret != 0) {
751 756 : if (current_cert < cert_chain + cert_chain_length) {
752 2 : verify_flag = false;
753 : }
754 756 : break;
755 : }
756 :
757 2416 : current_cert_len = asn1_len + (tmp_ptr - current_cert);
758 :
759 2416 : if (current_cert + current_cert_len > cert_chain + cert_chain_length) {
760 0 : verify_flag = false;
761 0 : break;
762 : }
763 :
764 2416 : if (libspdm_x509_verify_cert(current_cert, current_cert_len,
765 : preceding_cert,
766 2416 : preceding_cert_len) == false) {
767 3 : verify_flag = false;
768 3 : break;
769 : } else {
770 2413 : verify_flag = true;
771 : }
772 :
773 :
774 : /* Save preceding certificate*/
775 :
776 2413 : preceding_cert = current_cert;
777 2413 : preceding_cert_len = current_cert_len;
778 :
779 :
780 : /* Move current certificate to next;*/
781 :
782 2413 : current_cert = current_cert + current_cert_len;
783 : } while (true);
784 :
785 759 : return verify_flag;
786 : }
787 :
788 : /**
789 : * Get one X509 certificate from cert_chain.
790 : *
791 : * @param[in] cert_chain One or more ASN.1 DER-encoded X.509 certificates
792 : * where the first certificate is signed by the Root
793 : * Certificate or is the Root Certificate itself. and
794 : * subsequent certificate is signed by the preceding
795 : * certificate.
796 : * @param[in] cert_chain_length Total length of the certificate chain, in bytes.
797 : *
798 : * @param[in] cert_index index of certificate.
799 : *
800 : * @param[out] cert The certificate at the index of cert_chain.
801 : * @param[out] cert_length The length certificate at the index of cert_chain.
802 : *
803 : * @retval true Success.
804 : * @retval false Failed to get certificate from certificate chain.
805 : **/
806 2548 : bool libspdm_x509_get_cert_from_cert_chain(const uint8_t *cert_chain,
807 : size_t cert_chain_length,
808 : const int32_t cert_index, const uint8_t **cert,
809 : size_t *cert_length)
810 : {
811 : size_t asn1_len;
812 : int32_t current_index;
813 : size_t current_cert_len;
814 : const unsigned char *current_cert;
815 : const unsigned char *tmp_ptr;
816 : int ret;
817 :
818 2548 : current_cert_len = 0;
819 :
820 : /* Check input parameters.*/
821 :
822 2548 : if ((cert_chain == NULL) || (cert == NULL) || (cert_index < -1) ||
823 : (cert_length == NULL)) {
824 0 : return false;
825 : }
826 :
827 2548 : current_cert = (const unsigned char *)cert_chain;
828 2548 : current_index = -1;
829 :
830 :
831 : /* Traverse the certificate chain*/
832 :
833 : while (true) {
834 :
835 : /* Get asn1 tag len*/
836 :
837 5772 : tmp_ptr = current_cert;
838 5772 : ret = mbedtls_asn1_get_tag(
839 5772 : &tmp_ptr, cert_chain + cert_chain_length, &asn1_len,
840 : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
841 5772 : if (ret != 0) {
842 1016 : break;
843 : }
844 :
845 4756 : current_cert_len = asn1_len + (tmp_ptr - current_cert);
846 4756 : if (current_cert + current_cert_len > cert_chain + cert_chain_length) {
847 0 : return false;
848 : }
849 :
850 4756 : current_index++;
851 :
852 4756 : if (current_index == cert_index) {
853 1532 : *cert = current_cert;
854 1532 : *cert_length = current_cert_len;
855 1532 : return true;
856 : }
857 :
858 :
859 : /* Move to next*/
860 :
861 3224 : current_cert = current_cert + current_cert_len;
862 : }
863 :
864 :
865 : /* If cert_index is -1, Return the last certificate*/
866 :
867 1016 : if (cert_index == -1 && current_index >= 0) {
868 1016 : *cert = current_cert - current_cert_len;
869 1016 : *cert_length = current_cert_len;
870 1016 : return true;
871 : }
872 :
873 0 : return false;
874 : }
875 :
876 : /**
877 : * Retrieve the TBSCertificate from one given X.509 certificate.
878 : *
879 : * @param[in] cert Pointer to the given DER-encoded X509 certificate.
880 : * @param[in] cert_size size of the X509 certificate in bytes.
881 : * @param[out] tbs_cert DER-Encoded to-Be-Signed certificate.
882 : * @param[out] tbs_cert_size size of the TBS certificate in bytes.
883 : *
884 : * If cert is NULL, then return false.
885 : * If tbs_cert is NULL, then return false.
886 : * If tbs_cert_size is NULL, then return false.
887 : *
888 : * @retval true The TBSCertificate was retrieved successfully.
889 : * @retval false Invalid X.509 certificate.
890 : *
891 : **/
892 0 : bool libspdm_x509_get_tbs_cert(const uint8_t *cert, size_t cert_size,
893 : uint8_t **tbs_cert, size_t *tbs_cert_size)
894 : {
895 0 : return false;
896 : }
897 :
898 : /**
899 : * Retrieve the version from one X.509 certificate.
900 : *
901 : * If cert is NULL, then return false.
902 : * If cert_size is 0, then return false.
903 : * If this interface is not supported, then return false.
904 : *
905 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
906 : * @param[in] cert_size size of the X509 certificate in bytes.
907 : * @param[out] version Pointer to the retrieved version integer.
908 : *
909 : * @retval RETURN_SUCCESS The certificate version retrieved successfully.
910 : * @retval RETURN_INVALID_PARAMETER If cert is NULL or cert_size is Zero.
911 : * @retval RETURN_UNSUPPORTED The operation is not supported.
912 : *
913 : **/
914 784 : bool libspdm_x509_get_version(const uint8_t *cert, size_t cert_size,
915 : size_t *version)
916 : {
917 : mbedtls_x509_crt crt;
918 : int ret;
919 : bool status;
920 :
921 784 : if (cert == NULL) {
922 0 : return false;
923 : }
924 :
925 784 : status = false;
926 :
927 784 : mbedtls_x509_crt_init(&crt);
928 :
929 784 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
930 :
931 784 : if (ret == 0) {
932 784 : *version = crt.version - 1;
933 784 : status = true;
934 : }
935 :
936 784 : mbedtls_x509_crt_free(&crt);
937 :
938 784 : return status;
939 : }
940 :
941 : /**
942 : * Retrieve the serialNumber from one X.509 certificate.
943 : *
944 : * If cert is NULL, then return false.
945 : * If cert_size is 0, then return false.
946 : * If this interface is not supported, then return false.
947 : *
948 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
949 : * @param[in] cert_size size of the X509 certificate in bytes.
950 : * @param[out] serial_number Pointer to the retrieved certificate serial_number bytes.
951 : * @param[in, out] serial_number_size The size in bytes of the serial_number buffer on input,
952 : * and the size of buffer returned serial_number on output.
953 : *
954 : * @retval RETURN_SUCCESS The certificate serialNumber retrieved successfully.
955 : * @retval RETURN_INVALID_PARAMETER If cert is NULL or cert_size is Zero.
956 : * If serial_number_size is NULL.
957 : * If Certificate is invalid.
958 : * @retval RETURN_NOT_FOUND If no serial_number exists.
959 : * @retval RETURN_BUFFER_TOO_SMALL If the serial_number is NULL. The required buffer size
960 : * (including the final null) is returned in the
961 : * serial_number_size parameter.
962 : * @retval RETURN_UNSUPPORTED The operation is not supported.
963 : **/
964 784 : bool libspdm_x509_get_serial_number(const uint8_t *cert, size_t cert_size,
965 : uint8_t *serial_number,
966 : size_t *serial_number_size)
967 : {
968 : mbedtls_x509_crt crt;
969 : int ret;
970 : bool status;
971 :
972 784 : if (cert == NULL) {
973 0 : return false;
974 : }
975 :
976 784 : status = false;
977 :
978 784 : mbedtls_x509_crt_init(&crt);
979 :
980 784 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
981 :
982 784 : if (ret == 0) {
983 784 : if (*serial_number_size <= crt.serial.len) {
984 784 : *serial_number_size = crt.serial.len + 1;
985 784 : status = false;
986 784 : goto cleanup;
987 : }
988 0 : if (serial_number != NULL) {
989 0 : libspdm_copy_mem(serial_number, *serial_number_size, crt.serial.p, crt.serial.len);
990 0 : serial_number[crt.serial.len] = '\0';
991 : }
992 0 : *serial_number_size = crt.serial.len + 1;
993 0 : status = true;
994 : }
995 0 : cleanup:
996 784 : mbedtls_x509_crt_free(&crt);
997 :
998 784 : return status;
999 : }
1000 :
1001 : /**
1002 : * Retrieve the issuer bytes from one X.509 certificate.
1003 : *
1004 : * If cert is NULL, then return false.
1005 : * If issuer_size is NULL, then return false.
1006 : * If this interface is not supported, then return false.
1007 : *
1008 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1009 : * @param[in] cert_size size of the X509 certificate in bytes.
1010 : * @param[out] cert_issuer Pointer to the retrieved certificate subject bytes.
1011 : * @param[in, out] issuer_size The size in bytes of the cert_issuer buffer on input,
1012 : * and the size of buffer returned cert_issuer on output.
1013 : *
1014 : * @retval true If the issuer_size is not equal 0. The certificate issuer retrieved successfully.
1015 : * @retval true If the issuer_size is equal 0. The certificate parse successful. But the cert doesn't have issuer.
1016 : * @retval false If the issuer_size is not equal 0. The certificate issuer retrieved successfully. But the issuer_size is too small for the result.
1017 : * @retval false If the issuer_size is equal 0. Invalid certificate.
1018 : *
1019 : **/
1020 841 : bool libspdm_x509_get_issuer_name(const uint8_t *cert, size_t cert_size,
1021 : uint8_t *cert_issuer,
1022 : size_t *issuer_size)
1023 : {
1024 : mbedtls_x509_crt crt;
1025 : int ret;
1026 : bool status;
1027 :
1028 : /* Check input parameters.*/
1029 841 : if (cert == NULL || cert_size == 0 || issuer_size == NULL) {
1030 0 : if (issuer_size != NULL) {
1031 0 : *issuer_size = 0;
1032 : }
1033 0 : return false;
1034 : }
1035 :
1036 841 : status = false;
1037 :
1038 841 : mbedtls_x509_crt_init(&crt);
1039 :
1040 841 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
1041 :
1042 841 : if (ret == 0) {
1043 841 : if (*issuer_size < crt.issuer_raw.len) {
1044 782 : *issuer_size = crt.issuer_raw.len;
1045 782 : status = false;
1046 782 : goto cleanup;
1047 : }
1048 59 : if (cert_issuer != NULL) {
1049 59 : libspdm_copy_mem(cert_issuer, *issuer_size, crt.issuer_raw.p, crt.issuer_raw.len);
1050 : }
1051 59 : *issuer_size = crt.issuer_raw.len;
1052 59 : status = true;
1053 : } else {
1054 0 : *issuer_size = 0;
1055 : }
1056 :
1057 841 : cleanup:
1058 841 : mbedtls_x509_crt_free(&crt);
1059 :
1060 841 : return status;
1061 : }
1062 :
1063 : /**
1064 : * Retrieve the issuer common name (CN) string from one X.509 certificate.
1065 : *
1066 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1067 : * @param[in] cert_size size of the X509 certificate in bytes.
1068 : * @param[out] common_name buffer to contain the retrieved certificate issuer common
1069 : * name string. At most common_name_size bytes will be
1070 : * written and the string will be null terminated. May be
1071 : * NULL in order to determine the size buffer needed.
1072 : * @param[in,out] common_name_size The size in bytes of the common_name buffer on input,
1073 : * and the size of buffer returned common_name on output.
1074 : * If common_name is NULL then the amount of space needed
1075 : * in buffer (including the final null) is returned.
1076 : *
1077 : * @retval RETURN_SUCCESS The certificate Issuer common_name retrieved successfully.
1078 : * @retval RETURN_INVALID_PARAMETER If cert is NULL.
1079 : * If common_name_size is NULL.
1080 : * If common_name is not NULL and *common_name_size is 0.
1081 : * If Certificate is invalid.
1082 : * @retval RETURN_NOT_FOUND If no common_name entry exists.
1083 : * @retval RETURN_BUFFER_TOO_SMALL If the common_name is NULL. The required buffer size
1084 : * (including the final null) is returned in the
1085 : * common_name_size parameter.
1086 : * @retval RETURN_UNSUPPORTED The operation is not supported.
1087 : *
1088 : **/
1089 : bool
1090 0 : libspdm_x509_get_issuer_common_name(const uint8_t *cert, size_t cert_size,
1091 : char *common_name,
1092 : size_t *common_name_size)
1093 : {
1094 0 : return libspdm_internal_x509_get_issuer_nid_name(cert, cert_size,
1095 : m_libspdm_oid_common_name,
1096 : sizeof(m_libspdm_oid_common_name),
1097 : common_name, common_name_size);
1098 : }
1099 :
1100 : /**
1101 : * Retrieve the issuer organization name (O) string from one X.509 certificate.
1102 : *
1103 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1104 : * @param[in] cert_size size of the X509 certificate in bytes.
1105 : * @param[out] name_buffer buffer to contain the retrieved certificate issuer organization
1106 : * name string. At most name_buffer_size bytes will be
1107 : * written and the string will be null terminated. May be
1108 : * NULL in order to determine the size buffer needed.
1109 : * @param[in,out] name_buffer_size The size in bytes of the name buffer on input,
1110 : * and the size of buffer returned name on output.
1111 : * If name_buffer is NULL then the amount of space needed
1112 : * in buffer (including the final null) is returned.
1113 : *
1114 : * @retval RETURN_SUCCESS The certificate issuer Organization name retrieved successfully.
1115 : * @retval RETURN_INVALID_PARAMETER If cert is NULL.
1116 : * If name_buffer_size is NULL.
1117 : * If name_buffer is not NULL and *common_name_size is 0.
1118 : * If Certificate is invalid.
1119 : * @retval RETURN_NOT_FOUND If no Organization name entry exists.
1120 : * @retval RETURN_BUFFER_TOO_SMALL If the name_buffer is NULL. The required buffer size
1121 : * (including the final null) is returned in the
1122 : * common_name_size parameter.
1123 : * @retval RETURN_UNSUPPORTED The operation is not supported.
1124 : *
1125 : **/
1126 : bool
1127 0 : libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t cert_size,
1128 : char *name_buffer,
1129 : size_t *name_buffer_size)
1130 : {
1131 0 : return libspdm_internal_x509_get_issuer_nid_name(
1132 : cert, cert_size, m_libspdm_oid_organization_name,
1133 : sizeof(m_libspdm_oid_organization_name), name_buffer, name_buffer_size);
1134 : }
1135 :
1136 : /**
1137 : * Retrieve the signature algorithm from one X.509 certificate.
1138 : *
1139 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1140 : * @param[in] cert_size size of the X509 certificate in bytes.
1141 : * @param[out] oid signature algorithm Object identifier buffer.
1142 : * @param[in,out] oid_size signature algorithm Object identifier buffer size
1143 : *
1144 : * @retval true if the oid_size is equal 0, the cert parse successfully, but cert doesn't have signature algo.
1145 : * @retval true if the oid_size is not equal 0, the cert parse and get signature algo successfully.
1146 : * @retval false if the oid_size is equal 0, the cert parse failed.
1147 : * @retval false if the oid_size is not equal 0, the cert parse and get signature algo successfully, but the input buffer size is small.
1148 : **/
1149 784 : bool libspdm_x509_get_signature_algorithm(const uint8_t *cert,
1150 : size_t cert_size, uint8_t *oid,
1151 : size_t *oid_size)
1152 : {
1153 : mbedtls_x509_crt crt;
1154 : int ret;
1155 : bool status;
1156 :
1157 : /* Check input parameters.*/
1158 784 : if (cert == NULL || cert_size == 0 || oid_size == NULL) {
1159 0 : if (oid_size != NULL) {
1160 0 : *oid_size = 0;
1161 : }
1162 0 : return false;
1163 : }
1164 :
1165 784 : status = false;
1166 :
1167 784 : mbedtls_x509_crt_init(&crt);
1168 :
1169 784 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
1170 :
1171 784 : if (ret == 0) {
1172 784 : if (*oid_size < crt.sig_oid.len) {
1173 784 : *oid_size = crt.serial.len;
1174 784 : status = false;
1175 784 : goto cleanup;
1176 : }
1177 0 : if (oid != NULL) {
1178 0 : libspdm_copy_mem(oid, *oid_size, crt.sig_oid.p, crt.sig_oid.len);
1179 : }
1180 0 : *oid_size = crt.sig_oid.len;
1181 0 : status = true;
1182 : } else {
1183 0 : *oid_size = 0;
1184 : }
1185 :
1186 784 : cleanup:
1187 784 : mbedtls_x509_crt_free(&crt);
1188 :
1189 784 : return status;
1190 : }
1191 :
1192 : /**
1193 : * Find first Extension data match with given OID
1194 : *
1195 : * @param[in] start Pointer to the DER-encoded extensions data
1196 : * @param[in] end extensions data size in bytes
1197 : * @param[in ] oid OID for match
1198 : * @param[in ] oid_size OID size in bytes
1199 : * @param[out] find_extension_data output matched extension data.
1200 : * @param[out] find_extension_data_len matched extension data size.
1201 : *
1202 : **/
1203 : static bool
1204 2344 : libspdm_internal_x509_find_extension_data(uint8_t *start, uint8_t *end, const uint8_t *oid,
1205 : size_t oid_size, uint8_t **find_extension_data,
1206 : size_t *find_extension_data_len)
1207 : {
1208 : uint8_t *ptr;
1209 : uint8_t *extension_ptr;
1210 : size_t obj_len;
1211 : int ret;
1212 : bool status;
1213 : size_t find_extension_len;
1214 : size_t header_len;
1215 :
1216 : /*If no Extension entry match oid*/
1217 2344 : status = false;
1218 2344 : ptr = start;
1219 :
1220 2344 : ret = 0;
1221 :
1222 : while (true) {
1223 : /*
1224 : * Extension ::= SEQUENCE {
1225 : * extnID OBJECT IDENTIFIER,
1226 : * critical bool DEFAULT false,
1227 : * extnValue OCTET STRING }
1228 : */
1229 9407 : extension_ptr = ptr;
1230 9407 : ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
1231 : MBEDTLS_ASN1_CONSTRUCTED |
1232 : MBEDTLS_ASN1_SEQUENCE);
1233 9407 : if (ret == 0) {
1234 9392 : header_len = (size_t)(ptr - extension_ptr);
1235 9392 : find_extension_len = obj_len;
1236 : /* Get Object Identifier*/
1237 9392 : ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
1238 : MBEDTLS_ASN1_OID);
1239 : } else {
1240 15 : break;
1241 : }
1242 :
1243 9392 : if (ret == 0 && libspdm_consttime_is_mem_equal(ptr, oid, oid_size)) {
1244 2329 : ptr += obj_len;
1245 :
1246 2329 : ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
1247 : MBEDTLS_ASN1_BOOLEAN);
1248 2329 : if (ret == 0) {
1249 1551 : ptr += obj_len;
1250 : }
1251 :
1252 2329 : ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
1253 : MBEDTLS_ASN1_OCTET_STRING);
1254 : } else {
1255 7063 : ret = 1;
1256 : }
1257 :
1258 9392 : if (ret == 0) {
1259 2329 : *find_extension_data = ptr;
1260 2329 : *find_extension_data_len = obj_len;
1261 2329 : status = true;
1262 2329 : break;
1263 : }
1264 :
1265 : /* move to next*/
1266 7063 : ptr = extension_ptr + header_len + find_extension_len;
1267 7063 : ret = 0;
1268 : }
1269 :
1270 2344 : return status;
1271 : }
1272 :
1273 : /**
1274 : * Retrieve Extension data from one X.509 certificate.
1275 : *
1276 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1277 : * @param[in] cert_size size of the X509 certificate in bytes.
1278 : * @param[in] oid Object identifier buffer
1279 : * @param[in] oid_size Object identifier buffer size
1280 : * @param[out] extension_data Extension bytes.
1281 : * @param[in, out] extension_data_size Extension bytes size.
1282 : *
1283 : * @retval true If the returned extension_data_size == 0, it means that cert and oid are valid, but the oid extension is not found;
1284 : * If the returned extension_data_size != 0, it means that cert and oid are valid, and the oid extension is found;
1285 : * @retval false If the returned extension_data_size == 0, it means that cert or oid are invalid;
1286 : * If the returned extension_data_size != 0, it means that cert and oid are valid, and the oid extension is found,
1287 : * but the store buffer is too small.
1288 : **/
1289 2344 : bool libspdm_x509_get_extension_data(const uint8_t *cert, size_t cert_size,
1290 : const uint8_t *oid, size_t oid_size,
1291 : uint8_t *extension_data,
1292 : size_t *extension_data_size)
1293 : {
1294 : mbedtls_x509_crt crt;
1295 : int ret;
1296 : bool status;
1297 : uint8_t *ptr;
1298 : uint8_t *end;
1299 : size_t obj_len;
1300 :
1301 2344 : ptr = NULL;
1302 2344 : end = NULL;
1303 2344 : obj_len = 0;
1304 :
1305 2344 : if (cert == NULL || cert_size == 0 || oid == NULL || oid_size == 0 ||
1306 : extension_data_size == NULL) {
1307 0 : if (extension_data_size != NULL) {
1308 0 : *extension_data_size = 0;
1309 : }
1310 0 : return false;
1311 : }
1312 :
1313 2344 : status = false;
1314 :
1315 2344 : mbedtls_x509_crt_init(&crt);
1316 :
1317 2344 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
1318 :
1319 2344 : if (ret == 0) {
1320 2344 : ptr = crt.v3_ext.p;
1321 2344 : end = crt.v3_ext.p + crt.v3_ext.len;
1322 2344 : ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
1323 : MBEDTLS_ASN1_CONSTRUCTED |
1324 : MBEDTLS_ASN1_SEQUENCE);
1325 : }
1326 :
1327 2344 : if (ret == 0) {
1328 2344 : status = libspdm_internal_x509_find_extension_data(
1329 : ptr, end, oid, oid_size, &ptr, &obj_len);
1330 2344 : if (!status) {
1331 15 : status = true;
1332 15 : *extension_data_size = 0;
1333 15 : goto cleanup;
1334 : }
1335 : }
1336 :
1337 2329 : if (status) {
1338 2329 : if (*extension_data_size < obj_len) {
1339 6 : *extension_data_size = obj_len;
1340 6 : status = false;
1341 6 : goto cleanup;
1342 : }
1343 2323 : if (oid != NULL) {
1344 2323 : libspdm_copy_mem(extension_data, *extension_data_size, ptr, obj_len);
1345 : }
1346 2323 : *extension_data_size = obj_len;
1347 : } else {
1348 0 : *extension_data_size = 0;
1349 : }
1350 :
1351 2344 : cleanup:
1352 2344 : mbedtls_x509_crt_free(&crt);
1353 :
1354 2344 : return status;
1355 : }
1356 :
1357 : /**
1358 : * Retrieve the Validity from one X.509 certificate
1359 : *
1360 : * If cert is NULL, then return false.
1361 : * If CertIssuerSize is NULL, then return false.
1362 : * If this interface is not supported, then return false.
1363 : *
1364 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1365 : * @param[in] cert_size size of the X509 certificate in bytes.
1366 : * @param[out] from notBefore Pointer to date_time object.
1367 : * @param[in,out] from_size notBefore date_time object size.
1368 : * @param[out] to notAfter Pointer to date_time object.
1369 : * @param[in,out] to_size notAfter date_time object size.
1370 : *
1371 : * Note: libspdm_x509_compare_date_time to compare date_time object
1372 : * x509SetDateTime to get a date_time object from a date_time_str
1373 : *
1374 : * @retval true The certificate Validity retrieved successfully.
1375 : * @retval false Invalid certificate, or Validity retrieve failed.
1376 : * @retval false This interface is not supported.
1377 : **/
1378 782 : bool libspdm_x509_get_validity(const uint8_t *cert, size_t cert_size,
1379 : uint8_t *from, size_t *from_size, uint8_t *to,
1380 : size_t *to_size)
1381 : {
1382 : mbedtls_x509_crt crt;
1383 : int ret;
1384 : bool status;
1385 : size_t t_size;
1386 : size_t f_size;
1387 : mbedtls_x509_time zero_time;
1388 :
1389 : /* Check input parameters.*/
1390 782 : if (cert == NULL || from_size == NULL || to_size == NULL ||
1391 : cert_size == 0) {
1392 0 : if (from_size != NULL) {
1393 0 : *from_size = 0;
1394 : }
1395 0 : if (to_size != NULL) {
1396 0 : *to_size = 0;
1397 : }
1398 0 : return false;
1399 : }
1400 :
1401 782 : status = false;
1402 :
1403 782 : mbedtls_x509_crt_init(&crt);
1404 782 : libspdm_zero_mem(&zero_time, sizeof(mbedtls_x509_time));
1405 :
1406 782 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
1407 :
1408 782 : if (ret == 0) {
1409 782 : f_size = sizeof(mbedtls_x509_time);
1410 782 : if ((libspdm_consttime_is_mem_equal(&zero_time, &(crt.valid_from), f_size)) &&
1411 0 : (libspdm_consttime_is_mem_equal(&zero_time, &(crt.valid_to), f_size))) {
1412 0 : *from_size = 0;
1413 0 : *to_size = 0;
1414 0 : status = true;
1415 0 : goto done;
1416 : }
1417 :
1418 782 : if (*from_size < f_size) {
1419 0 : *from_size = f_size;
1420 0 : goto done;
1421 : }
1422 782 : if (from != NULL) {
1423 782 : libspdm_copy_mem(from, *from_size, &(crt.valid_from), f_size);
1424 : }
1425 782 : *from_size = f_size;
1426 :
1427 782 : t_size = sizeof(mbedtls_x509_time);
1428 782 : if (*to_size < t_size) {
1429 0 : *to_size = t_size;
1430 0 : goto done;
1431 : }
1432 782 : if (to != NULL) {
1433 782 : libspdm_copy_mem(to, *to_size, &(crt.valid_to),
1434 : sizeof(mbedtls_x509_time));
1435 : }
1436 782 : *to_size = t_size;
1437 782 : status = true;
1438 : } else {
1439 0 : *from_size = 0;
1440 0 : *to_size = 0;
1441 : }
1442 :
1443 782 : done:
1444 782 : mbedtls_x509_crt_free(&crt);
1445 :
1446 782 : return status;
1447 : }
1448 :
1449 : /**
1450 : * Retrieve the key usage from one X.509 certificate.
1451 : *
1452 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1453 : * @param[in] cert_size size of the X509 certificate in bytes.
1454 : * @param[out] usage key usage (LIBSPDM_CRYPTO_X509_KU_*)
1455 : *
1456 : * @retval true if the usage is no equal 0. The certificate key usage retrieved successfully.
1457 : * @retval true if the usage is equal 0. The certificate parse successfully, but the cert doesn't have key usage.
1458 : * @retval false Invalid certificate, or usage is NULL.
1459 : **/
1460 776 : bool libspdm_x509_get_key_usage(const uint8_t *cert, size_t cert_size,
1461 : size_t *usage)
1462 : {
1463 : mbedtls_x509_crt crt;
1464 : int ret;
1465 : bool status;
1466 :
1467 : /* Check input parameters.*/
1468 776 : if (cert == NULL || cert_size == 0 || usage == NULL) {
1469 0 : if (usage != NULL) {
1470 0 : *usage = 0;
1471 : }
1472 0 : return false;
1473 : }
1474 :
1475 776 : status = false;
1476 :
1477 776 : mbedtls_x509_crt_init(&crt);
1478 :
1479 776 : ret = wrapper_mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
1480 :
1481 776 : if (ret == 0) {
1482 776 : *usage = crt.MBEDTLS_PRIVATE(key_usage);
1483 776 : status = true;
1484 : } else {
1485 0 : *usage = 0;
1486 : }
1487 776 : mbedtls_x509_crt_free(&crt);
1488 :
1489 776 : return status;
1490 : }
1491 :
1492 : /**
1493 : * Retrieve the Extended key usage from one X.509 certificate.
1494 : *
1495 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1496 : * @param[in] cert_size size of the X509 certificate in bytes.
1497 : * @param[out] usage key usage bytes.
1498 : * @param[in, out] usage_size key usage buffer sizs in bytes.
1499 : *
1500 : * @retval true If the returned usage_size == 0, it means that cert and oid are valid, but the Extended key usage is not found;
1501 : * If the returned usage_size != 0, it means that cert and oid are valid, and the Extended key usage is found;
1502 : * @retval false If the returned usage_size == 0, it means that cert or oid are invalid;
1503 : * If the returned usage_size != 0, it means that cert and oid are valid, and the Extended key usage is found,
1504 : * but the store buffer is too small.
1505 : **/
1506 782 : bool libspdm_x509_get_extended_key_usage(const uint8_t *cert,
1507 : size_t cert_size, uint8_t *usage,
1508 : size_t *usage_size)
1509 : {
1510 : bool status;
1511 :
1512 782 : if (cert == NULL || cert_size == 0 || usage_size == NULL) {
1513 0 : return false;
1514 : }
1515 :
1516 782 : status = libspdm_x509_get_extension_data(cert, cert_size,
1517 : m_libspdm_oid_ext_key_usage,
1518 : sizeof(m_libspdm_oid_ext_key_usage), usage,
1519 : usage_size);
1520 :
1521 782 : return status;
1522 : }
1523 :
1524 : /**
1525 : * Retrieve the basic constraints from one X.509 certificate.
1526 : *
1527 : * @param[in] cert Pointer to the DER-encoded X509 certificate.
1528 : * @param[in] cert_size size of the X509 certificate in bytes.
1529 : * @param[out] basic_constraints basic constraints bytes.
1530 : * @param[in, out] basic_constraints_size basic constraints buffer sizs in bytes.
1531 : *
1532 : * @retval true If the returned basic_constraints_size == 0, it means that cert and oid are valid, but the basic_constraints is not found;
1533 : * If the returned basic_constraints_size != 0, it means that cert and oid are valid, and the basic_constraints is found;
1534 : * @retval false If the returned basic_constraints_size == 0, it means that cert or oid are invalid;
1535 : * If the returned basic_constraints_size != 0, it means that cert and oid are valid, and the basic_constraints is found,
1536 : * but the store buffer is too small.
1537 : **/
1538 776 : bool libspdm_x509_get_extended_basic_constraints(const uint8_t *cert,
1539 : size_t cert_size,
1540 : uint8_t *basic_constraints,
1541 : size_t *basic_constraints_size)
1542 : {
1543 : bool status;
1544 :
1545 776 : if (cert == NULL || cert_size == 0 || basic_constraints_size == NULL) {
1546 0 : return false;
1547 : }
1548 :
1549 776 : status = libspdm_x509_get_extension_data(cert, cert_size,
1550 : m_libspdm_oid_basic_constraints,
1551 : sizeof(m_libspdm_oid_basic_constraints),
1552 : basic_constraints,
1553 : basic_constraints_size);
1554 776 : return status;
1555 : }
1556 :
1557 : /**
1558 : * Return 0 if before <= after, 1 otherwise
1559 : **/
1560 1564 : static int32_t libspdm_internal_x509_check_time(const mbedtls_x509_time *before,
1561 : const mbedtls_x509_time *after)
1562 : {
1563 1564 : if (before->year > after->year) {
1564 1564 : return (1);
1565 : }
1566 :
1567 0 : if (before->year == after->year && before->mon > after->mon) {
1568 0 : return (1);
1569 : }
1570 :
1571 0 : if (before->year == after->year && before->mon == after->mon &&
1572 0 : before->day > after->day) {
1573 0 : return (1);
1574 : }
1575 :
1576 0 : if (before->year == after->year && before->mon == after->mon &&
1577 0 : before->day == after->day && before->hour > after->hour) {
1578 0 : return (1);
1579 : }
1580 :
1581 0 : if (before->year == after->year && before->mon == after->mon &&
1582 0 : before->day == after->day && before->hour == after->hour &&
1583 0 : before->min > after->min) {
1584 0 : return (1);
1585 : }
1586 :
1587 0 : if (before->year == after->year && before->mon == after->mon &&
1588 0 : before->day == after->day && before->hour == after->hour &&
1589 0 : before->min == after->min && before->sec > after->sec) {
1590 0 : return (1);
1591 : }
1592 :
1593 0 : return (0);
1594 : }
1595 :
1596 9384 : static int32_t libspdm_internal_atoi(const char *p_start, char const *p_end)
1597 : {
1598 9384 : const char *p = p_start;
1599 9384 : int32_t k = 0;
1600 31280 : while (p < p_end) {
1601 :
1602 : /* k = k * 2³ + k * 2¹ = k * 8 + k * 2 = k * 10*/
1603 :
1604 21896 : k = (k << 3) + (k << 1) + (*p) - '0';
1605 21896 : p++;
1606 : }
1607 9384 : return k;
1608 : }
1609 :
1610 : /**
1611 : * format a date_time object into DataTime buffer
1612 : *
1613 : * If date_time_str is NULL, then return false.
1614 : * If date_time_size is NULL, then return false.
1615 : * If this interface is not supported, then return false.
1616 : *
1617 : * @param[in] date_time_str date_time string like YYYYMMDDhhmmssZ
1618 : * Ref: https://www.w3.org/TR/NOTE-datetime
1619 : * Z stand for UTC time
1620 : * @param[out] date_time Pointer to a date_time object.
1621 : * @param[in,out] date_time_size date_time object buffer size.
1622 : *
1623 : * @retval RETURN_SUCCESS The date_time object create successfully.
1624 : * @retval RETURN_INVALID_PARAMETER If date_time_str is NULL.
1625 : * If date_time_size is NULL.
1626 : * If date_time is not NULL and *date_time_size is 0.
1627 : * If year month day hour minute second combination is invalid datetime.
1628 : * @retval RETURN_BUFFER_TOO_SMALL If the date_time is NULL. The required buffer size
1629 : * (including the final null) is returned in the
1630 : * date_time_size parameter.
1631 : * @retval RETURN_UNSUPPORTED The operation is not supported.
1632 : **/
1633 1564 : bool libspdm_x509_set_date_time(const char *date_time_str, void *date_time, size_t *date_time_size)
1634 : {
1635 : mbedtls_x509_time dt;
1636 :
1637 : int32_t year;
1638 : int32_t month;
1639 : int32_t day;
1640 : int32_t hour;
1641 : int32_t minute;
1642 : int32_t second;
1643 : bool status;
1644 : const char *p;
1645 :
1646 1564 : p = date_time_str;
1647 :
1648 1564 : year = libspdm_internal_atoi(p, p + 4);
1649 1564 : p += 4;
1650 1564 : month = libspdm_internal_atoi(p, p + 2);
1651 1564 : p += 2;
1652 1564 : day = libspdm_internal_atoi(p, p + 2);
1653 1564 : p += 2;
1654 1564 : hour = libspdm_internal_atoi(p, p + 2);
1655 1564 : p += 2;
1656 1564 : minute = libspdm_internal_atoi(p, p + 2);
1657 1564 : p += 2;
1658 1564 : second = libspdm_internal_atoi(p, p + 2);
1659 1564 : p += 2;
1660 1564 : dt.year = (int)year;
1661 1564 : dt.mon = (int)month;
1662 1564 : dt.day = (int)day;
1663 1564 : dt.hour = (int)hour;
1664 1564 : dt.min = (int)minute;
1665 1564 : dt.sec = (int)second;
1666 :
1667 1564 : if (*date_time_size < sizeof(mbedtls_x509_time)) {
1668 0 : *date_time_size = sizeof(mbedtls_x509_time);
1669 0 : status = false;
1670 0 : goto cleanup;
1671 : }
1672 1564 : if (date_time != NULL) {
1673 1564 : libspdm_copy_mem(date_time, *date_time_size, &dt, sizeof(mbedtls_x509_time));
1674 : }
1675 1564 : *date_time_size = sizeof(mbedtls_x509_time);
1676 1564 : status = true;
1677 1564 : cleanup:
1678 1564 : return status;
1679 : }
1680 :
1681 : /**
1682 : * Compare date_time1 object and date_time2 object.
1683 : *
1684 : * If date_time1 is NULL, then return -2.
1685 : * If date_time2 is NULL, then return -2.
1686 : * If date_time1 == date_time2, then return 0
1687 : * If date_time1 > date_time2, then return 1
1688 : * If date_time1 < date_time2, then return -1
1689 : *
1690 : * @param[in] date_time1 Pointer to a date_time Object
1691 : * @param[in] date_time2 Pointer to a date_time Object
1692 : *
1693 : * @retval 0 If date_time1 == date_time2
1694 : * @retval 1 If date_time1 > date_time2
1695 : * @retval -1 If date_time1 < date_time2
1696 : **/
1697 1564 : int32_t libspdm_x509_compare_date_time(const void *date_time1, const void *date_time2)
1698 : {
1699 1564 : if (date_time1 == NULL || date_time2 == NULL) {
1700 0 : return -2;
1701 : }
1702 1564 : if (libspdm_consttime_is_mem_equal(date_time2, date_time1, sizeof(mbedtls_x509_time))) {
1703 0 : return 0;
1704 : }
1705 1564 : if (libspdm_internal_x509_check_time((const mbedtls_x509_time *)date_time1,
1706 : (const mbedtls_x509_time *)date_time2) == 0) {
1707 0 : return -1;
1708 : } else {
1709 1564 : return 1;
1710 : }
1711 : }
1712 :
1713 2 : static bool libspdm_convert_subject_to_string(uint8_t *ptr, size_t obj_len,
1714 : uint8_t *buffer, int32_t buff_len)
1715 : {
1716 : bool ret;
1717 : uint8_t *end;
1718 : uint8_t *internal_p;
1719 :
1720 : libspdm_x509_subject_descriptor_t *cur;
1721 : /* X.509 DN attributes from RFC 5280, Appendix A.1. */
1722 2 : libspdm_x509_subject_descriptor_t x509_attrs[] =
1723 : {
1724 : { LIBSPDM_ADD_STRLEN( "CN" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_CN ),
1725 : MBEDTLS_ASN1_UTF8_STRING },
1726 : { LIBSPDM_ADD_STRLEN( "C" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_COUNTRY ),
1727 : MBEDTLS_ASN1_PRINTABLE_STRING },
1728 : { LIBSPDM_ADD_STRLEN( "O" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_ORGANIZATION ),
1729 : MBEDTLS_ASN1_UTF8_STRING },
1730 : { LIBSPDM_ADD_STRLEN( "L" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_LOCALITY ),
1731 : MBEDTLS_ASN1_UTF8_STRING },
1732 : { LIBSPDM_ADD_STRLEN( "R" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_PKCS9_EMAIL ),
1733 : MBEDTLS_ASN1_IA5_STRING },
1734 : { LIBSPDM_ADD_STRLEN( "OU" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_ORG_UNIT ),
1735 : MBEDTLS_ASN1_UTF8_STRING },
1736 : { LIBSPDM_ADD_STRLEN( "ST" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_STATE ),
1737 : MBEDTLS_ASN1_UTF8_STRING },
1738 : { LIBSPDM_ADD_STRLEN( "emailAddress" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_PKCS9_EMAIL ),
1739 : MBEDTLS_ASN1_IA5_STRING },
1740 : { LIBSPDM_ADD_STRLEN( "serialNumber" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),
1741 : MBEDTLS_ASN1_PRINTABLE_STRING },
1742 : { LIBSPDM_ADD_STRLEN( "postalAddress" ),
1743 : LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ), MBEDTLS_ASN1_PRINTABLE_STRING },
1744 : { LIBSPDM_ADD_STRLEN( "postalCode" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_POSTAL_CODE ),
1745 : MBEDTLS_ASN1_PRINTABLE_STRING },
1746 : { LIBSPDM_ADD_STRLEN( "dnQualifier" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_DN_QUALIFIER ),
1747 : MBEDTLS_ASN1_PRINTABLE_STRING },
1748 : { LIBSPDM_ADD_STRLEN( "title" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_TITLE ),
1749 : MBEDTLS_ASN1_UTF8_STRING },
1750 : { LIBSPDM_ADD_STRLEN( "SN" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_SUR_NAME ),
1751 : MBEDTLS_ASN1_UTF8_STRING },
1752 : { LIBSPDM_ADD_STRLEN( "GN" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_GIVEN_NAME ),
1753 : MBEDTLS_ASN1_UTF8_STRING },
1754 : { LIBSPDM_ADD_STRLEN( "initials" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_INITIALS ),
1755 : MBEDTLS_ASN1_UTF8_STRING },
1756 : { LIBSPDM_ADD_STRLEN( "pseudonym" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_PSEUDONYM ),
1757 : MBEDTLS_ASN1_UTF8_STRING },
1758 : { LIBSPDM_ADD_STRLEN( "generationQualifier" ),
1759 : LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ),
1760 : MBEDTLS_ASN1_UTF8_STRING },
1761 : { LIBSPDM_ADD_STRLEN( "DC" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_DOMAIN_COMPONENT ),
1762 : MBEDTLS_ASN1_IA5_STRING },
1763 : { NULL, 0, NULL, 0, MBEDTLS_ASN1_NULL }
1764 : };
1765 :
1766 2 : end = ptr + obj_len;
1767 :
1768 8 : while(ptr != end) {
1769 : /*SET*/
1770 6 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
1771 : LIBSPDM_CRYPTO_ASN1_SET | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1772 6 : if (!ret) {
1773 0 : return false;
1774 : }
1775 6 : internal_p = ptr;
1776 : /*move to next SET*/
1777 6 : ptr += obj_len;
1778 :
1779 : /*sequence*/
1780 6 : ret = libspdm_asn1_get_tag(&internal_p, end, &obj_len,
1781 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1782 6 : if (!ret) {
1783 0 : return false;
1784 : }
1785 :
1786 : /*OID*/
1787 6 : ret = libspdm_asn1_get_tag(&internal_p, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1788 6 : if (!ret) {
1789 0 : return false;
1790 : }
1791 :
1792 24 : for (cur = x509_attrs; cur->name != NULL; cur++) {
1793 46 : if ((cur->oid_len == obj_len) &&
1794 22 : (libspdm_consttime_is_mem_equal(cur->oid, internal_p, obj_len))) {
1795 : /*Concat subject string*/
1796 :
1797 : /*for example: CN=*/
1798 6 : libspdm_copy_mem(buffer, buff_len, cur->name, cur->name_len);
1799 6 : buff_len = (int32_t)(buff_len - cur->name_len);
1800 6 : buffer += cur->name_len;
1801 6 : *buffer = '=';
1802 6 : buff_len--;
1803 6 : buffer++;
1804 :
1805 : /*move to string*/
1806 6 : internal_p += obj_len;
1807 6 : ret = libspdm_asn1_get_tag(&internal_p, end, &obj_len, cur->default_tag);
1808 6 : if (!ret) {
1809 0 : return false;
1810 : }
1811 :
1812 : /*for example: AU,*/
1813 6 : libspdm_copy_mem(buffer, buff_len, internal_p, obj_len);
1814 6 : buff_len = (int32_t)(buff_len - obj_len);
1815 6 : buffer += obj_len;
1816 6 : *buffer = ',';
1817 6 : buff_len--;
1818 6 : buffer++;
1819 :
1820 6 : if (buff_len < 0) {
1821 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"the buffer is too small"));
1822 0 : return false;
1823 : }
1824 6 : break;
1825 : }
1826 : }
1827 :
1828 : /*can not find the same oid, the subject is wrong*/
1829 6 : if (cur->name == NULL) {
1830 0 : return false;
1831 : }
1832 : }
1833 :
1834 2 : *buffer = '\0';
1835 2 : return true;
1836 : }
1837 :
1838 : /**
1839 : * Set all attributes object form req_info to CSR
1840 : *
1841 : * @param[in] req CSR to set attributes
1842 : * @param[in] req_info requester info to gen CSR
1843 : * @param[in] req_info_len The len of requester info
1844 : *
1845 : * @retval true Success Set.
1846 : * @retval false Set failed.
1847 : **/
1848 2 : bool libspdm_set_attribute_for_req(mbedtls_x509write_csr *req,
1849 : uint8_t *req_info, size_t req_info_len,
1850 : uint8_t *pub_key_der, size_t pub_key_der_len)
1851 : {
1852 : uint8_t *ptr;
1853 : int32_t length;
1854 : size_t obj_len;
1855 : bool ret;
1856 : uint8_t *end;
1857 : uint8_t *ptr_old;
1858 :
1859 : uint8_t *oid;
1860 : size_t oid_len;
1861 : uint8_t *val;
1862 : size_t val_len;
1863 :
1864 : uint8_t *pkinfo;
1865 : size_t pkinfo_len;
1866 : uint8_t buffer[LIBSPDM_MAX_SUBJECT_BUFFER_SIZE];
1867 :
1868 2 : length = (int32_t)req_info_len;
1869 2 : ptr = req_info;
1870 2 : obj_len = 0;
1871 2 : end = ptr + length;
1872 2 : ret = false;
1873 :
1874 2 : if (req_info == NULL) {
1875 0 : return false;
1876 : }
1877 :
1878 : /*req_info sequence, all req_info format is ok because the req_info has been verified before*/
1879 2 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
1880 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1881 :
1882 : /*integer:version*/
1883 2 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
1884 : /*check req_info version. spec PKCS#10: It shall be 0 for this version of the standard.*/
1885 2 : if ((obj_len != 1) || (*ptr != 0)) {
1886 0 : return false;
1887 : }
1888 2 : ptr += obj_len;
1889 :
1890 : /*sequence:subject name*/
1891 2 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
1892 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1893 :
1894 : /**/
1895 2 : libspdm_zero_mem(buffer, sizeof(buffer));
1896 2 : ret = libspdm_convert_subject_to_string(ptr, obj_len, buffer, LIBSPDM_MAX_SUBJECT_BUFFER_SIZE);
1897 2 : if (!ret) {
1898 0 : return false;
1899 : }
1900 :
1901 : /*set subject name*/
1902 2 : ret = mbedtls_x509write_csr_set_subject_name(req, (const char *)buffer);
1903 2 : if (ret != 0) {
1904 0 : return false;
1905 : }
1906 :
1907 2 : ptr += obj_len;
1908 :
1909 2 : pkinfo = ptr;
1910 : /*sequence:subject pkinfo*/
1911 2 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
1912 : LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1913 :
1914 2 : pkinfo_len = obj_len + ptr - pkinfo;
1915 : /*check the public key info*/
1916 4 : if (!((pkinfo_len == pub_key_der_len) &&
1917 2 : (libspdm_consttime_is_mem_equal(pub_key_der, pkinfo, pkinfo_len)))) {
1918 0 : return false;
1919 : }
1920 :
1921 2 : ptr += obj_len;
1922 :
1923 : /*[0]: attributes*/
1924 2 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
1925 : LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
1926 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1927 : /*there is no attributes*/
1928 2 : if (ptr == end) {
1929 0 : return true;
1930 : }
1931 :
1932 : /*there is some attributes object: 1,2 ...*/
1933 4 : while (ret)
1934 : {
1935 2 : ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
1936 : LIBSPDM_CRYPTO_ASN1_SEQUENCE |
1937 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1938 2 : if (ret) {
1939 : /*save old position*/
1940 2 : ptr_old = ptr;
1941 :
1942 : /*move to the next sequence*/
1943 2 : ptr += obj_len;
1944 :
1945 : /*get attributes oid*/
1946 2 : ret = libspdm_asn1_get_tag(&ptr_old, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
1947 2 : if (!ret) {
1948 0 : return false;
1949 : }
1950 2 : oid = ptr_old;
1951 2 : oid_len = obj_len;
1952 :
1953 2 : ptr_old += obj_len;
1954 : /*get attributes val*/
1955 2 : ret = libspdm_asn1_get_tag(&ptr_old, end, &obj_len,
1956 : LIBSPDM_CRYPTO_ASN1_SET |
1957 : LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
1958 2 : if (!ret) {
1959 0 : return false;
1960 : }
1961 2 : ret = libspdm_asn1_get_tag(&ptr_old, end, &obj_len, LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
1962 2 : if (!ret) {
1963 0 : return false;
1964 : }
1965 2 : val = ptr_old;
1966 2 : val_len = obj_len;
1967 :
1968 : /*set attributes*/
1969 2 : ret = mbedtls_x509write_csr_set_extension(req, (const char *)oid, oid_len, 0, val,
1970 : val_len);
1971 :
1972 2 : if (ret) {
1973 0 : return false;
1974 : }
1975 :
1976 : } else {
1977 0 : break;
1978 : }
1979 : }
1980 :
1981 2 : if (ptr == end) {
1982 2 : return true;
1983 : } else {
1984 0 : return false;
1985 : }
1986 : }
1987 :
1988 : /**
1989 : * Gen CSR
1990 : *
1991 : * @param[in] hash_nid hash algo for sign
1992 : * @param[in] asym_nid asym algo for sign
1993 : *
1994 : * @param[in] requester_info requester info to gen CSR
1995 : * @param[in] requester_info_length The len of requester info
1996 : *
1997 : * @param[in] is_ca if true, set basic_constraints: CA:true; Otherwise, set to false.
1998 : *
1999 : * @param[in] context Pointer to asymmetric context
2000 : * @param[in] subject_name Subject name: should be break with ',' in the middle
2001 : * example: "C=AA,CN=BB"
2002 : * Subject names should contain a comma-separated list of OID types and values:
2003 : * The valid OID type name is in:
2004 : * {"CN", "commonName", "C", "countryName", "O", "organizationName","L",
2005 : * "OU", "organizationalUnitName", "ST", "stateOrProvinceName", "emailAddress",
2006 : * "serialNumber", "postalAddress", "postalCode", "dnQualifier", "title",
2007 : * "SN","givenName","GN", "initials", "pseudonym", "generationQualifier", "domainComponent", "DC"}.
2008 : * Note: The object of C and countryName should be CSR Supported Country Codes
2009 : *
2010 : * @param[in, out] csr_len For input, csr_len is the size of store CSR buffer.
2011 : * For output, csr_len is CSR len for DER format
2012 : * @param[in, out] csr_pointer For input, csr_pointer is buffer address to store CSR.
2013 : * For output, csr_pointer is address for stored CSR.
2014 : * The csr_pointer address will be changed.
2015 : * @param[in] base_cert An optional leaf certificate whose
2016 : * extensions should be copied to the CSR
2017 : *
2018 : * @retval true Success.
2019 : * @retval false Failed to gen CSR.
2020 : **/
2021 6 : bool libspdm_gen_x509_csr(size_t hash_nid, size_t asym_nid,
2022 : uint8_t *requester_info, size_t requester_info_length,
2023 : bool is_ca,
2024 : void *context, char *subject_name,
2025 : size_t *csr_len, uint8_t *csr_pointer,
2026 : void *base_cert)
2027 : {
2028 : int ret;
2029 : bool result;
2030 : size_t csr_buffer_size;
2031 :
2032 : mbedtls_x509write_csr req;
2033 : mbedtls_md_type_t md_alg;
2034 : mbedtls_asn1_sequence extns;
2035 : mbedtls_asn1_sequence *next_oid;
2036 : mbedtls_x509_buf buf;
2037 : mbedtls_x509_crt *cert;
2038 : mbedtls_pk_context key;
2039 :
2040 : uint8_t pubkey_buffer[LIBSPDM_MAX_PUBKEY_DER_BUFFER_SIZE];
2041 : uint8_t *pubkey_der_data;
2042 : size_t pubkey_der_len;
2043 : size_t oid_tag_len;
2044 :
2045 : /*basic_constraints: CA: false */
2046 : #define BASIC_CONSTRAINTS_STRING_FALSE {0x30, 0x00}
2047 6 : uint8_t basic_constraints_false[] = BASIC_CONSTRAINTS_STRING_FALSE;
2048 :
2049 : /*basic_constraints: CA: true */
2050 : #define BASIC_CONSTRAINTS_STRING_TRUE {0x30, 0x03, 0x01, 0x01, 0xFF}
2051 6 : uint8_t basic_constraints_true[] = BASIC_CONSTRAINTS_STRING_TRUE;
2052 :
2053 : /* Init */
2054 6 : mbedtls_x509write_csr_init(&req);
2055 6 : mbedtls_pk_init(&key);
2056 6 : csr_buffer_size = *csr_len;
2057 6 : libspdm_zero_mem(&extns, sizeof(mbedtls_asn1_sequence));
2058 6 : next_oid = NULL;
2059 :
2060 6 : ret = 1;
2061 6 : switch (asym_nid)
2062 : {
2063 0 : case LIBSPDM_CRYPTO_NID_RSASSA2048:
2064 : case LIBSPDM_CRYPTO_NID_RSAPSS2048:
2065 : case LIBSPDM_CRYPTO_NID_RSASSA3072:
2066 : case LIBSPDM_CRYPTO_NID_RSAPSS3072:
2067 : case LIBSPDM_CRYPTO_NID_RSASSA4096:
2068 : case LIBSPDM_CRYPTO_NID_RSAPSS4096:
2069 0 : ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
2070 0 : if (ret != 0) {
2071 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_pk_setup %d", ret));
2072 0 : goto free_all;
2073 : }
2074 0 : ret = mbedtls_rsa_copy(mbedtls_pk_rsa(key), (mbedtls_rsa_context *)context);
2075 0 : if (ret != 0) {
2076 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_rsa_copy %d", ret));
2077 0 : goto free_all;
2078 : }
2079 0 : ret = mbedtls_rsa_complete(mbedtls_pk_rsa(key));
2080 0 : if (ret != 0) {
2081 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_rsa_complete %d", ret));
2082 0 : goto free_all;
2083 : }
2084 0 : break;
2085 6 : case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P256:
2086 : case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P384:
2087 : case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P521:
2088 6 : ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
2089 6 : if (ret != 0) {
2090 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_pk_setup %d", ret));
2091 0 : goto free_all;
2092 : }
2093 : /*mbedtls_ecdh_context include mbedtls_ecdsa_context,can be treated as mbedtls_ecdsa_context*/
2094 6 : ret = mbedtls_ecdsa_from_keypair(mbedtls_pk_ec(key), (mbedtls_ecdsa_context *)context);
2095 6 : if (ret != 0) {
2096 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_ecdsa_from_keypair %d", ret));
2097 0 : goto free_all;
2098 : }
2099 6 : break;
2100 0 : default:
2101 0 : return false;
2102 : }
2103 :
2104 6 : switch (hash_nid)
2105 : {
2106 6 : case LIBSPDM_CRYPTO_NID_SHA256:
2107 6 : md_alg = MBEDTLS_MD_SHA256;
2108 6 : break;
2109 0 : case LIBSPDM_CRYPTO_NID_SHA384:
2110 0 : md_alg = MBEDTLS_MD_SHA384;
2111 0 : break;
2112 0 : case LIBSPDM_CRYPTO_NID_SHA512:
2113 0 : md_alg = MBEDTLS_MD_SHA512;
2114 0 : break;
2115 0 : case LIBSPDM_CRYPTO_NID_SHA3_256:
2116 0 : md_alg = MBEDTLS_MD_SHA3_256;
2117 0 : break;
2118 0 : case LIBSPDM_CRYPTO_NID_SHA3_384:
2119 0 : md_alg = MBEDTLS_MD_SHA3_384;
2120 0 : break;
2121 0 : case LIBSPDM_CRYPTO_NID_SHA3_512:
2122 0 : md_alg = MBEDTLS_MD_SHA3_512;
2123 0 : break;
2124 0 : default:
2125 0 : ret = 1;
2126 0 : goto free_all;
2127 : }
2128 :
2129 : /* Set the md alg */
2130 6 : mbedtls_x509write_csr_set_md_alg(&req, md_alg);
2131 :
2132 : /* Set the subject name */
2133 6 : if (subject_name != NULL) {
2134 6 : ret = mbedtls_x509write_csr_set_subject_name(&req, subject_name);
2135 6 : if (ret != 0) {
2136 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2137 : "failed\n ! mbedtls_x509write_csr_set_subject_name returned %d", ret));
2138 0 : goto free_all;
2139 : }
2140 : }
2141 :
2142 6 : libspdm_zero_mem(pubkey_buffer, sizeof(pubkey_buffer));
2143 6 : pubkey_der_len = mbedtls_pk_write_pubkey_der(&key, pubkey_buffer, sizeof(pubkey_buffer));
2144 6 : if (pubkey_der_len > 0) {
2145 : /*Note: data is written at the end of the buffer!*/
2146 6 : pubkey_der_data = pubkey_buffer + sizeof(pubkey_buffer) - pubkey_der_len;
2147 : } else {
2148 0 : goto free_all;
2149 : }
2150 :
2151 : /* requester info parse
2152 : * check the req_info version and subjectPKInfo;
2153 : * get attribute and subject from req_info and set them to CSR;
2154 : **/
2155 6 : if (requester_info_length != 0) {
2156 2 : result = libspdm_set_attribute_for_req(&req, requester_info, requester_info_length,
2157 : pubkey_der_data, pubkey_der_len);
2158 2 : if (!result) {
2159 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"set_attribute failed !\n"));
2160 0 : goto free_all;
2161 : }
2162 : }
2163 :
2164 : /* Set key */
2165 6 : mbedtls_x509write_csr_set_key(&req, &key);
2166 :
2167 : /*set basicConstraints*/
2168 6 : if (mbedtls_x509write_csr_set_extension(&req, MBEDTLS_OID_BASIC_CONSTRAINTS,
2169 : MBEDTLS_OID_SIZE(MBEDTLS_OID_BASIC_CONSTRAINTS),
2170 : 0,
2171 : is_ca ? basic_constraints_true : basic_constraints_false,
2172 : is_ca ?
2173 : sizeof(basic_constraints_true) :
2174 : sizeof(basic_constraints_false)
2175 : ) != 0) {
2176 0 : ret = 1;
2177 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2178 : "mbedtls_x509write_csr_set_extension set basicConstraints failed \n"));
2179 0 : goto free_all;
2180 : }
2181 :
2182 6 : if (base_cert != NULL) {
2183 6 : cert = base_cert;
2184 6 : buf = cert->v3_ext;
2185 6 : if (mbedtls_asn1_get_sequence_of(&buf.p, buf.p + buf.len, &extns,
2186 : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
2187 0 : ret = 1;
2188 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2189 : "mbedtls_x509write_csr_set_extension unable to get sequence\n"));
2190 0 : goto free_all;
2191 : }
2192 :
2193 6 : next_oid = &extns;
2194 : }
2195 :
2196 42 : while (next_oid) {
2197 36 : if (mbedtls_asn1_get_tag(&(next_oid->buf.p), next_oid->buf.p + next_oid->buf.len,
2198 : &oid_tag_len, MBEDTLS_ASN1_OID)) {
2199 0 : ret = 1;
2200 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2201 : "mbedtls_x509write_csr_set_extension unable to get OID tag\n"));
2202 0 : goto free_all;
2203 : }
2204 :
2205 36 : if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_BASIC_CONSTRAINTS, next_oid->buf.p, oid_tag_len) == 0) {
2206 6 : next_oid = next_oid->next;
2207 6 : continue;
2208 : }
2209 :
2210 30 : if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, next_oid->buf.p,
2211 : oid_tag_len) == 0) {
2212 0 : next_oid = next_oid->next;
2213 0 : continue;
2214 : }
2215 :
2216 30 : if (mbedtls_x509write_csr_set_extension(&req, (const char *)next_oid->buf.p,
2217 : oid_tag_len, 0,
2218 30 : next_oid->buf.p + oid_tag_len,
2219 30 : next_oid->buf.len - oid_tag_len
2220 : ) != 0) {
2221 0 : ret = 1;
2222 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
2223 : "mbedtls_x509write_csr_set_extension set custom OID failed \n"));
2224 0 : goto free_all;
2225 : }
2226 :
2227 30 : next_oid = next_oid->next;
2228 : }
2229 :
2230 : /*csr data is written at the end of the buffer*/
2231 6 : ret = mbedtls_x509write_csr_der(&req, csr_pointer, csr_buffer_size, libspdm_myrand, NULL);
2232 6 : if (ret <= 0) {
2233 0 : ret = 1;
2234 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"mbedtls_x509write_csr_der failed \n"));
2235 0 : goto free_all;
2236 : }
2237 :
2238 6 : *csr_len = (size_t)ret;
2239 : /*make csr_pointer store csr data*/
2240 6 : memmove(csr_pointer, csr_pointer + csr_buffer_size - *csr_len, *csr_len);
2241 :
2242 6 : ret = 0;
2243 6 : free_all:
2244 6 : mbedtls_x509write_csr_free(&req);
2245 6 : mbedtls_asn1_sequence_free(extns.next);
2246 6 : mbedtls_pk_free(&key);
2247 :
2248 6 : return(ret == 0);
2249 : }
2250 :
2251 0 : bool libspdm_gen_x509_csr_with_pqc(
2252 : size_t hash_nid, size_t asym_nid, size_t pqc_asym_nid,
2253 : uint8_t *requester_info, size_t requester_info_length,
2254 : bool is_ca,
2255 : void *context, char *subject_name,
2256 : size_t *csr_len, uint8_t *csr_pointer,
2257 : void *base_cert)
2258 : {
2259 0 : if (pqc_asym_nid != 0) {
2260 0 : return false;
2261 : }
2262 0 : return libspdm_gen_x509_csr(hash_nid, asym_nid, requester_info,
2263 : requester_info_length, is_ca, context,
2264 : subject_name, csr_len, csr_pointer, base_cert);
2265 : }
2266 :
2267 : #endif
|