LCOV - code coverage report
Current view: top level - library/spdm_crypt_lib - libspdm_crypt_cert.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 60.3 % 728 439
Test Date: 2026-01-18 08:10:21 Functions: 87.5 % 24 21

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

Generated by: LCOV version 2.0-1