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: 61.6 % 765 471
Test Date: 2025-07-27 08:10:33 Functions: 90.6 % 32 29

            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         1022 : libspdm_get_asym_get_public_key_from_x509(uint32_t base_asym_algo)
     192              : {
     193         1022 :     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          922 :     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          922 :         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         1022 : 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         1022 :     get_public_key_from_x509_function = libspdm_get_asym_get_public_key_from_x509(base_asym_algo);
     291         1022 :     if (get_public_key_from_x509_function == NULL) {
     292            0 :         return false;
     293              :     }
     294         1022 :     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          768 : 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          768 :     f0_size = 64;
     362          768 :     t0_size = 64;
     363              : 
     364          768 :     status = libspdm_x509_set_date_time("19700101000000Z", f0, &f0_size);
     365          768 :     if (!status) {
     366            0 :         return false;
     367              :     }
     368              : 
     369          768 :     status = libspdm_x509_set_date_time("99991231235959Z", t0, &t0_size);
     370          768 :     if (!status) {
     371            0 :         return false;
     372              :     }
     373              : 
     374              :     /* from >= f0*/
     375          768 :     ret = libspdm_x509_compare_date_time(from, f0);
     376          768 :     if (ret < 0) {
     377            0 :         return false;
     378              :     }
     379              : 
     380              :     /* to <= t0*/
     381          768 :     ret = libspdm_x509_compare_date_time(t0, to);
     382          768 :     if (ret < 0) {
     383            0 :         return false;
     384              :     }
     385              : 
     386          768 :     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         1528 : static uint32_t libspdm_get_public_key_algo_OID_len(
     397              :     uint32_t base_asym_algo, uint32_t pqc_asym_algo)
     398              : {
     399         1528 :     if (base_asym_algo != 0) {
     400         1528 :         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         1398 :         case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
     438              :     #if LIBSPDM_ECDSA_P256_SUPPORT
     439         1398 :             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          764 : 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          764 :     oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
     590          764 :     if(oid_len == 0) {
     591            0 :         return false;
     592              :     }
     593              : 
     594          764 :     if (base_asym_algo != 0) {
     595          764 :         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          699 :         case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256: {
     634              :     #if LIBSPDM_ECDSA_P256_SUPPORT
     635          699 :             uint8_t encry_algo_oid_ecc256[] = KEY_ENCRY_ALGO_ECC256_OID;
     636          699 :             libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc256, oid_len);
     637          699 :             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          764 : 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          764 :     length = (int32_t)cert_size;
     877          764 :     ptr = (uint8_t*)(size_t)cert;
     878          764 :     obj_len = 0;
     879          764 :     end = ptr + length;
     880          764 :     ret = true;
     881              : 
     882              :     /* TBSCertificate have 5 sequence before subjectPublicKeyInfo*/
     883          764 :     sequence_time = 5;
     884              : 
     885              :     /*all cert sequence*/
     886          764 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     887              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     888          764 :     if (!ret) {
     889            0 :         return false;
     890              :     }
     891              : 
     892              :     /*TBSCertificate sequence*/
     893          764 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     894              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     895          764 :     if (!ret) {
     896            0 :         return false;
     897              :     }
     898              : 
     899          764 :     end = ptr + obj_len;
     900              :     /*version*/
     901          764 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     902              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
     903              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     904          764 :     if (!ret) {
     905            0 :         return false;
     906              :     }
     907              : 
     908          764 :     ptr += obj_len;
     909              :     /*serialNumber*/
     910          764 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
     911          764 :     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         4584 :     for (index = 0; index < sequence_time; index++) {
     923         3820 :         ptr += obj_len;
     924         3820 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     925              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     926         3820 :         if (!ret) {
     927            0 :             return false;
     928              :         }
     929              :     }
     930              : 
     931          764 :     if (base_asym_algo != 0) {
     932          764 :         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          701 :         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          701 :             ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     965              :                                        LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     966          701 :             if (!ret) {
     967            0 :                 return false;
     968              :             }
     969          701 :             ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
     970          701 :             if (!ret) {
     971            0 :                 return false;
     972              :             }
     973              : 
     974              :             /*get ecc second oid*/
     975          701 :             ptr +=obj_len;
     976          701 :             ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
     977          701 :             if (!ret) {
     978            0 :                 return false;
     979              :             }
     980              : 
     981          701 :             if (oid_size != obj_len) {
     982            0 :                 return false;
     983              :             }
     984              : 
     985          701 :             libspdm_copy_mem(oid, oid_size, ptr, obj_len);
     986          701 :             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          763 :     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          763 :     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          764 : 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          764 :     libspdm_zero_mem(libspdm_public_key_crypt_algo_oid, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
    1080          764 :     libspdm_zero_mem(libspdm_public_key_crypt_algo_oid_other, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
    1081              : 
    1082              :     /*work around: skip the sm2*/
    1083          764 :     if (base_asym_algo == SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256) {
    1084            0 :         return true;
    1085              :     }
    1086              : 
    1087          764 :     oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
    1088          764 :     if(oid_len == 0) {
    1089            0 :         return false;
    1090              :     }
    1091              :     /*get public key encrypt algo OID from libspdm stored*/
    1092          764 :     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          764 :     if (!status) {
    1096            0 :         return status;
    1097              :     }
    1098              : 
    1099              :     /*get public key encrypt algo OID from cert*/
    1100          764 :     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          764 :     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          762 :     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          748 : 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          748 :     uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
    1133          748 :     uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
    1134              : 
    1135          748 :     len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
    1136              : 
    1137          748 :     status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
    1138              :                                                          cert_basic_constraints, &len);
    1139          748 :     if (!status) {
    1140            0 :         return false;
    1141          748 :     } 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         1490 :     if ((len == sizeof(basic_constraints_false_case1)) &&
    1151          744 :         (libspdm_consttime_is_mem_equal(cert_basic_constraints,
    1152              :                                         basic_constraints_false_case1,
    1153              :                                         sizeof(basic_constraints_false_case1)))) {
    1154          744 :         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           14 : 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           14 :     const uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
    1197           14 :     const uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
    1198           14 :     const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_STRING_TRUE_CASE;
    1199              : 
    1200           14 :     len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
    1201              : 
    1202           14 :     status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
    1203              :                                                          cert_basic_constraints, &len);
    1204           14 :     if (!status) {
    1205            0 :         return false;
    1206           14 :     } else if (need_basic_constraints && (len == 0)) {
    1207            0 :         return false;
    1208              :     }
    1209              : 
    1210           14 :     if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT) ||
    1211              :         (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1212            8 :         if (need_basic_constraints || (len != 0)) {
    1213           16 :             if ((len == sizeof(basic_constraints_false_case1)) &&
    1214            8 :                 (libspdm_consttime_is_mem_equal(cert_basic_constraints,
    1215              :                                                 basic_constraints_false_case1,
    1216              :                                                 sizeof(basic_constraints_false_case1)))) {
    1217            8 :                 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          768 : 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          768 :     uint8_t eku_requester_auth_oid[] = SPDM_OID_DMTF_EKU_REQUESTER_AUTH;
    1274          768 :     uint8_t eku_responder_auth_oid[] = SPDM_OID_DMTF_EKU_RESPONDER_AUTH;
    1275              : 
    1276          768 :     eku_size = sizeof(eku);
    1277          768 :     status = libspdm_x509_get_extended_key_usage(cert, cert_size, eku, &eku_size);
    1278          768 :     if (!status) {
    1279            0 :         return false;
    1280          768 :     } else if (eku_size == 0) {
    1281              :         /* eku is not present in cert */
    1282            0 :         return true;
    1283              :     }
    1284              : 
    1285          768 :     ptr = eku;
    1286          768 :     obj_len = 0;
    1287          768 :     req_auth_oid_find_success = false;
    1288          768 :     rsp_auth_oid_find_success = false;
    1289              : 
    1290          768 :     status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len,
    1291              :                                   LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1292          768 :     if (!status) {
    1293            0 :         return false;
    1294              :     }
    1295              : 
    1296         3075 :     while(ptr < eku + eku_size) {
    1297         2307 :         status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1298         2307 :         if (!status) {
    1299            0 :             return false;
    1300              :         }
    1301              : 
    1302         2315 :         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         2315 :         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         2307 :         ptr += obj_len;
    1314              :     }
    1315              : 
    1316          768 :     if (ptr != eku + eku_size) {
    1317            0 :         return false;
    1318              :     }
    1319              : 
    1320          768 :     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          748 :         if (req_auth_oid_find_success && !rsp_auth_oid_find_success) {
    1328            1 :             return false;
    1329              :         }
    1330              :     }
    1331              : 
    1332          766 :     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          760 : 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          760 :     uint8_t oid_spdm_extension[] = SPDM_OID_DMTF_SPDM_EXTENSION;
    1360          760 :     uint8_t hardware_identity_oid[] = SPDM_OID_DMTF_HARDWARE_IDENTITY;
    1361              : 
    1362          760 :     len = LIBSPDM_MAX_EXTENSION_LEN;
    1363              : 
    1364          760 :     if (cert == NULL || cert_size == 0) {
    1365            0 :         return false;
    1366              :     }
    1367              : 
    1368          760 :     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          760 :     if (!status) {
    1374            0 :         return false;
    1375          760 :     } else if(len == 0) {
    1376           13 :         return true;
    1377              :     }
    1378              : 
    1379              :     /*find the spdm hardware identity OID*/
    1380          747 :     find_sucessful = false;
    1381          747 :     ptr = spdm_extension;
    1382          747 :     obj_len = 0;
    1383              : 
    1384              :     /*id-spdm-cert-oids ::= SEQUENCE SIZE (1..MAX) OF id-spdm-cert-oid*/
    1385          747 :     status = libspdm_asn1_get_tag(
    1386              :         &ptr, spdm_extension + len, &obj_len,
    1387              :         LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1388          747 :     if (!status) {
    1389            0 :         return false;
    1390              :     }
    1391              : 
    1392         1494 :     while(ptr < spdm_extension + len) {
    1393          747 :         status = libspdm_asn1_get_tag(
    1394              :             &ptr, spdm_extension + len, &obj_len,
    1395              :             LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1396          747 :         if (!status) {
    1397            0 :             return false;
    1398              :         }
    1399              : 
    1400          747 :         temptr = ptr + obj_len;
    1401          747 :         status = libspdm_asn1_get_tag(
    1402              :             &ptr, spdm_extension + len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1403          747 :         if (!status) {
    1404            0 :             return false;
    1405              :         }
    1406         1494 :         if ((obj_len == sizeof(hardware_identity_oid)) &&
    1407          747 :             (libspdm_consttime_is_mem_equal(ptr, hardware_identity_oid,
    1408              :                                             sizeof(hardware_identity_oid)))) {
    1409          747 :             find_sucessful = true;
    1410              :         }
    1411          747 :         ptr = temptr;
    1412              :     }
    1413              : 
    1414          747 :     if (ptr != spdm_extension + len) {
    1415            0 :         return false;
    1416              :     }
    1417              : 
    1418              :     /* Responder does not determine Requester's certificate model */
    1419          747 :     if (!is_requester_cert) {
    1420          732 :         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          743 :     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          770 : 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              : #if LIBSPDM_ADDITIONAL_CHECK_CERT
    1458              :     size_t signature_algo_oid_size;
    1459              : #endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */
    1460              : 
    1461          770 :     if (cert == NULL || cert_size == 0) {
    1462            0 :         return false;
    1463              :     }
    1464              : 
    1465          770 :     status = true;
    1466          770 :     context = NULL;
    1467          770 :     end_cert_from_len = 64;
    1468          770 :     end_cert_to_len = 64;
    1469              : 
    1470              :     /* 1. version*/
    1471          770 :     cert_version = 0;
    1472          770 :     status = libspdm_x509_get_version(cert, cert_size, &cert_version);
    1473          770 :     if (!status) {
    1474            0 :         goto cleanup;
    1475              :     }
    1476          770 :     if (cert_version != 2) {
    1477            0 :         status = false;
    1478            0 :         goto cleanup;
    1479              :     }
    1480              : 
    1481              :     /* 2. serial_number*/
    1482          770 :     asn1_buffer_len = 0;
    1483          770 :     status = libspdm_x509_get_serial_number(cert, cert_size, NULL, &asn1_buffer_len);
    1484          770 :     if (asn1_buffer_len == 0) {
    1485            0 :         status = false;
    1486            0 :         goto cleanup;
    1487              :     }
    1488              : 
    1489              : #if LIBSPDM_ADDITIONAL_CHECK_CERT
    1490              :     /* 3. Verify signature algorithm. */
    1491              :     signature_algo_oid_size = 0;
    1492              :     status = libspdm_x509_get_signature_algorithm(cert, cert_size, NULL, &signature_algo_oid_size);
    1493              :     if (status) {
    1494              :         if ((signature_algo_oid_size == 0) &&
    1495              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1496              :             status = false;
    1497              :             goto cleanup;
    1498              :         }
    1499              :     } else {
    1500              :         if (signature_algo_oid_size == 0) {
    1501              :             status = false;
    1502              :             goto cleanup;
    1503              :         }
    1504              :     }
    1505              : #endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */
    1506              : 
    1507              :     /* 4. Verify public key algorithm.
    1508              :      *    If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
    1509              :      *    check should be skipped as the Device Certificate CA's public key does not have to use
    1510              :      *    the same algorithms as the connection's negotiated algorithms. */
    1511          770 :     if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
    1512          764 :         status = libspdm_verify_cert_subject_public_key_info(cert, cert_size, base_asym_algo, pqc_asym_algo);
    1513          764 :         if (!status) {
    1514            2 :             goto cleanup;
    1515              :         }
    1516              :     }
    1517              : 
    1518              :     /* 5. issuer_name*/
    1519          768 :     asn1_buffer_len = 0;
    1520          768 :     status = libspdm_x509_get_issuer_name(cert, cert_size, NULL, &asn1_buffer_len);
    1521          768 :     if (status) {
    1522            0 :         if ((asn1_buffer_len == 0) &&
    1523              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1524            0 :             status = false;
    1525            0 :             goto cleanup;
    1526              :         }
    1527              :     } else {
    1528          768 :         if (asn1_buffer_len == 0) {
    1529            0 :             status = false;
    1530            0 :             goto cleanup;
    1531              :         }
    1532              :     }
    1533              : 
    1534              :     /* 6. subject_name*/
    1535          768 :     asn1_buffer_len = 0;
    1536          768 :     status = libspdm_x509_get_subject_name(cert, cert_size, NULL, &asn1_buffer_len);
    1537          768 :     if (status) {
    1538            0 :         if ((asn1_buffer_len == 0) &&
    1539              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1540            0 :             status = false;
    1541            0 :             goto cleanup;
    1542              :         }
    1543              :     } else {
    1544          768 :         if (asn1_buffer_len == 0) {
    1545            0 :             status = false;
    1546            0 :             goto cleanup;
    1547              :         }
    1548              :     }
    1549              : 
    1550              :     /* 7. validity*/
    1551          768 :     status = libspdm_x509_get_validity(cert, cert_size, end_cert_from,
    1552              :                                        &end_cert_from_len, end_cert_to,
    1553              :                                        &end_cert_to_len);
    1554          768 :     if (status) {
    1555          768 :         if ((end_cert_from_len == 0) &&
    1556              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1557            0 :             status = false;
    1558            0 :             goto cleanup;
    1559              :         }
    1560              :     } else {
    1561            0 :         if (end_cert_from_len == 0) {
    1562            0 :             status = false;
    1563            0 :             goto cleanup;
    1564              :         }
    1565              :     }
    1566              : 
    1567          768 :     if (end_cert_from_len != 0) {
    1568          768 :         status = libspdm_internal_x509_date_time_check(
    1569              :             end_cert_from, end_cert_from_len, end_cert_to, end_cert_to_len);
    1570          768 :         if (!status) {
    1571            0 :             goto cleanup;
    1572              :         }
    1573              :     }
    1574              : 
    1575              :     /* 8. subject_public_key*/
    1576          768 :     if (base_asym_algo != 0) {
    1577          768 :         status = libspdm_asym_get_public_key_from_x509(base_asym_algo, cert, cert_size, &context);
    1578              :     }
    1579          768 :     if (pqc_asym_algo != 0) {
    1580            0 :         status = libspdm_pqc_asym_get_public_key_from_x509(pqc_asym_algo, cert, cert_size, &context);
    1581              :     }
    1582          768 :     if (!status) {
    1583            0 :         goto cleanup;
    1584              :     }
    1585              : 
    1586              :     /* 9. key_usage
    1587              :      *    If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
    1588              :      *    check should be skipped as the SPDM specification does not specify the presence or absence
    1589              :      *    of the Device Certificate CA's keyUsage field. */
    1590          768 :     if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
    1591          762 :         size_t value = 0;
    1592              : 
    1593          762 :         status = libspdm_x509_get_key_usage(cert, cert_size, &value);
    1594          762 :         if (!status) {
    1595            0 :             goto cleanup;
    1596              :         } else {
    1597          762 :             if (value == 0) {
    1598            0 :                 if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
    1599            0 :                     status = false;
    1600            0 :                     goto cleanup;
    1601              :                 }
    1602              :             } else {
    1603          762 :                 if ((LIBSPDM_CRYPTO_X509_KU_DIGITAL_SIGNATURE & value) == 0) {
    1604            0 :                     status = false;
    1605            0 :                     goto cleanup;
    1606              :                 }
    1607              :             }
    1608              :         }
    1609              :     }
    1610              : 
    1611              :     /* 10. verify spdm defined extended key usage*/
    1612          768 :     status = libspdm_verify_leaf_cert_spdm_eku(cert, cert_size, is_requester_cert);
    1613          768 :     if (!status) {
    1614            2 :         goto cleanup;
    1615              :     }
    1616              : 
    1617          766 :     if ((!set_cert) || (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT)) {
    1618              :         /* 11. verify spdm defined extension*/
    1619          760 :         status = libspdm_verify_leaf_cert_spdm_extension(cert, cert_size,
    1620              :                                                          is_requester_cert, cert_model);
    1621          760 :         if (!status) {
    1622            4 :             goto cleanup;
    1623              :         }
    1624              :     }
    1625              : 
    1626          762 : cleanup:
    1627          770 :     if (base_asym_algo != 0) {
    1628          770 :         libspdm_asym_free(base_asym_algo, context);
    1629              :     }
    1630          770 :     if (pqc_asym_algo != 0) {
    1631            0 :         libspdm_pqc_asym_free(pqc_asym_algo, context);
    1632              :     }
    1633          770 :     return status;
    1634              : }
    1635              : 
    1636              : /**
    1637              :  * Certificate Check for SPDM leaf cert when get_cert command
    1638              :  *
    1639              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1640              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1641              :  * @param[in]  base_asym_algo        SPDM base_asym_algo
    1642              :  * @param[in]  base_hash_algo        SPDM base_hash_algo
    1643              :  * @param[in]  is_requester          Is the function verifying a cert as a requester or responder.
    1644              :  * @param[in]  is_device_cert_model  If true, the local endpoint uses the DeviceCert model.
    1645              :  *                                   If false, the local endpoint uses the AliasCert model.
    1646              :  *
    1647              :  * @retval  true   Success.
    1648              :  * @retval  false  Certificate is not valid
    1649              :  **/
    1650           54 : bool libspdm_x509_certificate_check(const uint8_t *cert, size_t cert_size,
    1651              :                                     uint32_t base_asym_algo,
    1652              :                                     uint32_t base_hash_algo,
    1653              :                                     bool is_requester,
    1654              :                                     bool is_device_cert_model)
    1655              : {
    1656              :     bool status;
    1657              :     uint8_t cert_model;
    1658              : 
    1659           54 :     if (is_device_cert_model) {
    1660           48 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
    1661              :     } else {
    1662            6 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
    1663              :     }
    1664              : 
    1665           54 :     status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo, 0,
    1666              :                                                    base_hash_algo, is_requester,
    1667              :                                                    cert_model, false);
    1668           54 :     if (!status) {
    1669            5 :         return false;
    1670              :     }
    1671              : 
    1672              :     /* verify basic constraints: the leaf cert always is ca:false in get_cert*/
    1673           49 :     status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, false);
    1674           49 :     return status;
    1675              : }
    1676              : 
    1677              : 
    1678              : /**
    1679              :  * Certificate Check for SPDM leaf cert when get_cert command. It is used for SPDM 1.3.
    1680              :  *
    1681              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1682              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1683              :  * @param[in]  base_asym_algo        SPDM base_asym_algo
    1684              :  * @param[in]  base_hash_algo        SPDM base_hash_algo
    1685              :  * @param[in]  is_requester          Is the function verifying a cert as a requester or responder.
    1686              :  * @param[in]  cert_model            One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    1687              :  *
    1688              :  * @retval  true   Success.
    1689              :  * @retval  false  Certificate is not valid
    1690              :  **/
    1691          702 : bool libspdm_x509_certificate_check_with_pqc(const uint8_t *cert, size_t cert_size,
    1692              :                                              uint32_t base_asym_algo, uint32_t pqc_asym_algo,
    1693              :                                              uint32_t base_hash_algo,
    1694              :                                              bool is_requester,
    1695              :                                              uint8_t cert_model)
    1696              : {
    1697              :     bool status;
    1698              : 
    1699          702 :     status = libspdm_x509_common_certificate_check(
    1700              :         cert, cert_size, base_asym_algo, pqc_asym_algo,
    1701              :         base_hash_algo, is_requester,
    1702              :         cert_model, false);
    1703          702 :     if (!status) {
    1704            3 :         return false;
    1705              :     }
    1706              : 
    1707              :     /* verify basic constraints: the leaf cert always is ca:false in get_cert
    1708              :      * basic_constraints is mandatory in SPDM 1.3*/
    1709          699 :     status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, true);
    1710          699 :     return status;
    1711              : }
    1712              : 
    1713            9 : bool libspdm_x509_certificate_check_ex(const uint8_t *cert, size_t cert_size,
    1714              :                                        uint32_t base_asym_algo,
    1715              :                                        uint32_t base_hash_algo,
    1716              :                                        bool is_requester,
    1717              :                                        uint8_t cert_model)
    1718              : {
    1719            9 :     return libspdm_x509_certificate_check_with_pqc (
    1720              :         cert, cert_size,
    1721              :         base_asym_algo, 0, base_hash_algo,
    1722              :         is_requester, cert_model);
    1723              : }
    1724              : 
    1725            8 : bool libspdm_x509_set_cert_certificate_check(const uint8_t *cert, size_t cert_size,
    1726              :                                              uint32_t base_asym_algo, uint32_t base_hash_algo,
    1727              :                                              bool is_requester, bool is_device_cert_model)
    1728              : {
    1729              :     bool status;
    1730              :     uint8_t cert_model;
    1731              : 
    1732            8 :     if (is_device_cert_model) {
    1733            5 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
    1734              :     } else {
    1735            3 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
    1736              :     }
    1737              : 
    1738            8 :     status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo, 0,
    1739              :                                                    base_hash_algo, is_requester,
    1740              :                                                    cert_model, true);
    1741            8 :     if (!status) {
    1742            0 :         return false;
    1743              :     }
    1744              : 
    1745              :     /* verify basic constraints: need check with is_device_cert_model*/
    1746            8 :     status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
    1747              :         cert, cert_size, cert_model, false);
    1748            8 :     return status;
    1749              : }
    1750              : 
    1751            6 : bool libspdm_x509_set_cert_certificate_check_with_pqc(
    1752              :     const uint8_t *cert, size_t cert_size,
    1753              :     uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
    1754              :     bool is_requester, uint8_t cert_model)
    1755              : {
    1756              :     bool status;
    1757              : 
    1758            6 :     status = libspdm_x509_common_certificate_check(
    1759              :         cert, cert_size, base_asym_algo, pqc_asym_algo,
    1760              :         base_hash_algo, is_requester,
    1761              :         cert_model, true);
    1762            6 :     if (!status) {
    1763            0 :         return false;
    1764              :     }
    1765              : 
    1766              :     /* verify basic constraints: need check with is_device_cert_model*/
    1767            6 :     status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
    1768              :         cert, cert_size, cert_model, true);
    1769              : 
    1770            6 :     return status;
    1771              : }
    1772              : 
    1773            6 : bool libspdm_x509_set_cert_certificate_check_ex(const uint8_t *cert, size_t cert_size,
    1774              :                                                 uint32_t base_asym_algo, uint32_t base_hash_algo,
    1775              :                                                 bool is_requester, uint8_t cert_model)
    1776              : {
    1777            6 :     return libspdm_x509_set_cert_certificate_check_with_pqc (
    1778              :         cert, cert_size,
    1779              :         base_asym_algo, 0, base_hash_algo,
    1780              :         is_requester, cert_model);
    1781              : }
    1782              : 
    1783              : /**
    1784              :  * Return certificate is root cert or not.
    1785              :  * Certificate is considered as a root certificate if the subjectname equal issuername.
    1786              :  *
    1787              :  * @param[in]  cert            Pointer to the DER-encoded certificate data.
    1788              :  * @param[in]  cert_size        The size of certificate data in bytes.
    1789              :  *
    1790              :  * @retval  true   Certificate is self-signed.
    1791              :  * @retval  false  Certificate is not self-signed.
    1792              :  **/
    1793           59 : bool libspdm_is_root_certificate(const uint8_t *cert, size_t cert_size)
    1794              : {
    1795              :     uint8_t issuer_name[LIBSPDM_MAX_NAME_SIZE];
    1796              :     size_t issuer_name_len;
    1797              :     uint8_t subject_name[LIBSPDM_MAX_NAME_SIZE];
    1798              :     size_t subject_name_len;
    1799              :     bool result;
    1800              : 
    1801           59 :     if (cert == NULL || cert_size == 0) {
    1802            0 :         return false;
    1803              :     }
    1804              : 
    1805              :     /* 1. issuer_name*/
    1806           59 :     issuer_name_len = sizeof(issuer_name);
    1807           59 :     result = libspdm_x509_get_issuer_name(cert, cert_size, issuer_name, &issuer_name_len);
    1808           59 :     if (!result) {
    1809            0 :         return false;
    1810              :     }
    1811              : 
    1812              :     /* 2. subject_name*/
    1813           59 :     subject_name_len = sizeof(subject_name);
    1814           59 :     result = libspdm_x509_get_subject_name(cert, cert_size, subject_name, &subject_name_len);
    1815           59 :     if (!result) {
    1816            0 :         return false;
    1817              :     }
    1818              : 
    1819           59 :     if (issuer_name_len != subject_name_len) {
    1820            3 :         return false;
    1821              :     }
    1822           56 :     if (!libspdm_consttime_is_mem_equal(issuer_name, subject_name, issuer_name_len)) {
    1823            0 :         return false;
    1824              :     }
    1825              : 
    1826           56 :     return true;
    1827              : }
    1828              : 
    1829              : /**
    1830              :  * Retrieve the SubjectAltName from SubjectAltName Bytes.
    1831              :  *
    1832              :  * @param[in]      buffer           Pointer to subjectAltName oct bytes.
    1833              :  * @param[in]      len              size of buffer in bytes.
    1834              :  * @param[out]     name_buffer       buffer to contain the retrieved certificate
    1835              :  *                                 SubjectAltName. At most name_buffer_size bytes will be
    1836              :  *                                 written. Maybe NULL in order to determine the size
    1837              :  *                                 buffer needed.
    1838              :  * @param[in,out]  name_buffer_size   The size in bytes of the name buffer on input,
    1839              :  *                                 and the size of buffer returned name on output.
    1840              :  *                                 If name_buffer is NULL then the amount of space needed
    1841              :  *                                 in buffer (including the final null) is returned.
    1842              :  * @param[out]     oid              OID of otherName
    1843              :  * @param[in,out]  oid_size          the buffersize for required OID
    1844              :  *
    1845              :  * @retval true                     get the subjectAltName string successfully
    1846              :  * @retval failed                   get the subjectAltName string failed
    1847              :  **/
    1848            9 : bool libspdm_get_dmtf_subject_alt_name_from_bytes(
    1849              :     uint8_t *buffer, const size_t len, char *name_buffer,
    1850              :     size_t *name_buffer_size, uint8_t *oid,
    1851              :     size_t *oid_size)
    1852              : {
    1853              :     uint8_t *ptr;
    1854              :     int32_t length;
    1855              :     size_t obj_len;
    1856              :     int32_t ret;
    1857              : 
    1858              :     /*copy mem variable*/
    1859              :     volatile uint8_t* dst;
    1860              :     const volatile uint8_t* src;
    1861              :     size_t dst_len;
    1862              :     size_t src_len;
    1863              : 
    1864            9 :     length = (int32_t)len;
    1865            9 :     ptr = buffer;
    1866            9 :     obj_len = 0;
    1867              : 
    1868              :     /* Sequence*/
    1869            9 :     ret = libspdm_asn1_get_tag(&ptr, ptr + length, &obj_len,
    1870              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1871            9 :     if (!ret) {
    1872            0 :         return false;
    1873              :     }
    1874              : 
    1875            9 :     ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len,
    1876              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    1877              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1878              : 
    1879            9 :     ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1880            9 :     if (!ret) {
    1881            0 :         return false;
    1882              :     }
    1883              :     /* CopyData to OID*/
    1884            9 :     if (*oid_size < (size_t)obj_len) {
    1885            0 :         *oid_size = (size_t)obj_len;
    1886            0 :         return false;
    1887              :     }
    1888            9 :     if (oid != NULL) {
    1889            9 :         libspdm_copy_mem(oid, *oid_size, ptr, obj_len);
    1890            9 :         *oid_size = obj_len;
    1891              :     }
    1892              : 
    1893              :     /* Move to next element*/
    1894            9 :     ptr += obj_len;
    1895              : 
    1896            9 :     ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
    1897              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    1898              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1899            9 :     ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
    1900              :                                LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
    1901            9 :     if (!ret) {
    1902            0 :         return false;
    1903              :     }
    1904              : 
    1905            9 :     if (*name_buffer_size < (size_t)obj_len + 1) {
    1906            0 :         *name_buffer_size = (size_t)obj_len + 1;
    1907            0 :         return false;
    1908              :     }
    1909              : 
    1910              :     /* the src and dst address are overlap,
    1911              :      * When the function is called by libspdm_get_dmtf_subject_alt_name.
    1912              :      * libspdm_copy_mem can not be used. */
    1913            9 :     if ((name_buffer != NULL) && (ptr != NULL)) {
    1914            9 :         dst = (volatile uint8_t*) name_buffer;
    1915            9 :         src = (const volatile uint8_t*) ptr;
    1916            9 :         dst_len = *name_buffer_size;
    1917            9 :         src_len = obj_len;
    1918              : 
    1919              :         /* Check for case where "dst_len" may be invalid. Do not zero "dst" in this case. */
    1920            9 :         if (dst_len > (SIZE_MAX >> 1)) {
    1921            0 :             LIBSPDM_ASSERT(0);
    1922            0 :             return false;
    1923              :         }
    1924              : 
    1925              :         /* Guard against invalid lengths. Zero "dst" in these cases. */
    1926            9 :         if (src_len > dst_len ||
    1927            9 :             src_len > (SIZE_MAX >> 1)) {
    1928            0 :             libspdm_zero_mem(name_buffer, dst_len);
    1929            0 :             LIBSPDM_ASSERT(0);
    1930            0 :             return false;
    1931              :         }
    1932              : 
    1933          207 :         while (src_len-- != 0) {
    1934          198 :             *(dst++) = *(src++);
    1935              :         }
    1936              : 
    1937              :         /*encode name buffer to string*/
    1938            9 :         *name_buffer_size = obj_len + 1;
    1939            9 :         name_buffer[obj_len] = 0;
    1940            9 :         return true;
    1941              :     }
    1942              : 
    1943            0 :     return false;
    1944              : }
    1945              : 
    1946              : /**
    1947              :  * Retrieve the SubjectAltName from one X.509 certificate.
    1948              :  *
    1949              :  * @param[in]      cert             Pointer to the DER-encoded X509 certificate.
    1950              :  * @param[in]      cert_size         size of the X509 certificate in bytes.
    1951              :  * @param[out]     name_buffer       buffer to contain the retrieved certificate
    1952              :  *                                 SubjectAltName. At most name_buffer_size bytes will be
    1953              :  *                                 written. Maybe NULL in order to determine the size
    1954              :  *                                 buffer needed.
    1955              :  * @param[in,out]  name_buffer_size   The size in bytes of the name buffer on input,
    1956              :  *                                 and the size of buffer returned name on output.
    1957              :  *                                 If name_buffer is NULL then the amount of space needed
    1958              :  *                                 in buffer (including the final null) is returned.
    1959              :  * @param[out]     oid              OID of otherName
    1960              :  * @param[in,out]  oid_size          the buffersize for required OID
    1961              :  *
    1962              :  * @retval true                     get the subjectAltName string successfully
    1963              :  * @retval failed                   get the subjectAltName string failed
    1964              :  **/
    1965            6 : bool libspdm_get_dmtf_subject_alt_name(const uint8_t *cert, const size_t cert_size,
    1966              :                                        char *name_buffer,
    1967              :                                        size_t *name_buffer_size,
    1968              :                                        uint8_t *oid, size_t *oid_size)
    1969              : {
    1970              :     bool status;
    1971              :     size_t extension_data_size;
    1972            6 :     uint8_t oid_subject_alt_name[] = { 0x55, 0x1D, 0x11 };
    1973              : 
    1974            6 :     extension_data_size = 0;
    1975            6 :     status = libspdm_x509_get_extension_data(cert, cert_size,
    1976              :                                              oid_subject_alt_name,
    1977              :                                              sizeof(oid_subject_alt_name), NULL,
    1978              :                                              &extension_data_size);
    1979            6 :     if (status || (extension_data_size == 0)) {
    1980            0 :         *name_buffer_size = 0;
    1981            0 :         return false;
    1982              :     }
    1983            6 :     if (extension_data_size > *name_buffer_size) {
    1984            0 :         *name_buffer_size = extension_data_size;
    1985            0 :         return false;
    1986              :     }
    1987              :     status =
    1988            6 :         libspdm_x509_get_extension_data(cert, cert_size,
    1989              :                                         oid_subject_alt_name,
    1990              :                                         sizeof(oid_subject_alt_name),
    1991              :                                         (uint8_t *)name_buffer, name_buffer_size);
    1992            6 :     if (!status) {
    1993            0 :         return status;
    1994              :     }
    1995              : 
    1996            6 :     return libspdm_get_dmtf_subject_alt_name_from_bytes(
    1997              :         (uint8_t *)name_buffer, *name_buffer_size, name_buffer,
    1998              :         name_buffer_size, oid, oid_size);
    1999              : }
    2000              : 
    2001              : /**
    2002              :  * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
    2003              :  * It is used for SPDM 1.3.
    2004              :  *
    2005              :  * @param  cert_chain_data       The certificate chain data without spdm_cert_chain_t header.
    2006              :  * @param  cert_chain_data_size  Size in bytes of the certificate chain data.
    2007              :  * @param  base_asym_algo        SPDM base_asym_algo
    2008              :  * @param  base_hash_algo        SPDM base_hash_algo
    2009              :  * @param  is_requester_cert     Is the function verifying requester or responder cert.
    2010              :  * @param  cert_model            One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    2011              :  *
    2012              :  * @retval true  Certificate chain data integrity verification pass.
    2013              :  * @retval false Certificate chain data integrity verification fail.
    2014              :  **/
    2015            6 : bool libspdm_verify_cert_chain_data_ex(uint8_t *cert_chain_data, size_t cert_chain_data_size,
    2016              :                                        uint32_t base_asym_algo, uint32_t base_hash_algo,
    2017              :                                        bool is_requester_cert, uint8_t cert_model)
    2018              : {
    2019              :     const uint8_t *root_cert_buffer;
    2020              :     size_t root_cert_buffer_size;
    2021              :     const uint8_t *leaf_cert_buffer;
    2022              :     size_t leaf_cert_buffer_size;
    2023              : 
    2024            6 :     if (cert_chain_data_size >
    2025              :         SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
    2026            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2027              :                        "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
    2028            0 :         return false;
    2029              :     }
    2030              : 
    2031            6 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2032              :             cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
    2033              :             &root_cert_buffer_size)) {
    2034            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2035              :                        "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
    2036            0 :         return false;
    2037              :     }
    2038              : 
    2039            6 :     if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
    2040              :                                         cert_chain_data, cert_chain_data_size)) {
    2041            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2042              :                        "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
    2043            2 :         return false;
    2044              :     }
    2045              : 
    2046            4 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2047              :             cert_chain_data, cert_chain_data_size, -1,
    2048              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    2049            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2050              :                        "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
    2051            0 :         return false;
    2052              :     }
    2053              : 
    2054            4 :     if (!libspdm_x509_certificate_check_ex(leaf_cert_buffer, leaf_cert_buffer_size,
    2055              :                                            base_asym_algo, base_hash_algo,
    2056              :                                            is_requester_cert, cert_model)) {
    2057            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2058              :                        "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
    2059            1 :         return false;
    2060              :     }
    2061              : 
    2062            3 :     return true;
    2063              : }
    2064              : /**
    2065              :  * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
    2066              :  *
    2067              :  * @param  cert_chain_data          The certificate chain data without spdm_cert_chain_t header.
    2068              :  * @param  cert_chain_data_size      size in bytes of the certificate chain data.
    2069              :  * @param  base_asym_algo            SPDM base_asym_algo
    2070              :  * @param  base_hash_algo            SPDM base_hash_algo
    2071              :  * @param  is_requester_cert         Is the function verifying requester or responder cert.
    2072              :  * @param  is_device_cert_model      If true, the cert chain is DeviceCert model;
    2073              :  *                                   If false, the cert chain is AliasCert model;
    2074              :  *
    2075              :  * @retval true  certificate chain data integrity verification pass.
    2076              :  * @retval false certificate chain data integrity verification fail.
    2077              :  **/
    2078          689 : bool libspdm_verify_cert_chain_data_with_pqc(
    2079              :     uint8_t *cert_chain_data, size_t cert_chain_data_size,
    2080              :     uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
    2081              :     bool is_requester_cert, bool is_device_cert_model)
    2082              : {
    2083              :     const uint8_t *root_cert_buffer;
    2084              :     size_t root_cert_buffer_size;
    2085              :     const uint8_t *leaf_cert_buffer;
    2086              :     size_t leaf_cert_buffer_size;
    2087              : 
    2088          689 :     if (cert_chain_data_size >
    2089              :         SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
    2090            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2091              :                        "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
    2092            0 :         return false;
    2093              :     }
    2094              : 
    2095          689 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2096              :             cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
    2097              :             &root_cert_buffer_size)) {
    2098            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2099              :                        "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
    2100            0 :         return false;
    2101              :     }
    2102              : 
    2103          689 :     if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
    2104              :                                         cert_chain_data, cert_chain_data_size)) {
    2105            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2106              :                        "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
    2107            0 :         return false;
    2108              :     }
    2109              : 
    2110          689 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2111              :             cert_chain_data, cert_chain_data_size, -1,
    2112              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    2113            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2114              :                        "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
    2115            0 :         return false;
    2116              :     }
    2117              : 
    2118          689 :     if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
    2119              :                                                  base_asym_algo, pqc_asym_algo, base_hash_algo,
    2120              :                                                  is_requester_cert, is_device_cert_model)) {
    2121            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2122              :                        "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
    2123            0 :         return false;
    2124              :     }
    2125              : 
    2126          689 :     return true;
    2127              : }
    2128              : 
    2129          689 : bool libspdm_verify_cert_chain_data(uint8_t *cert_chain_data, size_t cert_chain_data_size,
    2130              :                                     uint32_t base_asym_algo, uint32_t base_hash_algo,
    2131              :                                     bool is_requester_cert, bool is_device_cert_model)
    2132              : {
    2133          689 :     return libspdm_verify_cert_chain_data_with_pqc (
    2134              :         cert_chain_data, cert_chain_data_size,
    2135              :         base_asym_algo, 0, base_hash_algo,
    2136              :         is_requester_cert, is_device_cert_model);
    2137              : }
    2138              : 
    2139              : /**
    2140              :  * This function verifies the integrity of certificate chain buffer including
    2141              :  * spdm_cert_chain_t header. It is used for SPDM 1.3.
    2142              :  *
    2143              :  * @param  base_hash_algo          SPDM base_hash_algo
    2144              :  * @param  base_asym_algo          SPDM base_asym_algo
    2145              :  * @param  cert_chain_buffer       The certificate chain buffer including spdm_cert_chain_t header.
    2146              :  * @param  cert_chain_buffer_size  Size in bytes of the certificate chain buffer.
    2147              :  * @param  is_requester_cert       Is the function verifying requester or responder cert.
    2148              :  * @param  cert_model              One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    2149              :  *
    2150              :  * @retval true   Certificate chain buffer integrity verification pass.
    2151              :  * @retval false  Certificate chain buffer integrity verification fail.
    2152              :  **/
    2153            6 : bool libspdm_verify_certificate_chain_buffer_with_pqc(
    2154              :     uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
    2155              :     const void *cert_chain_buffer,
    2156              :     size_t cert_chain_buffer_size,
    2157              :     bool is_requester_cert, uint8_t cert_model)
    2158              : {
    2159              :     const uint8_t *cert_chain_data;
    2160              :     size_t cert_chain_data_size;
    2161              :     const uint8_t *first_cert_buffer;
    2162              :     size_t first_cert_buffer_size;
    2163              :     size_t hash_size;
    2164              :     uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
    2165              :     const uint8_t *leaf_cert_buffer;
    2166              :     size_t leaf_cert_buffer_size;
    2167              :     bool result;
    2168              :     const spdm_cert_chain_t *cert_chain_header;
    2169              : 
    2170            6 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    2171              : 
    2172            6 :     if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
    2173            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2174              :                        "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
    2175            0 :         return false;
    2176              :     }
    2177              : 
    2178            6 :     cert_chain_header = cert_chain_buffer;
    2179            6 :     if (cert_chain_header->length != cert_chain_buffer_size) {
    2180            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2181              :                        "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
    2182            2 :         return false;
    2183              :     }
    2184              : 
    2185            4 :     cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
    2186            4 :     cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
    2187            4 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2188              :             cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
    2189              :             &first_cert_buffer_size)) {
    2190            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2191              :                        "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
    2192            0 :         return false;
    2193              :     }
    2194              : 
    2195            4 :     if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
    2196            4 :         result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
    2197              :                                   calc_root_cert_hash);
    2198            4 :         if (!result) {
    2199            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2200              :                            "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
    2201            0 :             return false;
    2202              :         }
    2203            4 :         if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
    2204              :                                             sizeof(spdm_cert_chain_t),
    2205              :                                             calc_root_cert_hash, hash_size)) {
    2206            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2207              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
    2208            0 :             return false;
    2209              :         }
    2210            4 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2211              :                        "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
    2212              :     }
    2213              : 
    2214              :     /*If the number of certificates in the certificate chain is more than 1,
    2215              :      * other certificates need to be verified.*/
    2216            4 :     if (cert_chain_data_size > first_cert_buffer_size) {
    2217            4 :         if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
    2218              :                                             cert_chain_data + first_cert_buffer_size,
    2219              :                                             cert_chain_data_size - first_cert_buffer_size)) {
    2220            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2221              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
    2222            0 :             return false;
    2223              :         }
    2224              :     }
    2225              : 
    2226            4 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2227              :             cert_chain_data, cert_chain_data_size, -1,
    2228              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    2229            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2230              :                        "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
    2231            0 :         return false;
    2232              :     }
    2233              : 
    2234            4 :     if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
    2235              :                                                  base_asym_algo, pqc_asym_algo, base_hash_algo,
    2236              :                                                  is_requester_cert, cert_model)) {
    2237            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2238              :                        "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
    2239            1 :         return false;
    2240              :     }
    2241              : 
    2242            3 :     return true;
    2243              : }
    2244              : 
    2245            6 : bool libspdm_verify_certificate_chain_buffer_ex(uint32_t base_hash_algo, uint32_t base_asym_algo,
    2246              :                                                 const void *cert_chain_buffer,
    2247              :                                                 size_t cert_chain_buffer_size,
    2248              :                                                 bool is_requester_cert, uint8_t cert_model)
    2249              : {
    2250            6 :     return libspdm_verify_certificate_chain_buffer_with_pqc (
    2251              :         base_hash_algo, base_asym_algo, 0,
    2252              :         cert_chain_buffer, cert_chain_buffer_size,
    2253              :         is_requester_cert, cert_model);
    2254              : }
    2255              : 
    2256           34 : bool libspdm_verify_certificate_chain_buffer(uint32_t base_hash_algo, uint32_t base_asym_algo,
    2257              :                                              const void *cert_chain_buffer,
    2258              :                                              size_t cert_chain_buffer_size,
    2259              :                                              bool is_requester_cert,
    2260              :                                              bool is_device_cert_model)
    2261              : {
    2262              :     const uint8_t *cert_chain_data;
    2263              :     size_t cert_chain_data_size;
    2264              :     const uint8_t *first_cert_buffer;
    2265              :     size_t first_cert_buffer_size;
    2266              :     size_t hash_size;
    2267              :     uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
    2268              :     const uint8_t *leaf_cert_buffer;
    2269              :     size_t leaf_cert_buffer_size;
    2270              :     bool result;
    2271              :     const spdm_cert_chain_t *cert_chain_header;
    2272              : 
    2273           34 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    2274              : 
    2275           34 :     if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
    2276            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2277              :                        "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
    2278            0 :         return false;
    2279              :     }
    2280              : 
    2281           34 :     cert_chain_header = cert_chain_buffer;
    2282           34 :     if (cert_chain_header->length != cert_chain_buffer_size) {
    2283            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2284              :                        "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
    2285            0 :         return false;
    2286              :     }
    2287              : 
    2288           34 :     cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
    2289           34 :     cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
    2290           34 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2291              :             cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
    2292              :             &first_cert_buffer_size)) {
    2293            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2294              :                        "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
    2295            0 :         return false;
    2296              :     }
    2297              : 
    2298           34 :     if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
    2299           32 :         result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
    2300              :                                   calc_root_cert_hash);
    2301           32 :         if (!result) {
    2302            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2303              :                            "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
    2304            0 :             return false;
    2305              :         }
    2306           32 :         if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
    2307              :                                             sizeof(spdm_cert_chain_t),
    2308              :                                             calc_root_cert_hash, hash_size)) {
    2309            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2310              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
    2311            0 :             return false;
    2312              :         }
    2313           32 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2314              :                        "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
    2315              :     }
    2316              : 
    2317              :     /*If the number of certificates in the certificate chain is more than 1,
    2318              :      * other certificates need to be verified.*/
    2319           34 :     if (cert_chain_data_size > first_cert_buffer_size) {
    2320           34 :         if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
    2321              :                                             cert_chain_data + first_cert_buffer_size,
    2322              :                                             cert_chain_data_size - first_cert_buffer_size)) {
    2323            3 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2324              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
    2325            3 :             return false;
    2326              :         }
    2327              :     }
    2328              : 
    2329           31 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2330              :             cert_chain_data, cert_chain_data_size, -1,
    2331              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    2332            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2333              :                        "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
    2334            0 :         return false;
    2335              :     }
    2336              : 
    2337           31 :     if (!libspdm_x509_certificate_check(leaf_cert_buffer, leaf_cert_buffer_size,
    2338              :                                         base_asym_algo, base_hash_algo,
    2339              :                                         is_requester_cert, is_device_cert_model)) {
    2340            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2341              :                        "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
    2342            2 :         return false;
    2343              :     }
    2344              : 
    2345           29 :     return true;
    2346              : }
    2347              : 
    2348          254 : bool libspdm_get_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
    2349              :                                                       uint32_t base_asym_alg,
    2350              :                                                       uint8_t *cert_chain_data,
    2351              :                                                       size_t cert_chain_data_size,
    2352              :                                                       void **public_key)
    2353              : {
    2354              :     size_t hash_size;
    2355              :     const uint8_t *cert_buffer;
    2356              :     size_t cert_buffer_size;
    2357              :     bool result;
    2358              : 
    2359          254 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    2360              : 
    2361          254 :     cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
    2362          254 :     cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
    2363              : 
    2364              :     /* Get leaf cert from cert chain */
    2365          254 :     result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
    2366              :                                                    cert_chain_data_size, -1,
    2367              :                                                    &cert_buffer, &cert_buffer_size);
    2368          254 :     if (!result) {
    2369            0 :         return false;
    2370              :     }
    2371              : 
    2372          254 :     result = libspdm_asym_get_public_key_from_x509(
    2373              :         base_asym_alg,
    2374              :         cert_buffer, cert_buffer_size, public_key);
    2375          254 :     if (!result) {
    2376            4 :         return false;
    2377              :     }
    2378              : 
    2379          250 :     return true;
    2380              : }
    2381              : 
    2382              : /**
    2383              :  * Retrieve the asymmetric public key from one DER-encoded X509 certificate,
    2384              :  * based upon negotiated asymmetric or requester asymmetric algorithm.
    2385              :  *
    2386              :  * @param  base_hash_algo        SPDM base_hash_algo.
    2387              :  * @param  pqc_asym_alg          SPDM pqc_asym_algo or req_pqc_asym_alg.
    2388              :  * @param  cert_chain_data       Certificate chain data with spdm_cert_chain_t header.
    2389              :  * @param  cert_chain_data_size  Size in bytes of the certificate chain data.
    2390              :  * @param  public_key            Pointer to newly generated asymmetric context which contain the
    2391              :  *                               retrieved public key component.
    2392              :  *
    2393              :  * @retval  true   Public key was retrieved successfully.
    2394              :  * @retval  false  Fail to retrieve public key from X509 certificate.
    2395              :  **/
    2396            0 : bool libspdm_get_pqc_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
    2397              :                                                           uint32_t pqc_asym_alg,
    2398              :                                                           uint8_t *cert_chain_data,
    2399              :                                                           size_t cert_chain_data_size,
    2400              :                                                           void **public_key)
    2401              : {
    2402              :     size_t hash_size;
    2403              :     const uint8_t *cert_buffer;
    2404              :     size_t cert_buffer_size;
    2405              :     bool result;
    2406              : 
    2407            0 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    2408              : 
    2409            0 :     cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
    2410            0 :     cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
    2411              : 
    2412              :     /* Get leaf cert from cert chain */
    2413            0 :     result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
    2414              :                                                    cert_chain_data_size, -1,
    2415              :                                                    &cert_buffer, &cert_buffer_size);
    2416            0 :     if (!result) {
    2417            0 :         return false;
    2418              :     }
    2419              : 
    2420            0 :     result = libspdm_pqc_asym_get_public_key_from_x509(
    2421              :         pqc_asym_alg,
    2422              :         cert_buffer, cert_buffer_size, public_key);
    2423            0 :     if (!result) {
    2424            0 :         return false;
    2425              :     }
    2426              : 
    2427            0 :     return true;
    2428              : }
    2429              : 
    2430           29 : bool libspdm_verify_req_info(uint8_t *req_info, uint16_t req_info_len)
    2431              : {
    2432              :     bool ret;
    2433              :     uint8_t *ptr;
    2434              :     int32_t length;
    2435              :     size_t obj_len;
    2436              :     uint8_t *end;
    2437              : 
    2438           29 :     length = (int32_t)req_info_len;
    2439           29 :     ptr = req_info;
    2440           29 :     obj_len = 0;
    2441           29 :     end = ptr + length;
    2442           29 :     ret = true;
    2443              : 
    2444           29 :     if (req_info_len == 0) {
    2445            4 :         return true;
    2446              :     }
    2447              : 
    2448              :     /*req_info sequence*/
    2449           25 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2450              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2451           25 :     if (!ret) {
    2452            2 :         return false;
    2453              :     }
    2454              : 
    2455              :     /*integer:version*/
    2456           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
    2457           23 :     if (!ret) {
    2458            0 :         return false;
    2459              :     } else {
    2460           23 :         ptr += obj_len;
    2461              :     }
    2462              : 
    2463              :     /*sequence:subject name*/
    2464           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2465              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2466           23 :     if (!ret) {
    2467            0 :         return false;
    2468              :     } else {
    2469           23 :         ptr += obj_len;
    2470              :     }
    2471              : 
    2472              :     /*sequence:subject pkinfo*/
    2473           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2474              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2475           23 :     if (!ret) {
    2476            0 :         return false;
    2477              :     } else {
    2478           23 :         ptr += obj_len;
    2479              :     }
    2480              : 
    2481              :     /*[0]: attributes*/
    2482           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2483              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    2484              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2485              :     /*req_info format error, don't have attributes tag*/
    2486           23 :     if (!ret) {
    2487            0 :         return false;
    2488              :     }
    2489              : 
    2490              :     /*there is no attributes object*/
    2491           23 :     if (ptr == end) {
    2492            0 :         return true;
    2493              :     }
    2494              : 
    2495              :     /*there is some attributes object: 0,1,2 ...*/
    2496           46 :     while (ret)
    2497              :     {
    2498           46 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2499              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE |
    2500              :                                    LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2501           46 :         if (ret) {
    2502           23 :             ptr += obj_len;
    2503              :         } else {
    2504           23 :             break;
    2505              :         }
    2506              :     }
    2507              : 
    2508           23 :     if (ptr == end) {
    2509           23 :         return true;
    2510              :     } else {
    2511            0 :         return false;
    2512              :     }
    2513              : }
    2514              : 
    2515              : #endif
        

Generated by: LCOV version 2.0-1