LCOV - code coverage report
Current view: top level - library/spdm_crypt_lib - libspdm_crypt_cert.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 70.3 % 647 455
Test Date: 2025-06-29 08:09:00 Functions: 92.6 % 27 25

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2025 DMTF. All rights reserved.
       4              :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5              :  **/
       6              : 
       7              : #include "internal/libspdm_crypt_lib.h"
       8              : 
       9              : #if LIBSPDM_CERT_PARSE_SUPPORT
      10              : 
      11              : /**pathLenConstraint is optional.
      12              :  * In https://www.pkisolutions.com/basic-constraints-certificate-extension/:
      13              :  * pathLenConstraint: How many CAs are allowed in the chain below current CA certificate.
      14              :  * This setting has no meaning for end entity certificates.
      15              :  **/
      16              : 
      17              : /**
      18              :  * leaf cert spdm extension len
      19              :  * len > 2 * (spdm id-DMTF-spdm size + 2)
      20              :  **/
      21              : 
      22              : #ifndef LIBSPDM_MAX_EXTENSION_LEN
      23              : #define LIBSPDM_MAX_EXTENSION_LEN 30
      24              : #endif
      25              : 
      26              : #ifndef LIBSPDM_MAX_NAME_SIZE
      27              : #define LIBSPDM_MAX_NAME_SIZE 100
      28              : #endif
      29              : 
      30              : /*max public key encryption algo oid len*/
      31              : #ifndef LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN
      32              : #define LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN 10
      33              : #endif
      34              : 
      35              : /* Maximum size of basicConstraints. This includes space for both cA and pathLen. */
      36              : #ifndef LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN
      37              : #define LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN 10
      38              : #endif
      39              : 
      40              : /**
      41              :  * 0x02 is integer;
      42              :  * 0x82 indicates that the length is expressed in two bytes;
      43              :  * 0x01 and 0x01 are rsa key len;
      44              :  **/
      45              : #if (LIBSPDM_RSA_SSA_2048_SUPPORT) || (LIBSPDM_RSA_PSS_2048_SUPPORT)
      46              : #define KEY_ENCRY_ALGO_RSA2048_FLAG {0x02, 0x82, 0x01, 0x01}
      47              : /* the other case is ASN1 code different when integer is 1 on highest position*/
      48              : #define KEY_ENCRY_ALGO_RSA2048_FLAG_OTHER {0x02, 0x82, 0x01, 0x00}
      49              : #endif
      50              : #if (LIBSPDM_RSA_SSA_3072_SUPPORT) || (LIBSPDM_RSA_PSS_3072_SUPPORT)
      51              : #define KEY_ENCRY_ALGO_RSA3072_FLAG {0x02, 0x82, 0x01, 0x81}
      52              : /* the other case is ASN1 code different when integer is 1 on highest position*/
      53              : #define KEY_ENCRY_ALGO_RSA3072_FLAG_OTHER {0x02, 0x82, 0x01, 0x80}
      54              : #endif
      55              : #if (LIBSPDM_RSA_SSA_4096_SUPPORT) || (LIBSPDM_RSA_PSS_4096_SUPPORT)
      56              : #define KEY_ENCRY_ALGO_RSA4096_FLAG {0x02, 0x82, 0x02, 0x01}
      57              : /* the other case is ASN1 code different when integer is 1 on highest position*/
      58              : #define KEY_ENCRY_ALGO_RSA4096_FLAG_OTHER {0x02, 0x82, 0x02, 0x00}
      59              : #endif
      60              : 
      61              : /**
      62              :  * https://oidref.com/1.2.840.10045.3.1.7
      63              :  * ECC256 curve OID: 1.2.840.10045.3.1.7
      64              :  * https://oidref.com/1.3.132.0.34
      65              :  * ECC384 curve OID: 1.3.132.0.34
      66              :  * https://oidref.com/1.3.132.0.35
      67              :  * ECC521 curve OID: 1.3.132.0.35
      68              :  **/
      69              : #if LIBSPDM_ECDSA_P256_SUPPORT
      70              : #define KEY_ENCRY_ALGO_ECC256_OID {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
      71              : #endif
      72              : #if LIBSPDM_ECDSA_P384_SUPPORT
      73              : #define KEY_ENCRY_ALGO_ECC384_OID {0x2B, 0x81, 0x04, 0x00, 0x22}
      74              : #endif
      75              : #if LIBSPDM_ECDSA_P521_SUPPORT
      76              : #define KEY_ENCRY_ALGO_ECC521_OID {0x2B, 0x81, 0x04, 0x00, 0x23}
      77              : #endif
      78              : 
      79              : /**
      80              :  * EDxxx OID: https://datatracker.ietf.org/doc/html/rfc8420
      81              :  * ED448 OID: 1.3.101.113
      82              :  * ED25519 OID: 1.3.101.112
      83              :  **/
      84              : #if LIBSPDM_EDDSA_ED25519_SUPPORT
      85              : #define ENCRY_ALGO_ED25519_OID {0x2B, 0x65, 0x70}
      86              : #endif
      87              : #if LIBSPDM_EDDSA_ED448_SUPPORT
      88              : #define ENCRY_ALGO_ED448_OID {0x2B, 0x65, 0x71}
      89              : #endif
      90              : 
      91              : /*leaf cert basic_constraints false case1: CA: false and CA object is excluded */
      92              : #define BASIC_CONSTRAINTS_STRING_FALSE_CASE1 {0x30, 0x00}
      93              : 
      94              : /*leaf cert basic_constraints false case2: CA: false */
      95              : #define BASIC_CONSTRAINTS_STRING_FALSE_CASE2 {0x30, 0x03, 0x01, 0x01, 0x00}
      96              : 
      97              : /*leaf cert basic_constraints true case: CA: true */
      98              : #define BASIC_CONSTRAINTS_STRING_TRUE_CASE {0x30, 0x03, 0x01, 0x01, 0xFF}
      99              : 
     100              : /**
     101              :  * Retrieve the asymmetric public key from one DER-encoded X509 certificate.
     102              :  *
     103              :  * @param  cert       Pointer to the DER-encoded X509 certificate.
     104              :  * @param  cert_size  Size of the X509 certificate in bytes.
     105              :  * @param  context    Pointer to newly generated asymmetric context which contain the retrieved public
     106              :  *                    key component. Use libspdm_asym_free() function to free the resource.
     107              :  *
     108              :  * @retval  true   public key was retrieved successfully.
     109              :  * @retval  false  Fail to retrieve public key from X509 certificate.
     110              :  **/
     111              : typedef bool (*libspdm_asym_get_public_key_from_x509_func)(const uint8_t *cert,
     112              :                                                            size_t cert_size,
     113              :                                                            void **context);
     114              : 
     115              : /**
     116              :  * Return asymmetric GET_PUBLIC_KEY_FROM_X509 function, based upon the negotiated asymmetric algorithm.
     117              :  *
     118              :  * @param  base_asym_algo                 SPDM base_asym_algo
     119              :  *
     120              :  * @return asymmetric GET_PUBLIC_KEY_FROM_X509 function
     121              :  **/
     122              : static libspdm_asym_get_public_key_from_x509_func
     123         1022 : libspdm_get_asym_get_public_key_from_x509(uint32_t base_asym_algo)
     124              : {
     125         1022 :     switch (base_asym_algo) {
     126          100 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
     127              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
     128              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
     129              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
     130              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
     131              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
     132              : #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
     133              : #if !LIBSPDM_RSA_SSA_2048_SUPPORT
     134              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048);
     135              : #endif
     136              : #if !LIBSPDM_RSA_SSA_3072_SUPPORT
     137              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072);
     138              : #endif
     139              : #if !LIBSPDM_RSA_SSA_4096_SUPPORT
     140              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096);
     141              : #endif
     142              : #if !LIBSPDM_RSA_PSS_2048_SUPPORT
     143              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048);
     144              : #endif
     145              : #if !LIBSPDM_RSA_PSS_3072_SUPPORT
     146              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072);
     147              : #endif
     148              : #if !LIBSPDM_RSA_PSS_4096_SUPPORT
     149              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096);
     150              : #endif
     151          100 :         return libspdm_rsa_get_public_key_from_x509;
     152              : #else
     153              :         LIBSPDM_ASSERT(false);
     154              :         break;
     155              : #endif
     156          922 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
     157              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
     158              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
     159              : #if LIBSPDM_ECDSA_SUPPORT
     160              : #if !LIBSPDM_ECDSA_P256_SUPPORT
     161              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256);
     162              : #endif
     163              : #if !LIBSPDM_ECDSA_P384_SUPPORT
     164              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384);
     165              : #endif
     166              : #if !LIBSPDM_ECDSA_P521_SUPPORT
     167              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521);
     168              : #endif
     169          922 :         return libspdm_ec_get_public_key_from_x509;
     170              : #else
     171              :         LIBSPDM_ASSERT(false);
     172              :         break;
     173              : #endif
     174            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
     175              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
     176              : #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
     177              : #if !LIBSPDM_EDDSA_ED25519_SUPPORT
     178              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519);
     179              : #endif
     180              : #if !LIBSPDM_EDDSA_ED448_SUPPORT
     181              :         LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448);
     182              : #endif
     183              :         return libspdm_ecd_get_public_key_from_x509;
     184              : #else
     185            0 :         LIBSPDM_ASSERT(false);
     186            0 :         break;
     187              : #endif
     188            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
     189              : #if LIBSPDM_SM2_DSA_SUPPORT
     190              :         return libspdm_sm2_get_public_key_from_x509;
     191              : #else
     192            0 :         LIBSPDM_ASSERT(false);
     193            0 :         break;
     194              : #endif
     195            0 :     default:
     196            0 :         LIBSPDM_ASSERT(false);
     197            0 :         break;
     198              :     }
     199              : 
     200            0 :     return NULL;
     201              : }
     202              : 
     203              : /**
     204              :  * Retrieve the asymmetric public key from one DER-encoded X509 certificate,
     205              :  * based upon negotiated asymmetric algorithm.
     206              :  *
     207              :  * @param  base_asym_algo                 SPDM base_asym_algo
     208              :  * @param  cert                         Pointer to the DER-encoded X509 certificate.
     209              :  * @param  cert_size                     size of the X509 certificate in bytes.
     210              :  * @param  context                      Pointer to newly generated asymmetric context which contain the retrieved public key component.
     211              :  *                                     Use libspdm_asym_free() function to free the resource.
     212              :  *
     213              :  * @retval  true   public key was retrieved successfully.
     214              :  * @retval  false  Fail to retrieve public key from X509 certificate.
     215              :  **/
     216         1022 : bool libspdm_asym_get_public_key_from_x509(uint32_t base_asym_algo,
     217              :                                            const uint8_t *cert,
     218              :                                            size_t cert_size,
     219              :                                            void **context)
     220              : {
     221              :     libspdm_asym_get_public_key_from_x509_func get_public_key_from_x509_function;
     222         1022 :     get_public_key_from_x509_function = libspdm_get_asym_get_public_key_from_x509(base_asym_algo);
     223         1022 :     if (get_public_key_from_x509_function == NULL) {
     224            0 :         return false;
     225              :     }
     226         1022 :     return get_public_key_from_x509_function(cert, cert_size, context);
     227              : }
     228              : 
     229              : /**
     230              :  * Return requester asymmetric GET_PUBLIC_KEY_FROM_X509 function, based upon the negotiated requester asymmetric algorithm.
     231              :  *
     232              :  * @param  req_base_asym_alg               SPDM req_base_asym_alg
     233              :  *
     234              :  * @return requester asymmetric GET_PUBLIC_KEY_FROM_X509 function
     235              :  **/
     236              : static libspdm_asym_get_public_key_from_x509_func
     237            0 : libspdm_get_req_asym_get_public_key_from_x509(uint16_t req_base_asym_alg)
     238              : {
     239            0 :     return libspdm_get_asym_get_public_key_from_x509(req_base_asym_alg);
     240              : }
     241              : 
     242              : /**
     243              :  * Retrieve the asymmetric public key from one DER-encoded X509 certificate,
     244              :  * based upon negotiated requester asymmetric algorithm.
     245              :  *
     246              :  * @param  req_base_asym_alg               SPDM req_base_asym_alg
     247              :  * @param  cert                         Pointer to the DER-encoded X509 certificate.
     248              :  * @param  cert_size                     size of the X509 certificate in bytes.
     249              :  * @param  context                      Pointer to newly generated asymmetric context which contain the retrieved public key component.
     250              :  *                                     Use libspdm_asym_free() function to free the resource.
     251              :  *
     252              :  * @retval  true   public key was retrieved successfully.
     253              :  * @retval  false  Fail to retrieve public key from X509 certificate.
     254              :  **/
     255            0 : bool libspdm_req_asym_get_public_key_from_x509(uint16_t req_base_asym_alg,
     256              :                                                const uint8_t *cert,
     257              :                                                size_t cert_size,
     258              :                                                void **context)
     259              : {
     260              :     libspdm_asym_get_public_key_from_x509_func get_public_key_from_x509_function;
     261              :     get_public_key_from_x509_function =
     262            0 :         libspdm_get_req_asym_get_public_key_from_x509(req_base_asym_alg);
     263            0 :     if (get_public_key_from_x509_function == NULL) {
     264            0 :         return false;
     265              :     }
     266            0 :     return get_public_key_from_x509_function(cert, cert_size, context);
     267              : }
     268              : 
     269              : /**
     270              :  * Check the X509 DataTime is within a valid range.
     271              :  *
     272              :  * @param  spdm_context                  A pointer to the SPDM context.
     273              :  * @param  from                         notBefore Pointer to date_time object.
     274              :  * @param  from_size                     notBefore date_time object size.
     275              :  * @param  to                           notAfter Pointer to date_time object.
     276              :  * @param  to_size                       notAfter date_time object size.
     277              :  *
     278              :  * @retval  true   verification pass.
     279              :  * @retval  false  verification fail.
     280              :  **/
     281          768 : static bool libspdm_internal_x509_date_time_check(const uint8_t *from,
     282              :                                                   size_t from_size,
     283              :                                                   const uint8_t *to,
     284              :                                                   size_t to_size)
     285              : {
     286              :     int32_t ret;
     287              :     bool status;
     288              :     uint8_t f0[64];
     289              :     uint8_t t0[64];
     290              :     size_t f0_size;
     291              :     size_t t0_size;
     292              : 
     293          768 :     f0_size = 64;
     294          768 :     t0_size = 64;
     295              : 
     296          768 :     status = libspdm_x509_set_date_time("19700101000000Z", f0, &f0_size);
     297          768 :     if (!status) {
     298            0 :         return false;
     299              :     }
     300              : 
     301          768 :     status = libspdm_x509_set_date_time("99991231235959Z", t0, &t0_size);
     302          768 :     if (!status) {
     303            0 :         return false;
     304              :     }
     305              : 
     306              :     /* from >= f0*/
     307          768 :     ret = libspdm_x509_compare_date_time(from, f0);
     308          768 :     if (ret < 0) {
     309            0 :         return false;
     310              :     }
     311              : 
     312              :     /* to <= t0*/
     313          768 :     ret = libspdm_x509_compare_date_time(t0, to);
     314          768 :     if (ret < 0) {
     315            0 :         return false;
     316              :     }
     317              : 
     318          768 :     return true;
     319              : }
     320              : 
     321              : /**
     322              :  * This function returns the SPDM public key encryption algorithm OID len.
     323              :  *
     324              :  * @param[in]  base_asym_algo          SPDM base_asym_algo
     325              :  *
     326              :  * @return SPDM public key encryption algorithms OID len.
     327              :  **/
     328         1528 : static uint32_t libspdm_get_public_key_algo_OID_len(uint32_t base_asym_algo)
     329              : {
     330         1528 :     switch (base_asym_algo) {
     331          116 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
     332              : #if LIBSPDM_RSA_SSA_2048_SUPPORT
     333          116 :         return 4;
     334              : #else
     335              :         return 0;
     336              : #endif
     337            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
     338              : #if LIBSPDM_RSA_PSS_2048_SUPPORT
     339            0 :         return 4;
     340              : #else
     341              :         return 0;
     342              : #endif
     343            6 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
     344              : #if LIBSPDM_RSA_SSA_3072_SUPPORT
     345            6 :         return 4;
     346              : #else
     347              :         return 0;
     348              : #endif
     349            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
     350              : #if LIBSPDM_RSA_PSS_3072_SUPPORT
     351            0 :         return 4;
     352              : #else
     353              :         return 0;
     354              : #endif
     355            4 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
     356              : #if LIBSPDM_RSA_SSA_4096_SUPPORT
     357            4 :         return 4;
     358              : #else
     359              :         return 0;
     360              : #endif
     361            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
     362              : #if LIBSPDM_RSA_PSS_4096_SUPPORT
     363            0 :         return 4;
     364              : #else
     365              :         return 0;
     366              : #endif
     367         1398 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
     368              : #if LIBSPDM_ECDSA_P256_SUPPORT
     369         1398 :         return 8;
     370              : #else
     371              :         return 0;
     372              : #endif
     373            2 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
     374              : #if LIBSPDM_ECDSA_P384_SUPPORT
     375            2 :         return 5;
     376              : #else
     377              :         return 0;
     378              : #endif
     379            2 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
     380              : #if LIBSPDM_ECDSA_P521_SUPPORT
     381            2 :         return 5;
     382              : #else
     383              :         return 0;
     384              : #endif
     385            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
     386              : #if LIBSPDM_EDDSA_ED25519_SUPPORT
     387              :         return 3;
     388              : #else
     389            0 :         return 0;
     390              : #endif
     391            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
     392              : #if LIBSPDM_EDDSA_ED448_SUPPORT
     393              :         return 3;
     394              : #else
     395            0 :         return 0;
     396              : #endif
     397            0 :     default:
     398            0 :         LIBSPDM_ASSERT(false);
     399            0 :         return 0;
     400              :     }
     401              : }
     402              : 
     403              : /**
     404              :  * This function get the SPDM public key encryption algorithm OID.
     405              :  *
     406              :  * @param[in]      base_asym_algo                 SPDM base_asym_algo
     407              :  * @param[in,out]  oid                            SPDM public key encryption algorithm OID
     408              :  * @param[in,out]  oid_other                      Other SPDM public key encryption algorithm OID
     409              :  *                                                because of ASN1 code for integer
     410              :  *
     411              :  * @retval  true   get OID successful.
     412              :  * @retval  false  get OID fail.
     413              :  **/
     414          764 : static bool libspdm_get_public_key_algo_OID(uint32_t base_asym_algo, uint8_t *oid,
     415              :                                             uint8_t *oid_other)
     416              : {
     417              :     uint32_t oid_len;
     418          764 :     oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo);
     419          764 :     if(oid_len == 0) {
     420            0 :         return false;
     421              :     }
     422              : 
     423          764 :     switch (base_asym_algo) {
     424           58 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
     425              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048: {
     426              : #if (LIBSPDM_RSA_SSA_2048_SUPPORT) || (LIBSPDM_RSA_PSS_2048_SUPPORT)
     427           58 :         uint8_t encry_algo_oid_rsa2048[] = KEY_ENCRY_ALGO_RSA2048_FLAG;
     428           58 :         uint8_t encry_algo_oid_rsa2048_ohter[] = KEY_ENCRY_ALGO_RSA2048_FLAG_OTHER;
     429           58 :         libspdm_copy_mem(oid, oid_len, encry_algo_oid_rsa2048, oid_len);
     430           58 :         libspdm_copy_mem(oid_other, oid_len, encry_algo_oid_rsa2048_ohter, oid_len);
     431           58 :         return true;
     432              : #else
     433              :         return false;
     434              : #endif
     435              :     }
     436            3 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
     437              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072: {
     438              : #if (LIBSPDM_RSA_SSA_3072_SUPPORT) || (LIBSPDM_RSA_PSS_3072_SUPPORT)
     439            3 :         uint8_t encry_algo_oid_rsa3072[] = KEY_ENCRY_ALGO_RSA3072_FLAG;
     440            3 :         uint8_t encry_algo_oid_rsa3072_ohter[] = KEY_ENCRY_ALGO_RSA3072_FLAG_OTHER;
     441            3 :         libspdm_copy_mem(oid, oid_len, encry_algo_oid_rsa3072, oid_len);
     442            3 :         libspdm_copy_mem(oid_other, oid_len, encry_algo_oid_rsa3072_ohter, oid_len);
     443            3 :         return true;
     444              : #else
     445              :         return false;
     446              : #endif
     447              :     }
     448            2 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
     449              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096: {
     450              : #if (LIBSPDM_RSA_SSA_4096_SUPPORT) || (LIBSPDM_RSA_PSS_4096_SUPPORT)
     451            2 :         uint8_t encry_algo_oid_rsa4096[] = KEY_ENCRY_ALGO_RSA4096_FLAG;
     452            2 :         uint8_t encry_algo_oid_rsa4096_ohter[] = KEY_ENCRY_ALGO_RSA4096_FLAG_OTHER;
     453            2 :         libspdm_copy_mem(oid, oid_len, encry_algo_oid_rsa4096, oid_len);
     454            2 :         libspdm_copy_mem(oid_other, oid_len, encry_algo_oid_rsa4096_ohter, oid_len);
     455            2 :         return true;
     456              : #else
     457              :         return false;
     458              : #endif
     459              :     }
     460              : 
     461          699 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256: {
     462              : #if LIBSPDM_ECDSA_P256_SUPPORT
     463          699 :         uint8_t encry_algo_oid_ecc256[] = KEY_ENCRY_ALGO_ECC256_OID;
     464          699 :         libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc256, oid_len);
     465          699 :         return true;
     466              : #else
     467              :         return false;
     468              : #endif
     469              :     }
     470            1 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384: {
     471              : #if LIBSPDM_ECDSA_P384_SUPPORT
     472            1 :         uint8_t encry_algo_oid_ecc384[] = KEY_ENCRY_ALGO_ECC384_OID;
     473            1 :         libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc384, oid_len);
     474            1 :         return true;
     475              : #else
     476              :         return false;
     477              : #endif
     478              :     }
     479            1 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521: {
     480              : #if LIBSPDM_ECDSA_P521_SUPPORT
     481            1 :         uint8_t encry_algo_oid_ecc521[] = KEY_ENCRY_ALGO_ECC521_OID;
     482            1 :         libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc521, oid_len);
     483            1 :         return true;
     484              : #else
     485              :         return false;
     486              : #endif
     487              :     }
     488              : 
     489              :     /*sm2 oid  TBD*/
     490            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
     491            0 :         return true;
     492              : 
     493            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519: {
     494              : #if LIBSPDM_EDDSA_ED25519_SUPPORT
     495              :         uint8_t encry_algo_oid_ed25519[] = ENCRY_ALGO_ED25519_OID;
     496              :         libspdm_copy_mem(oid, oid_len, encry_algo_oid_ed25519, oid_len);
     497              :         return true;
     498              : #else
     499            0 :         return false;
     500              : #endif
     501              :         break;
     502              :     }
     503            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448: {
     504              : #if LIBSPDM_EDDSA_ED448_SUPPORT
     505              :         uint8_t encry_algo_oid_ed448[] = ENCRY_ALGO_ED448_OID;
     506              :         libspdm_copy_mem(oid, oid_len, encry_algo_oid_ed448, oid_len);
     507              :         return true;
     508              : #else
     509            0 :         return false;
     510              : #endif
     511              :         break;
     512              :     }
     513              : 
     514            0 :     default:
     515            0 :         LIBSPDM_ASSERT(false);
     516            0 :         return false;
     517              :     }
     518              : }
     519              : 
     520              : /**
     521              :  * Verify cert public key encryption algorithm is matched to negotiated base_aysm algo
     522              :  *
     523              :  * @param[in]      cert                  Pointer to the DER-encoded certificate data.
     524              :  * @param[in]      cert_size             The size of certificate data in bytes.
     525              :  * @param[in]      base_asym_algo        SPDM base_asym_algo
     526              :  * @param[out]     oid                   cert public key encryption algorithm OID
     527              :  * @param[in]      oid_size              the buffer size for required OID
     528              :  *
     529              :  * @retval  true   get public key oid from cert successfully
     530              :  * @retval  false  get public key oid from cert fail
     531              :  **/
     532          764 : static bool libspdm_get_public_key_oid(const uint8_t *cert, size_t cert_size,
     533              :                                        uint8_t *oid, size_t oid_size, uint32_t base_asym_algo)
     534              : {
     535              :     bool ret;
     536              :     uint8_t *ptr;
     537              :     int32_t length;
     538              :     size_t obj_len;
     539              :     uint8_t *end;
     540              :     uint8_t index;
     541              :     uint8_t sequence_time;
     542              : 
     543          764 :     length = (int32_t)cert_size;
     544          764 :     ptr = (uint8_t*)(size_t)cert;
     545          764 :     obj_len = 0;
     546          764 :     end = ptr + length;
     547          764 :     ret = true;
     548              : 
     549              :     /* TBSCertificate have 5 sequence before subjectPublicKeyInfo*/
     550          764 :     sequence_time = 5;
     551              : 
     552              :     /*all cert sequence*/
     553          764 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     554              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     555          764 :     if (!ret) {
     556            0 :         return false;
     557              :     }
     558              : 
     559              :     /*TBSCertificate sequence*/
     560          764 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     561              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     562          764 :     if (!ret) {
     563            0 :         return false;
     564              :     }
     565              : 
     566          764 :     end = ptr + obj_len;
     567              :     /*version*/
     568          764 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     569              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
     570              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     571          764 :     if (!ret) {
     572            0 :         return false;
     573              :     }
     574              : 
     575          764 :     ptr += obj_len;
     576              :     /*serialNumber*/
     577          764 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
     578          764 :     if (!ret) {
     579            0 :         return false;
     580              :     }
     581              : 
     582              :     /**
     583              :      * signature AlgorithmIdentifier,
     584              :      * issuer Name,
     585              :      * validity Validity,
     586              :      * subject Name,
     587              :      * subjectPublicKeyInfo
     588              :      **/
     589         4584 :     for (index = 0; index < sequence_time; index++) {
     590         3820 :         ptr += obj_len;
     591         3820 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     592              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     593         3820 :         if (!ret) {
     594            0 :             return false;
     595              :         }
     596              :     }
     597              : 
     598          764 :     switch (base_asym_algo)
     599              :     {
     600           63 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
     601              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
     602              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
     603              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
     604              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
     605              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
     606           63 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     607              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     608           63 :         if (!ret) {
     609            0 :             return false;
     610              :         }
     611              : 
     612           63 :         ptr += obj_len;
     613           63 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_BIT_STRING);
     614           63 :         if (!ret) {
     615            0 :             return false;
     616              :         }
     617              : 
     618              :         /*get rsa key len*/
     619           63 :         ptr++;
     620           63 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     621              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     622           63 :         if (!ret) {
     623            1 :             return false;
     624              :         }
     625           62 :         libspdm_copy_mem(oid, oid_size, ptr, oid_size);
     626           62 :         break;
     627          701 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
     628              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
     629              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
     630          701 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     631              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     632          701 :         if (!ret) {
     633            0 :             return false;
     634              :         }
     635          701 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
     636          701 :         if (!ret) {
     637            0 :             return false;
     638              :         }
     639              : 
     640              :         /*get ecc second oid*/
     641          701 :         ptr +=obj_len;
     642          701 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
     643          701 :         if (!ret) {
     644            0 :             return false;
     645              :         }
     646              : 
     647          701 :         if (oid_size != obj_len) {
     648            0 :             return false;
     649              :         }
     650              : 
     651          701 :         libspdm_copy_mem(oid, oid_size, ptr, obj_len);
     652          701 :         break;
     653            0 :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
     654              :     case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
     655            0 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     656              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     657            0 :         if (!ret) {
     658            0 :             return false;
     659              :         }
     660              : 
     661              :         /*get eddsa oid*/
     662            0 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
     663            0 :         if (!ret) {
     664            0 :             return false;
     665              :         }
     666              : 
     667            0 :         if (oid_size != obj_len) {
     668            0 :             return false;
     669              :         }
     670              : 
     671            0 :         libspdm_copy_mem(oid, oid_size, ptr, obj_len);
     672            0 :         break;
     673            0 :     default:
     674            0 :         LIBSPDM_ASSERT(false);
     675            0 :         return false;
     676              :     }
     677              : 
     678          763 :     return true;
     679              : }
     680              : 
     681              : /**
     682              :  * Verify cert public key encryption algorithm is matched to negotiated base_aysm algo
     683              :  *
     684              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
     685              :  * @param[in]  cert_size             The size of certificate data in bytes.
     686              :  * @param[in]  base_asym_algo        SPDM base_asym_algo
     687              :  *
     688              :  * @retval  true   verify pass
     689              :  * @retval  false  verify fail
     690              :  **/
     691          764 : static bool libspdm_verify_cert_subject_public_key_info(const uint8_t *cert, size_t cert_size,
     692              :                                                         uint32_t base_asym_algo)
     693              : {
     694              :     size_t oid_len;
     695              :     bool status;
     696              : 
     697              :     /*public key encrypt algo OID from cert*/
     698              :     uint8_t cert_public_key_crypt_algo_oid[LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN];
     699              :     /*public key encrypt algo OID from libspdm stored*/
     700              :     uint8_t libspdm_public_key_crypt_algo_oid[LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN];
     701              :     uint8_t libspdm_public_key_crypt_algo_oid_other[LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN];
     702              : 
     703          764 :     libspdm_zero_mem(libspdm_public_key_crypt_algo_oid, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
     704          764 :     libspdm_zero_mem(libspdm_public_key_crypt_algo_oid_other, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
     705              : 
     706              :     /*work around: skip the sm2*/
     707          764 :     if (base_asym_algo == SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256) {
     708            0 :         return true;
     709              :     }
     710              : 
     711          764 :     oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo);
     712          764 :     if(oid_len == 0) {
     713            0 :         return false;
     714              :     }
     715              :     /*get public key encrypt algo OID from libspdm stored*/
     716          764 :     status = libspdm_get_public_key_algo_OID(base_asym_algo,
     717              :                                              libspdm_public_key_crypt_algo_oid,
     718              :                                              libspdm_public_key_crypt_algo_oid_other);
     719          764 :     if (!status) {
     720            0 :         return status;
     721              :     }
     722              : 
     723              :     /*get public key encrypt algo OID from cert*/
     724          764 :     status = libspdm_get_public_key_oid(cert, cert_size, cert_public_key_crypt_algo_oid, oid_len,
     725              :                                         base_asym_algo);
     726          764 :     if (!status || (!libspdm_consttime_is_mem_equal(cert_public_key_crypt_algo_oid,
     727            1 :                                                     libspdm_public_key_crypt_algo_oid, oid_len) &&
     728            1 :                     !libspdm_consttime_is_mem_equal(cert_public_key_crypt_algo_oid,
     729              :                                                     libspdm_public_key_crypt_algo_oid_other,
     730              :                                                     oid_len))) {
     731            2 :         return false;
     732              :     }
     733              : 
     734          762 :     return status;
     735              : }
     736              : 
     737              : /**
     738              :  * Verify leaf cert basic_constraints CA is false
     739              :  *
     740              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
     741              :  * @param[in]  cert_size             The size of certificate data in bytes.
     742              :  * @param[in]  need_basic_constraints  This value indicates whether basic_constraints must be present in the Cert
     743              :  *
     744              :  * @retval  true   verify pass,two case: 1.basic constraints is not present in cert, when need_basic_constraints is false;
     745              :  *                                       2. cert basic_constraints CA is false;
     746              :  * @retval  false  verify fail
     747              :  **/
     748          748 : static bool libspdm_verify_leaf_cert_basic_constraints(const uint8_t *cert, size_t cert_size,
     749              :                                                        bool need_basic_constraints)
     750              : {
     751              :     bool status;
     752              :     /*basic_constraints from cert*/
     753              :     uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
     754              :     size_t len;
     755              : 
     756          748 :     uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
     757          748 :     uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
     758              : 
     759          748 :     len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
     760              : 
     761          748 :     status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
     762              :                                                          cert_basic_constraints, &len);
     763          748 :     if (!status) {
     764            0 :         return false;
     765          748 :     } else if (len == 0) {
     766              :         /* basic constraints is not present in cert */
     767            2 :         if (need_basic_constraints) {
     768            1 :             return false;
     769              :         } else {
     770            1 :             return true;
     771              :         }
     772              :     }
     773              : 
     774         1490 :     if ((len == sizeof(basic_constraints_false_case1)) &&
     775          744 :         (libspdm_consttime_is_mem_equal(cert_basic_constraints,
     776              :                                         basic_constraints_false_case1,
     777              :                                         sizeof(basic_constraints_false_case1)))) {
     778          744 :         return true;
     779              :     }
     780              : 
     781            4 :     if ((len == sizeof(basic_constraints_false_case2)) &&
     782            2 :         (libspdm_consttime_is_mem_equal(cert_basic_constraints,
     783              :                                         basic_constraints_false_case2,
     784              :                                         sizeof(basic_constraints_false_case2)))) {
     785            0 :         return true;
     786              :     }
     787              : 
     788            2 :     return false;
     789              : }
     790              : 
     791              : /**
     792              :  * Verify leaf certificate basic_constraints CA is correct for set certificate.
     793              :  *
     794              :  * For SPDM 1.2
     795              :  *     - If certificate model is DeviceCert and CA is present then CA must be false.
     796              :  *     - If certificate model is AliasCert and CA is present then CA must be true.
     797              :  *
     798              :  * For SPDM 1.3 and up, CA must be present and
     799              :  *     - If certificate model is DeviceCert or GenericCert then CA must be false.
     800              :  *     - If certificate model is AliasCert then CA must be true.
     801              :  *
     802              :  * @param[in]  cert                   Pointer to the DER-encoded certificate data.
     803              :  * @param[in]  cert_size              The size of certificate data in bytes.
     804              :  * @param[in]  cert_model             The certificate model.
     805              :  * @param[in]  need_basic_constraints This value indicates whether basic_constraints must be present
     806              :  *                                    in the certificate.
     807              :  *
     808              :  * @retval  true   verify pass 1. basic_constraints is not present when allowed.
     809              :  *                             2. basic_constraints is present and correct.
     810              :  * @retval  false  verify fail
     811              :  **/
     812           14 : static bool libspdm_verify_set_cert_leaf_cert_basic_constraints(
     813              :     const uint8_t *cert, size_t cert_size, uint8_t cert_model, bool need_basic_constraints)
     814              : {
     815              :     bool status;
     816              :     /* basic_constraints from certificate. */
     817              :     uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
     818              :     size_t len;
     819              : 
     820           14 :     const uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
     821           14 :     const uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
     822           14 :     const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_STRING_TRUE_CASE;
     823              : 
     824           14 :     len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
     825              : 
     826           14 :     status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
     827              :                                                          cert_basic_constraints, &len);
     828           14 :     if (!status) {
     829            0 :         return false;
     830           14 :     } else if (need_basic_constraints && (len == 0)) {
     831            0 :         return false;
     832              :     }
     833              : 
     834           14 :     if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT) ||
     835              :         (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
     836            8 :         if (need_basic_constraints || (len != 0)) {
     837           16 :             if ((len == sizeof(basic_constraints_false_case1)) &&
     838            8 :                 (libspdm_consttime_is_mem_equal(cert_basic_constraints,
     839              :                                                 basic_constraints_false_case1,
     840              :                                                 sizeof(basic_constraints_false_case1)))) {
     841            8 :                 return true;
     842              :             }
     843              : 
     844            0 :             if ((len == sizeof(basic_constraints_false_case2)) &&
     845            0 :                 (libspdm_consttime_is_mem_equal(cert_basic_constraints,
     846              :                                                 basic_constraints_false_case2,
     847              :                                                 sizeof(basic_constraints_false_case2)))) {
     848            0 :                 return true;
     849              :             }
     850              :         }
     851              :     } else {
     852              :         /* Alias certificate model. */
     853            6 :         if (need_basic_constraints || (len != 0)) {
     854              :             /* basicConstraints may include the pathLen field. Therefore do not check sequence
     855              :              * length. */
     856            6 :             if (len >= sizeof(basic_constraints_true_case)) {
     857            4 :                 if (cert_basic_constraints[0] != basic_constraints_true_case[0]) {
     858            0 :                     return false;
     859              :                 }
     860            4 :                 if  (libspdm_consttime_is_mem_equal(&cert_basic_constraints[2],
     861              :                                                     &basic_constraints_true_case[2],
     862              :                                                     sizeof(basic_constraints_true_case) - 2)) {
     863            4 :                     return true;
     864              :                 }
     865              :             }
     866              :         }
     867              :     }
     868            2 :     return false;
     869              : }
     870              : 
     871              : /**
     872              :  * Verify leaf cert spdm defined extended key usage
     873              :  *
     874              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
     875              :  * @param[in]  cert_size             The size of certificate data in bytes.
     876              :  * @param[in]  is_requester_cert     Is the function verifying requester or responder cert.
     877              :  *
     878              :  * @retval  true   verify pass, two cases:
     879              :  *                 1. spdm defined eku is not present in cert;
     880              :  *                 2. spdm defined eku is compliant with requester/responder identity;
     881              :  * @retval  false  verify fail, two cases:
     882              :  *                 1. requester's cert has only responder auth oid in eku;
     883              :  *                 2. responder's cert has only requester auth oid in eku;
     884              :  **/
     885          768 : static bool libspdm_verify_leaf_cert_spdm_eku(const uint8_t *cert, size_t cert_size,
     886              :                                               bool is_requester_cert)
     887              : {
     888              :     bool status;
     889              :     uint8_t eku[256];
     890              :     size_t eku_size;
     891              :     bool req_auth_oid_find_success;
     892              :     bool rsp_auth_oid_find_success;
     893              :     uint8_t *ptr;
     894              :     size_t obj_len;
     895              : 
     896              :     /* SPDM defined OID */
     897          768 :     uint8_t eku_requester_auth_oid[] = SPDM_OID_DMTF_EKU_REQUESTER_AUTH;
     898          768 :     uint8_t eku_responder_auth_oid[] = SPDM_OID_DMTF_EKU_RESPONDER_AUTH;
     899              : 
     900          768 :     eku_size = sizeof(eku);
     901          768 :     status = libspdm_x509_get_extended_key_usage(cert, cert_size, eku, &eku_size);
     902          768 :     if (!status) {
     903            0 :         return false;
     904          768 :     } else if (eku_size == 0) {
     905              :         /* eku is not present in cert */
     906            0 :         return true;
     907              :     }
     908              : 
     909          768 :     ptr = eku;
     910          768 :     obj_len = 0;
     911          768 :     req_auth_oid_find_success = false;
     912          768 :     rsp_auth_oid_find_success = false;
     913              : 
     914          768 :     status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len,
     915              :                                   LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     916          768 :     if (!status) {
     917            0 :         return false;
     918              :     }
     919              : 
     920         3075 :     while(ptr < eku + eku_size) {
     921         2307 :         status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
     922         2307 :         if (!status) {
     923            0 :             return false;
     924              :         }
     925              : 
     926         2315 :         if ((obj_len == sizeof(eku_requester_auth_oid)) &&
     927            8 :             (libspdm_consttime_is_mem_equal(ptr, eku_requester_auth_oid,
     928              :                                             sizeof(eku_requester_auth_oid)))) {
     929            4 :             req_auth_oid_find_success = true;
     930              :         }
     931         2315 :         if ((obj_len == sizeof(eku_responder_auth_oid)) &&
     932            8 :             (libspdm_consttime_is_mem_equal(ptr, eku_responder_auth_oid,
     933              :                                             sizeof(eku_responder_auth_oid)))) {
     934            4 :             rsp_auth_oid_find_success = true;
     935              :         }
     936              : 
     937         2307 :         ptr += obj_len;
     938              :     }
     939              : 
     940          768 :     if (ptr != eku + eku_size) {
     941            0 :         return false;
     942              :     }
     943              : 
     944          768 :     if (is_requester_cert) {
     945              :         /* it should not only contain responder auth oid */
     946           20 :         if (!req_auth_oid_find_success && rsp_auth_oid_find_success) {
     947            1 :             return false;
     948              :         }
     949              :     } else {
     950              :         /* it should not only contain requester auth oid */
     951          748 :         if (req_auth_oid_find_success && !rsp_auth_oid_find_success) {
     952            1 :             return false;
     953              :         }
     954              :     }
     955              : 
     956          766 :     return true;
     957              : }
     958              : 
     959              : /**
     960              :  * Verify leaf cert spdm defined extension
     961              :  *
     962              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
     963              :  * @param[in]  cert_size             The size of certificate data in bytes.
     964              :  * @param[in]  is_requester_cert     Is the function verifying requester or responder cert.
     965              :  *
     966              :  * @retval  true   verify pass
     967              :  * @retval  false  verify fail,two case: 1. return is not RETURN_SUCCESS or RETURN_NOT_FOUND;
     968              :  *                                       2. hardware_identity_oid is found in AliasCert model;
     969              :  **/
     970          760 : static bool libspdm_verify_leaf_cert_spdm_extension(const uint8_t *cert, size_t cert_size,
     971              :                                                     bool is_requester_cert,
     972              :                                                     uint8_t cert_model)
     973              : {
     974              :     bool status;
     975              :     bool find_sucessful;
     976              :     uint8_t spdm_extension[LIBSPDM_MAX_EXTENSION_LEN];
     977              :     size_t len;
     978              :     uint8_t *ptr;
     979              :     uint8_t *temptr;
     980              :     size_t obj_len;
     981              : 
     982              :     /* SPDM defined OID */
     983          760 :     uint8_t oid_spdm_extension[] = SPDM_OID_DMTF_SPDM_EXTENSION;
     984          760 :     uint8_t hardware_identity_oid[] = SPDM_OID_DMTF_HARDWARE_IDENTITY;
     985              : 
     986          760 :     len = LIBSPDM_MAX_EXTENSION_LEN;
     987              : 
     988          760 :     if (cert == NULL || cert_size == 0) {
     989            0 :         return false;
     990              :     }
     991              : 
     992          760 :     status = libspdm_x509_get_extension_data(cert, cert_size,
     993              :                                              (const uint8_t *)oid_spdm_extension,
     994              :                                              sizeof(oid_spdm_extension),
     995              :                                              spdm_extension,
     996              :                                              &len);
     997          760 :     if (!status) {
     998            0 :         return false;
     999          760 :     } else if(len == 0) {
    1000           13 :         return true;
    1001              :     }
    1002              : 
    1003              :     /*find the spdm hardware identity OID*/
    1004          747 :     find_sucessful = false;
    1005          747 :     ptr = spdm_extension;
    1006          747 :     obj_len = 0;
    1007              : 
    1008              :     /*id-spdm-cert-oids ::= SEQUENCE SIZE (1..MAX) OF id-spdm-cert-oid*/
    1009          747 :     status = libspdm_asn1_get_tag(
    1010              :         &ptr, spdm_extension + len, &obj_len,
    1011              :         LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1012          747 :     if (!status) {
    1013            0 :         return false;
    1014              :     }
    1015              : 
    1016         1494 :     while(ptr < spdm_extension + len) {
    1017          747 :         status = libspdm_asn1_get_tag(
    1018              :             &ptr, spdm_extension + len, &obj_len,
    1019              :             LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1020          747 :         if (!status) {
    1021            0 :             return false;
    1022              :         }
    1023              : 
    1024          747 :         temptr = ptr + obj_len;
    1025          747 :         status = libspdm_asn1_get_tag(
    1026              :             &ptr, spdm_extension + len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1027          747 :         if (!status) {
    1028            0 :             return false;
    1029              :         }
    1030         1494 :         if ((obj_len == sizeof(hardware_identity_oid)) &&
    1031          747 :             (libspdm_consttime_is_mem_equal(ptr, hardware_identity_oid,
    1032              :                                             sizeof(hardware_identity_oid)))) {
    1033          747 :             find_sucessful = true;
    1034              :         }
    1035          747 :         ptr = temptr;
    1036              :     }
    1037              : 
    1038          747 :     if (ptr != spdm_extension + len) {
    1039            0 :         return false;
    1040              :     }
    1041              : 
    1042              :     /* Responder does not determine Requester's certificate model */
    1043          747 :     if (!is_requester_cert) {
    1044          732 :         if ((find_sucessful) && (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
    1045              :             /* Hardware_identity_OID is found in alias cert model */
    1046            4 :             return false;
    1047              :         }
    1048              :     }
    1049              : 
    1050          743 :     return true;
    1051              : }
    1052              : 
    1053              : /**
    1054              :  * Certificate common Check for SPDM leaf cert when get_cert and set_cert.
    1055              :  *
    1056              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1057              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1058              :  * @param[in]  base_asym_algo        SPDM base_asym_algo
    1059              :  * @param[in]  base_hash_algo        SPDM base_hash_algo
    1060              :  * @param[in]  is_requester_cert     Is the function verifying requester or responder cert.
    1061              :  * @param[in]  cert_model            One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    1062              :  * @param[in]  set_cert              Is the function verifying a set certificate operation.
    1063              :  *
    1064              :  * @retval  true   Success.
    1065              :  * @retval  false  Certificate is not valid.
    1066              :  **/
    1067          770 : bool libspdm_x509_common_certificate_check(const uint8_t *cert, size_t cert_size,
    1068              :                                            uint32_t base_asym_algo, uint32_t base_hash_algo,
    1069              :                                            bool is_requester_cert, uint8_t cert_model,
    1070              :                                            bool set_cert)
    1071              : {
    1072              :     uint8_t end_cert_from[64];
    1073              :     size_t end_cert_from_len;
    1074              :     uint8_t end_cert_to[64];
    1075              :     size_t end_cert_to_len;
    1076              :     size_t asn1_buffer_len;
    1077              :     bool status;
    1078              :     size_t cert_version;
    1079              :     void *context;
    1080              : #if LIBSPDM_ADDITIONAL_CHECK_CERT
    1081              :     size_t signature_algo_oid_size;
    1082              : #endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */
    1083              : 
    1084          770 :     if (cert == NULL || cert_size == 0) {
    1085            0 :         return false;
    1086              :     }
    1087              : 
    1088          770 :     status = true;
    1089          770 :     context = NULL;
    1090          770 :     end_cert_from_len = 64;
    1091          770 :     end_cert_to_len = 64;
    1092              : 
    1093              :     /* 1. version*/
    1094          770 :     cert_version = 0;
    1095          770 :     status = libspdm_x509_get_version(cert, cert_size, &cert_version);
    1096          770 :     if (!status) {
    1097            0 :         goto cleanup;
    1098              :     }
    1099          770 :     if (cert_version != 2) {
    1100            0 :         status = false;
    1101            0 :         goto cleanup;
    1102              :     }
    1103              : 
    1104              :     /* 2. serial_number*/
    1105          770 :     asn1_buffer_len = 0;
    1106          770 :     status = libspdm_x509_get_serial_number(cert, cert_size, NULL, &asn1_buffer_len);
    1107          770 :     if (asn1_buffer_len == 0) {
    1108            0 :         status = false;
    1109            0 :         goto cleanup;
    1110              :     }
    1111              : 
    1112              : #if LIBSPDM_ADDITIONAL_CHECK_CERT
    1113              :     /* 3. Verify signature algorithm. */
    1114              :     signature_algo_oid_size = 0;
    1115              :     status = libspdm_x509_get_signature_algorithm(cert, cert_size, NULL, &signature_algo_oid_size);
    1116              :     if (status) {
    1117              :         if ((signature_algo_oid_size == 0) &&
    1118              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1119              :             status = false;
    1120              :             goto cleanup;
    1121              :         }
    1122              :     } else {
    1123              :         if (signature_algo_oid_size == 0) {
    1124              :             status = false;
    1125              :             goto cleanup;
    1126              :         }
    1127              :     }
    1128              : #endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */
    1129              : 
    1130              :     /* 4. Verify public key algorithm.
    1131              :      *    If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
    1132              :      *    check should be skipped as the Device Certificate CA's public key does not have to use
    1133              :      *    the same algorithms as the connection's negotiated algorithms. */
    1134          770 :     if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
    1135          764 :         status = libspdm_verify_cert_subject_public_key_info(cert, cert_size, base_asym_algo);
    1136          764 :         if (!status) {
    1137            2 :             goto cleanup;
    1138              :         }
    1139              :     }
    1140              : 
    1141              :     /* 5. issuer_name*/
    1142          768 :     asn1_buffer_len = 0;
    1143          768 :     status = libspdm_x509_get_issuer_name(cert, cert_size, NULL, &asn1_buffer_len);
    1144          768 :     if (status) {
    1145            0 :         if ((asn1_buffer_len == 0) &&
    1146              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1147            0 :             status = false;
    1148            0 :             goto cleanup;
    1149              :         }
    1150              :     } else {
    1151          768 :         if (asn1_buffer_len == 0) {
    1152            0 :             status = false;
    1153            0 :             goto cleanup;
    1154              :         }
    1155              :     }
    1156              : 
    1157              :     /* 6. subject_name*/
    1158          768 :     asn1_buffer_len = 0;
    1159          768 :     status = libspdm_x509_get_subject_name(cert, cert_size, NULL, &asn1_buffer_len);
    1160          768 :     if (status) {
    1161            0 :         if ((asn1_buffer_len == 0) &&
    1162              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1163            0 :             status = false;
    1164            0 :             goto cleanup;
    1165              :         }
    1166              :     } else {
    1167          768 :         if (asn1_buffer_len == 0) {
    1168            0 :             status = false;
    1169            0 :             goto cleanup;
    1170              :         }
    1171              :     }
    1172              : 
    1173              :     /* 7. validity*/
    1174          768 :     status = libspdm_x509_get_validity(cert, cert_size, end_cert_from,
    1175              :                                        &end_cert_from_len, end_cert_to,
    1176              :                                        &end_cert_to_len);
    1177          768 :     if (status) {
    1178          768 :         if ((end_cert_from_len == 0) &&
    1179              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1180            0 :             status = false;
    1181            0 :             goto cleanup;
    1182              :         }
    1183              :     } else {
    1184            0 :         if (end_cert_from_len == 0) {
    1185            0 :             status = false;
    1186            0 :             goto cleanup;
    1187              :         }
    1188              :     }
    1189              : 
    1190          768 :     if (end_cert_from_len != 0) {
    1191          768 :         status = libspdm_internal_x509_date_time_check(
    1192              :             end_cert_from, end_cert_from_len, end_cert_to, end_cert_to_len);
    1193          768 :         if (!status) {
    1194            0 :             goto cleanup;
    1195              :         }
    1196              :     }
    1197              : 
    1198              :     /* 8. subject_public_key*/
    1199          768 :     status = libspdm_asym_get_public_key_from_x509(base_asym_algo, cert, cert_size, &context);
    1200          768 :     if (!status) {
    1201            0 :         goto cleanup;
    1202              :     }
    1203              : 
    1204              :     /* 9. key_usage
    1205              :      *    If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
    1206              :      *    check should be skipped as the SPDM specification does not specify the presence or absence
    1207              :      *    of the Device Certificate CA's keyUsage field. */
    1208          768 :     if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
    1209          762 :         size_t value = 0;
    1210              : 
    1211          762 :         status = libspdm_x509_get_key_usage(cert, cert_size, &value);
    1212          762 :         if (!status) {
    1213            0 :             goto cleanup;
    1214              :         } else {
    1215          762 :             if (value == 0) {
    1216            0 :                 if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
    1217            0 :                     status = false;
    1218            0 :                     goto cleanup;
    1219              :                 }
    1220              :             } else {
    1221          762 :                 if ((LIBSPDM_CRYPTO_X509_KU_DIGITAL_SIGNATURE & value) == 0) {
    1222            0 :                     status = false;
    1223            0 :                     goto cleanup;
    1224              :                 }
    1225              :             }
    1226              :         }
    1227              :     }
    1228              : 
    1229              :     /* 10. verify spdm defined extended key usage*/
    1230          768 :     status = libspdm_verify_leaf_cert_spdm_eku(cert, cert_size, is_requester_cert);
    1231          768 :     if (!status) {
    1232            2 :         goto cleanup;
    1233              :     }
    1234              : 
    1235          766 :     if ((!set_cert) || (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT)) {
    1236              :         /* 11. verify spdm defined extension*/
    1237          760 :         status = libspdm_verify_leaf_cert_spdm_extension(cert, cert_size,
    1238              :                                                          is_requester_cert, cert_model);
    1239          760 :         if (!status) {
    1240            4 :             goto cleanup;
    1241              :         }
    1242              :     }
    1243              : 
    1244          762 : cleanup:
    1245          770 :     libspdm_asym_free(base_asym_algo, context);
    1246          770 :     return status;
    1247              : }
    1248              : 
    1249              : /**
    1250              :  * Certificate Check for SPDM leaf cert when get_cert command
    1251              :  *
    1252              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1253              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1254              :  * @param[in]  base_asym_algo        SPDM base_asym_algo
    1255              :  * @param[in]  base_hash_algo        SPDM base_hash_algo
    1256              :  * @param[in]  is_requester          Is the function verifying a cert as a requester or responder.
    1257              :  * @param[in]  is_device_cert_model  If true, the local endpoint uses the DeviceCert model.
    1258              :  *                                   If false, the local endpoint uses the AliasCert model.
    1259              :  *
    1260              :  * @retval  true   Success.
    1261              :  * @retval  false  Certificate is not valid
    1262              :  **/
    1263          743 : bool libspdm_x509_certificate_check(const uint8_t *cert, size_t cert_size,
    1264              :                                     uint32_t base_asym_algo,
    1265              :                                     uint32_t base_hash_algo,
    1266              :                                     bool is_requester,
    1267              :                                     bool is_device_cert_model)
    1268              : {
    1269              :     bool status;
    1270              :     uint8_t cert_model;
    1271              : 
    1272          743 :     if (is_device_cert_model) {
    1273          737 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
    1274              :     } else {
    1275            6 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
    1276              :     }
    1277              : 
    1278          743 :     status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo,
    1279              :                                                    base_hash_algo, is_requester,
    1280              :                                                    cert_model, false);
    1281          743 :     if (!status) {
    1282            5 :         return false;
    1283              :     }
    1284              : 
    1285              :     /* verify basic constraints: the leaf cert always is ca:false in get_cert*/
    1286          738 :     status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, false);
    1287          738 :     return status;
    1288              : }
    1289              : 
    1290              : 
    1291              : /**
    1292              :  * Certificate Check for SPDM leaf cert when get_cert command. It is used for SPDM 1.3.
    1293              :  *
    1294              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1295              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1296              :  * @param[in]  base_asym_algo        SPDM base_asym_algo
    1297              :  * @param[in]  base_hash_algo        SPDM base_hash_algo
    1298              :  * @param[in]  is_requester          Is the function verifying a cert as a requester or responder.
    1299              :  * @param[in]  cert_model            One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    1300              :  *
    1301              :  * @retval  true   Success.
    1302              :  * @retval  false  Certificate is not valid
    1303              :  **/
    1304           13 : bool libspdm_x509_certificate_check_ex(const uint8_t *cert, size_t cert_size,
    1305              :                                        uint32_t base_asym_algo,
    1306              :                                        uint32_t base_hash_algo,
    1307              :                                        bool is_requester,
    1308              :                                        uint8_t cert_model)
    1309              : {
    1310              :     bool status;
    1311              : 
    1312           13 :     status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo,
    1313              :                                                    base_hash_algo, is_requester,
    1314              :                                                    cert_model, false);
    1315           13 :     if (!status) {
    1316            3 :         return false;
    1317              :     }
    1318              : 
    1319              :     /* verify basic constraints: the leaf cert always is ca:false in get_cert
    1320              :      * basic_constraints is mandatory in SPDM 1.3*/
    1321           10 :     status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, true);
    1322           10 :     return status;
    1323              : }
    1324              : 
    1325            8 : bool libspdm_x509_set_cert_certificate_check(const uint8_t *cert, size_t cert_size,
    1326              :                                              uint32_t base_asym_algo, uint32_t base_hash_algo,
    1327              :                                              bool is_requester, bool is_device_cert_model)
    1328              : {
    1329              :     bool status;
    1330              :     uint8_t cert_model;
    1331              : 
    1332            8 :     if (is_device_cert_model) {
    1333            5 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
    1334              :     } else {
    1335            3 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
    1336              :     }
    1337              : 
    1338            8 :     status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo,
    1339              :                                                    base_hash_algo, is_requester,
    1340              :                                                    cert_model, true);
    1341            8 :     if (!status) {
    1342            0 :         return false;
    1343              :     }
    1344              : 
    1345              :     /* verify basic constraints: need check with is_device_cert_model*/
    1346            8 :     status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
    1347              :         cert, cert_size, cert_model, false);
    1348            8 :     return status;
    1349              : }
    1350              : 
    1351            6 : bool libspdm_x509_set_cert_certificate_check_ex(const uint8_t *cert, size_t cert_size,
    1352              :                                                 uint32_t base_asym_algo, uint32_t base_hash_algo,
    1353              :                                                 bool is_requester, uint8_t cert_model)
    1354              : {
    1355              :     bool status;
    1356              : 
    1357            6 :     status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo,
    1358              :                                                    base_hash_algo, is_requester,
    1359              :                                                    cert_model, true);
    1360            6 :     if (!status) {
    1361            0 :         return false;
    1362              :     }
    1363              : 
    1364              :     /* verify basic constraints: need check with is_device_cert_model*/
    1365            6 :     status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
    1366              :         cert, cert_size, cert_model, true);
    1367              : 
    1368            6 :     return status;
    1369              : }
    1370              : 
    1371              : /**
    1372              :  * Return certificate is root cert or not.
    1373              :  * Certificate is considered as a root certificate if the subjectname equal issuername.
    1374              :  *
    1375              :  * @param[in]  cert            Pointer to the DER-encoded certificate data.
    1376              :  * @param[in]  cert_size        The size of certificate data in bytes.
    1377              :  *
    1378              :  * @retval  true   Certificate is self-signed.
    1379              :  * @retval  false  Certificate is not self-signed.
    1380              :  **/
    1381           59 : bool libspdm_is_root_certificate(const uint8_t *cert, size_t cert_size)
    1382              : {
    1383              :     uint8_t issuer_name[LIBSPDM_MAX_NAME_SIZE];
    1384              :     size_t issuer_name_len;
    1385              :     uint8_t subject_name[LIBSPDM_MAX_NAME_SIZE];
    1386              :     size_t subject_name_len;
    1387              :     bool result;
    1388              : 
    1389           59 :     if (cert == NULL || cert_size == 0) {
    1390            0 :         return false;
    1391              :     }
    1392              : 
    1393              :     /* 1. issuer_name*/
    1394           59 :     issuer_name_len = sizeof(issuer_name);
    1395           59 :     result = libspdm_x509_get_issuer_name(cert, cert_size, issuer_name, &issuer_name_len);
    1396           59 :     if (!result) {
    1397            0 :         return false;
    1398              :     }
    1399              : 
    1400              :     /* 2. subject_name*/
    1401           59 :     subject_name_len = sizeof(subject_name);
    1402           59 :     result = libspdm_x509_get_subject_name(cert, cert_size, subject_name, &subject_name_len);
    1403           59 :     if (!result) {
    1404            0 :         return false;
    1405              :     }
    1406              : 
    1407           59 :     if (issuer_name_len != subject_name_len) {
    1408            3 :         return false;
    1409              :     }
    1410           56 :     if (!libspdm_consttime_is_mem_equal(issuer_name, subject_name, issuer_name_len)) {
    1411            0 :         return false;
    1412              :     }
    1413              : 
    1414           56 :     return true;
    1415              : }
    1416              : 
    1417              : /**
    1418              :  * Retrieve the SubjectAltName from SubjectAltName Bytes.
    1419              :  *
    1420              :  * @param[in]      buffer           Pointer to subjectAltName oct bytes.
    1421              :  * @param[in]      len              size of buffer in bytes.
    1422              :  * @param[out]     name_buffer       buffer to contain the retrieved certificate
    1423              :  *                                 SubjectAltName. At most name_buffer_size bytes will be
    1424              :  *                                 written. Maybe NULL in order to determine the size
    1425              :  *                                 buffer needed.
    1426              :  * @param[in,out]  name_buffer_size   The size in bytes of the name buffer on input,
    1427              :  *                                 and the size of buffer returned name on output.
    1428              :  *                                 If name_buffer is NULL then the amount of space needed
    1429              :  *                                 in buffer (including the final null) is returned.
    1430              :  * @param[out]     oid              OID of otherName
    1431              :  * @param[in,out]  oid_size          the buffersize for required OID
    1432              :  *
    1433              :  * @retval true                     get the subjectAltName string successfully
    1434              :  * @retval failed                   get the subjectAltName string failed
    1435              :  **/
    1436            9 : bool libspdm_get_dmtf_subject_alt_name_from_bytes(
    1437              :     uint8_t *buffer, const size_t len, char *name_buffer,
    1438              :     size_t *name_buffer_size, uint8_t *oid,
    1439              :     size_t *oid_size)
    1440              : {
    1441              :     uint8_t *ptr;
    1442              :     int32_t length;
    1443              :     size_t obj_len;
    1444              :     int32_t ret;
    1445              : 
    1446              :     /*copy mem variable*/
    1447              :     volatile uint8_t* dst;
    1448              :     const volatile uint8_t* src;
    1449              :     size_t dst_len;
    1450              :     size_t src_len;
    1451              : 
    1452            9 :     length = (int32_t)len;
    1453            9 :     ptr = buffer;
    1454            9 :     obj_len = 0;
    1455              : 
    1456              :     /* Sequence*/
    1457            9 :     ret = libspdm_asn1_get_tag(&ptr, ptr + length, &obj_len,
    1458              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1459            9 :     if (!ret) {
    1460            0 :         return false;
    1461              :     }
    1462              : 
    1463            9 :     ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len,
    1464              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    1465              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1466              : 
    1467            9 :     ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1468            9 :     if (!ret) {
    1469            0 :         return false;
    1470              :     }
    1471              :     /* CopyData to OID*/
    1472            9 :     if (*oid_size < (size_t)obj_len) {
    1473            0 :         *oid_size = (size_t)obj_len;
    1474            0 :         return false;
    1475              :     }
    1476            9 :     if (oid != NULL) {
    1477            9 :         libspdm_copy_mem(oid, *oid_size, ptr, obj_len);
    1478            9 :         *oid_size = obj_len;
    1479              :     }
    1480              : 
    1481              :     /* Move to next element*/
    1482            9 :     ptr += obj_len;
    1483              : 
    1484            9 :     ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
    1485              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    1486              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1487            9 :     ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
    1488              :                                LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
    1489            9 :     if (!ret) {
    1490            0 :         return false;
    1491              :     }
    1492              : 
    1493            9 :     if (*name_buffer_size < (size_t)obj_len + 1) {
    1494            0 :         *name_buffer_size = (size_t)obj_len + 1;
    1495            0 :         return false;
    1496              :     }
    1497              : 
    1498              :     /* the src and dst address are overlap,
    1499              :      * When the function is called by libspdm_get_dmtf_subject_alt_name.
    1500              :      * libspdm_copy_mem can not be used. */
    1501            9 :     if ((name_buffer != NULL) && (ptr != NULL)) {
    1502            9 :         dst = (volatile uint8_t*) name_buffer;
    1503            9 :         src = (const volatile uint8_t*) ptr;
    1504            9 :         dst_len = *name_buffer_size;
    1505            9 :         src_len = obj_len;
    1506              : 
    1507              :         /* Check for case where "dst_len" may be invalid. Do not zero "dst" in this case. */
    1508            9 :         if (dst_len > (SIZE_MAX >> 1)) {
    1509            0 :             LIBSPDM_ASSERT(0);
    1510            0 :             return false;
    1511              :         }
    1512              : 
    1513              :         /* Guard against invalid lengths. Zero "dst" in these cases. */
    1514            9 :         if (src_len > dst_len ||
    1515            9 :             src_len > (SIZE_MAX >> 1)) {
    1516            0 :             libspdm_zero_mem(name_buffer, dst_len);
    1517            0 :             LIBSPDM_ASSERT(0);
    1518            0 :             return false;
    1519              :         }
    1520              : 
    1521          207 :         while (src_len-- != 0) {
    1522          198 :             *(dst++) = *(src++);
    1523              :         }
    1524              : 
    1525              :         /*encode name buffer to string*/
    1526            9 :         *name_buffer_size = obj_len + 1;
    1527            9 :         name_buffer[obj_len] = 0;
    1528            9 :         return true;
    1529              :     }
    1530              : 
    1531            0 :     return false;
    1532              : }
    1533              : 
    1534              : /**
    1535              :  * Retrieve the SubjectAltName from one X.509 certificate.
    1536              :  *
    1537              :  * @param[in]      cert             Pointer to the DER-encoded X509 certificate.
    1538              :  * @param[in]      cert_size         size of the X509 certificate in bytes.
    1539              :  * @param[out]     name_buffer       buffer to contain the retrieved certificate
    1540              :  *                                 SubjectAltName. At most name_buffer_size bytes will be
    1541              :  *                                 written. Maybe NULL in order to determine the size
    1542              :  *                                 buffer needed.
    1543              :  * @param[in,out]  name_buffer_size   The size in bytes of the name buffer on input,
    1544              :  *                                 and the size of buffer returned name on output.
    1545              :  *                                 If name_buffer is NULL then the amount of space needed
    1546              :  *                                 in buffer (including the final null) is returned.
    1547              :  * @param[out]     oid              OID of otherName
    1548              :  * @param[in,out]  oid_size          the buffersize for required OID
    1549              :  *
    1550              :  * @retval true                     get the subjectAltName string successfully
    1551              :  * @retval failed                   get the subjectAltName string failed
    1552              :  **/
    1553            6 : bool libspdm_get_dmtf_subject_alt_name(const uint8_t *cert, const size_t cert_size,
    1554              :                                        char *name_buffer,
    1555              :                                        size_t *name_buffer_size,
    1556              :                                        uint8_t *oid, size_t *oid_size)
    1557              : {
    1558              :     bool status;
    1559              :     size_t extension_data_size;
    1560            6 :     uint8_t oid_subject_alt_name[] = { 0x55, 0x1D, 0x11 };
    1561              : 
    1562            6 :     extension_data_size = 0;
    1563            6 :     status = libspdm_x509_get_extension_data(cert, cert_size,
    1564              :                                              oid_subject_alt_name,
    1565              :                                              sizeof(oid_subject_alt_name), NULL,
    1566              :                                              &extension_data_size);
    1567            6 :     if (status || (extension_data_size == 0)) {
    1568            0 :         *name_buffer_size = 0;
    1569            0 :         return false;
    1570              :     }
    1571            6 :     if (extension_data_size > *name_buffer_size) {
    1572            0 :         *name_buffer_size = extension_data_size;
    1573            0 :         return false;
    1574              :     }
    1575              :     status =
    1576            6 :         libspdm_x509_get_extension_data(cert, cert_size,
    1577              :                                         oid_subject_alt_name,
    1578              :                                         sizeof(oid_subject_alt_name),
    1579              :                                         (uint8_t *)name_buffer, name_buffer_size);
    1580            6 :     if (!status) {
    1581            0 :         return status;
    1582              :     }
    1583              : 
    1584            6 :     return libspdm_get_dmtf_subject_alt_name_from_bytes(
    1585              :         (uint8_t *)name_buffer, *name_buffer_size, name_buffer,
    1586              :         name_buffer_size, oid, oid_size);
    1587              : }
    1588              : 
    1589              : /**
    1590              :  * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
    1591              :  * It is used for SPDM 1.3.
    1592              :  *
    1593              :  * @param  cert_chain_data       The certificate chain data without spdm_cert_chain_t header.
    1594              :  * @param  cert_chain_data_size  Size in bytes of the certificate chain data.
    1595              :  * @param  base_asym_algo        SPDM base_asym_algo
    1596              :  * @param  base_hash_algo        SPDM base_hash_algo
    1597              :  * @param  is_requester_cert     Is the function verifying requester or responder cert.
    1598              :  * @param  cert_model            One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    1599              :  *
    1600              :  * @retval true  Certificate chain data integrity verification pass.
    1601              :  * @retval false Certificate chain data integrity verification fail.
    1602              :  **/
    1603            6 : bool libspdm_verify_cert_chain_data_ex(uint8_t *cert_chain_data, size_t cert_chain_data_size,
    1604              :                                        uint32_t base_asym_algo, uint32_t base_hash_algo,
    1605              :                                        bool is_requester_cert, uint8_t cert_model)
    1606              : {
    1607              :     const uint8_t *root_cert_buffer;
    1608              :     size_t root_cert_buffer_size;
    1609              :     const uint8_t *leaf_cert_buffer;
    1610              :     size_t leaf_cert_buffer_size;
    1611              : 
    1612            6 :     if (cert_chain_data_size >
    1613              :         0xFFFF - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
    1614            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1615              :                        "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
    1616            0 :         return false;
    1617              :     }
    1618              : 
    1619            6 :     if (!libspdm_x509_get_cert_from_cert_chain(
    1620              :             cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
    1621              :             &root_cert_buffer_size)) {
    1622            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1623              :                        "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
    1624            0 :         return false;
    1625              :     }
    1626              : 
    1627            6 :     if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
    1628              :                                         cert_chain_data, cert_chain_data_size)) {
    1629            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1630              :                        "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
    1631            2 :         return false;
    1632              :     }
    1633              : 
    1634            4 :     if (!libspdm_x509_get_cert_from_cert_chain(
    1635              :             cert_chain_data, cert_chain_data_size, -1,
    1636              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    1637            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1638              :                        "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
    1639            0 :         return false;
    1640              :     }
    1641              : 
    1642            4 :     if (!libspdm_x509_certificate_check_ex(leaf_cert_buffer, leaf_cert_buffer_size,
    1643              :                                            base_asym_algo, base_hash_algo,
    1644              :                                            is_requester_cert, cert_model)) {
    1645            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1646              :                        "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
    1647            1 :         return false;
    1648              :     }
    1649              : 
    1650            3 :     return true;
    1651              : }
    1652              : /**
    1653              :  * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
    1654              :  *
    1655              :  * @param  cert_chain_data          The certificate chain data without spdm_cert_chain_t header.
    1656              :  * @param  cert_chain_data_size      size in bytes of the certificate chain data.
    1657              :  * @param  base_asym_algo            SPDM base_asym_algo
    1658              :  * @param  base_hash_algo            SPDM base_hash_algo
    1659              :  * @param  is_requester_cert         Is the function verifying requester or responder cert.
    1660              :  * @param  is_device_cert_model      If true, the cert chain is DeviceCert model;
    1661              :  *                                   If false, the cert chain is AliasCert model;
    1662              :  *
    1663              :  * @retval true  certificate chain data integrity verification pass.
    1664              :  * @retval false certificate chain data integrity verification fail.
    1665              :  **/
    1666          689 : bool libspdm_verify_cert_chain_data(uint8_t *cert_chain_data, size_t cert_chain_data_size,
    1667              :                                     uint32_t base_asym_algo, uint32_t base_hash_algo,
    1668              :                                     bool is_requester_cert, bool is_device_cert_model)
    1669              : {
    1670              :     const uint8_t *root_cert_buffer;
    1671              :     size_t root_cert_buffer_size;
    1672              :     const uint8_t *leaf_cert_buffer;
    1673              :     size_t leaf_cert_buffer_size;
    1674              : 
    1675          689 :     if (cert_chain_data_size >
    1676              :         0xFFFF - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
    1677            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1678              :                        "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
    1679            0 :         return false;
    1680              :     }
    1681              : 
    1682          689 :     if (!libspdm_x509_get_cert_from_cert_chain(
    1683              :             cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
    1684              :             &root_cert_buffer_size)) {
    1685            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1686              :                        "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
    1687            0 :         return false;
    1688              :     }
    1689              : 
    1690          689 :     if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
    1691              :                                         cert_chain_data, cert_chain_data_size)) {
    1692            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1693              :                        "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
    1694            0 :         return false;
    1695              :     }
    1696              : 
    1697          689 :     if (!libspdm_x509_get_cert_from_cert_chain(
    1698              :             cert_chain_data, cert_chain_data_size, -1,
    1699              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    1700            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1701              :                        "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
    1702            0 :         return false;
    1703              :     }
    1704              : 
    1705          689 :     if (!libspdm_x509_certificate_check(leaf_cert_buffer, leaf_cert_buffer_size,
    1706              :                                         base_asym_algo, base_hash_algo,
    1707              :                                         is_requester_cert, is_device_cert_model)) {
    1708            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1709              :                        "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
    1710            0 :         return false;
    1711              :     }
    1712              : 
    1713          689 :     return true;
    1714              : }
    1715              : 
    1716              : /**
    1717              :  * This function verifies the integrity of certificate chain buffer including
    1718              :  * spdm_cert_chain_t header. It is used for SPDM 1.3.
    1719              :  *
    1720              :  * @param  base_hash_algo          SPDM base_hash_algo
    1721              :  * @param  base_asym_algo          SPDM base_asym_algo
    1722              :  * @param  cert_chain_buffer       The certificate chain buffer including spdm_cert_chain_t header.
    1723              :  * @param  cert_chain_buffer_size  Size in bytes of the certificate chain buffer.
    1724              :  * @param  is_requester_cert       Is the function verifying requester or responder cert.
    1725              :  * @param  cert_model              One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    1726              :  *
    1727              :  * @retval true   Certificate chain buffer integrity verification pass.
    1728              :  * @retval false  Certificate chain buffer integrity verification fail.
    1729              :  **/
    1730            6 : bool libspdm_verify_certificate_chain_buffer_ex(uint32_t base_hash_algo, uint32_t base_asym_algo,
    1731              :                                                 const void *cert_chain_buffer,
    1732              :                                                 size_t cert_chain_buffer_size,
    1733              :                                                 bool is_requester_cert, uint8_t cert_model)
    1734              : {
    1735              :     const uint8_t *cert_chain_data;
    1736              :     size_t cert_chain_data_size;
    1737              :     const uint8_t *first_cert_buffer;
    1738              :     size_t first_cert_buffer_size;
    1739              :     size_t hash_size;
    1740              :     uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
    1741              :     const uint8_t *leaf_cert_buffer;
    1742              :     size_t leaf_cert_buffer_size;
    1743              :     bool result;
    1744              :     const spdm_cert_chain_t *cert_chain_header;
    1745              : 
    1746            6 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    1747              : 
    1748            6 :     if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
    1749            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1750              :                        "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
    1751            0 :         return false;
    1752              :     }
    1753              : 
    1754            6 :     cert_chain_header = cert_chain_buffer;
    1755            6 :     if (cert_chain_header->length != cert_chain_buffer_size) {
    1756            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1757              :                        "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
    1758            2 :         return false;
    1759              :     }
    1760              : 
    1761            4 :     cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
    1762            4 :     cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
    1763            4 :     if (!libspdm_x509_get_cert_from_cert_chain(
    1764              :             cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
    1765              :             &first_cert_buffer_size)) {
    1766            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1767              :                        "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
    1768            0 :         return false;
    1769              :     }
    1770              : 
    1771            4 :     if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
    1772            4 :         result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
    1773              :                                   calc_root_cert_hash);
    1774            4 :         if (!result) {
    1775            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1776              :                            "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
    1777            0 :             return false;
    1778              :         }
    1779            4 :         if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
    1780              :                                             sizeof(spdm_cert_chain_t),
    1781              :                                             calc_root_cert_hash, hash_size)) {
    1782            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1783              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
    1784            0 :             return false;
    1785              :         }
    1786            4 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1787              :                        "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
    1788              :     }
    1789              : 
    1790              :     /*If the number of certificates in the certificate chain is more than 1,
    1791              :      * other certificates need to be verified.*/
    1792            4 :     if (cert_chain_data_size > first_cert_buffer_size) {
    1793            4 :         if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
    1794              :                                             cert_chain_data + first_cert_buffer_size,
    1795              :                                             cert_chain_data_size - first_cert_buffer_size)) {
    1796            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1797              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
    1798            0 :             return false;
    1799              :         }
    1800              :     }
    1801              : 
    1802            4 :     if (!libspdm_x509_get_cert_from_cert_chain(
    1803              :             cert_chain_data, cert_chain_data_size, -1,
    1804              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    1805            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1806              :                        "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
    1807            0 :         return false;
    1808              :     }
    1809              : 
    1810            4 :     if (!libspdm_x509_certificate_check_ex(leaf_cert_buffer, leaf_cert_buffer_size,
    1811              :                                            base_asym_algo, base_hash_algo,
    1812              :                                            is_requester_cert, cert_model)) {
    1813            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1814              :                        "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
    1815            1 :         return false;
    1816              :     }
    1817              : 
    1818            3 :     return true;
    1819              : }
    1820              : 
    1821           34 : bool libspdm_verify_certificate_chain_buffer(uint32_t base_hash_algo, uint32_t base_asym_algo,
    1822              :                                              const void *cert_chain_buffer,
    1823              :                                              size_t cert_chain_buffer_size,
    1824              :                                              bool is_requester_cert,
    1825              :                                              bool is_device_cert_model)
    1826              : {
    1827              :     const uint8_t *cert_chain_data;
    1828              :     size_t cert_chain_data_size;
    1829              :     const uint8_t *first_cert_buffer;
    1830              :     size_t first_cert_buffer_size;
    1831              :     size_t hash_size;
    1832              :     uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
    1833              :     const uint8_t *leaf_cert_buffer;
    1834              :     size_t leaf_cert_buffer_size;
    1835              :     bool result;
    1836              :     const spdm_cert_chain_t *cert_chain_header;
    1837              : 
    1838           34 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    1839              : 
    1840           34 :     if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
    1841            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1842              :                        "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
    1843            0 :         return false;
    1844              :     }
    1845              : 
    1846           34 :     cert_chain_header = cert_chain_buffer;
    1847           34 :     if (cert_chain_header->length != cert_chain_buffer_size) {
    1848            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1849              :                        "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
    1850            0 :         return false;
    1851              :     }
    1852              : 
    1853           34 :     cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
    1854           34 :     cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
    1855           34 :     if (!libspdm_x509_get_cert_from_cert_chain(
    1856              :             cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
    1857              :             &first_cert_buffer_size)) {
    1858            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1859              :                        "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
    1860            0 :         return false;
    1861              :     }
    1862              : 
    1863           34 :     if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
    1864           32 :         result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
    1865              :                                   calc_root_cert_hash);
    1866           32 :         if (!result) {
    1867            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1868              :                            "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
    1869            0 :             return false;
    1870              :         }
    1871           32 :         if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
    1872              :                                             sizeof(spdm_cert_chain_t),
    1873              :                                             calc_root_cert_hash, hash_size)) {
    1874            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1875              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
    1876            0 :             return false;
    1877              :         }
    1878           32 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1879              :                        "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
    1880              :     }
    1881              : 
    1882              :     /*If the number of certificates in the certificate chain is more than 1,
    1883              :      * other certificates need to be verified.*/
    1884           34 :     if (cert_chain_data_size > first_cert_buffer_size) {
    1885           34 :         if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
    1886              :                                             cert_chain_data + first_cert_buffer_size,
    1887              :                                             cert_chain_data_size - first_cert_buffer_size)) {
    1888            3 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1889              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
    1890            3 :             return false;
    1891              :         }
    1892              :     }
    1893              : 
    1894           31 :     if (!libspdm_x509_get_cert_from_cert_chain(
    1895              :             cert_chain_data, cert_chain_data_size, -1,
    1896              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    1897            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1898              :                        "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
    1899            0 :         return false;
    1900              :     }
    1901              : 
    1902           31 :     if (!libspdm_x509_certificate_check(leaf_cert_buffer, leaf_cert_buffer_size,
    1903              :                                         base_asym_algo, base_hash_algo,
    1904              :                                         is_requester_cert, is_device_cert_model)) {
    1905            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1906              :                        "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
    1907            2 :         return false;
    1908              :     }
    1909              : 
    1910           29 :     return true;
    1911              : }
    1912              : 
    1913          254 : bool libspdm_get_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
    1914              :                                                       uint32_t base_asym_alg,
    1915              :                                                       uint8_t *cert_chain_data,
    1916              :                                                       size_t cert_chain_data_size,
    1917              :                                                       void **public_key)
    1918              : {
    1919              :     size_t hash_size;
    1920              :     const uint8_t *cert_buffer;
    1921              :     size_t cert_buffer_size;
    1922              :     bool result;
    1923              : 
    1924          254 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    1925              : 
    1926          254 :     cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
    1927          254 :     cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
    1928              : 
    1929              :     /* Get leaf cert from cert chain */
    1930          254 :     result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
    1931              :                                                    cert_chain_data_size, -1,
    1932              :                                                    &cert_buffer, &cert_buffer_size);
    1933          254 :     if (!result) {
    1934            0 :         return false;
    1935              :     }
    1936              : 
    1937          254 :     result = libspdm_asym_get_public_key_from_x509(
    1938              :         base_asym_alg,
    1939              :         cert_buffer, cert_buffer_size, public_key);
    1940          254 :     if (!result) {
    1941            4 :         return false;
    1942              :     }
    1943              : 
    1944          250 :     return true;
    1945              : }
    1946              : 
    1947           29 : bool libspdm_verify_req_info(uint8_t *req_info, uint16_t req_info_len)
    1948              : {
    1949              :     bool ret;
    1950              :     uint8_t *ptr;
    1951              :     int32_t length;
    1952              :     size_t obj_len;
    1953              :     uint8_t *end;
    1954              : 
    1955           29 :     length = (int32_t)req_info_len;
    1956           29 :     ptr = req_info;
    1957           29 :     obj_len = 0;
    1958           29 :     end = ptr + length;
    1959           29 :     ret = true;
    1960              : 
    1961           29 :     if (req_info_len == 0) {
    1962            4 :         return true;
    1963              :     }
    1964              : 
    1965              :     /*req_info sequence*/
    1966           25 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    1967              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1968           25 :     if (!ret) {
    1969            2 :         return false;
    1970              :     }
    1971              : 
    1972              :     /*integer:version*/
    1973           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
    1974           23 :     if (!ret) {
    1975            0 :         return false;
    1976              :     } else {
    1977           23 :         ptr += obj_len;
    1978              :     }
    1979              : 
    1980              :     /*sequence:subject name*/
    1981           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    1982              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1983           23 :     if (!ret) {
    1984            0 :         return false;
    1985              :     } else {
    1986           23 :         ptr += obj_len;
    1987              :     }
    1988              : 
    1989              :     /*sequence:subject pkinfo*/
    1990           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    1991              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1992           23 :     if (!ret) {
    1993            0 :         return false;
    1994              :     } else {
    1995           23 :         ptr += obj_len;
    1996              :     }
    1997              : 
    1998              :     /*[0]: attributes*/
    1999           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2000              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    2001              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2002              :     /*req_info format error, don't have attributes tag*/
    2003           23 :     if (!ret) {
    2004            0 :         return false;
    2005              :     }
    2006              : 
    2007              :     /*there is no attributes object*/
    2008           23 :     if (ptr == end) {
    2009            0 :         return true;
    2010              :     }
    2011              : 
    2012              :     /*there is some attributes object: 0,1,2 ...*/
    2013           46 :     while (ret)
    2014              :     {
    2015           46 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2016              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE |
    2017              :                                    LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2018           46 :         if (ret) {
    2019           23 :             ptr += obj_len;
    2020              :         } else {
    2021           23 :             break;
    2022              :         }
    2023              :     }
    2024              : 
    2025           23 :     if (ptr == end) {
    2026           23 :         return true;
    2027              :     } else {
    2028            0 :         return false;
    2029              :     }
    2030              : }
    2031              : 
    2032              : #endif
        

Generated by: LCOV version 2.0-1