LCOV - code coverage report
Current view: top level - os_stub/cryptlib_mbedtls/pk - x509.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 63.3 % 679 430
Test Date: 2025-06-29 08:09:00 Functions: 63.2 % 38 24

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2024 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        14760 : bool libspdm_asn1_get_tag(uint8_t **ptr, const uint8_t *end, size_t *length,
     244              :                           uint32_t tag)
     245              : {
     246        14760 :     if (mbedtls_asn1_get_tag(ptr, end, length, (int32_t)tag) == 0) {
     247        14731 :         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          827 : 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          827 :     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          827 :     status = false;
     287              : 
     288          827 :     mbedtls_x509_crt_init(&crt);
     289              : 
     290          827 :     ret = mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
     291              : 
     292          827 :     if (ret == 0) {
     293          827 :         if (*subject_size < crt.subject_raw.len) {
     294          768 :             *subject_size = crt.subject_raw.len;
     295          768 :             status = false;
     296          768 :             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          827 : cleanup:
     309          827 :     mbedtls_x509_crt_free(&crt);
     310              : 
     311          827 :     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          925 : 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          925 :     mbedtls_x509_crt_init(&crt);
     551              : 
     552          925 :     if (mbedtls_x509_crt_parse_der(&crt, cert, cert_size) != 0) {
     553            0 :         return false;
     554              :     }
     555              : 
     556          925 :     if (mbedtls_pk_get_type(&crt.pk) != MBEDTLS_PK_ECKEY) {
     557            1 :         mbedtls_x509_crt_free(&crt);
     558            1 :         return false;
     559              :     }
     560              : 
     561          924 :     ecdh = allocate_zero_pool(sizeof(mbedtls_ecdh_context));
     562          924 :     if (ecdh == NULL) {
     563            0 :         mbedtls_x509_crt_free(&crt);
     564            0 :         return false;
     565              :     }
     566          924 :     mbedtls_ecdh_init(ecdh);
     567              : 
     568          924 :     ret = mbedtls_ecdh_get_params(ecdh, mbedtls_pk_ec(crt.pk),
     569              :                                   MBEDTLS_ECDH_OURS);
     570          924 :     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          924 :     mbedtls_x509_crt_free(&crt);
     577              : 
     578          924 :     *ec_context = ecdh;
     579          924 :     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         2375 : 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         2375 :     uint32_t v_flag = 0;
     648         2375 :     mbedtls_x509_crt_profile profile = { 0 };
     649              : 
     650         2375 :     if (cert == NULL || ca_cert == NULL) {
     651            0 :         return false;
     652              :     }
     653              : 
     654         2375 :     libspdm_copy_mem(&profile, sizeof(profile),
     655              :                      &mbedtls_x509_crt_profile_default,
     656              :                      sizeof(mbedtls_x509_crt_profile));
     657              : 
     658         2375 :     mbedtls_x509_crt_init(&ca);
     659         2375 :     mbedtls_x509_crt_init(&end);
     660              : 
     661         2375 :     ret = mbedtls_x509_crt_parse_der(&ca, ca_cert, ca_cert_size);
     662              : 
     663         2375 :     if (ret == 0) {
     664         2375 :         ret = mbedtls_x509_crt_parse_der(&end, cert, cert_size);
     665              :     }
     666              : 
     667         2375 :     if (ret == 0) {
     668         2375 :         ret = mbedtls_x509_crt_verify_with_profile(
     669              :             &end, &ca, NULL, &profile, NULL, &v_flag, NULL, NULL);
     670              :     }
     671              : 
     672         2375 :     mbedtls_x509_crt_free(&ca);
     673         2375 :     mbedtls_x509_crt_free(&end);
     674              : 
     675         2375 :     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          745 : 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          745 :     verify_flag = false;
     709          745 :     preceding_cert = root_cert;
     710          745 :     preceding_cert_len = root_cert_length;
     711              : 
     712          745 :     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         3116 :         tmp_ptr = current_cert;
     719         3116 :         ret = mbedtls_asn1_get_tag(
     720         3116 :             &tmp_ptr, cert_chain + cert_chain_length, &asn1_len,
     721              :             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
     722         3116 :         if (ret != 0) {
     723          742 :             if (current_cert < cert_chain + cert_chain_length) {
     724            2 :                 verify_flag = false;
     725              :             }
     726          742 :             break;
     727              :         }
     728              : 
     729         2374 :         current_cert_len = asn1_len + (tmp_ptr - current_cert);
     730              : 
     731         2374 :         if (current_cert + current_cert_len > cert_chain + cert_chain_length) {
     732            0 :             verify_flag = false;
     733            0 :             break;
     734              :         }
     735              : 
     736         2374 :         if (libspdm_x509_verify_cert(current_cert, current_cert_len,
     737              :                                      preceding_cert,
     738         2374 :                                      preceding_cert_len) == false) {
     739            3 :             verify_flag = false;
     740            3 :             break;
     741              :         } else {
     742         2371 :             verify_flag = true;
     743              :         }
     744              : 
     745              : 
     746              :         /* Save preceding certificate*/
     747              : 
     748         2371 :         preceding_cert = current_cert;
     749         2371 :         preceding_cert_len = current_cert_len;
     750              : 
     751              : 
     752              :         /* Move current certificate to next;*/
     753              : 
     754         2371 :         current_cert = current_cert + current_cert_len;
     755              :     } while (true);
     756              : 
     757          745 :     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         2505 : 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         2505 :     current_cert_len = 0;
     791              : 
     792              :     /* Check input parameters.*/
     793              : 
     794         2505 :     if ((cert_chain == NULL) || (cert == NULL) || (cert_index < -1) ||
     795              :         (cert_length == NULL)) {
     796            0 :         return false;
     797              :     }
     798              : 
     799         2505 :     current_cert = (const unsigned char *)cert_chain;
     800         2505 :     current_index = -1;
     801              : 
     802              : 
     803              :     /* Traverse the certificate chain*/
     804              : 
     805              :     while (true) {
     806              : 
     807              :         /* Get asn1 tag len*/
     808              : 
     809         5681 :         tmp_ptr = current_cert;
     810         5681 :         ret = mbedtls_asn1_get_tag(
     811         5681 :             &tmp_ptr, cert_chain + cert_chain_length, &asn1_len,
     812              :             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
     813         5681 :         if (ret != 0) {
     814         1000 :             break;
     815              :         }
     816              : 
     817         4681 :         current_cert_len = asn1_len + (tmp_ptr - current_cert);
     818         4681 :         if (current_cert + current_cert_len > cert_chain + cert_chain_length) {
     819            0 :             return false;
     820              :         }
     821              : 
     822         4681 :         current_index++;
     823              : 
     824         4681 :         if (current_index == cert_index) {
     825         1505 :             *cert = current_cert;
     826         1505 :             *cert_length = current_cert_len;
     827         1505 :             return true;
     828              :         }
     829              : 
     830              : 
     831              :         /* Move to next*/
     832              : 
     833         3176 :         current_cert = current_cert + current_cert_len;
     834              :     }
     835              : 
     836              : 
     837              :     /* If cert_index is -1, Return the last certificate*/
     838              : 
     839         1000 :     if (cert_index == -1 && current_index >= 0) {
     840         1000 :         *cert = current_cert - current_cert_len;
     841         1000 :         *cert_length = current_cert_len;
     842         1000 :         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          770 : 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          770 :     if (cert == NULL) {
     894            0 :         return false;
     895              :     }
     896              : 
     897          770 :     status = false;
     898              : 
     899          770 :     mbedtls_x509_crt_init(&crt);
     900              : 
     901          770 :     ret = mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
     902              : 
     903          770 :     if (ret == 0) {
     904          770 :         *version = crt.version - 1;
     905          770 :         status = true;
     906              :     }
     907              : 
     908          770 :     mbedtls_x509_crt_free(&crt);
     909              : 
     910          770 :     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          770 : 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          770 :     if (cert == NULL) {
     945            0 :         return false;
     946              :     }
     947              : 
     948          770 :     status = false;
     949              : 
     950          770 :     mbedtls_x509_crt_init(&crt);
     951              : 
     952          770 :     ret = mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
     953              : 
     954          770 :     if (ret == 0) {
     955          770 :         if (*serial_number_size <= crt.serial.len) {
     956          770 :             *serial_number_size = crt.serial.len + 1;
     957          770 :             status = false;
     958          770 :             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          770 :     mbedtls_x509_crt_free(&crt);
     969              : 
     970          770 :     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          827 : 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          827 :     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          827 :     status = false;
    1009              : 
    1010          827 :     mbedtls_x509_crt_init(&crt);
    1011              : 
    1012          827 :     ret = mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
    1013              : 
    1014          827 :     if (ret == 0) {
    1015          827 :         if (*issuer_size < crt.issuer_raw.len) {
    1016          768 :             *issuer_size = crt.issuer_raw.len;
    1017          768 :             status = false;
    1018          768 :             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          827 : cleanup:
    1030          827 :     mbedtls_x509_crt_free(&crt);
    1031              : 
    1032          827 :     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              : #if LIBSPDM_ADDITIONAL_CHECK_CERT
    1109              : /**
    1110              :  * Retrieve the signature algorithm from one X.509 certificate.
    1111              :  *
    1112              :  * @param[in]      cert             Pointer to the DER-encoded X509 certificate.
    1113              :  * @param[in]      cert_size         size of the X509 certificate in bytes.
    1114              :  * @param[out]     oid              signature algorithm Object identifier buffer.
    1115              :  * @param[in,out]  oid_size          signature algorithm Object identifier buffer size
    1116              :  *
    1117              :  * @retval  true    if the oid_size is equal 0, the cert parse successfully, but cert doesn't have signature algo.
    1118              :  * @retval  true    if the oid_size is not equal 0, the cert parse and get signature algo successfully.
    1119              :  * @retval  false   if the oid_size is equal 0, the cert parse failed.
    1120              :  * @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.
    1121              :  **/
    1122              : bool libspdm_x509_get_signature_algorithm(const uint8_t *cert,
    1123              :                                           size_t cert_size, uint8_t *oid,
    1124              :                                           size_t *oid_size)
    1125              : {
    1126              :     mbedtls_x509_crt crt;
    1127              :     int ret;
    1128              :     bool status;
    1129              : 
    1130              :     /* Check input parameters.*/
    1131              :     if (cert == NULL || cert_size == 0 || oid_size == NULL) {
    1132              :         if (oid_size != NULL) {
    1133              :             *oid_size = 0;
    1134              :         }
    1135              :         return false;
    1136              :     }
    1137              : 
    1138              :     status = false;
    1139              : 
    1140              :     mbedtls_x509_crt_init(&crt);
    1141              : 
    1142              :     ret = mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
    1143              : 
    1144              :     if (ret == 0) {
    1145              :         if (*oid_size < crt.sig_oid.len) {
    1146              :             *oid_size = crt.serial.len;
    1147              :             status = false;
    1148              :             goto cleanup;
    1149              :         }
    1150              :         if (oid != NULL) {
    1151              :             libspdm_copy_mem(oid, *oid_size, crt.sig_oid.p, crt.sig_oid.len);
    1152              :         }
    1153              :         *oid_size = crt.sig_oid.len;
    1154              :         status = true;
    1155              :     } else {
    1156              :         *oid_size = 0;
    1157              :     }
    1158              : 
    1159              : cleanup:
    1160              :     mbedtls_x509_crt_free(&crt);
    1161              : 
    1162              :     return status;
    1163              : }
    1164              : #endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */
    1165              : 
    1166              : /**
    1167              :  * Find first Extension data match with given OID
    1168              :  *
    1169              :  * @param[in]      start             Pointer to the DER-encoded extensions data
    1170              :  * @param[in]      end               extensions data size in bytes
    1171              :  * @param[in ]     oid               OID for match
    1172              :  * @param[in ]     oid_size           OID size in bytes
    1173              :  * @param[out]     find_extension_data output matched extension data.
    1174              :  * @param[out]     find_extension_data_len matched extension data size.
    1175              :  *
    1176              :  **/
    1177              : static bool
    1178         2302 : libspdm_internal_x509_find_extension_data(uint8_t *start, uint8_t *end, const uint8_t *oid,
    1179              :                                           size_t oid_size, uint8_t **find_extension_data,
    1180              :                                           size_t *find_extension_data_len)
    1181              : {
    1182              :     uint8_t *ptr;
    1183              :     uint8_t *extension_ptr;
    1184              :     size_t obj_len;
    1185              :     int ret;
    1186              :     bool status;
    1187              :     size_t find_extension_len;
    1188              :     size_t header_len;
    1189              : 
    1190              :     /*If no Extension entry match oid*/
    1191         2302 :     status = false;
    1192         2302 :     ptr = start;
    1193              : 
    1194         2302 :     ret = 0;
    1195              : 
    1196              :     while (true) {
    1197              :         /*
    1198              :          * Extension  ::=  SEQUENCE  {
    1199              :          *      extnID      OBJECT IDENTIFIER,
    1200              :          *      critical    bool DEFAULT false,
    1201              :          *      extnValue   OCTET STRING  }
    1202              :          */
    1203         9239 :         extension_ptr = ptr;
    1204         9239 :         ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
    1205              :                                    MBEDTLS_ASN1_CONSTRUCTED |
    1206              :                                    MBEDTLS_ASN1_SEQUENCE);
    1207         9239 :         if (ret == 0) {
    1208         9224 :             header_len = (size_t)(ptr - extension_ptr);
    1209         9224 :             find_extension_len = obj_len;
    1210              :             /* Get Object Identifier*/
    1211         9224 :             ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
    1212              :                                        MBEDTLS_ASN1_OID);
    1213              :         } else {
    1214           15 :             break;
    1215              :         }
    1216              : 
    1217         9224 :         if (ret == 0 && libspdm_consttime_is_mem_equal(ptr, oid, oid_size)) {
    1218         2287 :             ptr += obj_len;
    1219              : 
    1220         2287 :             ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
    1221              :                                        MBEDTLS_ASN1_BOOLEAN);
    1222         2287 :             if (ret == 0) {
    1223         1523 :                 ptr += obj_len;
    1224              :             }
    1225              : 
    1226         2287 :             ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
    1227              :                                        MBEDTLS_ASN1_OCTET_STRING);
    1228              :         } else {
    1229         6937 :             ret = 1;
    1230              :         }
    1231              : 
    1232         9224 :         if (ret == 0) {
    1233         2287 :             *find_extension_data = ptr;
    1234         2287 :             *find_extension_data_len = obj_len;
    1235         2287 :             status = true;
    1236         2287 :             break;
    1237              :         }
    1238              : 
    1239              :         /* move to next*/
    1240         6937 :         ptr = extension_ptr + header_len + find_extension_len;
    1241         6937 :         ret = 0;
    1242              :     }
    1243              : 
    1244         2302 :     return status;
    1245              : }
    1246              : 
    1247              : /**
    1248              :  * Retrieve Extension data from one X.509 certificate.
    1249              :  *
    1250              :  * @param[in]      cert             Pointer to the DER-encoded X509 certificate.
    1251              :  * @param[in]      cert_size         size of the X509 certificate in bytes.
    1252              :  * @param[in]      oid              Object identifier buffer
    1253              :  * @param[in]      oid_size          Object identifier buffer size
    1254              :  * @param[out]     extension_data    Extension bytes.
    1255              :  * @param[in, out] extension_data_size Extension bytes size.
    1256              :  *
    1257              :  * @retval true   If the returned extension_data_size == 0, it means that cert and oid are valid, but the oid extension is not found;
    1258              :  *                If the returned extension_data_size != 0, it means that cert and oid are valid, and the oid extension is found;
    1259              :  * @retval false  If the returned extension_data_size == 0, it means that cert or oid are invalid;
    1260              :  *                If the returned extension_data_size != 0, it means that cert and oid are valid, and the oid extension is found,
    1261              :  *                                                          but the store buffer is too small.
    1262              :  **/
    1263         2302 : bool libspdm_x509_get_extension_data(const uint8_t *cert, size_t cert_size,
    1264              :                                      const uint8_t *oid, size_t oid_size,
    1265              :                                      uint8_t *extension_data,
    1266              :                                      size_t *extension_data_size)
    1267              : {
    1268              :     mbedtls_x509_crt crt;
    1269              :     int ret;
    1270              :     bool status;
    1271              :     uint8_t *ptr;
    1272              :     uint8_t *end;
    1273              :     size_t obj_len;
    1274              : 
    1275         2302 :     ptr = NULL;
    1276         2302 :     end = NULL;
    1277         2302 :     obj_len = 0;
    1278              : 
    1279         2302 :     if (cert == NULL || cert_size == 0 || oid == NULL || oid_size == 0 ||
    1280              :         extension_data_size == NULL) {
    1281            0 :         if (extension_data_size != NULL) {
    1282            0 :             *extension_data_size = 0;
    1283              :         }
    1284            0 :         return false;
    1285              :     }
    1286              : 
    1287         2302 :     status = false;
    1288              : 
    1289         2302 :     mbedtls_x509_crt_init(&crt);
    1290              : 
    1291         2302 :     ret = mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
    1292              : 
    1293         2302 :     if (ret == 0) {
    1294         2302 :         ptr = crt.v3_ext.p;
    1295         2302 :         end = crt.v3_ext.p + crt.v3_ext.len;
    1296         2302 :         ret = mbedtls_asn1_get_tag(&ptr, end, &obj_len,
    1297              :                                    MBEDTLS_ASN1_CONSTRUCTED |
    1298              :                                    MBEDTLS_ASN1_SEQUENCE);
    1299              :     }
    1300              : 
    1301         2302 :     if (ret == 0) {
    1302         2302 :         status = libspdm_internal_x509_find_extension_data(
    1303              :             ptr, end, oid, oid_size, &ptr, &obj_len);
    1304         2302 :         if (!status) {
    1305           15 :             status = true;
    1306           15 :             *extension_data_size = 0;
    1307           15 :             goto cleanup;
    1308              :         }
    1309              :     }
    1310              : 
    1311         2287 :     if (status) {
    1312         2287 :         if (*extension_data_size < obj_len) {
    1313            6 :             *extension_data_size = obj_len;
    1314            6 :             status = false;
    1315            6 :             goto cleanup;
    1316              :         }
    1317         2281 :         if (oid != NULL) {
    1318         2281 :             libspdm_copy_mem(extension_data, *extension_data_size, ptr, obj_len);
    1319              :         }
    1320         2281 :         *extension_data_size = obj_len;
    1321              :     } else {
    1322            0 :         *extension_data_size = 0;
    1323              :     }
    1324              : 
    1325         2302 : cleanup:
    1326         2302 :     mbedtls_x509_crt_free(&crt);
    1327              : 
    1328         2302 :     return status;
    1329              : }
    1330              : 
    1331              : /**
    1332              :  * Retrieve the Validity from one X.509 certificate
    1333              :  *
    1334              :  * If cert is NULL, then return false.
    1335              :  * If CertIssuerSize is NULL, then return false.
    1336              :  * If this interface is not supported, then return false.
    1337              :  *
    1338              :  * @param[in]      cert         Pointer to the DER-encoded X509 certificate.
    1339              :  * @param[in]      cert_size     size of the X509 certificate in bytes.
    1340              :  * @param[out]     from         notBefore Pointer to date_time object.
    1341              :  * @param[in,out]  from_size     notBefore date_time object size.
    1342              :  * @param[out]     to           notAfter Pointer to date_time object.
    1343              :  * @param[in,out]  to_size       notAfter date_time object size.
    1344              :  *
    1345              :  * Note: libspdm_x509_compare_date_time to compare date_time object
    1346              :  *      x509SetDateTime to get a date_time object from a date_time_str
    1347              :  *
    1348              :  * @retval  true   The certificate Validity retrieved successfully.
    1349              :  * @retval  false  Invalid certificate, or Validity retrieve failed.
    1350              :  * @retval  false  This interface is not supported.
    1351              :  **/
    1352          768 : bool libspdm_x509_get_validity(const uint8_t *cert, size_t cert_size,
    1353              :                                uint8_t *from, size_t *from_size, uint8_t *to,
    1354              :                                size_t *to_size)
    1355              : {
    1356              :     mbedtls_x509_crt crt;
    1357              :     int ret;
    1358              :     bool status;
    1359              :     size_t t_size;
    1360              :     size_t f_size;
    1361              :     mbedtls_x509_time zero_time;
    1362              : 
    1363              :     /* Check input parameters.*/
    1364          768 :     if (cert == NULL || from_size == NULL || to_size == NULL ||
    1365              :         cert_size == 0) {
    1366            0 :         if (from_size != NULL) {
    1367            0 :             *from_size = 0;
    1368              :         }
    1369            0 :         if (to_size != NULL) {
    1370            0 :             *to_size = 0;
    1371              :         }
    1372            0 :         return false;
    1373              :     }
    1374              : 
    1375          768 :     status = false;
    1376              : 
    1377          768 :     mbedtls_x509_crt_init(&crt);
    1378          768 :     libspdm_zero_mem(&zero_time, sizeof(mbedtls_x509_time));
    1379              : 
    1380          768 :     ret = mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
    1381              : 
    1382          768 :     if (ret == 0) {
    1383          768 :         f_size = sizeof(mbedtls_x509_time);
    1384          768 :         if ((libspdm_consttime_is_mem_equal(&zero_time, &(crt.valid_from), f_size)) &&
    1385            0 :             (libspdm_consttime_is_mem_equal(&zero_time, &(crt.valid_to), f_size))) {
    1386            0 :             *from_size = 0;
    1387            0 :             *to_size = 0;
    1388            0 :             status = true;
    1389            0 :             goto done;
    1390              :         }
    1391              : 
    1392          768 :         if (*from_size < f_size) {
    1393            0 :             *from_size = f_size;
    1394            0 :             goto done;
    1395              :         }
    1396          768 :         if (from != NULL) {
    1397          768 :             libspdm_copy_mem(from, *from_size, &(crt.valid_from), f_size);
    1398              :         }
    1399          768 :         *from_size = f_size;
    1400              : 
    1401          768 :         t_size = sizeof(mbedtls_x509_time);
    1402          768 :         if (*to_size < t_size) {
    1403            0 :             *to_size = t_size;
    1404            0 :             goto done;
    1405              :         }
    1406          768 :         if (to != NULL) {
    1407          768 :             libspdm_copy_mem(to, *to_size, &(crt.valid_to),
    1408              :                              sizeof(mbedtls_x509_time));
    1409              :         }
    1410          768 :         *to_size = t_size;
    1411          768 :         status = true;
    1412              :     } else {
    1413            0 :         *from_size = 0;
    1414            0 :         *to_size = 0;
    1415              :     }
    1416              : 
    1417          768 : done:
    1418          768 :     mbedtls_x509_crt_free(&crt);
    1419              : 
    1420          768 :     return status;
    1421              : }
    1422              : 
    1423              : /**
    1424              :  * Retrieve the key usage from one X.509 certificate.
    1425              :  *
    1426              :  * @param[in]      cert             Pointer to the DER-encoded X509 certificate.
    1427              :  * @param[in]      cert_size         size of the X509 certificate in bytes.
    1428              :  * @param[out]     usage            key usage (LIBSPDM_CRYPTO_X509_KU_*)
    1429              :  *
    1430              :  * @retval  true   if the usage is no equal 0. The certificate key usage retrieved successfully.
    1431              :  * @retval  true   if the usage is equal 0. The certificate parse successfully, but the cert doesn't have key usage.
    1432              :  * @retval  false  Invalid certificate, or usage is NULL.
    1433              :  **/
    1434          762 : bool libspdm_x509_get_key_usage(const uint8_t *cert, size_t cert_size,
    1435              :                                 size_t *usage)
    1436              : {
    1437              :     mbedtls_x509_crt crt;
    1438              :     int ret;
    1439              :     bool status;
    1440              : 
    1441              :     /* Check input parameters.*/
    1442          762 :     if (cert == NULL || cert_size == 0 || usage == NULL) {
    1443            0 :         if (usage != NULL) {
    1444            0 :             *usage = 0;
    1445              :         }
    1446            0 :         return false;
    1447              :     }
    1448              : 
    1449          762 :     status = false;
    1450              : 
    1451          762 :     mbedtls_x509_crt_init(&crt);
    1452              : 
    1453          762 :     ret = mbedtls_x509_crt_parse_der(&crt, cert, cert_size);
    1454              : 
    1455          762 :     if (ret == 0) {
    1456          762 :         *usage = crt.MBEDTLS_PRIVATE(key_usage);
    1457          762 :         status = true;
    1458              :     } else {
    1459            0 :         *usage = 0;
    1460              :     }
    1461          762 :     mbedtls_x509_crt_free(&crt);
    1462              : 
    1463          762 :     return status;
    1464              : }
    1465              : 
    1466              : /**
    1467              :  * Retrieve the Extended key usage from one X.509 certificate.
    1468              :  *
    1469              :  * @param[in]      cert             Pointer to the DER-encoded X509 certificate.
    1470              :  * @param[in]      cert_size         size of the X509 certificate in bytes.
    1471              :  * @param[out]     usage            key usage bytes.
    1472              :  * @param[in, out] usage_size        key usage buffer sizs in bytes.
    1473              :  *
    1474              :  * @retval true   If the returned usage_size == 0, it means that cert and oid are valid, but the Extended key usage is not found;
    1475              :  *                If the returned usage_size != 0, it means that cert and oid are valid, and the Extended key usage is found;
    1476              :  * @retval false  If the returned usage_size == 0, it means that cert or oid are invalid;
    1477              :  *                If the returned usage_size != 0, it means that cert and oid are valid, and the Extended key usage is found,
    1478              :  *                                                 but the store buffer is too small.
    1479              :  **/
    1480          768 : bool libspdm_x509_get_extended_key_usage(const uint8_t *cert,
    1481              :                                          size_t cert_size, uint8_t *usage,
    1482              :                                          size_t *usage_size)
    1483              : {
    1484              :     bool status;
    1485              : 
    1486          768 :     if (cert == NULL || cert_size == 0 || usage_size == NULL) {
    1487            0 :         return false;
    1488              :     }
    1489              : 
    1490          768 :     status = libspdm_x509_get_extension_data(cert, cert_size,
    1491              :                                              m_libspdm_oid_ext_key_usage,
    1492              :                                              sizeof(m_libspdm_oid_ext_key_usage), usage,
    1493              :                                              usage_size);
    1494              : 
    1495          768 :     return status;
    1496              : }
    1497              : 
    1498              : /**
    1499              :  * Retrieve the basic constraints from one X.509 certificate.
    1500              :  *
    1501              :  * @param[in]      cert                     Pointer to the DER-encoded X509 certificate.
    1502              :  * @param[in]      cert_size                size of the X509 certificate in bytes.
    1503              :  * @param[out]     basic_constraints        basic constraints bytes.
    1504              :  * @param[in, out] basic_constraints_size   basic constraints buffer sizs in bytes.
    1505              :  *
    1506              :  * @retval true   If the returned basic_constraints_size == 0, it means that cert and oid are valid, but the basic_constraints is not found;
    1507              :  *                If the returned basic_constraints_size != 0, it means that cert and oid are valid, and the basic_constraints is found;
    1508              :  * @retval false  If the returned basic_constraints_size == 0, it means that cert or oid are invalid;
    1509              :  *                If the returned basic_constraints_size != 0, it means that cert and oid are valid, and the basic_constraints is found,
    1510              :  *                                                             but the store buffer is too small.
    1511              :  **/
    1512          762 : bool libspdm_x509_get_extended_basic_constraints(const uint8_t *cert,
    1513              :                                                  size_t cert_size,
    1514              :                                                  uint8_t *basic_constraints,
    1515              :                                                  size_t *basic_constraints_size)
    1516              : {
    1517              :     bool status;
    1518              : 
    1519          762 :     if (cert == NULL || cert_size == 0 || basic_constraints_size == NULL) {
    1520            0 :         return false;
    1521              :     }
    1522              : 
    1523          762 :     status = libspdm_x509_get_extension_data(cert, cert_size,
    1524              :                                              m_libspdm_oid_basic_constraints,
    1525              :                                              sizeof(m_libspdm_oid_basic_constraints),
    1526              :                                              basic_constraints,
    1527              :                                              basic_constraints_size);
    1528          762 :     return status;
    1529              : }
    1530              : 
    1531              : /**
    1532              :  * Return 0 if before <= after, 1 otherwise
    1533              :  **/
    1534         1536 : static int32_t libspdm_internal_x509_check_time(const mbedtls_x509_time *before,
    1535              :                                                 const mbedtls_x509_time *after)
    1536              : {
    1537         1536 :     if (before->year > after->year) {
    1538         1536 :         return (1);
    1539              :     }
    1540              : 
    1541            0 :     if (before->year == after->year && before->mon > after->mon) {
    1542            0 :         return (1);
    1543              :     }
    1544              : 
    1545            0 :     if (before->year == after->year && before->mon == after->mon &&
    1546            0 :         before->day > after->day) {
    1547            0 :         return (1);
    1548              :     }
    1549              : 
    1550            0 :     if (before->year == after->year && before->mon == after->mon &&
    1551            0 :         before->day == after->day && before->hour > after->hour) {
    1552            0 :         return (1);
    1553              :     }
    1554              : 
    1555            0 :     if (before->year == after->year && before->mon == after->mon &&
    1556            0 :         before->day == after->day && before->hour == after->hour &&
    1557            0 :         before->min > after->min) {
    1558            0 :         return (1);
    1559              :     }
    1560              : 
    1561            0 :     if (before->year == after->year && before->mon == after->mon &&
    1562            0 :         before->day == after->day && before->hour == after->hour &&
    1563            0 :         before->min == after->min && before->sec > after->sec) {
    1564            0 :         return (1);
    1565              :     }
    1566              : 
    1567            0 :     return (0);
    1568              : }
    1569              : 
    1570         9216 : static int32_t libspdm_internal_atoi(const char *p_start, char const *p_end)
    1571              : {
    1572         9216 :     const char *p = p_start;
    1573         9216 :     int32_t k = 0;
    1574        30720 :     while (p < p_end) {
    1575              : 
    1576              :         /* k = k * 2³ + k * 2¹ = k * 8 + k * 2 = k * 10*/
    1577              : 
    1578        21504 :         k = (k << 3) + (k << 1) + (*p) - '0';
    1579        21504 :         p++;
    1580              :     }
    1581         9216 :     return k;
    1582              : }
    1583              : 
    1584              : /**
    1585              :  * format a date_time object into DataTime buffer
    1586              :  *
    1587              :  * If date_time_str is NULL, then return false.
    1588              :  * If date_time_size is NULL, then return false.
    1589              :  * If this interface is not supported, then return false.
    1590              :  *
    1591              :  * @param[in]      date_time_str      date_time string like YYYYMMDDhhmmssZ
    1592              :  *                                 Ref: https://www.w3.org/TR/NOTE-datetime
    1593              :  *                                 Z stand for UTC time
    1594              :  * @param[out]     date_time         Pointer to a date_time object.
    1595              :  * @param[in,out]  date_time_size     date_time object buffer size.
    1596              :  *
    1597              :  * @retval RETURN_SUCCESS           The date_time object create successfully.
    1598              :  * @retval RETURN_INVALID_PARAMETER If date_time_str is NULL.
    1599              :  *                                 If date_time_size is NULL.
    1600              :  *                                 If date_time is not NULL and *date_time_size is 0.
    1601              :  *                                 If year month day hour minute second combination is invalid datetime.
    1602              :  * @retval RETURN_BUFFER_TOO_SMALL  If the date_time is NULL. The required buffer size
    1603              :  *                                 (including the final null) is returned in the
    1604              :  *                                 date_time_size parameter.
    1605              :  * @retval RETURN_UNSUPPORTED       The operation is not supported.
    1606              :  **/
    1607         1536 : bool libspdm_x509_set_date_time(const char *date_time_str, void *date_time, size_t *date_time_size)
    1608              : {
    1609              :     mbedtls_x509_time dt;
    1610              : 
    1611              :     int32_t year;
    1612              :     int32_t month;
    1613              :     int32_t day;
    1614              :     int32_t hour;
    1615              :     int32_t minute;
    1616              :     int32_t second;
    1617              :     bool status;
    1618              :     const char *p;
    1619              : 
    1620         1536 :     p = date_time_str;
    1621              : 
    1622         1536 :     year = libspdm_internal_atoi(p, p + 4);
    1623         1536 :     p += 4;
    1624         1536 :     month = libspdm_internal_atoi(p, p + 2);
    1625         1536 :     p += 2;
    1626         1536 :     day = libspdm_internal_atoi(p, p + 2);
    1627         1536 :     p += 2;
    1628         1536 :     hour = libspdm_internal_atoi(p, p + 2);
    1629         1536 :     p += 2;
    1630         1536 :     minute = libspdm_internal_atoi(p, p + 2);
    1631         1536 :     p += 2;
    1632         1536 :     second = libspdm_internal_atoi(p, p + 2);
    1633         1536 :     p += 2;
    1634         1536 :     dt.year = (int)year;
    1635         1536 :     dt.mon = (int)month;
    1636         1536 :     dt.day = (int)day;
    1637         1536 :     dt.hour = (int)hour;
    1638         1536 :     dt.min = (int)minute;
    1639         1536 :     dt.sec = (int)second;
    1640              : 
    1641         1536 :     if (*date_time_size < sizeof(mbedtls_x509_time)) {
    1642            0 :         *date_time_size = sizeof(mbedtls_x509_time);
    1643            0 :         status = false;
    1644            0 :         goto cleanup;
    1645              :     }
    1646         1536 :     if (date_time != NULL) {
    1647         1536 :         libspdm_copy_mem(date_time, *date_time_size, &dt, sizeof(mbedtls_x509_time));
    1648              :     }
    1649         1536 :     *date_time_size = sizeof(mbedtls_x509_time);
    1650         1536 :     status = true;
    1651         1536 : cleanup:
    1652         1536 :     return status;
    1653              : }
    1654              : 
    1655              : /**
    1656              :  * Compare date_time1 object and date_time2 object.
    1657              :  *
    1658              :  * If date_time1 is NULL, then return -2.
    1659              :  * If date_time2 is NULL, then return -2.
    1660              :  * If date_time1 == date_time2, then return 0
    1661              :  * If date_time1 > date_time2, then return 1
    1662              :  * If date_time1 < date_time2, then return -1
    1663              :  *
    1664              :  * @param[in]      date_time1         Pointer to a date_time Object
    1665              :  * @param[in]      date_time2         Pointer to a date_time Object
    1666              :  *
    1667              :  * @retval  0      If date_time1 == date_time2
    1668              :  * @retval  1      If date_time1 > date_time2
    1669              :  * @retval  -1     If date_time1 < date_time2
    1670              :  **/
    1671         1536 : int32_t libspdm_x509_compare_date_time(const void *date_time1, const void *date_time2)
    1672              : {
    1673         1536 :     if (date_time1 == NULL || date_time2 == NULL) {
    1674            0 :         return -2;
    1675              :     }
    1676         1536 :     if (libspdm_consttime_is_mem_equal(date_time2, date_time1, sizeof(mbedtls_x509_time))) {
    1677            0 :         return 0;
    1678              :     }
    1679         1536 :     if (libspdm_internal_x509_check_time((const mbedtls_x509_time *)date_time1,
    1680              :                                          (const mbedtls_x509_time *)date_time2) == 0) {
    1681            0 :         return -1;
    1682              :     } else {
    1683         1536 :         return 1;
    1684              :     }
    1685              : }
    1686              : 
    1687            2 : static bool libspdm_convert_subject_to_string(uint8_t *ptr, size_t obj_len,
    1688              :                                               uint8_t *buffer, int32_t buff_len)
    1689              : {
    1690              :     bool ret;
    1691              :     uint8_t *end;
    1692              :     uint8_t *internal_p;
    1693              : 
    1694              :     libspdm_x509_subject_descriptor_t *cur;
    1695              :     /* X.509 DN attributes from RFC 5280, Appendix A.1. */
    1696            2 :     libspdm_x509_subject_descriptor_t x509_attrs[] =
    1697              :     {
    1698              :         { LIBSPDM_ADD_STRLEN( "CN" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_CN ),
    1699              :           MBEDTLS_ASN1_UTF8_STRING },
    1700              :         { LIBSPDM_ADD_STRLEN( "C" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_COUNTRY ),
    1701              :           MBEDTLS_ASN1_PRINTABLE_STRING },
    1702              :         { LIBSPDM_ADD_STRLEN( "O" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_ORGANIZATION ),
    1703              :           MBEDTLS_ASN1_UTF8_STRING },
    1704              :         { LIBSPDM_ADD_STRLEN( "L" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_LOCALITY ),
    1705              :           MBEDTLS_ASN1_UTF8_STRING },
    1706              :         { LIBSPDM_ADD_STRLEN( "R" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_PKCS9_EMAIL ),
    1707              :           MBEDTLS_ASN1_IA5_STRING },
    1708              :         { LIBSPDM_ADD_STRLEN( "OU" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_ORG_UNIT ),
    1709              :           MBEDTLS_ASN1_UTF8_STRING },
    1710              :         { LIBSPDM_ADD_STRLEN( "ST" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_STATE ),
    1711              :           MBEDTLS_ASN1_UTF8_STRING },
    1712              :         { LIBSPDM_ADD_STRLEN( "emailAddress" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_PKCS9_EMAIL ),
    1713              :           MBEDTLS_ASN1_IA5_STRING },
    1714              :         { LIBSPDM_ADD_STRLEN( "serialNumber" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),
    1715              :           MBEDTLS_ASN1_PRINTABLE_STRING },
    1716              :         { LIBSPDM_ADD_STRLEN( "postalAddress" ),
    1717              :           LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ), MBEDTLS_ASN1_PRINTABLE_STRING },
    1718              :         { LIBSPDM_ADD_STRLEN( "postalCode" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_POSTAL_CODE ),
    1719              :           MBEDTLS_ASN1_PRINTABLE_STRING },
    1720              :         { LIBSPDM_ADD_STRLEN( "dnQualifier" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_DN_QUALIFIER ),
    1721              :           MBEDTLS_ASN1_PRINTABLE_STRING },
    1722              :         { LIBSPDM_ADD_STRLEN( "title" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_TITLE ),
    1723              :           MBEDTLS_ASN1_UTF8_STRING },
    1724              :         { LIBSPDM_ADD_STRLEN( "SN" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_SUR_NAME ),
    1725              :           MBEDTLS_ASN1_UTF8_STRING },
    1726              :         { LIBSPDM_ADD_STRLEN( "GN" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_GIVEN_NAME ),
    1727              :           MBEDTLS_ASN1_UTF8_STRING },
    1728              :         { LIBSPDM_ADD_STRLEN( "initials" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_INITIALS ),
    1729              :           MBEDTLS_ASN1_UTF8_STRING },
    1730              :         { LIBSPDM_ADD_STRLEN( "pseudonym" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_PSEUDONYM ),
    1731              :           MBEDTLS_ASN1_UTF8_STRING },
    1732              :         { LIBSPDM_ADD_STRLEN( "generationQualifier" ),
    1733              :           LIBSPDM_ADD_STRLEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ),
    1734              :           MBEDTLS_ASN1_UTF8_STRING },
    1735              :         { LIBSPDM_ADD_STRLEN( "DC" ), LIBSPDM_ADD_STRLEN( MBEDTLS_OID_DOMAIN_COMPONENT ),
    1736              :           MBEDTLS_ASN1_IA5_STRING },
    1737              :         { NULL, 0, NULL, 0, MBEDTLS_ASN1_NULL }
    1738              :     };
    1739              : 
    1740            2 :     end = ptr + obj_len;
    1741              : 
    1742            8 :     while(ptr != end) {
    1743              :         /*SET*/
    1744            6 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    1745              :                                    LIBSPDM_CRYPTO_ASN1_SET | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1746            6 :         if (!ret) {
    1747            0 :             return false;
    1748              :         }
    1749            6 :         internal_p = ptr;
    1750              :         /*move to next SET*/
    1751            6 :         ptr += obj_len;
    1752              : 
    1753              :         /*sequence*/
    1754            6 :         ret = libspdm_asn1_get_tag(&internal_p, end, &obj_len,
    1755              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1756            6 :         if (!ret) {
    1757            0 :             return false;
    1758              :         }
    1759              : 
    1760              :         /*OID*/
    1761            6 :         ret = libspdm_asn1_get_tag(&internal_p, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1762            6 :         if (!ret) {
    1763            0 :             return false;
    1764              :         }
    1765              : 
    1766           24 :         for (cur = x509_attrs; cur->name != NULL; cur++) {
    1767           46 :             if ((cur->oid_len == obj_len) &&
    1768           22 :                 (libspdm_consttime_is_mem_equal(cur->oid, internal_p, obj_len))) {
    1769              :                 /*Concat subject string*/
    1770              : 
    1771              :                 /*for example: CN=*/
    1772            6 :                 libspdm_copy_mem(buffer, buff_len, cur->name, cur->name_len);
    1773            6 :                 buff_len = (int32_t)(buff_len - cur->name_len);
    1774            6 :                 buffer += cur->name_len;
    1775            6 :                 *buffer = '=';
    1776            6 :                 buff_len--;
    1777            6 :                 buffer++;
    1778              : 
    1779              :                 /*move to string*/
    1780            6 :                 internal_p += obj_len;
    1781            6 :                 ret = libspdm_asn1_get_tag(&internal_p, end, &obj_len, cur->default_tag);
    1782            6 :                 if (!ret) {
    1783            0 :                     return false;
    1784              :                 }
    1785              : 
    1786              :                 /*for example: AU,*/
    1787            6 :                 libspdm_copy_mem(buffer, buff_len, internal_p, obj_len);
    1788            6 :                 buff_len = (int32_t)(buff_len - obj_len);
    1789            6 :                 buffer += obj_len;
    1790            6 :                 *buffer = ',';
    1791            6 :                 buff_len--;
    1792            6 :                 buffer++;
    1793              : 
    1794            6 :                 if (buff_len < 0) {
    1795            0 :                     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"the buffer is too small"));
    1796            0 :                     return false;
    1797              :                 }
    1798            6 :                 break;
    1799              :             }
    1800              :         }
    1801              : 
    1802              :         /*can not find the same oid, the subject is wrong*/
    1803            6 :         if (cur->name == NULL) {
    1804            0 :             return false;
    1805              :         }
    1806              :     }
    1807              : 
    1808            2 :     *buffer = '\0';
    1809            2 :     return true;
    1810              : }
    1811              : 
    1812              : /**
    1813              :  * Set all attributes object form req_info to CSR
    1814              :  *
    1815              :  * @param[in]      req                   CSR to set attributes
    1816              :  * @param[in]      req_info              requester info to gen CSR
    1817              :  * @param[in]      req_info_len          The len of requester info
    1818              :  *
    1819              :  * @retval  true   Success Set.
    1820              :  * @retval  false  Set failed.
    1821              :  **/
    1822            2 : bool libspdm_set_attribute_for_req(mbedtls_x509write_csr *req,
    1823              :                                    uint8_t *req_info, size_t req_info_len,
    1824              :                                    uint8_t *pub_key_der, size_t pub_key_der_len)
    1825              : {
    1826              :     uint8_t *ptr;
    1827              :     int32_t length;
    1828              :     size_t obj_len;
    1829              :     bool ret;
    1830              :     uint8_t *end;
    1831              :     uint8_t *ptr_old;
    1832              : 
    1833              :     uint8_t *oid;
    1834              :     size_t oid_len;
    1835              :     uint8_t *val;
    1836              :     size_t val_len;
    1837              : 
    1838              :     uint8_t *pkinfo;
    1839              :     size_t pkinfo_len;
    1840              :     uint8_t buffer[LIBSPDM_MAX_SUBJECT_BUFFER_SIZE];
    1841              : 
    1842            2 :     length = (int32_t)req_info_len;
    1843            2 :     ptr = req_info;
    1844            2 :     obj_len = 0;
    1845            2 :     end = ptr + length;
    1846            2 :     ret = false;
    1847              : 
    1848            2 :     if (req_info == NULL) {
    1849            0 :         return false;
    1850              :     }
    1851              : 
    1852              :     /*req_info sequence, all req_info format is ok because the req_info has been verified before*/
    1853            2 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    1854              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1855              : 
    1856              :     /*integer:version*/
    1857            2 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
    1858              :     /*check req_info version. spec PKCS#10: It shall be 0 for this version of the standard.*/
    1859            2 :     if ((obj_len != 1) || (*ptr != 0)) {
    1860            0 :         return false;
    1861              :     }
    1862            2 :     ptr += obj_len;
    1863              : 
    1864              :     /*sequence:subject name*/
    1865            2 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    1866              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1867              : 
    1868              :     /**/
    1869            2 :     libspdm_zero_mem(buffer, sizeof(buffer));
    1870            2 :     ret = libspdm_convert_subject_to_string(ptr, obj_len, buffer, LIBSPDM_MAX_SUBJECT_BUFFER_SIZE);
    1871            2 :     if (!ret) {
    1872            0 :         return false;
    1873              :     }
    1874              : 
    1875              :     /*set subject name*/
    1876            2 :     ret = mbedtls_x509write_csr_set_subject_name(req, (const char *)buffer);
    1877            2 :     if (ret != 0) {
    1878            0 :         return false;
    1879              :     }
    1880              : 
    1881            2 :     ptr += obj_len;
    1882              : 
    1883            2 :     pkinfo = ptr;
    1884              :     /*sequence:subject pkinfo*/
    1885            2 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    1886              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1887              : 
    1888            2 :     pkinfo_len = obj_len + ptr - pkinfo;
    1889              :     /*check the public key info*/
    1890            4 :     if (!((pkinfo_len == pub_key_der_len) &&
    1891            2 :           (libspdm_consttime_is_mem_equal(pub_key_der, pkinfo, pkinfo_len)))) {
    1892            0 :         return false;
    1893              :     }
    1894              : 
    1895            2 :     ptr += obj_len;
    1896              : 
    1897              :     /*[0]: attributes*/
    1898            2 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    1899              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    1900              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1901              :     /*there is no attributes*/
    1902            2 :     if (ptr == end) {
    1903            0 :         return true;
    1904              :     }
    1905              : 
    1906              :     /*there is some attributes object: 1,2 ...*/
    1907            4 :     while (ret)
    1908              :     {
    1909            2 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    1910              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE |
    1911              :                                    LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1912            2 :         if (ret) {
    1913              :             /*save old position*/
    1914            2 :             ptr_old = ptr;
    1915              : 
    1916              :             /*move to the next sequence*/
    1917            2 :             ptr += obj_len;
    1918              : 
    1919              :             /*get attributes oid*/
    1920            2 :             ret = libspdm_asn1_get_tag(&ptr_old, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1921            2 :             if (!ret) {
    1922            0 :                 return false;
    1923              :             }
    1924            2 :             oid = ptr_old;
    1925            2 :             oid_len = obj_len;
    1926              : 
    1927            2 :             ptr_old += obj_len;
    1928              :             /*get attributes val*/
    1929            2 :             ret = libspdm_asn1_get_tag(&ptr_old, end, &obj_len,
    1930              :                                        LIBSPDM_CRYPTO_ASN1_SET |
    1931              :                                        LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1932            2 :             if (!ret) {
    1933            0 :                 return false;
    1934              :             }
    1935            2 :             ret = libspdm_asn1_get_tag(&ptr_old, end, &obj_len, LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
    1936            2 :             if (!ret) {
    1937            0 :                 return false;
    1938              :             }
    1939            2 :             val = ptr_old;
    1940            2 :             val_len = obj_len;
    1941              : 
    1942              :             /*set attributes*/
    1943            2 :             ret = mbedtls_x509write_csr_set_extension(req, (const char *)oid, oid_len, 0, val,
    1944              :                                                       val_len);
    1945              : 
    1946            2 :             if (ret) {
    1947            0 :                 return false;
    1948              :             }
    1949              : 
    1950              :         } else {
    1951            0 :             break;
    1952              :         }
    1953              :     }
    1954              : 
    1955            2 :     if (ptr == end) {
    1956            2 :         return true;
    1957              :     } else {
    1958            0 :         return false;
    1959              :     }
    1960              : }
    1961              : 
    1962              : /**
    1963              :  * Gen CSR
    1964              :  *
    1965              :  * @param[in]      hash_nid              hash algo for sign
    1966              :  * @param[in]      asym_nid              asym algo for sign
    1967              :  *
    1968              :  * @param[in]      requester_info        requester info to gen CSR
    1969              :  * @param[in]      requester_info_length The len of requester info
    1970              :  *
    1971              :  * @param[in]       is_ca                if true, set basic_constraints: CA:true; Otherwise, set to false.
    1972              :  *
    1973              :  * @param[in]      context               Pointer to asymmetric context
    1974              :  * @param[in]      subject_name          Subject name: should be break with ',' in the middle
    1975              :  *                                       example: "C=AA,CN=BB"
    1976              :  * Subject names should contain a comma-separated list of OID types and values:
    1977              :  * The valid OID type name is in:
    1978              :  * {"CN", "commonName", "C", "countryName", "O", "organizationName","L",
    1979              :  * "OU", "organizationalUnitName", "ST", "stateOrProvinceName", "emailAddress",
    1980              :  * "serialNumber", "postalAddress", "postalCode", "dnQualifier", "title",
    1981              :  * "SN","givenName","GN", "initials", "pseudonym", "generationQualifier", "domainComponent", "DC"}.
    1982              :  * Note: The object of C and countryName should be CSR Supported Country Codes
    1983              :  *
    1984              :  * @param[in, out]      csr_len               For input, csr_len is the size of store CSR buffer.
    1985              :  *                                            For output, csr_len is CSR len for DER format
    1986              :  * @param[in, out]      csr_pointer           For input, csr_pointer is buffer address to store CSR.
    1987              :  *                                            For output, csr_pointer is address for stored CSR.
    1988              :  *                                            The csr_pointer address will be changed.
    1989              :  * @param[in]           base_cert             An optional leaf certificate whose
    1990              :  *                                            extensions should be copied to the CSR
    1991              :  *
    1992              :  * @retval  true   Success.
    1993              :  * @retval  false  Failed to gen CSR.
    1994              :  **/
    1995            6 : bool libspdm_gen_x509_csr(size_t hash_nid, size_t asym_nid,
    1996              :                           uint8_t *requester_info, size_t requester_info_length,
    1997              :                           bool is_ca,
    1998              :                           void *context, char *subject_name,
    1999              :                           size_t *csr_len, uint8_t *csr_pointer,
    2000              :                           void *base_cert)
    2001              : {
    2002              :     int ret;
    2003              :     bool result;
    2004              :     size_t csr_buffer_size;
    2005              : 
    2006              :     mbedtls_x509write_csr req;
    2007              :     mbedtls_md_type_t md_alg;
    2008              :     mbedtls_asn1_sequence extns;
    2009              :     mbedtls_asn1_sequence *next_oid;
    2010              :     mbedtls_x509_buf buf;
    2011              :     mbedtls_x509_crt *cert;
    2012              :     mbedtls_pk_context key;
    2013              : 
    2014              :     uint8_t pubkey_buffer[LIBSPDM_MAX_PUBKEY_DER_BUFFER_SIZE];
    2015              :     uint8_t *pubkey_der_data;
    2016              :     size_t pubkey_der_len;
    2017              :     size_t oid_tag_len;
    2018              : 
    2019              :     /*basic_constraints: CA: false */
    2020              :     #define BASIC_CONSTRAINTS_STRING_FALSE {0x30, 0x00}
    2021            6 :     uint8_t basic_constraints_false[] = BASIC_CONSTRAINTS_STRING_FALSE;
    2022              : 
    2023              :     /*basic_constraints: CA: true */
    2024              :     #define BASIC_CONSTRAINTS_STRING_TRUE {0x30, 0x03, 0x01, 0x01, 0xFF}
    2025            6 :     uint8_t basic_constraints_true[] = BASIC_CONSTRAINTS_STRING_TRUE;
    2026              : 
    2027              :     /* Init */
    2028            6 :     mbedtls_x509write_csr_init(&req);
    2029            6 :     mbedtls_pk_init(&key);
    2030            6 :     csr_buffer_size = *csr_len;
    2031            6 :     next_oid = NULL;
    2032              : 
    2033            6 :     ret = 1;
    2034            6 :     switch (asym_nid)
    2035              :     {
    2036            0 :     case LIBSPDM_CRYPTO_NID_RSASSA2048:
    2037              :     case LIBSPDM_CRYPTO_NID_RSAPSS2048:
    2038              :     case LIBSPDM_CRYPTO_NID_RSASSA3072:
    2039              :     case LIBSPDM_CRYPTO_NID_RSAPSS3072:
    2040              :     case LIBSPDM_CRYPTO_NID_RSASSA4096:
    2041              :     case LIBSPDM_CRYPTO_NID_RSAPSS4096:
    2042            0 :         ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
    2043            0 :         if (ret != 0) {
    2044            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_pk_setup %d", ret));
    2045            0 :             goto free_all;
    2046              :         }
    2047            0 :         ret = mbedtls_rsa_copy(mbedtls_pk_rsa(key), (mbedtls_rsa_context *)context);
    2048            0 :         if (ret != 0) {
    2049            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_rsa_copy %d", ret));
    2050            0 :             goto free_all;
    2051              :         }
    2052            0 :         ret = mbedtls_rsa_complete(mbedtls_pk_rsa(key));
    2053            0 :         if (ret != 0) {
    2054            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_rsa_complete %d", ret));
    2055            0 :             goto free_all;
    2056              :         }
    2057            0 :         break;
    2058            6 :     case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P256:
    2059              :     case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P384:
    2060              :     case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P521:
    2061            6 :         ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
    2062            6 :         if (ret != 0) {
    2063            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_pk_setup %d", ret));
    2064            0 :             goto free_all;
    2065              :         }
    2066              :         /*mbedtls_ecdh_context include mbedtls_ecdsa_context,can be treated as mbedtls_ecdsa_context*/
    2067            6 :         ret = mbedtls_ecdsa_from_keypair(mbedtls_pk_ec(key), (mbedtls_ecdsa_context *)context);
    2068            6 :         if (ret != 0) {
    2069            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"failed\n ! mbedtls_ecdsa_from_keypair %d", ret));
    2070            0 :             goto free_all;
    2071              :         }
    2072            6 :         break;
    2073            0 :     default:
    2074            0 :         return false;
    2075              :     }
    2076              : 
    2077            6 :     switch (hash_nid)
    2078              :     {
    2079            6 :     case LIBSPDM_CRYPTO_NID_SHA256:
    2080            6 :         md_alg = MBEDTLS_MD_SHA256;
    2081            6 :         break;
    2082            0 :     case LIBSPDM_CRYPTO_NID_SHA384:
    2083            0 :         md_alg = MBEDTLS_MD_SHA384;
    2084            0 :         break;
    2085            0 :     case LIBSPDM_CRYPTO_NID_SHA512:
    2086            0 :         md_alg = MBEDTLS_MD_SHA512;
    2087            0 :         break;
    2088            0 :     case LIBSPDM_CRYPTO_NID_SHA3_256:
    2089            0 :         md_alg = MBEDTLS_MD_SHA3_256;
    2090            0 :         break;
    2091            0 :     case LIBSPDM_CRYPTO_NID_SHA3_384:
    2092            0 :         md_alg = MBEDTLS_MD_SHA3_384;
    2093            0 :         break;
    2094            0 :     case LIBSPDM_CRYPTO_NID_SHA3_512:
    2095            0 :         md_alg = MBEDTLS_MD_SHA3_512;
    2096            0 :         break;
    2097            0 :     default:
    2098            0 :         ret = 1;
    2099            0 :         goto free_all;
    2100              :     }
    2101              : 
    2102              :     /* Set the md alg */
    2103            6 :     mbedtls_x509write_csr_set_md_alg(&req, md_alg);
    2104              : 
    2105              :     /* Set the subject name */
    2106            6 :     if (subject_name != NULL) {
    2107            6 :         ret = mbedtls_x509write_csr_set_subject_name(&req, subject_name);
    2108            6 :         if (ret != 0) {
    2109            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2110              :                            "failed\n ! mbedtls_x509write_csr_set_subject_name returned %d", ret));
    2111            0 :             goto free_all;
    2112              :         }
    2113              :     }
    2114              : 
    2115            6 :     libspdm_zero_mem(pubkey_buffer, sizeof(pubkey_buffer));
    2116            6 :     pubkey_der_len = mbedtls_pk_write_pubkey_der(&key, pubkey_buffer, sizeof(pubkey_buffer));
    2117            6 :     if (pubkey_der_len > 0) {
    2118              :         /*Note: data is written at the end of the buffer!*/
    2119            6 :         pubkey_der_data = pubkey_buffer + sizeof(pubkey_buffer) - pubkey_der_len;
    2120              :     } else {
    2121            0 :         goto free_all;
    2122              :     }
    2123              : 
    2124              :     /* requester info parse
    2125              :      * check the req_info version and subjectPKInfo;
    2126              :      * get attribute and subject from req_info and set them to CSR;
    2127              :      **/
    2128            6 :     if (requester_info_length != 0) {
    2129            2 :         result = libspdm_set_attribute_for_req(&req, requester_info, requester_info_length,
    2130              :                                                pubkey_der_data, pubkey_der_len);
    2131            2 :         if (!result) {
    2132            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"set_attribute failed !\n"));
    2133            0 :             goto free_all;
    2134              :         }
    2135              :     }
    2136              : 
    2137              :     /* Set key */
    2138            6 :     mbedtls_x509write_csr_set_key(&req, &key);
    2139              : 
    2140              :     /*set basicConstraints*/
    2141            6 :     if (mbedtls_x509write_csr_set_extension(&req, MBEDTLS_OID_BASIC_CONSTRAINTS,
    2142              :                                             MBEDTLS_OID_SIZE(MBEDTLS_OID_BASIC_CONSTRAINTS),
    2143              :                                             0,
    2144              :                                             is_ca ? basic_constraints_true : basic_constraints_false,
    2145              :                                             is_ca ?
    2146              :                                             sizeof(basic_constraints_true) :
    2147              :                                             sizeof(basic_constraints_false)
    2148              :                                             ) != 0) {
    2149            0 :         ret = 1;
    2150            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2151              :                        "mbedtls_x509write_csr_set_extension set basicConstraints failed \n"));
    2152            0 :         goto free_all;
    2153              :     }
    2154              : 
    2155            6 :     if (base_cert != NULL) {
    2156            6 :         cert = base_cert;
    2157            6 :         buf = cert->v3_ext;
    2158            6 :         if (mbedtls_asn1_get_sequence_of(&buf.p, buf.p + buf.len, &extns,
    2159              :                                          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
    2160            0 :             ret = 1;
    2161            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2162              :                            "mbedtls_x509write_csr_set_extension unable to get sequence\n"));
    2163            0 :             goto free_all;
    2164              :         }
    2165              : 
    2166            6 :         next_oid = &extns;
    2167              :     }
    2168              : 
    2169           42 :     while (next_oid) {
    2170           36 :         if (mbedtls_asn1_get_tag(&(next_oid->buf.p), next_oid->buf.p + next_oid->buf.len,
    2171              :                                  &oid_tag_len, MBEDTLS_ASN1_OID)) {
    2172            0 :             ret = 1;
    2173            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2174              :                            "mbedtls_x509write_csr_set_extension unable to get OID tag\n"));
    2175            0 :             goto free_all;
    2176              :         }
    2177              : 
    2178           36 :         if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_BASIC_CONSTRAINTS, next_oid->buf.p, oid_tag_len) == 0) {
    2179            6 :             next_oid = next_oid->next;
    2180            6 :             continue;
    2181              :         }
    2182              : 
    2183           30 :         if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, next_oid->buf.p,
    2184              :                                 oid_tag_len) == 0) {
    2185            0 :             next_oid = next_oid->next;
    2186            0 :             continue;
    2187              :         }
    2188              : 
    2189           30 :         if (mbedtls_x509write_csr_set_extension(&req, (const char *)next_oid->buf.p,
    2190              :                                                 oid_tag_len, 0,
    2191           30 :                                                 next_oid->buf.p + oid_tag_len,
    2192           30 :                                                 next_oid->buf.len - oid_tag_len
    2193              :                                                 ) != 0) {
    2194            0 :             ret = 1;
    2195            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2196              :                            "mbedtls_x509write_csr_set_extension set custom OID failed \n"));
    2197            0 :             goto free_all;
    2198              :         }
    2199              : 
    2200           30 :         next_oid = next_oid->next;
    2201              :     }
    2202              : 
    2203              :     /*csr data is written at the end of the buffer*/
    2204            6 :     ret = mbedtls_x509write_csr_der(&req, csr_pointer, csr_buffer_size, libspdm_myrand, NULL);
    2205            6 :     if (ret <= 0) {
    2206            0 :         ret = 1;
    2207            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"mbedtls_x509write_csr_der failed \n"));
    2208            0 :         goto free_all;
    2209              :     }
    2210              : 
    2211            6 :     *csr_len = (size_t)ret;
    2212              :     /*make csr_pointer store csr data*/
    2213            6 :     memmove(csr_pointer, csr_pointer + csr_buffer_size - *csr_len, *csr_len);
    2214              : 
    2215            6 :     ret = 0;
    2216            6 : free_all:
    2217            6 :     mbedtls_x509write_csr_free(&req);
    2218            6 :     mbedtls_pk_free(&key);
    2219              : 
    2220            6 :     return(ret == 0);
    2221              : }
    2222              : 
    2223              : #endif
        

Generated by: LCOV version 2.0-1