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.3 % 728 439
Test Date: 2026-02-22 08:11:49 Functions: 87.5 % 24 21

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

Generated by: LCOV version 2.0-1