LCOV - code coverage report
Current view: top level - os_stub/cryptlib_mbedtls/pk - x509.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 62.9 % 704 443
Test Date: 2025-09-14 08:11:04 Functions: 62.5 % 40 25

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

Generated by: LCOV version 2.0-1