LCOV - code coverage report
Current view: top level - os_stub/cryptlib_mbedtls/pk - x509.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 63.0 % 706 445
Test Date: 2025-10-12 08:10:56 Functions: 63.4 % 41 26

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

Generated by: LCOV version 2.0-1