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.6 % 711 452
Test Date: 2025-11-02 08:10:32 Functions: 65.9 % 41 27

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

Generated by: LCOV version 2.0-1