LCOV - code coverage report
Current view: top level - library/spdm_crypt_lib - libspdm_crypt_cert.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 58.1 % 807 469
Test Date: 2025-11-23 08:10:21 Functions: 87.5 % 32 28

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2025 DMTF. All rights reserved.
       4              :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5              :  **/
       6              : 
       7              : #include "internal/libspdm_crypt_lib.h"
       8              : 
       9              : #if LIBSPDM_CERT_PARSE_SUPPORT
      10              : 
      11              : /**pathLenConstraint is optional.
      12              :  * In https://www.pkisolutions.com/basic-constraints-certificate-extension/:
      13              :  * pathLenConstraint: How many CAs are allowed in the chain below current CA certificate.
      14              :  * This setting has no meaning for end entity certificates.
      15              :  **/
      16              : 
      17              : /**
      18              :  * leaf cert spdm extension len
      19              :  * len > 2 * (spdm id-DMTF-spdm size + 2)
      20              :  **/
      21              : 
      22              : #ifndef LIBSPDM_MAX_EXTENSION_LEN
      23              : #define LIBSPDM_MAX_EXTENSION_LEN 30
      24              : #endif
      25              : 
      26              : #ifndef LIBSPDM_MAX_NAME_SIZE
      27              : #define LIBSPDM_MAX_NAME_SIZE 100
      28              : #endif
      29              : 
      30              : /*max public key encryption algo oid len*/
      31              : #ifndef LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN
      32              : #define LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN 10
      33              : #endif
      34              : 
      35              : /* Maximum size of basicConstraints. This includes space for both cA and pathLen. */
      36              : #ifndef LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN
      37              : #define LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN 10
      38              : #endif
      39              : 
      40              : /**
      41              :  * 0x02 is integer;
      42              :  * 0x82 indicates that the length is expressed in two bytes;
      43              :  * 0x01 and 0x01 are rsa key len;
      44              :  **/
      45              : #if (LIBSPDM_RSA_SSA_2048_SUPPORT) || (LIBSPDM_RSA_PSS_2048_SUPPORT)
      46              : #define KEY_ENCRY_ALGO_RSA2048_FLAG {0x02, 0x82, 0x01, 0x01}
      47              : /* the other case is ASN1 code different when integer is 1 on highest position*/
      48              : #define KEY_ENCRY_ALGO_RSA2048_FLAG_OTHER {0x02, 0x82, 0x01, 0x00}
      49              : #endif
      50              : #if (LIBSPDM_RSA_SSA_3072_SUPPORT) || (LIBSPDM_RSA_PSS_3072_SUPPORT)
      51              : #define KEY_ENCRY_ALGO_RSA3072_FLAG {0x02, 0x82, 0x01, 0x81}
      52              : /* the other case is ASN1 code different when integer is 1 on highest position*/
      53              : #define KEY_ENCRY_ALGO_RSA3072_FLAG_OTHER {0x02, 0x82, 0x01, 0x80}
      54              : #endif
      55              : #if (LIBSPDM_RSA_SSA_4096_SUPPORT) || (LIBSPDM_RSA_PSS_4096_SUPPORT)
      56              : #define KEY_ENCRY_ALGO_RSA4096_FLAG {0x02, 0x82, 0x02, 0x01}
      57              : /* the other case is ASN1 code different when integer is 1 on highest position*/
      58              : #define KEY_ENCRY_ALGO_RSA4096_FLAG_OTHER {0x02, 0x82, 0x02, 0x00}
      59              : #endif
      60              : 
      61              : /**
      62              :  * https://oidref.com/1.2.840.10045.3.1.7
      63              :  * ECC256 curve OID: 1.2.840.10045.3.1.7
      64              :  * https://oidref.com/1.3.132.0.34
      65              :  * ECC384 curve OID: 1.3.132.0.34
      66              :  * https://oidref.com/1.3.132.0.35
      67              :  * ECC521 curve OID: 1.3.132.0.35
      68              :  **/
      69              : #if LIBSPDM_ECDSA_P256_SUPPORT
      70              : #define KEY_ENCRY_ALGO_ECC256_OID {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
      71              : #endif
      72              : #if LIBSPDM_ECDSA_P384_SUPPORT
      73              : #define KEY_ENCRY_ALGO_ECC384_OID {0x2B, 0x81, 0x04, 0x00, 0x22}
      74              : #endif
      75              : #if LIBSPDM_ECDSA_P521_SUPPORT
      76              : #define KEY_ENCRY_ALGO_ECC521_OID {0x2B, 0x81, 0x04, 0x00, 0x23}
      77              : #endif
      78              : 
      79              : /**
      80              :  * EDxxx OID: https://datatracker.ietf.org/doc/html/rfc8420
      81              :  * ED448 OID: 1.3.101.113
      82              :  * ED25519 OID: 1.3.101.112
      83              :  **/
      84              : #if LIBSPDM_EDDSA_ED25519_SUPPORT
      85              : #define ENCRY_ALGO_ED25519_OID {0x2B, 0x65, 0x70}
      86              : #endif
      87              : #if LIBSPDM_EDDSA_ED448_SUPPORT
      88              : #define ENCRY_ALGO_ED448_OID {0x2B, 0x65, 0x71}
      89              : #endif
      90              : 
      91              : /**
      92              :  * MLDSA OID: https://datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates
      93              :  * MLDSA44 OID: 2.16.840.1.101.3.4.3.17
      94              :  * MLDSA65 OID: 2.16.840.1.101.3.4.3.18
      95              :  * MLDSA87 OID: 2.16.840.1.101.3.4.3.19
      96              :  **/
      97              : #if LIBSPDM_ML_DSA_44_SUPPORT
      98              : #define ALGO_MLDSA44_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x11}
      99              : #endif
     100              : #if LIBSPDM_ML_DSA_65_SUPPORT
     101              : #define ALGO_MLDSA65_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x12}
     102              : #endif
     103              : #if LIBSPDM_ML_DSA_87_SUPPORT
     104              : #define ALGO_MLDSA87_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x13}
     105              : #endif
     106              : 
     107              : /**
     108              :  * SLHDSA OID: https://datatracker.ietf.org/doc/draft-ietf-lamps-x509-slhdsa
     109              :  * SLHDSA_SHA2_128S OID: 2.16.840.1.101.3.4.3.20
     110              :  * SLHDSA_SHA2_128F OID: 2.16.840.1.101.3.4.3.21
     111              :  * SLHDSA_SHA2_192S OID: 2.16.840.1.101.3.4.3.22
     112              :  * SLHDSA_SHA2_192F OID: 2.16.840.1.101.3.4.3.23
     113              :  * SLHDSA_SHA2_256S OID: 2.16.840.1.101.3.4.3.24
     114              :  * SLHDSA_SHA2_256F OID: 2.16.840.1.101.3.4.3.25
     115              :  * SLHDSA_SHAKE_128S OID: 2.16.840.1.101.3.4.3.26
     116              :  * SLHDSA_SHAKE_128F OID: 2.16.840.1.101.3.4.3.27
     117              :  * SLHDSA_SHAKE_192S OID: 2.16.840.1.101.3.4.3.28
     118              :  * SLHDSA_SHAKE_192F OID: 2.16.840.1.101.3.4.3.29
     119              :  * SLHDSA_SHAKE_256S OID: 2.16.840.1.101.3.4.3.30
     120              :  * SLHDSA_SHAKE_256F OID: 2.16.840.1.101.3.4.3.31
     121              :  **/
     122              : #if LIBSPDM_SLH_DSA_SHA2_128S_SUPPORT
     123              : #define ALGO_SLHDSA_SHA2_128S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x14}
     124              : #endif
     125              : #if LIBSPDM_SLH_DSA_SHA2_128F_SUPPORT
     126              : #define ALGO_SLHDSA_SHA2_128F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x15}
     127              : #endif
     128              : #if LIBSPDM_SLH_DSA_SHA2_192S_SUPPORT
     129              : #define ALGO_SLHDSA_SHA2_192S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x16}
     130              : #endif
     131              : #if LIBSPDM_SLH_DSA_SHA2_192F_SUPPORT
     132              : #define ALGO_SLHDSA_SHA2_192F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x17}
     133              : #endif
     134              : #if LIBSPDM_SLH_DSA_SHA2_256S_SUPPORT
     135              : #define ALGO_SLHDSA_SHA2_256S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x18}
     136              : #endif
     137              : #if LIBSPDM_SLH_DSA_SHA2_256F_SUPPORT
     138              : #define ALGO_SLHDSA_SHA2_256F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x19}
     139              : #endif
     140              : #if LIBSPDM_SLH_DSA_SHAKE_128S_SUPPORT
     141              : #define ALGO_SLHDSA_SHAKE_128S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1A}
     142              : #endif
     143              : #if LIBSPDM_SLH_DSA_SHAKE_128F_SUPPORT
     144              : #define ALGO_SLHDSA_SHAKE_128F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1B}
     145              : #endif
     146              : #if LIBSPDM_SLH_DSA_SHAKE_192S_SUPPORT
     147              : #define ALGO_SLHDSA_SHAKE_192S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1C}
     148              : #endif
     149              : #if LIBSPDM_SLH_DSA_SHAKE_192F_SUPPORT
     150              : #define ALGO_SLHDSA_SHAKE_192F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1D}
     151              : #endif
     152              : #if LIBSPDM_SLH_DSA_SHAKE_256S_SUPPORT
     153              : #define ALGO_SLHDSA_SHAKE_256S_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1E}
     154              : #endif
     155              : #if LIBSPDM_SLH_DSA_SHAKE_256F_SUPPORT
     156              : #define ALGO_SLHDSA_SHAKE_256F_OID {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1F}
     157              : #endif
     158              : 
     159              : /*leaf cert basic_constraints false case1: CA: false and CA object is excluded */
     160              : #define BASIC_CONSTRAINTS_STRING_FALSE_CASE1 {0x30, 0x00}
     161              : 
     162              : /*leaf cert basic_constraints false case2: CA: false */
     163              : #define BASIC_CONSTRAINTS_STRING_FALSE_CASE2 {0x30, 0x03, 0x01, 0x01, 0x00}
     164              : 
     165              : /*leaf cert basic_constraints true case: CA: true */
     166              : #define BASIC_CONSTRAINTS_STRING_TRUE_CASE {0x30, 0x03, 0x01, 0x01, 0xFF}
     167              : 
     168              : /**
     169              :  * Retrieve the asymmetric public key from one DER-encoded X509 certificate.
     170              :  *
     171              :  * @param  cert       Pointer to the DER-encoded X509 certificate.
     172              :  * @param  cert_size  Size of the X509 certificate in bytes.
     173              :  * @param  context    Pointer to newly generated asymmetric context which contain the retrieved public
     174              :  *                    key component. Use libspdm_asym_free() function to free the resource.
     175              :  *
     176              :  * @retval  true   public key was retrieved successfully.
     177              :  * @retval  false  Fail to retrieve public key from X509 certificate.
     178              :  **/
     179              : typedef bool (*libspdm_asym_get_public_key_from_x509_func)(const uint8_t *cert,
     180              :                                                            size_t cert_size,
     181              :                                                            void **context);
     182              : 
     183              : /**
     184              :  * Return asymmetric GET_PUBLIC_KEY_FROM_X509 function, based upon the negotiated asymmetric algorithm.
     185              :  *
     186              :  * @param  base_asym_algo                 SPDM base_asym_algo
     187              :  *
     188              :  * @return asymmetric GET_PUBLIC_KEY_FROM_X509 function
     189              :  **/
     190              : static libspdm_asym_get_public_key_from_x509_func
     191         1038 : libspdm_get_asym_get_public_key_from_x509(uint32_t base_asym_algo)
     192              : {
     193         1038 :     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          938 :     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          938 :         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         1038 : 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         1038 :     get_public_key_from_x509_function = libspdm_get_asym_get_public_key_from_x509(base_asym_algo);
     291         1038 :     if (get_public_key_from_x509_function == NULL) {
     292            0 :         return false;
     293              :     }
     294         1038 :     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          782 : 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          782 :     f0_size = 64;
     362          782 :     t0_size = 64;
     363              : 
     364          782 :     status = libspdm_x509_set_date_time("19700101000000Z", f0, &f0_size);
     365          782 :     if (!status) {
     366            0 :         return false;
     367              :     }
     368              : 
     369          782 :     status = libspdm_x509_set_date_time("99991231235959Z", t0, &t0_size);
     370          782 :     if (!status) {
     371            0 :         return false;
     372              :     }
     373              : 
     374              :     /* from >= f0*/
     375          782 :     ret = libspdm_x509_compare_date_time(from, f0);
     376          782 :     if (ret < 0) {
     377            0 :         return false;
     378              :     }
     379              : 
     380              :     /* to <= t0*/
     381          782 :     ret = libspdm_x509_compare_date_time(t0, to);
     382          782 :     if (ret < 0) {
     383            0 :         return false;
     384              :     }
     385              : 
     386          782 :     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         1556 : static uint32_t libspdm_get_public_key_algo_OID_len(
     397              :     uint32_t base_asym_algo, uint32_t pqc_asym_algo)
     398              : {
     399         1556 :     if (base_asym_algo != 0) {
     400         1556 :         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         1426 :         case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
     438              :     #if LIBSPDM_ECDSA_P256_SUPPORT
     439         1426 :             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          778 : 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          778 :     oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
     590          778 :     if (oid_len == 0) {
     591            0 :         return false;
     592              :     }
     593              : 
     594          778 :     if (base_asym_algo != 0) {
     595          778 :         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          713 :         case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256: {
     634              :     #if LIBSPDM_ECDSA_P256_SUPPORT
     635          713 :             uint8_t encry_algo_oid_ecc256[] = KEY_ENCRY_ALGO_ECC256_OID;
     636          713 :             libspdm_copy_mem(oid, oid_len, encry_algo_oid_ecc256, oid_len);
     637          713 :             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          778 : 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          778 :     length = (int32_t)cert_size;
     877          778 :     ptr = (uint8_t*)(size_t)cert;
     878          778 :     obj_len = 0;
     879          778 :     end = ptr + length;
     880          778 :     ret = true;
     881              : 
     882              :     /* TBSCertificate have 5 sequence before subjectPublicKeyInfo*/
     883          778 :     sequence_time = 5;
     884              : 
     885              :     /*all cert sequence*/
     886          778 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     887              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     888          778 :     if (!ret) {
     889            0 :         return false;
     890              :     }
     891              : 
     892              :     /*TBSCertificate sequence*/
     893          778 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     894              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     895          778 :     if (!ret) {
     896            0 :         return false;
     897              :     }
     898              : 
     899          778 :     end = ptr + obj_len;
     900              :     /*version*/
     901          778 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     902              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
     903              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     904          778 :     if (!ret) {
     905            0 :         return false;
     906              :     }
     907              : 
     908          778 :     ptr += obj_len;
     909              :     /*serialNumber*/
     910          778 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
     911          778 :     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         4668 :     for (index = 0; index < sequence_time; index++) {
     923         3890 :         ptr += obj_len;
     924         3890 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     925              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     926         3890 :         if (!ret) {
     927            0 :             return false;
     928              :         }
     929              :     }
     930              : 
     931          778 :     if (base_asym_algo != 0) {
     932          778 :         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          715 :         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          715 :             ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
     965              :                                        LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
     966          715 :             if (!ret) {
     967            0 :                 return false;
     968              :             }
     969          715 :             ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
     970          715 :             if (!ret) {
     971            0 :                 return false;
     972              :             }
     973              : 
     974              :             /*get ecc second oid*/
     975          715 :             ptr +=obj_len;
     976          715 :             ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
     977          715 :             if (!ret) {
     978            0 :                 return false;
     979              :             }
     980              : 
     981          715 :             if (oid_size != obj_len) {
     982            0 :                 return false;
     983              :             }
     984              : 
     985          715 :             libspdm_copy_mem(oid, oid_size, ptr, obj_len);
     986          715 :             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          777 :     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          777 :     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          778 : 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          778 :     libspdm_zero_mem(libspdm_public_key_crypt_algo_oid, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
    1080          778 :     libspdm_zero_mem(libspdm_public_key_crypt_algo_oid_other, LIBSPDM_MAX_ENCRYPTION_ALGO_OID_LEN);
    1081              : 
    1082              :     /*work around: skip the sm2*/
    1083          778 :     if (base_asym_algo == SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256) {
    1084            0 :         return true;
    1085              :     }
    1086              : 
    1087          778 :     oid_len = libspdm_get_public_key_algo_OID_len(base_asym_algo, pqc_asym_algo);
    1088          778 :     if (oid_len == 0) {
    1089            0 :         return false;
    1090              :     }
    1091              :     /*get public key encrypt algo OID from libspdm stored*/
    1092          778 :     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          778 :     if (!status) {
    1096            0 :         return status;
    1097              :     }
    1098              : 
    1099              :     /*get public key encrypt algo OID from cert*/
    1100          778 :     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          778 :     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          776 :     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          761 : 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          761 :     uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
    1133          761 :     uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
    1134              : 
    1135          761 :     len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
    1136              : 
    1137          761 :     status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
    1138              :                                                          cert_basic_constraints, &len);
    1139          761 :     if (!status) {
    1140            0 :         return false;
    1141          761 :     } 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         1516 :     if ((len == sizeof(basic_constraints_false_case1)) &&
    1151          757 :         (libspdm_consttime_is_mem_equal(cert_basic_constraints,
    1152              :                                         basic_constraints_false_case1,
    1153              :                                         sizeof(basic_constraints_false_case1)))) {
    1154          757 :         return true;
    1155              :     }
    1156              : 
    1157            4 :     if ((len == sizeof(basic_constraints_false_case2)) &&
    1158            2 :         (libspdm_consttime_is_mem_equal(cert_basic_constraints,
    1159              :                                         basic_constraints_false_case2,
    1160              :                                         sizeof(basic_constraints_false_case2)))) {
    1161            0 :         return true;
    1162              :     }
    1163              : 
    1164            2 :     return false;
    1165              : }
    1166              : 
    1167              : /**
    1168              :  * Verify leaf certificate basic_constraints CA is correct for set certificate.
    1169              :  *
    1170              :  * For SPDM 1.2
    1171              :  *     - If certificate model is DeviceCert and CA is present then CA must be false.
    1172              :  *     - If certificate model is AliasCert and CA is present then CA must be true.
    1173              :  *
    1174              :  * For SPDM 1.3 and up, CA must be present and
    1175              :  *     - If certificate model is DeviceCert or GenericCert then CA must be false.
    1176              :  *     - If certificate model is AliasCert then CA must be true.
    1177              :  *
    1178              :  * @param[in]  cert                   Pointer to the DER-encoded certificate data.
    1179              :  * @param[in]  cert_size              The size of certificate data in bytes.
    1180              :  * @param[in]  cert_model             The certificate model.
    1181              :  * @param[in]  need_basic_constraints This value indicates whether basic_constraints must be present
    1182              :  *                                    in the certificate.
    1183              :  *
    1184              :  * @retval  true   verify pass 1. basic_constraints is not present when allowed.
    1185              :  *                             2. basic_constraints is present and correct.
    1186              :  * @retval  false  verify fail
    1187              :  **/
    1188           15 : static bool libspdm_verify_set_cert_leaf_cert_basic_constraints(
    1189              :     const uint8_t *cert, size_t cert_size, uint8_t cert_model, bool need_basic_constraints)
    1190              : {
    1191              :     bool status;
    1192              :     /* basic_constraints from certificate. */
    1193              :     uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
    1194              :     size_t len;
    1195              : 
    1196           15 :     const uint8_t basic_constraints_false_case1[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE1;
    1197           15 :     const uint8_t basic_constraints_false_case2[] = BASIC_CONSTRAINTS_STRING_FALSE_CASE2;
    1198           15 :     const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_STRING_TRUE_CASE;
    1199              : 
    1200           15 :     len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
    1201              : 
    1202           15 :     status = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
    1203              :                                                          cert_basic_constraints, &len);
    1204           15 :     if (!status) {
    1205            0 :         return false;
    1206           15 :     } else if (need_basic_constraints && (len == 0)) {
    1207            0 :         return false;
    1208              :     }
    1209              : 
    1210           15 :     if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT) ||
    1211              :         (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1212            9 :         if (need_basic_constraints || (len != 0)) {
    1213           18 :             if ((len == sizeof(basic_constraints_false_case1)) &&
    1214            9 :                 (libspdm_consttime_is_mem_equal(cert_basic_constraints,
    1215              :                                                 basic_constraints_false_case1,
    1216              :                                                 sizeof(basic_constraints_false_case1)))) {
    1217            9 :                 return true;
    1218              :             }
    1219              : 
    1220            0 :             if ((len == sizeof(basic_constraints_false_case2)) &&
    1221            0 :                 (libspdm_consttime_is_mem_equal(cert_basic_constraints,
    1222              :                                                 basic_constraints_false_case2,
    1223              :                                                 sizeof(basic_constraints_false_case2)))) {
    1224            0 :                 return true;
    1225              :             }
    1226              :         }
    1227              :     } else {
    1228              :         /* Alias certificate model. */
    1229            6 :         if (need_basic_constraints || (len != 0)) {
    1230              :             /* basicConstraints may include the pathLen field. Therefore do not check sequence
    1231              :              * length. */
    1232            6 :             if (len >= sizeof(basic_constraints_true_case)) {
    1233            4 :                 if (cert_basic_constraints[0] != basic_constraints_true_case[0]) {
    1234            0 :                     return false;
    1235              :                 }
    1236            4 :                 if  (libspdm_consttime_is_mem_equal(&cert_basic_constraints[2],
    1237              :                                                     &basic_constraints_true_case[2],
    1238              :                                                     sizeof(basic_constraints_true_case) - 2)) {
    1239            4 :                     return true;
    1240              :                 }
    1241              :             }
    1242              :         }
    1243              :     }
    1244            2 :     return false;
    1245              : }
    1246              : 
    1247              : /**
    1248              :  * Verify leaf cert spdm defined extended key usage
    1249              :  *
    1250              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1251              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1252              :  * @param[in]  is_requester_cert     Is the function verifying requester or responder cert.
    1253              :  *
    1254              :  * @retval  true   verify pass, two cases:
    1255              :  *                 1. spdm defined eku is not present in cert;
    1256              :  *                 2. spdm defined eku is compliant with requester/responder identity;
    1257              :  * @retval  false  verify fail, two cases:
    1258              :  *                 1. requester's cert has only responder auth oid in eku;
    1259              :  *                 2. responder's cert has only requester auth oid in eku;
    1260              :  **/
    1261          782 : 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          782 :     uint8_t eku_requester_auth_oid[] = SPDM_OID_DMTF_EKU_REQUESTER_AUTH;
    1274          782 :     uint8_t eku_responder_auth_oid[] = SPDM_OID_DMTF_EKU_RESPONDER_AUTH;
    1275              : 
    1276          782 :     eku_size = sizeof(eku);
    1277          782 :     status = libspdm_x509_get_extended_key_usage(cert, cert_size, eku, &eku_size);
    1278          782 :     if (!status) {
    1279            0 :         return false;
    1280          782 :     } else if (eku_size == 0) {
    1281              :         /* eku is not present in cert */
    1282            0 :         return true;
    1283              :     }
    1284              : 
    1285          782 :     ptr = eku;
    1286          782 :     obj_len = 0;
    1287          782 :     req_auth_oid_find_success = false;
    1288          782 :     rsp_auth_oid_find_success = false;
    1289              : 
    1290          782 :     status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len,
    1291              :                                   LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1292          782 :     if (!status) {
    1293            0 :         return false;
    1294              :     }
    1295              : 
    1296         3131 :     while(ptr < eku + eku_size) {
    1297         2349 :         status = libspdm_asn1_get_tag(&ptr, eku + eku_size, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1298         2349 :         if (!status) {
    1299            0 :             return false;
    1300              :         }
    1301              : 
    1302         2357 :         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         2357 :         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         2349 :         ptr += obj_len;
    1314              :     }
    1315              : 
    1316          782 :     if (ptr != eku + eku_size) {
    1317            0 :         return false;
    1318              :     }
    1319              : 
    1320          782 :     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 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Requester certificate contains Responder OID.\n"));
    1324            1 :             return false;
    1325              :         }
    1326              :     } else {
    1327              :         /* it should not only contain requester auth oid */
    1328          762 :         if (req_auth_oid_find_success && !rsp_auth_oid_find_success) {
    1329            1 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Responder certificate contains Requester OID.\n"));
    1330            1 :             return false;
    1331              :         }
    1332              :     }
    1333              : 
    1334          780 :     return true;
    1335              : }
    1336              : 
    1337              : /**
    1338              :  * Verify leaf cert spdm defined extension
    1339              :  *
    1340              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1341              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1342              :  * @param[in]  is_requester_cert     Is the function verifying requester or responder cert.
    1343              :  *
    1344              :  * @retval  true   verify pass
    1345              :  * @retval  false  verify fail,two case: 1. Unable to get get or validate extension data.
    1346              :  *                                       2. hardware_identity_oid is found in AliasCert model;
    1347              :  **/
    1348          774 : static bool libspdm_verify_leaf_cert_spdm_extension(const uint8_t *cert, size_t cert_size,
    1349              :                                                     bool is_requester_cert,
    1350              :                                                     uint8_t cert_model)
    1351              : {
    1352              :     bool status;
    1353              :     bool find_sucessful;
    1354              :     uint8_t spdm_extension[LIBSPDM_MAX_EXTENSION_LEN];
    1355              :     size_t len;
    1356              :     uint8_t *ptr;
    1357              :     uint8_t *temptr;
    1358              :     size_t obj_len;
    1359              : 
    1360              :     /* SPDM defined OID */
    1361          774 :     uint8_t oid_spdm_extension[] = SPDM_OID_DMTF_SPDM_EXTENSION;
    1362          774 :     uint8_t hardware_identity_oid[] = SPDM_OID_DMTF_HARDWARE_IDENTITY;
    1363              : 
    1364          774 :     len = LIBSPDM_MAX_EXTENSION_LEN;
    1365              : 
    1366          774 :     if (cert == NULL || cert_size == 0) {
    1367            0 :         return false;
    1368              :     }
    1369              : 
    1370          774 :     status = libspdm_x509_get_extension_data(cert, cert_size,
    1371              :                                              (const uint8_t *)oid_spdm_extension,
    1372              :                                              sizeof(oid_spdm_extension),
    1373              :                                              spdm_extension,
    1374              :                                              &len);
    1375          774 :     if (!status) {
    1376            0 :         return false;
    1377          774 :     } else if (len == 0) {
    1378           13 :         return true;
    1379              :     }
    1380              : 
    1381              :     /*find the spdm hardware identity OID*/
    1382          761 :     find_sucessful = false;
    1383          761 :     ptr = spdm_extension;
    1384          761 :     obj_len = 0;
    1385              : 
    1386              :     /*id-spdm-cert-oids ::= SEQUENCE SIZE (1..MAX) OF id-spdm-cert-oid*/
    1387          761 :     status = libspdm_asn1_get_tag(
    1388              :         &ptr, spdm_extension + len, &obj_len,
    1389              :         LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1390          761 :     if (!status) {
    1391            0 :         return false;
    1392              :     }
    1393              : 
    1394         1522 :     while(ptr < spdm_extension + len) {
    1395          761 :         status = libspdm_asn1_get_tag(
    1396              :             &ptr, spdm_extension + len, &obj_len,
    1397              :             LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1398          761 :         if (!status) {
    1399            0 :             return false;
    1400              :         }
    1401              : 
    1402          761 :         temptr = ptr + obj_len;
    1403          761 :         status = libspdm_asn1_get_tag(
    1404              :             &ptr, spdm_extension + len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1405          761 :         if (!status) {
    1406            0 :             return false;
    1407              :         }
    1408         1522 :         if ((obj_len == sizeof(hardware_identity_oid)) &&
    1409          761 :             (libspdm_consttime_is_mem_equal(ptr, hardware_identity_oid,
    1410              :                                             sizeof(hardware_identity_oid)))) {
    1411          761 :             find_sucessful = true;
    1412              :         }
    1413          761 :         ptr = temptr;
    1414              :     }
    1415              : 
    1416          761 :     if (ptr != spdm_extension + len) {
    1417            0 :         return false;
    1418              :     }
    1419              : 
    1420              :     /* Responder does not determine Requester's certificate model */
    1421          761 :     if (!is_requester_cert) {
    1422          746 :         if ((find_sucessful) && (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
    1423              :             /* Hardware_identity_OID is found in alias cert model */
    1424            4 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1425              :                            "Hardware identity OID present in alias leaf certificate.\n"));
    1426            4 :             return false;
    1427              :         }
    1428              :     }
    1429              : 
    1430          757 :     return true;
    1431              : }
    1432              : 
    1433              : /**
    1434              :  * Certificate common Check for SPDM leaf cert when get_cert and set_cert.
    1435              :  *
    1436              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1437              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1438              :  * @param[in]  base_asym_algo        SPDM base_asym_algo
    1439              :  * @param[in]  base_hash_algo        SPDM base_hash_algo
    1440              :  * @param[in]  is_requester_cert     Is the function verifying requester or responder cert.
    1441              :  * @param[in]  cert_model            One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    1442              :  * @param[in]  set_cert              Is the function verifying a set certificate operation.
    1443              :  *
    1444              :  * @retval  true   Success.
    1445              :  * @retval  false  Certificate is not valid.
    1446              :  **/
    1447          784 : bool libspdm_x509_common_certificate_check(
    1448              :     const uint8_t *cert, size_t cert_size,
    1449              :     uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
    1450              :     bool is_requester_cert, uint8_t cert_model,
    1451              :     bool set_cert)
    1452              : {
    1453              :     uint8_t end_cert_from[64];
    1454              :     size_t end_cert_from_len;
    1455              :     uint8_t end_cert_to[64];
    1456              :     size_t end_cert_to_len;
    1457              :     size_t asn1_buffer_len;
    1458              :     bool status;
    1459              :     size_t cert_version;
    1460              :     void *context;
    1461              :     size_t signature_algo_oid_size;
    1462              : 
    1463          784 :     if (cert == NULL || cert_size == 0) {
    1464            0 :         return false;
    1465              :     }
    1466              : 
    1467          784 :     status = true;
    1468          784 :     context = NULL;
    1469          784 :     end_cert_from_len = 64;
    1470          784 :     end_cert_to_len = 64;
    1471              : 
    1472              :     /* 1. Version */
    1473          784 :     cert_version = 0;
    1474          784 :     status = libspdm_x509_get_version(cert, cert_size, &cert_version);
    1475          784 :     if (!status) {
    1476            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Version field is not present.\n"));
    1477            0 :         goto cleanup;
    1478              :     }
    1479          784 :     if (cert_version != 2) {
    1480            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1481              :                        "Expected Version to be equal to 2 but it is actually %zu.\n", cert_version));
    1482            0 :         status = false;
    1483            0 :         goto cleanup;
    1484              :     }
    1485              : 
    1486              :     /* 2. Serial Number */
    1487          784 :     asn1_buffer_len = 0;
    1488          784 :     status = libspdm_x509_get_serial_number(cert, cert_size, NULL, &asn1_buffer_len);
    1489          784 :     if (asn1_buffer_len == 0) {
    1490            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Serial Number field is not present.\n"));
    1491            0 :         status = false;
    1492            0 :         goto cleanup;
    1493              :     }
    1494              : 
    1495              :     /* 3. Signature Algorithm */
    1496          784 :     signature_algo_oid_size = 0;
    1497          784 :     status = libspdm_x509_get_signature_algorithm(cert, cert_size, NULL, &signature_algo_oid_size);
    1498          784 :     if (status) {
    1499            0 :         if ((signature_algo_oid_size == 0) &&
    1500              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1501            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1502              :                            "The mandatory Signature Algorithm field is not present.\n"));
    1503            0 :             status = false;
    1504            0 :             goto cleanup;
    1505              :         }
    1506              :     } else {
    1507          784 :         if (signature_algo_oid_size == 0) {
    1508            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1509              :                            "The mandatory Signature Algorithm field is not present.\n"));
    1510            0 :             status = false;
    1511            0 :             goto cleanup;
    1512              :         }
    1513              :     }
    1514              : 
    1515              :     /* 4. Verify public key algorithm.
    1516              :      *    If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
    1517              :      *    check should be skipped as the Device Certificate CA's public key does not have to use
    1518              :      *    the same algorithms as the connection's negotiated algorithms. */
    1519          784 :     if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
    1520          778 :         status = libspdm_verify_cert_subject_public_key_info(cert, cert_size, base_asym_algo,
    1521              :                                                              pqc_asym_algo);
    1522          778 :         if (!status) {
    1523            2 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1524              :                            "Error in verifying the Public Key Algorithm field.\n"));
    1525            2 :             goto cleanup;
    1526              :         }
    1527              :     }
    1528              : 
    1529              :     /* 5. Issuer */
    1530          782 :     asn1_buffer_len = 0;
    1531          782 :     status = libspdm_x509_get_issuer_name(cert, cert_size, NULL, &asn1_buffer_len);
    1532          782 :     if (status) {
    1533            0 :         if ((asn1_buffer_len == 0) &&
    1534              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1535            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Issuer field is not present.\n"));
    1536            0 :             status = false;
    1537            0 :             goto cleanup;
    1538              :         }
    1539              :     } else {
    1540          782 :         if (asn1_buffer_len == 0) {
    1541            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Issuer field is not present.\n"));
    1542            0 :             status = false;
    1543            0 :             goto cleanup;
    1544              :         }
    1545              :     }
    1546              : 
    1547              :     /* 6. subject_name*/
    1548          782 :     asn1_buffer_len = 0;
    1549          782 :     status = libspdm_x509_get_subject_name(cert, cert_size, NULL, &asn1_buffer_len);
    1550          782 :     if (status) {
    1551            0 :         if ((asn1_buffer_len == 0) &&
    1552              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1553            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Subject field is not present.\n"));
    1554            0 :             status = false;
    1555            0 :             goto cleanup;
    1556              :         }
    1557              :     } else {
    1558          782 :         if (asn1_buffer_len == 0) {
    1559            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Subject field is not present.\n"));
    1560            0 :             status = false;
    1561            0 :             goto cleanup;
    1562              :         }
    1563              :     }
    1564              : 
    1565              :     /* 7. Validity */
    1566          782 :     status = libspdm_x509_get_validity(cert, cert_size, end_cert_from,
    1567              :                                        &end_cert_from_len, end_cert_to,
    1568              :                                        &end_cert_to_len);
    1569          782 :     if (status) {
    1570          782 :         if ((end_cert_from_len == 0) &&
    1571              :             (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
    1572            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Validity field is not present.\n"));
    1573            0 :             status = false;
    1574            0 :             goto cleanup;
    1575              :         }
    1576              :     } else {
    1577            0 :         if (end_cert_from_len == 0) {
    1578            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Validity field is not present.\n"));
    1579            0 :             status = false;
    1580            0 :             goto cleanup;
    1581              :         }
    1582              :     }
    1583              : 
    1584          782 :     if (end_cert_from_len != 0) {
    1585          782 :         status = libspdm_internal_x509_date_time_check(
    1586              :             end_cert_from, end_cert_from_len, end_cert_to, end_cert_to_len);
    1587          782 :         if (!status) {
    1588            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1589              :                            "The certificate is outside its validity period.\n"));
    1590            0 :             goto cleanup;
    1591              :         }
    1592              :     }
    1593              : 
    1594              :     /* 8. Subject Public Key Info */
    1595          782 :     if (base_asym_algo != 0) {
    1596          782 :         status = libspdm_asym_get_public_key_from_x509(base_asym_algo, cert, cert_size, &context);
    1597              :     }
    1598          782 :     if (pqc_asym_algo != 0) {
    1599            0 :         status = libspdm_pqc_asym_get_public_key_from_x509(pqc_asym_algo, cert, cert_size, &context);
    1600              :     }
    1601          782 :     if (!status) {
    1602            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1603              :                        "The mandatory Subject Public Key Info field is not present.\n"));
    1604            0 :         goto cleanup;
    1605              :     }
    1606              : 
    1607              :     /* 9. Key Usage
    1608              :      *    If this is a SET_CERTIFICATE operation and the endpoint uses the AliasCert model then the
    1609              :      *    check should be skipped as the SPDM specification does not specify the presence or absence
    1610              :      *    of the Device Certificate CA's keyUsage field. */
    1611          782 :     if (!set_cert || (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT)) {
    1612          776 :         size_t value = 0;
    1613              : 
    1614          776 :         status = libspdm_x509_get_key_usage(cert, cert_size, &value);
    1615          776 :         if (!status) {
    1616            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "The mandatory Key Usage field is not present.\n"));
    1617            0 :             goto cleanup;
    1618              :         } else {
    1619          776 :             if (value == 0) {
    1620            0 :                 if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
    1621            0 :                     status = false;
    1622            0 :                     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1623              :                                    "The mandatory Key Usage field is not present.\n"));
    1624            0 :                     goto cleanup;
    1625              :                 }
    1626              :             } else {
    1627          776 :                 if ((LIBSPDM_CRYPTO_X509_KU_DIGITAL_SIGNATURE & value) == 0) {
    1628            0 :                     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    1629              :                                    "The Mandatory digital signature bit in Key Usage field is not set.\n"));
    1630            0 :                     status = false;
    1631            0 :                     goto cleanup;
    1632              :                 }
    1633              :             }
    1634              :         }
    1635              :     }
    1636              : 
    1637              :     /* 10. Extended Key Usage */
    1638          782 :     status = libspdm_verify_leaf_cert_spdm_eku(cert, cert_size, is_requester_cert);
    1639          782 :     if (!status) {
    1640            2 :         goto cleanup;
    1641              :     }
    1642              : 
    1643          780 :     if ((!set_cert) || (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT)) {
    1644              :         /* 11. verify spdm defined extension*/
    1645          774 :         status = libspdm_verify_leaf_cert_spdm_extension(cert, cert_size,
    1646              :                                                          is_requester_cert, cert_model);
    1647          774 :         if (!status) {
    1648            4 :             goto cleanup;
    1649              :         }
    1650              :     }
    1651              : 
    1652          776 : cleanup:
    1653          784 :     if (base_asym_algo != 0) {
    1654          784 :         libspdm_asym_free(base_asym_algo, context);
    1655              :     }
    1656          784 :     if (pqc_asym_algo != 0) {
    1657            0 :         libspdm_pqc_asym_free(pqc_asym_algo, context);
    1658              :     }
    1659          784 :     return status;
    1660              : }
    1661              : 
    1662              : /**
    1663              :  * Certificate Check for SPDM leaf cert when get_cert command
    1664              :  *
    1665              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1666              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1667              :  * @param[in]  base_asym_algo        SPDM base_asym_algo
    1668              :  * @param[in]  base_hash_algo        SPDM base_hash_algo
    1669              :  * @param[in]  is_requester          Is the function verifying a cert as a requester or responder.
    1670              :  * @param[in]  is_device_cert_model  If true, the local endpoint uses the DeviceCert model.
    1671              :  *                                   If false, the local endpoint uses the AliasCert model.
    1672              :  *
    1673              :  * @retval  true   Success.
    1674              :  * @retval  false  Certificate is not valid
    1675              :  **/
    1676           23 : bool libspdm_x509_certificate_check(const uint8_t *cert, size_t cert_size,
    1677              :                                     uint32_t base_asym_algo,
    1678              :                                     uint32_t base_hash_algo,
    1679              :                                     bool is_requester,
    1680              :                                     bool is_device_cert_model)
    1681              : {
    1682              :     bool status;
    1683              :     uint8_t cert_model;
    1684              : 
    1685           23 :     if (is_device_cert_model) {
    1686           20 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
    1687              :     } else {
    1688            3 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
    1689              :     }
    1690              : 
    1691           23 :     status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo, 0,
    1692              :                                                    base_hash_algo, is_requester,
    1693              :                                                    cert_model, false);
    1694           23 :     if (!status) {
    1695            4 :         return false;
    1696              :     }
    1697              : 
    1698              :     /* verify basic constraints: the leaf cert always is ca:false in get_cert*/
    1699           19 :     status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, false);
    1700           19 :     return status;
    1701              : }
    1702              : 
    1703              : 
    1704              : /**
    1705              :  * Certificate Check for SPDM leaf cert when get_cert command. It is used for SPDM 1.3.
    1706              :  *
    1707              :  * @param[in]  cert                  Pointer to the DER-encoded certificate data.
    1708              :  * @param[in]  cert_size             The size of certificate data in bytes.
    1709              :  * @param[in]  base_asym_algo        SPDM base_asym_algo
    1710              :  * @param[in]  base_hash_algo        SPDM base_hash_algo
    1711              :  * @param[in]  is_requester          Is the function verifying a cert as a requester or responder.
    1712              :  * @param[in]  cert_model            One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    1713              :  *
    1714              :  * @retval  true   Success.
    1715              :  * @retval  false  Certificate is not valid
    1716              :  **/
    1717          746 : bool libspdm_x509_certificate_check_with_pqc(const uint8_t *cert, size_t cert_size,
    1718              :                                              uint32_t base_asym_algo, uint32_t pqc_asym_algo,
    1719              :                                              uint32_t base_hash_algo,
    1720              :                                              bool is_requester,
    1721              :                                              uint8_t cert_model)
    1722              : {
    1723              :     bool status;
    1724              : 
    1725          746 :     status = libspdm_x509_common_certificate_check(
    1726              :         cert, cert_size, base_asym_algo, pqc_asym_algo,
    1727              :         base_hash_algo, is_requester,
    1728              :         cert_model, false);
    1729          746 :     if (!status) {
    1730            4 :         return false;
    1731              :     }
    1732              : 
    1733              :     /* verify basic constraints: the leaf cert always is ca:false in get_cert
    1734              :      * basic_constraints is mandatory in SPDM 1.3*/
    1735          742 :     status = libspdm_verify_leaf_cert_basic_constraints(cert, cert_size, true);
    1736          742 :     return status;
    1737              : }
    1738              : 
    1739            9 : bool libspdm_x509_certificate_check_ex(const uint8_t *cert, size_t cert_size,
    1740              :                                        uint32_t base_asym_algo,
    1741              :                                        uint32_t base_hash_algo,
    1742              :                                        bool is_requester,
    1743              :                                        uint8_t cert_model)
    1744              : {
    1745            9 :     return libspdm_x509_certificate_check_with_pqc (
    1746              :         cert, cert_size,
    1747              :         base_asym_algo, 0, base_hash_algo,
    1748              :         is_requester, cert_model);
    1749              : }
    1750              : 
    1751            9 : bool libspdm_x509_set_cert_certificate_check(const uint8_t *cert, size_t cert_size,
    1752              :                                              uint32_t base_asym_algo, uint32_t base_hash_algo,
    1753              :                                              bool is_requester, bool is_device_cert_model)
    1754              : {
    1755              :     bool status;
    1756              :     uint8_t cert_model;
    1757              : 
    1758            9 :     if (is_device_cert_model) {
    1759            6 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT;
    1760              :     } else {
    1761            3 :         cert_model = SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
    1762              :     }
    1763              : 
    1764            9 :     status = libspdm_x509_common_certificate_check(cert, cert_size, base_asym_algo, 0,
    1765              :                                                    base_hash_algo, is_requester,
    1766              :                                                    cert_model, true);
    1767            9 :     if (!status) {
    1768            0 :         return false;
    1769              :     }
    1770              : 
    1771              :     /* verify basic constraints: need check with is_device_cert_model*/
    1772            9 :     status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
    1773              :         cert, cert_size, cert_model, false);
    1774            9 :     return status;
    1775              : }
    1776              : 
    1777            6 : bool libspdm_x509_set_cert_certificate_check_with_pqc(
    1778              :     const uint8_t *cert, size_t cert_size,
    1779              :     uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
    1780              :     bool is_requester, uint8_t cert_model)
    1781              : {
    1782              :     bool status;
    1783              : 
    1784            6 :     status = libspdm_x509_common_certificate_check(
    1785              :         cert, cert_size, base_asym_algo, pqc_asym_algo,
    1786              :         base_hash_algo, is_requester,
    1787              :         cert_model, true);
    1788            6 :     if (!status) {
    1789            0 :         return false;
    1790              :     }
    1791              : 
    1792              :     /* verify basic constraints: need check with is_device_cert_model*/
    1793            6 :     status = libspdm_verify_set_cert_leaf_cert_basic_constraints(
    1794              :         cert, cert_size, cert_model, true);
    1795              : 
    1796            6 :     return status;
    1797              : }
    1798              : 
    1799            5 : bool libspdm_x509_set_cert_certificate_check_ex(const uint8_t *cert, size_t cert_size,
    1800              :                                                 uint32_t base_asym_algo, uint32_t base_hash_algo,
    1801              :                                                 bool is_requester, uint8_t cert_model)
    1802              : {
    1803            5 :     return libspdm_x509_set_cert_certificate_check_with_pqc (
    1804              :         cert, cert_size,
    1805              :         base_asym_algo, 0, base_hash_algo,
    1806              :         is_requester, cert_model);
    1807              : }
    1808              : 
    1809           59 : bool libspdm_is_root_certificate(const uint8_t *cert, size_t cert_size)
    1810              : {
    1811              :     uint8_t issuer_name[LIBSPDM_MAX_NAME_SIZE];
    1812              :     size_t issuer_name_len;
    1813              :     uint8_t subject_name[LIBSPDM_MAX_NAME_SIZE];
    1814              :     size_t subject_name_len;
    1815              :     bool result;
    1816              :     uint8_t cert_basic_constraints[LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN];
    1817              :     size_t cert_basic_constraints_len;
    1818           59 :     const uint8_t basic_constraints_true_case[] = BASIC_CONSTRAINTS_STRING_TRUE_CASE;
    1819              : 
    1820           59 :     if (cert == NULL || cert_size == 0) {
    1821            0 :         return false;
    1822              :     }
    1823              : 
    1824              :     /* 1. issuer_name*/
    1825           59 :     issuer_name_len = sizeof(issuer_name);
    1826           59 :     result = libspdm_x509_get_issuer_name(cert, cert_size, issuer_name, &issuer_name_len);
    1827           59 :     if (!result) {
    1828            0 :         return false;
    1829              :     }
    1830              : 
    1831              :     /* 2. subject_name*/
    1832           59 :     subject_name_len = sizeof(subject_name);
    1833           59 :     result = libspdm_x509_get_subject_name(cert, cert_size, subject_name, &subject_name_len);
    1834           59 :     if (!result) {
    1835            0 :         return false;
    1836              :     }
    1837              : 
    1838           59 :     if (issuer_name_len != subject_name_len) {
    1839            3 :         return false;
    1840              :     }
    1841           56 :     if (!libspdm_consttime_is_mem_equal(issuer_name, subject_name, issuer_name_len)) {
    1842            0 :         return false;
    1843              :     }
    1844              : 
    1845              :     /* 3. cA must be present in Basic Constraints */
    1846           56 :     cert_basic_constraints_len = LIBSPDM_MAX_BASIC_CONSTRAINTS_CA_LEN;
    1847           56 :     result = libspdm_x509_get_extended_basic_constraints(cert, cert_size,
    1848              :                                                          cert_basic_constraints, &cert_basic_constraints_len);
    1849           56 :     if (!result || cert_basic_constraints_len == 0) {
    1850            0 :         return false;
    1851              :     }
    1852           56 :     if (cert_basic_constraints_len >= sizeof(basic_constraints_true_case)) {
    1853           56 :         if (cert_basic_constraints[0] != basic_constraints_true_case[0]) {
    1854            0 :             return false;
    1855              :         }
    1856           56 :         if (!libspdm_consttime_is_mem_equal(&cert_basic_constraints[2],
    1857              :                                             &basic_constraints_true_case[2],
    1858              :                                             sizeof(basic_constraints_true_case) - 2)) {
    1859            0 :             return false;
    1860              :         }
    1861              :     }
    1862              : 
    1863              :     /* 4. certificate must be self-signed */
    1864           56 :     result = libspdm_x509_verify_cert(cert, cert_size, cert, cert_size);
    1865           56 :     if (!result) {
    1866            1 :         return false;
    1867              :     }
    1868              : 
    1869           55 :     return true;
    1870              : }
    1871              : 
    1872              : /**
    1873              :  * Retrieve the SubjectAltName from SubjectAltName Bytes.
    1874              :  *
    1875              :  * @param[in]      buffer           Pointer to subjectAltName oct bytes.
    1876              :  * @param[in]      len              size of buffer in bytes.
    1877              :  * @param[out]     name_buffer       buffer to contain the retrieved certificate
    1878              :  *                                 SubjectAltName. At most name_buffer_size bytes will be
    1879              :  *                                 written. Maybe NULL in order to determine the size
    1880              :  *                                 buffer needed.
    1881              :  * @param[in,out]  name_buffer_size   The size in bytes of the name buffer on input,
    1882              :  *                                 and the size of buffer returned name on output.
    1883              :  *                                 If name_buffer is NULL then the amount of space needed
    1884              :  *                                 in buffer (including the final null) is returned.
    1885              :  * @param[out]     oid              OID of otherName
    1886              :  * @param[in,out]  oid_size          the buffersize for required OID
    1887              :  *
    1888              :  * @retval true                     get the subjectAltName string successfully
    1889              :  * @retval failed                   get the subjectAltName string failed
    1890              :  **/
    1891            9 : bool libspdm_get_dmtf_subject_alt_name_from_bytes(
    1892              :     uint8_t *buffer, const size_t len, char *name_buffer,
    1893              :     size_t *name_buffer_size, uint8_t *oid,
    1894              :     size_t *oid_size)
    1895              : {
    1896              :     uint8_t *ptr;
    1897              :     int32_t length;
    1898              :     size_t obj_len;
    1899              :     int32_t ret;
    1900              : 
    1901              :     /*copy mem variable*/
    1902              :     volatile uint8_t* dst;
    1903              :     const volatile uint8_t* src;
    1904              :     size_t dst_len;
    1905              :     size_t src_len;
    1906              : 
    1907            9 :     length = (int32_t)len;
    1908            9 :     ptr = buffer;
    1909            9 :     obj_len = 0;
    1910              : 
    1911              :     /* Sequence*/
    1912            9 :     ret = libspdm_asn1_get_tag(&ptr, ptr + length, &obj_len,
    1913              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1914            9 :     if (!ret) {
    1915            0 :         return false;
    1916              :     }
    1917              : 
    1918            9 :     ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len,
    1919              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    1920              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1921              : 
    1922            9 :     ret = libspdm_asn1_get_tag(&ptr, ptr + obj_len, &obj_len, LIBSPDM_CRYPTO_ASN1_OID);
    1923            9 :     if (!ret) {
    1924            0 :         return false;
    1925              :     }
    1926              :     /* CopyData to OID*/
    1927            9 :     if (*oid_size < (size_t)obj_len) {
    1928            0 :         *oid_size = (size_t)obj_len;
    1929            0 :         return false;
    1930              :     }
    1931            9 :     if (oid != NULL) {
    1932            9 :         libspdm_copy_mem(oid, *oid_size, ptr, obj_len);
    1933            9 :         *oid_size = obj_len;
    1934              :     }
    1935              : 
    1936              :     /* Move to next element*/
    1937            9 :     ptr += obj_len;
    1938              : 
    1939            9 :     ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
    1940              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    1941              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    1942            9 :     ret = libspdm_asn1_get_tag(&ptr, (uint8_t *)(buffer + length), &obj_len,
    1943              :                                LIBSPDM_CRYPTO_ASN1_UTF8_STRING);
    1944            9 :     if (!ret) {
    1945            0 :         return false;
    1946              :     }
    1947              : 
    1948            9 :     if (*name_buffer_size < (size_t)obj_len + 1) {
    1949            0 :         *name_buffer_size = (size_t)obj_len + 1;
    1950            0 :         return false;
    1951              :     }
    1952              : 
    1953              :     /* the src and dst address are overlap,
    1954              :      * When the function is called by libspdm_get_dmtf_subject_alt_name.
    1955              :      * libspdm_copy_mem can not be used. */
    1956            9 :     if ((name_buffer != NULL) && (ptr != NULL)) {
    1957            9 :         dst = (volatile uint8_t*) name_buffer;
    1958            9 :         src = (const volatile uint8_t*) ptr;
    1959            9 :         dst_len = *name_buffer_size;
    1960            9 :         src_len = obj_len;
    1961              : 
    1962              :         /* Check for case where "dst_len" may be invalid. Do not zero "dst" in this case. */
    1963            9 :         if (dst_len > (SIZE_MAX >> 1)) {
    1964            0 :             LIBSPDM_ASSERT(0);
    1965            0 :             return false;
    1966              :         }
    1967              : 
    1968              :         /* Guard against invalid lengths. Zero "dst" in these cases. */
    1969            9 :         if (src_len > dst_len ||
    1970            9 :             src_len > (SIZE_MAX >> 1)) {
    1971            0 :             libspdm_zero_mem(name_buffer, dst_len);
    1972            0 :             LIBSPDM_ASSERT(0);
    1973            0 :             return false;
    1974              :         }
    1975              : 
    1976          207 :         while (src_len-- != 0) {
    1977          198 :             *(dst++) = *(src++);
    1978              :         }
    1979              : 
    1980              :         /*encode name buffer to string*/
    1981            9 :         *name_buffer_size = obj_len + 1;
    1982            9 :         name_buffer[obj_len] = 0;
    1983            9 :         return true;
    1984              :     }
    1985              : 
    1986            0 :     return false;
    1987              : }
    1988              : 
    1989              : /**
    1990              :  * Retrieve the SubjectAltName from one X.509 certificate.
    1991              :  *
    1992              :  * @param[in]      cert             Pointer to the DER-encoded X509 certificate.
    1993              :  * @param[in]      cert_size         size of the X509 certificate in bytes.
    1994              :  * @param[out]     name_buffer       buffer to contain the retrieved certificate
    1995              :  *                                 SubjectAltName. At most name_buffer_size bytes will be
    1996              :  *                                 written. Maybe NULL in order to determine the size
    1997              :  *                                 buffer needed.
    1998              :  * @param[in,out]  name_buffer_size   The size in bytes of the name buffer on input,
    1999              :  *                                 and the size of buffer returned name on output.
    2000              :  *                                 If name_buffer is NULL then the amount of space needed
    2001              :  *                                 in buffer (including the final null) is returned.
    2002              :  * @param[out]     oid              OID of otherName
    2003              :  * @param[in,out]  oid_size          the buffersize for required OID
    2004              :  *
    2005              :  * @retval true                     get the subjectAltName string successfully
    2006              :  * @retval failed                   get the subjectAltName string failed
    2007              :  **/
    2008            6 : bool libspdm_get_dmtf_subject_alt_name(const uint8_t *cert, const size_t cert_size,
    2009              :                                        char *name_buffer,
    2010              :                                        size_t *name_buffer_size,
    2011              :                                        uint8_t *oid, size_t *oid_size)
    2012              : {
    2013              :     bool status;
    2014              :     size_t extension_data_size;
    2015            6 :     uint8_t oid_subject_alt_name[] = { 0x55, 0x1D, 0x11 };
    2016              : 
    2017            6 :     extension_data_size = 0;
    2018            6 :     status = libspdm_x509_get_extension_data(cert, cert_size,
    2019              :                                              oid_subject_alt_name,
    2020              :                                              sizeof(oid_subject_alt_name), NULL,
    2021              :                                              &extension_data_size);
    2022            6 :     if (status || (extension_data_size == 0)) {
    2023            0 :         *name_buffer_size = 0;
    2024            0 :         return false;
    2025              :     }
    2026            6 :     if (extension_data_size > *name_buffer_size) {
    2027            0 :         *name_buffer_size = extension_data_size;
    2028            0 :         return false;
    2029              :     }
    2030              :     status =
    2031            6 :         libspdm_x509_get_extension_data(cert, cert_size,
    2032              :                                         oid_subject_alt_name,
    2033              :                                         sizeof(oid_subject_alt_name),
    2034              :                                         (uint8_t *)name_buffer, name_buffer_size);
    2035            6 :     if (!status) {
    2036            0 :         return status;
    2037              :     }
    2038              : 
    2039            6 :     return libspdm_get_dmtf_subject_alt_name_from_bytes(
    2040              :         (uint8_t *)name_buffer, *name_buffer_size, name_buffer,
    2041              :         name_buffer_size, oid, oid_size);
    2042              : }
    2043              : 
    2044              : /**
    2045              :  * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
    2046              :  * It is used for SPDM 1.3.
    2047              :  *
    2048              :  * @param  cert_chain_data       The certificate chain data without spdm_cert_chain_t header.
    2049              :  * @param  cert_chain_data_size  Size in bytes of the certificate chain data.
    2050              :  * @param  base_asym_algo        SPDM base_asym_algo
    2051              :  * @param  base_hash_algo        SPDM base_hash_algo
    2052              :  * @param  is_requester_cert     Is the function verifying requester or responder cert.
    2053              :  * @param  cert_model            One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    2054              :  *
    2055              :  * @retval true  Certificate chain data integrity verification pass.
    2056              :  * @retval false Certificate chain data integrity verification fail.
    2057              :  **/
    2058            6 : bool libspdm_verify_cert_chain_data_ex(uint8_t *cert_chain_data, size_t cert_chain_data_size,
    2059              :                                        uint32_t base_asym_algo, uint32_t base_hash_algo,
    2060              :                                        bool is_requester_cert, uint8_t cert_model)
    2061              : {
    2062              :     const uint8_t *root_cert_buffer;
    2063              :     size_t root_cert_buffer_size;
    2064              :     const uint8_t *leaf_cert_buffer;
    2065              :     size_t leaf_cert_buffer_size;
    2066              : 
    2067            6 :     if (cert_chain_data_size >
    2068              :         SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
    2069            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2070              :                        "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
    2071            0 :         return false;
    2072              :     }
    2073              : 
    2074            6 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2075              :             cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
    2076              :             &root_cert_buffer_size)) {
    2077            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2078              :                        "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
    2079            0 :         return false;
    2080              :     }
    2081              : 
    2082            6 :     if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
    2083              :                                         cert_chain_data, cert_chain_data_size)) {
    2084            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2085              :                        "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
    2086            2 :         return false;
    2087              :     }
    2088              : 
    2089            4 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2090              :             cert_chain_data, cert_chain_data_size, -1,
    2091              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    2092            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2093              :                        "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
    2094            0 :         return false;
    2095              :     }
    2096              : 
    2097            4 :     if (!libspdm_x509_certificate_check_ex(leaf_cert_buffer, leaf_cert_buffer_size,
    2098              :                                            base_asym_algo, base_hash_algo,
    2099              :                                            is_requester_cert, cert_model)) {
    2100            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2101              :                        "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
    2102            1 :         return false;
    2103              :     }
    2104              : 
    2105            3 :     return true;
    2106              : }
    2107              : /**
    2108              :  * This function verifies the integrity of certificate chain data without spdm_cert_chain_t header.
    2109              :  *
    2110              :  * @param  cert_chain_data          The certificate chain data without spdm_cert_chain_t header.
    2111              :  * @param  cert_chain_data_size      size in bytes of the certificate chain data.
    2112              :  * @param  base_asym_algo            SPDM base_asym_algo
    2113              :  * @param  base_hash_algo            SPDM base_hash_algo
    2114              :  * @param  is_requester_cert         Is the function verifying requester or responder cert.
    2115              :  * @param  is_device_cert_model      If true, the cert chain is DeviceCert model;
    2116              :  *                                   If false, the cert chain is AliasCert model;
    2117              :  *
    2118              :  * @retval true  certificate chain data integrity verification pass.
    2119              :  * @retval false certificate chain data integrity verification fail.
    2120              :  **/
    2121          702 : bool libspdm_verify_cert_chain_data_with_pqc(
    2122              :     uint8_t *cert_chain_data, size_t cert_chain_data_size,
    2123              :     uint32_t base_asym_algo, uint32_t pqc_asym_algo, uint32_t base_hash_algo,
    2124              :     bool is_requester_cert, bool is_device_cert_model)
    2125              : {
    2126              :     const uint8_t *root_cert_buffer;
    2127              :     size_t root_cert_buffer_size;
    2128              :     const uint8_t *leaf_cert_buffer;
    2129              :     size_t leaf_cert_buffer_size;
    2130              : 
    2131          702 :     if (cert_chain_data_size >
    2132              :         SPDM_MAX_CERTIFICATE_CHAIN_SIZE - (sizeof(spdm_cert_chain_t) + LIBSPDM_MAX_HASH_SIZE)) {
    2133            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2134              :                        "!!! VerifyCertificateChainData - FAIL (chain size too large) !!!\n"));
    2135            0 :         return false;
    2136              :     }
    2137              : 
    2138          702 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2139              :             cert_chain_data, cert_chain_data_size, 0, &root_cert_buffer,
    2140              :             &root_cert_buffer_size)) {
    2141            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2142              :                        "!!! VerifyCertificateChainData - FAIL (get root certificate failed)!!!\n"));
    2143            0 :         return false;
    2144              :     }
    2145              : 
    2146          702 :     if (!libspdm_x509_verify_cert_chain(root_cert_buffer, root_cert_buffer_size,
    2147              :                                         cert_chain_data, cert_chain_data_size)) {
    2148            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2149              :                        "!!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!\n"));
    2150            0 :         return false;
    2151              :     }
    2152              : 
    2153          702 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2154              :             cert_chain_data, cert_chain_data_size, -1,
    2155              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    2156            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2157              :                        "!!! VerifyCertificateChainData - FAIL (get leaf certificate failed)!!!\n"));
    2158            0 :         return false;
    2159              :     }
    2160              : 
    2161          702 :     if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
    2162              :                                                  base_asym_algo, pqc_asym_algo, base_hash_algo,
    2163              :                                                  is_requester_cert, is_device_cert_model)) {
    2164            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2165              :                        "!!! VerifyCertificateChainData - FAIL (leaf certificate check failed)!!!\n"));
    2166            0 :         return false;
    2167              :     }
    2168              : 
    2169          702 :     return true;
    2170              : }
    2171              : 
    2172          702 : bool libspdm_verify_cert_chain_data(uint8_t *cert_chain_data, size_t cert_chain_data_size,
    2173              :                                     uint32_t base_asym_algo, uint32_t base_hash_algo,
    2174              :                                     bool is_requester_cert, bool is_device_cert_model)
    2175              : {
    2176          702 :     return libspdm_verify_cert_chain_data_with_pqc (
    2177              :         cert_chain_data, cert_chain_data_size,
    2178              :         base_asym_algo, 0, base_hash_algo,
    2179              :         is_requester_cert, is_device_cert_model);
    2180              : }
    2181              : 
    2182              : /**
    2183              :  * This function verifies the integrity of certificate chain buffer including
    2184              :  * spdm_cert_chain_t header. It is used for SPDM 1.3.
    2185              :  *
    2186              :  * @param  base_hash_algo          SPDM base_hash_algo
    2187              :  * @param  base_asym_algo          SPDM base_asym_algo
    2188              :  * @param  cert_chain_buffer       The certificate chain buffer including spdm_cert_chain_t header.
    2189              :  * @param  cert_chain_buffer_size  Size in bytes of the certificate chain buffer.
    2190              :  * @param  is_requester_cert       Is the function verifying requester or responder cert.
    2191              :  * @param  cert_model              One of the SPDM_CERTIFICATE_INFO_CERT_MODEL_* macros.
    2192              :  *
    2193              :  * @retval true   Certificate chain buffer integrity verification pass.
    2194              :  * @retval false  Certificate chain buffer integrity verification fail.
    2195              :  **/
    2196           40 : bool libspdm_verify_certificate_chain_buffer_with_pqc(
    2197              :     uint32_t base_hash_algo, uint32_t base_asym_algo, uint32_t pqc_asym_algo,
    2198              :     const void *cert_chain_buffer,
    2199              :     size_t cert_chain_buffer_size,
    2200              :     bool is_requester_cert, uint8_t cert_model)
    2201              : {
    2202              :     const uint8_t *cert_chain_data;
    2203              :     size_t cert_chain_data_size;
    2204              :     const uint8_t *first_cert_buffer;
    2205              :     size_t first_cert_buffer_size;
    2206              :     size_t hash_size;
    2207              :     uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
    2208              :     const uint8_t *leaf_cert_buffer;
    2209              :     size_t leaf_cert_buffer_size;
    2210              :     bool result;
    2211              :     const spdm_cert_chain_t *cert_chain_header;
    2212              : 
    2213           40 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    2214              : 
    2215           40 :     if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
    2216            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2217              :                        "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
    2218            0 :         return false;
    2219              :     }
    2220              : 
    2221           40 :     cert_chain_header = cert_chain_buffer;
    2222           40 :     if (cert_chain_header->length != cert_chain_buffer_size) {
    2223            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2224              :                        "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
    2225            2 :         return false;
    2226              :     }
    2227              : 
    2228           38 :     cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
    2229           38 :     cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
    2230           38 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2231              :             cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
    2232              :             &first_cert_buffer_size)) {
    2233            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2234              :                        "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
    2235            0 :         return false;
    2236              :     }
    2237              : 
    2238           38 :     if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
    2239           35 :         result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
    2240              :                                   calc_root_cert_hash);
    2241           35 :         if (!result) {
    2242            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2243              :                            "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
    2244            0 :             return false;
    2245              :         }
    2246           35 :         if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
    2247              :                                             sizeof(spdm_cert_chain_t),
    2248              :                                             calc_root_cert_hash, hash_size)) {
    2249            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2250              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
    2251            0 :             return false;
    2252              :         }
    2253           35 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2254              :                        "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
    2255              :     }
    2256              : 
    2257              :     /*If the number of certificates in the certificate chain is more than 1,
    2258              :      * other certificates need to be verified.*/
    2259           38 :     if (cert_chain_data_size > first_cert_buffer_size) {
    2260           38 :         if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
    2261              :                                             cert_chain_data + first_cert_buffer_size,
    2262              :                                             cert_chain_data_size - first_cert_buffer_size)) {
    2263            3 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2264              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
    2265            3 :             return false;
    2266              :         }
    2267              :     }
    2268              : 
    2269           35 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2270              :             cert_chain_data, cert_chain_data_size, -1,
    2271              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    2272            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2273              :                        "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
    2274            0 :         return false;
    2275              :     }
    2276              : 
    2277           35 :     if (!libspdm_x509_certificate_check_with_pqc(leaf_cert_buffer, leaf_cert_buffer_size,
    2278              :                                                  base_asym_algo, pqc_asym_algo, base_hash_algo,
    2279              :                                                  is_requester_cert, cert_model)) {
    2280            3 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2281              :                        "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
    2282            3 :         return false;
    2283              :     }
    2284              : 
    2285           32 :     return true;
    2286              : }
    2287              : 
    2288            6 : bool libspdm_verify_certificate_chain_buffer_ex(uint32_t base_hash_algo, uint32_t base_asym_algo,
    2289              :                                                 const void *cert_chain_buffer,
    2290              :                                                 size_t cert_chain_buffer_size,
    2291              :                                                 bool is_requester_cert, uint8_t cert_model)
    2292              : {
    2293            6 :     return libspdm_verify_certificate_chain_buffer_with_pqc (
    2294              :         base_hash_algo, base_asym_algo, 0,
    2295              :         cert_chain_buffer, cert_chain_buffer_size,
    2296              :         is_requester_cert, cert_model);
    2297              : }
    2298              : 
    2299            0 : bool libspdm_verify_certificate_chain_buffer(uint32_t base_hash_algo, uint32_t base_asym_algo,
    2300              :                                              const void *cert_chain_buffer,
    2301              :                                              size_t cert_chain_buffer_size,
    2302              :                                              bool is_requester_cert,
    2303              :                                              bool is_device_cert_model)
    2304              : {
    2305              :     const uint8_t *cert_chain_data;
    2306              :     size_t cert_chain_data_size;
    2307              :     const uint8_t *first_cert_buffer;
    2308              :     size_t first_cert_buffer_size;
    2309              :     size_t hash_size;
    2310              :     uint8_t calc_root_cert_hash[LIBSPDM_MAX_HASH_SIZE];
    2311              :     const uint8_t *leaf_cert_buffer;
    2312              :     size_t leaf_cert_buffer_size;
    2313              :     bool result;
    2314              :     const spdm_cert_chain_t *cert_chain_header;
    2315              : 
    2316            0 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    2317              : 
    2318            0 :     if (cert_chain_buffer_size <= sizeof(spdm_cert_chain_t) + hash_size) {
    2319            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2320              :                        "!!! VerifyCertificateChainBuffer - FAIL (buffer too small) !!!\n"));
    2321            0 :         return false;
    2322              :     }
    2323              : 
    2324            0 :     cert_chain_header = cert_chain_buffer;
    2325            0 :     if (cert_chain_header->length != cert_chain_buffer_size) {
    2326            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2327              :                        "!!! VerifyCertificateChainBuffer - FAIL (cert_chain->length mismatch) !!!\n"));
    2328            0 :         return false;
    2329              :     }
    2330              : 
    2331            0 :     cert_chain_data = (const uint8_t *)cert_chain_buffer + sizeof(spdm_cert_chain_t) + hash_size;
    2332            0 :     cert_chain_data_size = cert_chain_buffer_size - sizeof(spdm_cert_chain_t) - hash_size;
    2333            0 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2334              :             cert_chain_data, cert_chain_data_size, 0, &first_cert_buffer,
    2335              :             &first_cert_buffer_size)) {
    2336            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2337              :                        "!!! VerifyCertificateChainBuffer - FAIL (get root certificate failed)!!!\n"));
    2338            0 :         return false;
    2339              :     }
    2340              : 
    2341            0 :     if (libspdm_is_root_certificate(first_cert_buffer, first_cert_buffer_size)) {
    2342            0 :         result = libspdm_hash_all(base_hash_algo, first_cert_buffer, first_cert_buffer_size,
    2343              :                                   calc_root_cert_hash);
    2344            0 :         if (!result) {
    2345            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2346              :                            "!!! VerifyCertificateChainBuffer - FAIL (hash calculation fail) !!!\n"));
    2347            0 :             return false;
    2348              :         }
    2349            0 :         if (!libspdm_consttime_is_mem_equal((const uint8_t *)cert_chain_buffer +
    2350              :                                             sizeof(spdm_cert_chain_t),
    2351              :                                             calc_root_cert_hash, hash_size)) {
    2352            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2353              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert root hash mismatch) !!!\n"));
    2354            0 :             return false;
    2355              :         }
    2356            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2357              :                        "!!! VerifyCertificateChainBuffer - PASS (cert root hash match) !!!\n"));
    2358              :     }
    2359              : 
    2360              :     /*If the number of certificates in the certificate chain is more than 1,
    2361              :      * other certificates need to be verified.*/
    2362            0 :     if (cert_chain_data_size > first_cert_buffer_size) {
    2363            0 :         if (!libspdm_x509_verify_cert_chain(first_cert_buffer, first_cert_buffer_size,
    2364              :                                             cert_chain_data + first_cert_buffer_size,
    2365              :                                             cert_chain_data_size - first_cert_buffer_size)) {
    2366            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2367              :                            "!!! VerifyCertificateChainBuffer - FAIL (cert chain verify failed)!!!\n"));
    2368            0 :             return false;
    2369              :         }
    2370              :     }
    2371              : 
    2372            0 :     if (!libspdm_x509_get_cert_from_cert_chain(
    2373              :             cert_chain_data, cert_chain_data_size, -1,
    2374              :             &leaf_cert_buffer, &leaf_cert_buffer_size)) {
    2375            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2376              :                        "!!! VerifyCertificateChainBuffer - FAIL (get leaf certificate failed)!!!\n"));
    2377            0 :         return false;
    2378              :     }
    2379              : 
    2380            0 :     if (!libspdm_x509_certificate_check(leaf_cert_buffer, leaf_cert_buffer_size,
    2381              :                                         base_asym_algo, base_hash_algo,
    2382              :                                         is_requester_cert, is_device_cert_model)) {
    2383            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
    2384              :                        "!!! VerifyCertificateChainBuffer - FAIL (leaf certificate check failed)!!!\n"));
    2385            0 :         return false;
    2386              :     }
    2387              : 
    2388            0 :     return true;
    2389              : }
    2390              : 
    2391          256 : bool libspdm_get_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
    2392              :                                                       uint32_t base_asym_alg,
    2393              :                                                       uint8_t *cert_chain_data,
    2394              :                                                       size_t cert_chain_data_size,
    2395              :                                                       void **public_key)
    2396              : {
    2397              :     size_t hash_size;
    2398              :     const uint8_t *cert_buffer;
    2399              :     size_t cert_buffer_size;
    2400              :     bool result;
    2401              : 
    2402          256 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    2403              : 
    2404          256 :     cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
    2405          256 :     cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
    2406              : 
    2407              :     /* Get leaf cert from cert chain */
    2408          256 :     result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
    2409              :                                                    cert_chain_data_size, -1,
    2410              :                                                    &cert_buffer, &cert_buffer_size);
    2411          256 :     if (!result) {
    2412            0 :         return false;
    2413              :     }
    2414              : 
    2415          256 :     result = libspdm_asym_get_public_key_from_x509(
    2416              :         base_asym_alg,
    2417              :         cert_buffer, cert_buffer_size, public_key);
    2418          256 :     if (!result) {
    2419            4 :         return false;
    2420              :     }
    2421              : 
    2422          252 :     return true;
    2423              : }
    2424              : 
    2425              : /**
    2426              :  * Retrieve the asymmetric public key from one DER-encoded X509 certificate,
    2427              :  * based upon negotiated asymmetric or requester asymmetric algorithm.
    2428              :  *
    2429              :  * @param  base_hash_algo        SPDM base_hash_algo.
    2430              :  * @param  pqc_asym_alg          SPDM pqc_asym_algo or req_pqc_asym_alg.
    2431              :  * @param  cert_chain_data       Certificate chain data with spdm_cert_chain_t header.
    2432              :  * @param  cert_chain_data_size  Size in bytes of the certificate chain data.
    2433              :  * @param  public_key            Pointer to newly generated asymmetric context which contain the
    2434              :  *                               retrieved public key component.
    2435              :  *
    2436              :  * @retval  true   Public key was retrieved successfully.
    2437              :  * @retval  false  Fail to retrieve public key from X509 certificate.
    2438              :  **/
    2439            0 : bool libspdm_get_pqc_leaf_cert_public_key_from_cert_chain(uint32_t base_hash_algo,
    2440              :                                                           uint32_t pqc_asym_alg,
    2441              :                                                           uint8_t *cert_chain_data,
    2442              :                                                           size_t cert_chain_data_size,
    2443              :                                                           void **public_key)
    2444              : {
    2445              :     size_t hash_size;
    2446              :     const uint8_t *cert_buffer;
    2447              :     size_t cert_buffer_size;
    2448              :     bool result;
    2449              : 
    2450            0 :     hash_size = libspdm_get_hash_size(base_hash_algo);
    2451              : 
    2452            0 :     cert_chain_data = cert_chain_data + sizeof(spdm_cert_chain_t) + hash_size;
    2453            0 :     cert_chain_data_size = cert_chain_data_size - (sizeof(spdm_cert_chain_t) + hash_size);
    2454              : 
    2455              :     /* Get leaf cert from cert chain */
    2456            0 :     result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data,
    2457              :                                                    cert_chain_data_size, -1,
    2458              :                                                    &cert_buffer, &cert_buffer_size);
    2459            0 :     if (!result) {
    2460            0 :         return false;
    2461              :     }
    2462              : 
    2463            0 :     result = libspdm_pqc_asym_get_public_key_from_x509(
    2464              :         pqc_asym_alg,
    2465              :         cert_buffer, cert_buffer_size, public_key);
    2466            0 :     if (!result) {
    2467            0 :         return false;
    2468              :     }
    2469              : 
    2470            0 :     return true;
    2471              : }
    2472              : 
    2473           29 : bool libspdm_verify_req_info(uint8_t *req_info, uint16_t req_info_len)
    2474              : {
    2475              :     bool ret;
    2476              :     uint8_t *ptr;
    2477              :     int32_t length;
    2478              :     size_t obj_len;
    2479              :     uint8_t *end;
    2480              : 
    2481           29 :     length = (int32_t)req_info_len;
    2482           29 :     ptr = req_info;
    2483           29 :     obj_len = 0;
    2484           29 :     end = ptr + length;
    2485           29 :     ret = true;
    2486              : 
    2487           29 :     if (req_info_len == 0) {
    2488            4 :         return true;
    2489              :     }
    2490              : 
    2491              :     /*req_info sequence*/
    2492           25 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2493              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2494           25 :     if (!ret) {
    2495            2 :         return false;
    2496              :     }
    2497              : 
    2498              :     /*integer:version*/
    2499           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len, LIBSPDM_CRYPTO_ASN1_INTEGER);
    2500           23 :     if (!ret) {
    2501            0 :         return false;
    2502              :     } else {
    2503           23 :         ptr += obj_len;
    2504              :     }
    2505              : 
    2506              :     /*sequence:subject name*/
    2507           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2508              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2509           23 :     if (!ret) {
    2510            0 :         return false;
    2511              :     } else {
    2512           23 :         ptr += obj_len;
    2513              :     }
    2514              : 
    2515              :     /*sequence:subject pkinfo*/
    2516           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2517              :                                LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2518           23 :     if (!ret) {
    2519            0 :         return false;
    2520              :     } else {
    2521           23 :         ptr += obj_len;
    2522              :     }
    2523              : 
    2524              :     /*[0]: attributes*/
    2525           23 :     ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2526              :                                LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC |
    2527              :                                LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2528              :     /*req_info format error, don't have attributes tag*/
    2529           23 :     if (!ret) {
    2530            0 :         return false;
    2531              :     }
    2532              : 
    2533              :     /*there is no attributes object*/
    2534           23 :     if (ptr == end) {
    2535            0 :         return true;
    2536              :     }
    2537              : 
    2538              :     /*there is some attributes object: 0,1,2 ...*/
    2539           46 :     while (ret)
    2540              :     {
    2541           46 :         ret = libspdm_asn1_get_tag(&ptr, end, &obj_len,
    2542              :                                    LIBSPDM_CRYPTO_ASN1_SEQUENCE |
    2543              :                                    LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
    2544           46 :         if (ret) {
    2545           23 :             ptr += obj_len;
    2546              :         } else {
    2547           23 :             break;
    2548              :         }
    2549              :     }
    2550              : 
    2551           23 :     if (ptr == end) {
    2552           23 :         return true;
    2553              :     } else {
    2554            0 :         return false;
    2555              :     }
    2556              : }
    2557              : 
    2558              : #endif
        

Generated by: LCOV version 2.0-1