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: 60.5 % 731 442
Test Date: 2026-07-26 08:53:33 Functions: 88.0 % 25 22

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

Generated by: LCOV version 2.0-1