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: 58.8 % 774 455
Test Date: 2025-09-14 08:11:04 Functions: 87.5 % 32 28

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

Generated by: LCOV version 2.0-1