Code coverage report for DMTF/libspdm
Current view: top level - library/spdm_crypt_lib - libspdm_crypt_cert.c (source / functions) Coverage Total Hit
Test: 7d53225164c4aa249b863da608f94d42383fed1c Lines: 79.9 % 785 627
Test Date: 2026-11-15 08:32:33 Functions: 100.0 % 25 25
Branches: 72.4 % 417 302

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

Generated by: LCOV version 2.0-1