LCOV - code coverage report
Current view: top level - crypto - CHIPCryptoPALOpenSSL.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 1214 1229 98.8 %
Date: 2024-02-15 08:20:41 Functions: 74 75 98.7 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020-2023 Project CHIP Authors
       4             :  *
       5             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6             :  *    you may not use this file except in compliance with the License.
       7             :  *    You may obtain a copy of the License at
       8             :  *
       9             :  *        http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  *    Unless required by applicable law or agreed to in writing, software
      12             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  *    See the License for the specific language governing permissions and
      15             :  *    limitations under the License.
      16             :  */
      17             : 
      18             : /**
      19             :  *    @file
      20             :  *      openSSL based implementation of CHIP crypto primitives
      21             :  */
      22             : 
      23             : #include "CHIPCryptoPAL.h"
      24             : 
      25             : #include <type_traits>
      26             : 
      27             : #if CHIP_CRYPTO_BORINGSSL
      28             : #include <openssl/aead.h>
      29             : #endif // CHIP_CRYPTO_BORINGSSL
      30             : 
      31             : #include <openssl/bn.h>
      32             : #include <openssl/conf.h>
      33             : #include <openssl/ec.h>
      34             : #include <openssl/ecdsa.h>
      35             : #include <openssl/err.h>
      36             : #include <openssl/evp.h>
      37             : #include <openssl/hmac.h>
      38             : #include <openssl/kdf.h>
      39             : #include <openssl/ossl_typ.h>
      40             : #include <openssl/pem.h>
      41             : #include <openssl/rand.h>
      42             : #include <openssl/sha.h>
      43             : #include <openssl/x509.h>
      44             : #include <openssl/x509v3.h>
      45             : 
      46             : #include <lib/asn1/ASN1.h>
      47             : #include <lib/core/CHIPSafeCasts.h>
      48             : #include <lib/support/BufferWriter.h>
      49             : #include <lib/support/BytesToHex.h>
      50             : #include <lib/support/CHIPArgParser.hpp>
      51             : #include <lib/support/CodeUtils.h>
      52             : #include <lib/support/SafeInt.h>
      53             : #include <lib/support/SafePointerCast.h>
      54             : #include <lib/support/logging/CHIPLogging.h>
      55             : 
      56             : #include <string.h>
      57             : 
      58             : namespace chip {
      59             : namespace Crypto {
      60             : 
      61             : // BoringSSL is designed to implement the same interface as OpenSSL in most
      62             : // cases. However, it removes some APIs that can allow very weak configuration.
      63             : // (Example: CCM ciphers with low tag lengths.) In order to support Matter,
      64             : // a more specific inteface is required.
      65             : #if CHIP_CRYPTO_BORINGSSL
      66             : #define RAND_priv_bytes RAND_bytes
      67             : #define BN_CTX_secure_new BN_CTX_new
      68             : #define EC_GROUP_clear_free EC_GROUP_free
      69             : using boringssl_size_t_openssl_int = size_t;
      70             : using boringssl_uint_openssl_int   = unsigned int;
      71             : using libssl_err_type              = uint32_t;
      72             : #else
      73             : using boringssl_size_t_openssl_int = int;
      74             : using boringssl_uint_openssl_int   = int;
      75             : using libssl_err_type              = unsigned long;
      76             : #endif // CHIP_CRYPTO_BORINGSSL
      77             : 
      78             : #define kKeyLengthInBits 256
      79             : 
      80             : typedef struct stack_st_X509 X509_LIST;
      81             : 
      82             : enum class DigestType
      83             : {
      84             :     SHA256
      85             : };
      86             : 
      87             : enum class ECName
      88             : {
      89             :     None   = 0,
      90             :     P256v1 = 1,
      91             : };
      92             : 
      93        3625 : static int _nidForCurve(ECName name)
      94             : {
      95        3625 :     switch (name)
      96             :     {
      97        3625 :     case ECName::P256v1:
      98        3625 :         return EC_curve_nist2nid("P-256");
      99             :         break;
     100             : 
     101           0 :     default:
     102           0 :         return NID_undef;
     103             :         break;
     104             :     }
     105             : }
     106             : 
     107        4043 : static void _logSSLError()
     108             : {
     109        4043 :     unsigned long ssl_err_code = ERR_get_error();
     110        4046 :     while (ssl_err_code != 0)
     111             :     {
     112             : #if CHIP_ERROR_LOGGING
     113           3 :         const char * err_str_lib     = ERR_lib_error_string(static_cast<libssl_err_type>(ssl_err_code));
     114           3 :         const char * err_str_routine = ERR_func_error_string(static_cast<libssl_err_type>(ssl_err_code));
     115           3 :         const char * err_str_reason  = ERR_reason_error_string(static_cast<libssl_err_type>(ssl_err_code));
     116           3 :         if (err_str_lib)
     117             :         {
     118           3 :             ChipLogError(Crypto, " ssl err  %s %s %s\n", StringOrNullMarker(err_str_lib), StringOrNullMarker(err_str_routine),
     119             :                          StringOrNullMarker(err_str_reason));
     120             :         }
     121             : #endif // CHIP_ERROR_LOGGING
     122           3 :         ssl_err_code = ERR_get_error();
     123             :     }
     124        4043 : }
     125             : 
     126          11 : static const EVP_MD * _digestForType(DigestType digestType)
     127             : {
     128          11 :     switch (digestType)
     129             :     {
     130          11 :     case DigestType::SHA256:
     131          11 :         return EVP_sha256();
     132             :         break;
     133             : 
     134           0 :     default:
     135           0 :         return nullptr;
     136             :         break;
     137             :     }
     138             : }
     139             : 
     140          20 : static int _compareDaysAndSeconds(const int days, const int seconds)
     141             : {
     142          20 :     if (days > 0 || seconds > 0)
     143           3 :         return 1;
     144          17 :     if (days < 0 || seconds < 0)
     145          11 :         return -1;
     146           6 :     return 0;
     147             : }
     148             : 
     149        9627 : CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
     150             :                            const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
     151             :                            uint8_t * tag, size_t tag_length)
     152             : {
     153             : #if CHIP_CRYPTO_BORINGSSL
     154             :     EVP_AEAD_CTX * context = nullptr;
     155             :     size_t written_tag_len = 0;
     156             :     const EVP_AEAD * aead  = nullptr;
     157             : #else
     158        9627 :     EVP_CIPHER_CTX * context = nullptr;
     159        9627 :     int bytesWritten         = 0;
     160        9627 :     size_t ciphertext_length = 0;
     161        9627 :     const EVP_CIPHER * type  = nullptr;
     162             : #endif
     163        9627 :     CHIP_ERROR error = CHIP_NO_ERROR;
     164        9627 :     int result       = 1;
     165             : 
     166             :     // Placeholder location for avoiding null params for plaintexts when
     167             :     // size is zero.
     168        9627 :     uint8_t placeholder_empty_plaintext = 0;
     169             : 
     170             :     // Ciphertext block to hold a finalized ciphertext block if output
     171             :     // `ciphertext` buffer is nullptr or plaintext_length is zero (i.e.
     172             :     // we are only doing auth and don't care about output).
     173             :     uint8_t placeholder_ciphertext[kAES_CCM128_Block_Length];
     174        9627 :     bool ciphertext_was_null = (ciphertext == nullptr);
     175             : 
     176        9627 :     if (plaintext_length == 0)
     177             :     {
     178           4 :         if (plaintext == nullptr)
     179             :         {
     180           4 :             plaintext = &placeholder_empty_plaintext;
     181             :         }
     182             :         // Make sure we have at least 1 full block size buffer for the
     183             :         // extraction of final block (required by OpenSSL EVP_EncryptFinal_ex)
     184           4 :         if (ciphertext_was_null)
     185             :         {
     186           4 :             ciphertext = &placeholder_ciphertext[0];
     187             :         }
     188             :     }
     189             : 
     190        9627 :     VerifyOrExit((plaintext_length != 0) || ciphertext_was_null, error = CHIP_ERROR_INVALID_ARGUMENT);
     191        9627 :     VerifyOrExit(plaintext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     192        9627 :     VerifyOrExit(ciphertext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     193        9627 :     VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     194        9627 :     VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     195        9626 :     VerifyOrExit(CanCastTo<int>(nonce_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     196        9626 :     VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     197             : #if CHIP_CRYPTO_BORINGSSL
     198             :     VerifyOrExit(tag_length == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, error = CHIP_ERROR_INVALID_ARGUMENT);
     199             : #else
     200        9626 :     VerifyOrExit(tag_length == 8 || tag_length == 12 || tag_length == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES,
     201             :                               error = CHIP_ERROR_INVALID_ARGUMENT);
     202             : #endif // CHIP_CRYPTO_BORINGSSL
     203             : 
     204             : #if CHIP_CRYPTO_BORINGSSL
     205             :     aead = EVP_aead_aes_128_ccm_matter();
     206             : 
     207             :     context = EVP_AEAD_CTX_new(aead, key.As<Symmetric128BitsKeyByteArray>(), sizeof(Symmetric128BitsKeyByteArray), tag_length);
     208             :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
     209             : 
     210             :     result = EVP_AEAD_CTX_seal_scatter(context, ciphertext, tag, &written_tag_len, tag_length, nonce, nonce_length, plaintext,
     211             :                                        plaintext_length, nullptr, 0, aad, aad_length);
     212             :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     213             :     VerifyOrExit(written_tag_len == tag_length, error = CHIP_ERROR_INTERNAL);
     214             : #else
     215             : 
     216        9625 :     type = EVP_aes_128_ccm();
     217             : 
     218        9625 :     context = EVP_CIPHER_CTX_new();
     219        9625 :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
     220             : 
     221             :     // Pass in cipher
     222        9625 :     result = EVP_EncryptInit_ex(context, type, nullptr, nullptr, nullptr);
     223        9625 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     224             : 
     225             :     // Pass in nonce length.  Cast is safe because we checked with CanCastTo.
     226        9625 :     result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_IVLEN, static_cast<int>(nonce_length), nullptr);
     227        9625 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     228             : 
     229             :     // Pass in tag length. Cast is safe because we checked against CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES.
     230        9625 :     result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_TAG, static_cast<int>(tag_length), nullptr);
     231        9625 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     232             : 
     233             :     // Pass in key + nonce
     234             :     static_assert(kAES_CCM128_Key_Length == sizeof(Symmetric128BitsKeyByteArray), "Unexpected key length");
     235        9625 :     result = EVP_EncryptInit_ex(context, nullptr, nullptr, key.As<Symmetric128BitsKeyByteArray>(), Uint8::to_const_uchar(nonce));
     236        9625 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     237             : 
     238             :     // Pass in plain text length
     239        9625 :     VerifyOrExit(CanCastTo<int>(plaintext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     240        9625 :     result = EVP_EncryptUpdate(context, nullptr, &bytesWritten, nullptr, static_cast<int>(plaintext_length));
     241        9625 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     242             : 
     243             :     // Pass in AAD
     244        9625 :     if (aad_length > 0 && aad != nullptr)
     245             :     {
     246        9528 :         VerifyOrExit(CanCastTo<int>(aad_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     247        9528 :         result = EVP_EncryptUpdate(context, nullptr, &bytesWritten, Uint8::to_const_uchar(aad), static_cast<int>(aad_length));
     248        9528 :         VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     249             :     }
     250             : 
     251             :     // Encrypt
     252        9625 :     VerifyOrExit(CanCastTo<int>(plaintext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     253        9625 :     result = EVP_EncryptUpdate(context, Uint8::to_uchar(ciphertext), &bytesWritten, Uint8::to_const_uchar(plaintext),
     254             :                                             static_cast<int>(plaintext_length));
     255        9625 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     256        9625 :     VerifyOrExit((ciphertext_was_null && bytesWritten == 0) || (bytesWritten >= 0), error = CHIP_ERROR_INTERNAL);
     257        9625 :     ciphertext_length = static_cast<unsigned int>(bytesWritten);
     258             : 
     259             :     // Finalize encryption
     260        9625 :     result = EVP_EncryptFinal_ex(context, ciphertext + ciphertext_length, &bytesWritten);
     261        9625 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     262        9625 :     VerifyOrExit(bytesWritten >= 0 && bytesWritten <= static_cast<int>(plaintext_length), error = CHIP_ERROR_INTERNAL);
     263             : 
     264             :     // Get tag
     265        9625 :     VerifyOrExit(CanCastTo<int>(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     266        9625 :     result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_GET_TAG, static_cast<int>(tag_length), Uint8::to_uchar(tag));
     267        9625 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     268             : #endif // CHIP_CRYPTO_BORINGSSL
     269             : 
     270        9627 : exit:
     271        9627 :     if (context != nullptr)
     272             :     {
     273             : #if CHIP_CRYPTO_BORINGSSL
     274             :         EVP_AEAD_CTX_free(context);
     275             : #else
     276        9625 :         EVP_CIPHER_CTX_free(context);
     277             : #endif // CHIP_CRYPTO_BORINGSSL
     278        9625 :         context = nullptr;
     279             :     }
     280             : 
     281        9627 :     return error;
     282             : }
     283             : 
     284        9484 : CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, const uint8_t * aad, size_t aad_length,
     285             :                            const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce,
     286             :                            size_t nonce_length, uint8_t * plaintext)
     287             : {
     288             : #if CHIP_CRYPTO_BORINGSSL
     289             :     EVP_AEAD_CTX * context = nullptr;
     290             :     const EVP_AEAD * aead  = nullptr;
     291             : #else
     292             : 
     293        9484 :     EVP_CIPHER_CTX * context = nullptr;
     294        9484 :     int bytesOutput          = 0;
     295        9484 :     const EVP_CIPHER * type  = nullptr;
     296             : #endif // CHIP_CRYPTO_BORINGSSL
     297        9484 :     CHIP_ERROR error = CHIP_NO_ERROR;
     298        9484 :     int result       = 1;
     299             : 
     300             :     // Placeholder location for avoiding null params for ciphertext when
     301             :     // size is zero.
     302        9484 :     uint8_t placeholder_empty_ciphertext = 0;
     303             : 
     304             :     // Plaintext block to hold a finalized plaintext block if output
     305             :     // `plaintext` buffer is nullptr or ciphertext_length is zero (i.e.
     306             :     // we are only doing auth and don't care about output).
     307             :     uint8_t placeholder_plaintext[kAES_CCM128_Block_Length];
     308        9484 :     bool plaintext_was_null = (plaintext == nullptr);
     309             : 
     310        9484 :     if (ciphertext_length == 0)
     311             :     {
     312           3 :         if (ciphertext == nullptr)
     313             :         {
     314           3 :             ciphertext = &placeholder_empty_ciphertext;
     315             :         }
     316             :         // Make sure we have at least 1 full block size buffer for the
     317             :         // extraction of final block (required by OpenSSL EVP_DecryptFinal_ex)
     318           3 :         if (plaintext_was_null)
     319             :         {
     320           3 :             plaintext = &placeholder_plaintext[0];
     321             :         }
     322             :     }
     323             : 
     324        9484 :     VerifyOrExit(ciphertext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     325        9484 :     VerifyOrExit(plaintext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     326        9484 :     VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     327             : #if CHIP_CRYPTO_BORINGSSL
     328             :     VerifyOrExit(tag_length == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, error = CHIP_ERROR_INVALID_ARGUMENT);
     329             : #else
     330        9484 :     VerifyOrExit(tag_length == 8 || tag_length == 12 || tag_length == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES,
     331             :                               error = CHIP_ERROR_INVALID_ARGUMENT);
     332             : #endif // CHIP_CRYPTO_BORINGSSL
     333        9484 :     VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     334        9484 :     VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     335             : 
     336             : #if CHIP_CRYPTO_BORINGSSL
     337             :     aead = EVP_aead_aes_128_ccm_matter();
     338             : 
     339             :     context = EVP_AEAD_CTX_new(aead, key.As<Symmetric128BitsKeyByteArray>(), sizeof(Symmetric128BitsKeyByteArray), tag_length);
     340             :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
     341             : 
     342             :     result = EVP_AEAD_CTX_open_gather(context, plaintext, nonce, nonce_length, ciphertext, ciphertext_length, tag, tag_length, aad,
     343             :                                       aad_length);
     344             :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     345             : #else
     346        9483 :     type = EVP_aes_128_ccm();
     347             : 
     348        9483 :     context = EVP_CIPHER_CTX_new();
     349        9483 :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
     350             : 
     351             :     // Pass in cipher
     352        9483 :     result = EVP_DecryptInit_ex(context, type, nullptr, nullptr, nullptr);
     353        9483 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     354             : 
     355             :     // Pass in nonce length
     356        9483 :     VerifyOrExit(CanCastTo<int>(nonce_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     357        9483 :     result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_IVLEN, static_cast<int>(nonce_length), nullptr);
     358        9483 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     359             : 
     360             :     // Pass in expected tag
     361             :     // Removing "const" from |tag| here should hopefully be safe as
     362             :     // we're writing the tag, not reading.
     363        9483 :     VerifyOrExit(CanCastTo<int>(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     364        9483 :     result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_TAG, static_cast<int>(tag_length),
     365             :                                               const_cast<void *>(static_cast<const void *>(tag)));
     366        9483 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     367             : 
     368             :     // Pass in key + nonce
     369             :     static_assert(kAES_CCM128_Key_Length == sizeof(Symmetric128BitsKeyByteArray), "Unexpected key length");
     370        9483 :     result = EVP_DecryptInit_ex(context, nullptr, nullptr, key.As<Symmetric128BitsKeyByteArray>(), Uint8::to_const_uchar(nonce));
     371        9483 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     372             : 
     373             :     // Pass in cipher text length
     374        9483 :     VerifyOrExit(CanCastTo<int>(ciphertext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     375        9483 :     result = EVP_DecryptUpdate(context, nullptr, &bytesOutput, nullptr, static_cast<int>(ciphertext_length));
     376        9483 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     377        9483 :     VerifyOrExit(bytesOutput <= static_cast<int>(ciphertext_length), error = CHIP_ERROR_INTERNAL);
     378             : 
     379             :     // Pass in aad
     380        9483 :     if (aad_length > 0 && aad != nullptr)
     381             :     {
     382        9420 :         VerifyOrExit(CanCastTo<int>(aad_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     383        9420 :         result = EVP_DecryptUpdate(context, nullptr, &bytesOutput, Uint8::to_const_uchar(aad), static_cast<int>(aad_length));
     384        9420 :         VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     385        9420 :         VerifyOrExit(bytesOutput <= static_cast<int>(aad_length), error = CHIP_ERROR_INTERNAL);
     386             :     }
     387             : 
     388             :     // Pass in ciphertext. We wont get anything if validation fails.
     389        9483 :     VerifyOrExit(CanCastTo<int>(ciphertext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     390        9483 :     result = EVP_DecryptUpdate(context, Uint8::to_uchar(plaintext), &bytesOutput, Uint8::to_const_uchar(ciphertext),
     391             :                                             static_cast<int>(ciphertext_length));
     392        9483 :     if (plaintext_was_null)
     393             :     {
     394           3 :         VerifyOrExit(bytesOutput <= static_cast<int>(sizeof(placeholder_plaintext)), error = CHIP_ERROR_INTERNAL);
     395             :     }
     396        9483 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     397             : #endif // CHIP_CRYPTO_BORINGSSL
     398             : 
     399        9484 : exit:
     400        9484 :     if (context != nullptr)
     401             :     {
     402             : #if CHIP_CRYPTO_BORINGSSL
     403             :         EVP_AEAD_CTX_free(context);
     404             : #else
     405        9483 :         EVP_CIPHER_CTX_free(context);
     406             : #endif // CHIP_CRYPTO_BORINGSSL
     407             : 
     408        9483 :         context = nullptr;
     409             :     }
     410             : 
     411        9484 :     return error;
     412             : }
     413             : 
     414        3897 : CHIP_ERROR Hash_SHA256(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
     415             : {
     416             :     // zero data length hash is supported.
     417        3897 :     VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     418        3897 :     VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     419             : 
     420        3897 :     SHA256(data, data_length, Uint8::to_uchar(out_buffer));
     421             : 
     422        3897 :     return CHIP_NO_ERROR;
     423             : }
     424             : 
     425         284 : CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
     426             : {
     427             :     // zero data length hash is supported.
     428         284 :     VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     429         284 :     VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     430             : 
     431         284 :     SHA1(data, data_length, Uint8::to_uchar(out_buffer));
     432             : 
     433         284 :     return CHIP_NO_ERROR;
     434             : }
     435             : 
     436        1326 : Hash_SHA256_stream::Hash_SHA256_stream() {}
     437             : 
     438        1326 : Hash_SHA256_stream::~Hash_SHA256_stream()
     439             : {
     440        1326 :     Clear();
     441        1326 : }
     442             : 
     443             : static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(SHA256_CTX),
     444             :               "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying SHA256_CTX");
     445             : 
     446        9528 : static inline SHA256_CTX * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context)
     447             : {
     448        9528 :     return SafePointerCast<SHA256_CTX *>(context);
     449             : }
     450             : 
     451        1328 : CHIP_ERROR Hash_SHA256_stream::Begin()
     452             : {
     453        1328 :     SHA256_CTX * const context = to_inner_hash_sha256_context(&mContext);
     454             : 
     455        1328 :     const int result = SHA256_Init(context);
     456        1328 :     VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
     457             : 
     458        1328 :     return CHIP_NO_ERROR;
     459             : }
     460             : 
     461        2868 : CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data)
     462             : {
     463        2868 :     SHA256_CTX * const context = to_inner_hash_sha256_context(&mContext);
     464             : 
     465        2868 :     const int result = SHA256_Update(context, Uint8::to_const_uchar(data.data()), data.size());
     466        2868 :     VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
     467             : 
     468        2868 :     return CHIP_NO_ERROR;
     469             : }
     470             : 
     471        2079 : CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer)
     472             : {
     473        2079 :     SHA256_CTX * context = to_inner_hash_sha256_context(&mContext);
     474             : 
     475             :     // Back-up context as we are about to finalize the hash to extract digest.
     476        2079 :     SHA256_CTX previous_ctx = *context;
     477             : 
     478             :     // Pad + compute digest, then finalize context. It is restored next line to continue.
     479        2079 :     CHIP_ERROR result = Finish(out_buffer);
     480             : 
     481             :     // Restore context prior to finalization.
     482        2079 :     *context = previous_ctx;
     483             : 
     484        2079 :     return result;
     485             : }
     486             : 
     487        3255 : CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer)
     488             : {
     489        3255 :     VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
     490             : 
     491        3253 :     SHA256_CTX * const context = to_inner_hash_sha256_context(&mContext);
     492        3253 :     const int result           = SHA256_Final(Uint8::to_uchar(out_buffer.data()), context);
     493        3253 :     VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
     494        3253 :     out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length);
     495             : 
     496        3253 :     return CHIP_NO_ERROR;
     497             : }
     498             : 
     499        1489 : void Hash_SHA256_stream::Clear()
     500             : {
     501        1489 :     OPENSSL_cleanse(this, sizeof(*this));
     502        1489 : }
     503             : 
     504        3479 : CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length,
     505             :                                  const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length)
     506             : {
     507        3479 :     CHIP_ERROR error = CHIP_NO_ERROR;
     508        3479 :     int result       = 1;
     509             : 
     510        3479 :     EVP_PKEY_CTX * const context = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
     511        3479 :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_INTERNAL);
     512             : 
     513        3479 :     VerifyOrExit(secret != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     514        3479 :     VerifyOrExit(secret_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     515             : 
     516             :     // Salt is optional
     517        3479 :     if (salt_length > 0)
     518             :     {
     519         945 :         VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     520             :     }
     521             : 
     522        3479 :     VerifyOrExit(info_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     523        3479 :     VerifyOrExit(info != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     524        3479 :     VerifyOrExit(out_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     525        3479 :     VerifyOrExit(out_buffer != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     526             : 
     527        3479 :     result = EVP_PKEY_derive_init(context);
     528        3479 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     529             : 
     530        3479 :     result = EVP_PKEY_CTX_set_hkdf_md(context, EVP_sha256());
     531        3479 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     532             : 
     533        3479 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(secret_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     534        3479 :     result = EVP_PKEY_CTX_set1_hkdf_key(context, Uint8::to_const_uchar(secret),
     535             :                                         static_cast<boringssl_size_t_openssl_int>(secret_length));
     536        3479 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     537             : 
     538        3479 :     if (salt_length > 0 && salt != nullptr)
     539             :     {
     540         945 :         VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(salt_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     541         945 :         result = EVP_PKEY_CTX_set1_hkdf_salt(context, Uint8::to_const_uchar(salt),
     542             :                                              static_cast<boringssl_size_t_openssl_int>(salt_length));
     543         945 :         VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     544             :     }
     545             : 
     546        3479 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(info_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     547             :     result =
     548        3479 :         EVP_PKEY_CTX_add1_hkdf_info(context, Uint8::to_const_uchar(info), static_cast<boringssl_size_t_openssl_int>(info_length));
     549        3479 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     550             : 
     551        3479 :     result = EVP_PKEY_CTX_hkdf_mode(context, EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND);
     552        3479 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     553             : 
     554             :     // Get the OKM (Output Key Material)
     555        3479 :     result = EVP_PKEY_derive(context, Uint8::to_uchar(out_buffer), &out_length);
     556        3479 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     557             : 
     558        3479 : exit:
     559        3479 :     if (context != nullptr)
     560             :     {
     561        3479 :         EVP_PKEY_CTX_free(context);
     562             :     }
     563        3479 :     return error;
     564             : }
     565             : 
     566          98 : CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length,
     567             :                                  uint8_t * out_buffer, size_t out_length)
     568             : {
     569          98 :     VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     570          98 :     VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
     571          98 :     VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     572          98 :     VerifyOrReturnError(message_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
     573          98 :     VerifyOrReturnError(out_length >= kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
     574          98 :     VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     575             : 
     576          98 :     CHIP_ERROR error         = CHIP_ERROR_INTERNAL;
     577          98 :     int error_openssl        = 0;
     578          98 :     unsigned int mac_out_len = 0;
     579             : 
     580          98 :     HMAC_CTX * mac_ctx = HMAC_CTX_new();
     581          98 :     VerifyOrExit(mac_ctx != nullptr, error = CHIP_ERROR_INTERNAL);
     582             : 
     583          98 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(key_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     584          98 :     error_openssl = HMAC_Init_ex(mac_ctx, Uint8::to_const_uchar(key), static_cast<boringssl_size_t_openssl_int>(key_length),
     585             :                                  EVP_sha256(), nullptr);
     586          98 :     VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
     587             : 
     588          98 :     error_openssl = HMAC_Update(mac_ctx, Uint8::to_const_uchar(message), message_length);
     589          98 :     VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
     590             : 
     591          98 :     mac_out_len   = static_cast<unsigned int>(CHIP_CRYPTO_HASH_LEN_BYTES);
     592          98 :     error_openssl = HMAC_Final(mac_ctx, Uint8::to_uchar(out_buffer), &mac_out_len);
     593          98 :     VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
     594             : 
     595          98 :     error = CHIP_NO_ERROR;
     596          98 : exit:
     597          98 :     HMAC_CTX_free(mac_ctx);
     598          98 :     return error;
     599             : }
     600             : 
     601          25 : CHIP_ERROR HMAC_sha::HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length, uint8_t * out_buffer,
     602             :                                  size_t out_length)
     603             : {
     604          25 :     return HMAC_SHA256(key.As<Symmetric128BitsKeyByteArray>(), sizeof(Symmetric128BitsKeyByteArray), message, message_length,
     605          25 :                        out_buffer, out_length);
     606             : }
     607             : 
     608          16 : CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen,
     609             :                                         unsigned int iteration_count, uint32_t key_length, uint8_t * output)
     610             : {
     611          16 :     CHIP_ERROR error  = CHIP_NO_ERROR;
     612          16 :     int result        = 1;
     613          16 :     const EVP_MD * md = nullptr;
     614             : 
     615          16 :     VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     616          15 :     VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     617          15 :     VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     618          13 :     VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
     619          12 :     VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
     620          11 :     VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     621          11 :     VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     622             : 
     623          11 :     md = _digestForType(DigestType::SHA256);
     624          11 :     VerifyOrExit(md != nullptr, error = CHIP_ERROR_INTERNAL);
     625             : 
     626          11 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(plen), error = CHIP_ERROR_INVALID_ARGUMENT);
     627          11 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(slen), error = CHIP_ERROR_INVALID_ARGUMENT);
     628          11 :     VerifyOrExit(CanCastTo<boringssl_uint_openssl_int>(iteration_count), error = CHIP_ERROR_INVALID_ARGUMENT);
     629          11 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(key_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     630          11 :     result = PKCS5_PBKDF2_HMAC(Uint8::to_const_char(password), static_cast<boringssl_size_t_openssl_int>(plen),
     631             :                                Uint8::to_const_uchar(salt), static_cast<boringssl_size_t_openssl_int>(slen),
     632             :                                static_cast<boringssl_uint_openssl_int>(iteration_count), md,
     633             :                                static_cast<boringssl_size_t_openssl_int>(key_length), Uint8::to_uchar(output));
     634             : 
     635          11 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     636             : 
     637          16 : exit:
     638          16 :     if (error != CHIP_NO_ERROR)
     639             :     {
     640           5 :         _logSSLError();
     641             :     }
     642             : 
     643          16 :     return error;
     644             : }
     645             : 
     646           2 : CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold)
     647             : {
     648           2 :     return CHIP_NO_ERROR;
     649             : }
     650             : 
     651      145765 : CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length)
     652             : {
     653      145765 :     VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     654      145764 :     VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
     655             : 
     656      145763 :     VerifyOrReturnError(CanCastTo<boringssl_size_t_openssl_int>(out_length), CHIP_ERROR_INVALID_ARGUMENT);
     657      145763 :     const int result = RAND_priv_bytes(Uint8::to_uchar(out_buffer), static_cast<boringssl_size_t_openssl_int>(out_length));
     658      145763 :     VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
     659             : 
     660      145763 :     return CHIP_NO_ERROR;
     661             : }
     662             : 
     663        3625 : ECName MapECName(SupportedECPKeyTypes keyType)
     664             : {
     665        3625 :     switch (keyType)
     666             :     {
     667        3625 :     case SupportedECPKeyTypes::ECP256R1:
     668        3625 :         return ECName::P256v1;
     669           0 :     default:
     670           0 :         return ECName::None;
     671             :     }
     672             : }
     673             : 
     674        1506 : static inline void from_EC_KEY(EC_KEY * key, P256KeypairContext * context)
     675             : {
     676        1506 :     *SafePointerCast<EC_KEY **>(context) = key;
     677        1506 : }
     678             : 
     679        1801 : static inline EC_KEY * to_EC_KEY(P256KeypairContext * context)
     680             : {
     681        1801 :     return *SafePointerCast<EC_KEY **>(context);
     682             : }
     683             : 
     684         638 : static inline const EC_KEY * to_const_EC_KEY(const P256KeypairContext * context)
     685             : {
     686         638 :     return *SafePointerCast<const EC_KEY * const *>(context);
     687             : }
     688             : 
     689         272 : CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
     690             : {
     691         272 :     CHIP_ERROR error = CHIP_NO_ERROR;
     692         272 :     int nid          = NID_undef;
     693         272 :     EC_KEY * ec_key  = nullptr;
     694         272 :     ECDSA_SIG * sig  = nullptr;
     695         272 :     const BIGNUM * r = nullptr;
     696         272 :     const BIGNUM * s = nullptr;
     697             : 
     698         272 :     VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
     699             : 
     700             :     uint8_t digest[kSHA256_Hash_Length];
     701         270 :     memset(&digest[0], 0, sizeof(digest));
     702             : 
     703         270 :     ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
     704             : 
     705         270 :     ERR_clear_error();
     706             : 
     707             :     static_assert(P256ECDSASignature::Capacity() >= kP256_ECDSA_Signature_Length_Raw, "P256ECDSASignature must be large enough");
     708         270 :     VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
     709         270 :     nid = _nidForCurve(MapECName(mPublicKey.Type()));
     710         270 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
     711             : 
     712         270 :     ec_key = to_EC_KEY(&mKeypair);
     713         270 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
     714             : 
     715         270 :     sig = ECDSA_do_sign(Uint8::to_const_uchar(&digest[0]), static_cast<boringssl_size_t_openssl_int>(sizeof(digest)), ec_key);
     716         270 :     VerifyOrExit(sig != nullptr, error = CHIP_ERROR_INTERNAL);
     717         270 :     ECDSA_SIG_get0(sig, &r, &s);
     718         270 :     VerifyOrExit((r != nullptr) && (s != nullptr), error = CHIP_ERROR_INTERNAL);
     719         270 :     VerifyOrExit(CanCastTo<size_t>(BN_num_bytes(r)) && CanCastTo<size_t>(BN_num_bytes(s)), error = CHIP_ERROR_INTERNAL);
     720         270 :     VerifyOrExit((static_cast<size_t>(BN_num_bytes(r)) <= kP256_FE_Length) &&
     721             :                      (static_cast<size_t>(BN_num_bytes(s)) <= kP256_FE_Length),
     722             :                  error = CHIP_ERROR_INTERNAL);
     723             : 
     724             :     // Concatenate r and s to output. Sizes were checked above.
     725         270 :     VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
     726         270 :     VerifyOrExit(BN_bn2binpad(r, out_signature.Bytes() + 0u, kP256_FE_Length) == kP256_FE_Length, error = CHIP_ERROR_INTERNAL);
     727         270 :     VerifyOrExit(BN_bn2binpad(s, out_signature.Bytes() + kP256_FE_Length, kP256_FE_Length) == kP256_FE_Length,
     728             :                  error = CHIP_ERROR_INTERNAL);
     729             : 
     730         270 : exit:
     731         270 :     if (sig != nullptr)
     732             :     {
     733             :         // SIG owns the memory of r, s
     734         270 :         ECDSA_SIG_free(sig);
     735             :     }
     736             : 
     737         270 :     if (error != CHIP_NO_ERROR)
     738             :     {
     739           0 :         _logSSLError();
     740             :     }
     741             : 
     742         270 :     return error;
     743             : }
     744             : 
     745         130 : CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length,
     746             :                                                        const P256ECDSASignature & signature) const
     747             : {
     748         130 :     VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
     749             : 
     750             :     uint8_t digest[kSHA256_Hash_Length];
     751         128 :     memset(&digest[0], 0, sizeof(digest));
     752             : 
     753         128 :     ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
     754         128 :     return ECDSA_validate_hash_signature(&digest[0], sizeof(digest), signature);
     755             : }
     756             : 
     757        1668 : CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length,
     758             :                                                         const P256ECDSASignature & signature) const
     759             : {
     760        1668 :     ERR_clear_error();
     761        1668 :     CHIP_ERROR error     = CHIP_ERROR_INTERNAL;
     762        1668 :     int nid              = NID_undef;
     763        1668 :     EC_KEY * ec_key      = nullptr;
     764        1668 :     EC_POINT * key_point = nullptr;
     765        1668 :     EC_GROUP * ec_group  = nullptr;
     766        1668 :     ECDSA_SIG * ec_sig   = nullptr;
     767        1668 :     BIGNUM * r           = nullptr;
     768        1668 :     BIGNUM * s           = nullptr;
     769        1668 :     int result           = 0;
     770             : 
     771        1668 :     VerifyOrExit(hash != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     772        1667 :     VerifyOrExit(hash_length == kSHA256_Hash_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
     773        1666 :     VerifyOrExit(signature.Length() == kP256_ECDSA_Signature_Length_Raw, error = CHIP_ERROR_INVALID_ARGUMENT);
     774             : 
     775        1666 :     nid = _nidForCurve(MapECName(Type()));
     776        1666 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
     777             : 
     778        1666 :     ec_group = EC_GROUP_new_by_curve_name(nid);
     779        1666 :     VerifyOrExit(ec_group != nullptr, error = CHIP_ERROR_NO_MEMORY);
     780             : 
     781        1666 :     key_point = EC_POINT_new(ec_group);
     782        1666 :     VerifyOrExit(key_point != nullptr, error = CHIP_ERROR_NO_MEMORY);
     783             : 
     784        1666 :     result = EC_POINT_oct2point(ec_group, key_point, Uint8::to_const_uchar(*this), Length(), nullptr);
     785        1666 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     786             : 
     787        1666 :     ec_key = EC_KEY_new_by_curve_name(nid);
     788        1666 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_NO_MEMORY);
     789             : 
     790        1666 :     result = EC_KEY_set_public_key(ec_key, key_point);
     791        1666 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     792             : 
     793        1666 :     result = EC_KEY_check_key(ec_key);
     794        1666 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     795             : 
     796             :     // Build-up the signature object from raw <r,s> tuple
     797        1666 :     r = BN_bin2bn(Uint8::to_const_uchar(signature.ConstBytes()) + 0u, kP256_FE_Length, nullptr);
     798        1666 :     VerifyOrExit(r != nullptr, error = CHIP_ERROR_NO_MEMORY);
     799             : 
     800        1666 :     s = BN_bin2bn(Uint8::to_const_uchar(signature.ConstBytes()) + kP256_FE_Length, kP256_FE_Length, nullptr);
     801        1666 :     VerifyOrExit(s != nullptr, error = CHIP_ERROR_NO_MEMORY);
     802             : 
     803        1666 :     ec_sig = ECDSA_SIG_new();
     804        1666 :     VerifyOrExit(ec_sig != nullptr, error = CHIP_ERROR_NO_MEMORY);
     805             : 
     806        1666 :     result = ECDSA_SIG_set0(ec_sig, r, s);
     807        1666 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     808             : 
     809        1666 :     result = ECDSA_do_verify(Uint8::to_const_uchar(hash), static_cast<boringssl_size_t_openssl_int>(hash_length), ec_sig, ec_key);
     810        1666 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INVALID_SIGNATURE);
     811        1656 :     error = CHIP_NO_ERROR;
     812             : 
     813        1668 : exit:
     814        1668 :     _logSSLError();
     815        1668 :     if (ec_sig != nullptr)
     816             :     {
     817        1666 :         ECDSA_SIG_free(ec_sig);
     818             : 
     819             :         // After ECDSA_SIG_set0 succeeds, r and s memory is managed by ECDSA_SIG object.
     820             :         // We set to nullptr so that we don't try to double-free
     821        1666 :         r = nullptr;
     822        1666 :         s = nullptr;
     823             :     }
     824        1668 :     if (s != nullptr)
     825             :     {
     826           0 :         BN_clear_free(s);
     827             :     }
     828        1668 :     if (r != nullptr)
     829             :     {
     830           0 :         BN_clear_free(r);
     831             :     }
     832        1668 :     if (ec_key != nullptr)
     833             :     {
     834        1666 :         EC_KEY_free(ec_key);
     835             :     }
     836        1668 :     if (key_point != nullptr)
     837             :     {
     838        1666 :         EC_POINT_clear_free(key_point);
     839             :     }
     840        1668 :     if (ec_group != nullptr)
     841             :     {
     842        1666 :         EC_GROUP_free(ec_group);
     843             :     }
     844        1668 :     return error;
     845             : }
     846             : 
     847             : // helper function to populate octet key into EVP_PKEY out_evp_pkey. Caller must free out_evp_pkey
     848          22 : static CHIP_ERROR _create_evp_key_from_binary_p256_key(const P256PublicKey & key, EVP_PKEY ** out_evp_pkey)
     849             : {
     850             : 
     851          22 :     CHIP_ERROR error = CHIP_NO_ERROR;
     852          22 :     EC_KEY * ec_key  = nullptr;
     853          22 :     int result       = -1;
     854          22 :     EC_POINT * point = nullptr;
     855          22 :     EC_GROUP * group = nullptr;
     856          22 :     int nid          = NID_undef;
     857             : 
     858          22 :     VerifyOrExit(*out_evp_pkey == nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     859             : 
     860          22 :     nid = _nidForCurve(MapECName(key.Type()));
     861          22 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INTERNAL);
     862             : 
     863          22 :     ec_key = EC_KEY_new_by_curve_name(nid);
     864          22 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
     865             : 
     866          22 :     group = EC_GROUP_new_by_curve_name(nid);
     867          22 :     VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
     868             : 
     869          22 :     point = EC_POINT_new(group);
     870          22 :     VerifyOrExit(point != nullptr, error = CHIP_ERROR_INTERNAL);
     871             : 
     872          22 :     result = EC_POINT_oct2point(group, point, Uint8::to_const_uchar(key), key.Length(), nullptr);
     873          22 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     874             : 
     875          22 :     result = EC_KEY_set_public_key(ec_key, point);
     876             : 
     877          22 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     878             : 
     879          22 :     *out_evp_pkey = EVP_PKEY_new();
     880          22 :     VerifyOrExit(*out_evp_pkey != nullptr, error = CHIP_ERROR_INTERNAL);
     881             : 
     882          22 :     result = EVP_PKEY_set1_EC_KEY(*out_evp_pkey, ec_key);
     883          22 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     884             : 
     885          22 : exit:
     886          22 :     if (ec_key != nullptr)
     887             :     {
     888          22 :         EC_KEY_free(ec_key);
     889          22 :         ec_key = nullptr;
     890             :     }
     891             : 
     892          22 :     if (error != CHIP_NO_ERROR && *out_evp_pkey)
     893             :     {
     894           0 :         EVP_PKEY_free(*out_evp_pkey);
     895           0 :         out_evp_pkey = nullptr;
     896             :     }
     897             : 
     898          22 :     if (point != nullptr)
     899             :     {
     900          22 :         EC_POINT_free(point);
     901          22 :         point = nullptr;
     902             :     }
     903             : 
     904          22 :     if (group != nullptr)
     905             :     {
     906          22 :         EC_GROUP_free(group);
     907          22 :         group = nullptr;
     908             :     }
     909             : 
     910          22 :     return error;
     911             : }
     912             : 
     913          22 : CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
     914             : {
     915          22 :     ERR_clear_error();
     916          22 :     CHIP_ERROR error      = CHIP_NO_ERROR;
     917          22 :     int result            = -1;
     918          22 :     EVP_PKEY * local_key  = nullptr;
     919          22 :     EVP_PKEY * remote_key = nullptr;
     920             : 
     921          22 :     EVP_PKEY_CTX * context = nullptr;
     922          22 :     size_t out_buf_length  = 0;
     923             : 
     924          22 :     EC_KEY * ec_key = EC_KEY_dup(to_const_EC_KEY(&mKeypair));
     925          22 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
     926             : 
     927          22 :     VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
     928             : 
     929          22 :     local_key = EVP_PKEY_new();
     930          22 :     VerifyOrExit(local_key != nullptr, error = CHIP_ERROR_INTERNAL);
     931             : 
     932          22 :     result = EVP_PKEY_set1_EC_KEY(local_key, ec_key);
     933          22 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     934             : 
     935          22 :     error = _create_evp_key_from_binary_p256_key(remote_public_key, &remote_key);
     936          22 :     SuccessOrExit(error);
     937             : 
     938          22 :     context = EVP_PKEY_CTX_new(local_key, nullptr);
     939          22 :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_INTERNAL);
     940             : 
     941          22 :     result = EVP_PKEY_derive_init(context);
     942          22 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     943             : 
     944          22 :     result = EVP_PKEY_derive_set_peer(context, remote_key);
     945          22 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     946             : 
     947          22 :     out_buf_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length();
     948          22 :     result         = EVP_PKEY_derive(context, out_secret.Bytes(), &out_buf_length);
     949          22 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     950          22 :     SuccessOrExit(error = out_secret.SetLength(out_buf_length));
     951             : 
     952          22 : exit:
     953          22 :     if (ec_key != nullptr)
     954             :     {
     955          22 :         EC_KEY_free(ec_key);
     956          22 :         ec_key = nullptr;
     957             :     }
     958             : 
     959          22 :     if (local_key != nullptr)
     960             :     {
     961          22 :         EVP_PKEY_free(local_key);
     962          22 :         local_key = nullptr;
     963             :     }
     964             : 
     965          22 :     if (remote_key != nullptr)
     966             :     {
     967          22 :         EVP_PKEY_free(remote_key);
     968          22 :         remote_key = nullptr;
     969             :     }
     970             : 
     971          22 :     if (context != nullptr)
     972             :     {
     973          22 :         EVP_PKEY_CTX_free(context);
     974          22 :         context = nullptr;
     975             :     }
     976             : 
     977          22 :     _logSSLError();
     978          22 :     return error;
     979             : }
     980             : 
     981      414752 : void ClearSecretData(uint8_t * buf, size_t len)
     982             : {
     983      414752 :     OPENSSL_cleanse(buf, len);
     984      414752 : }
     985             : 
     986         676 : bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n)
     987             : {
     988         676 :     return CRYPTO_memcmp(a, b, n) == 0;
     989             : }
     990             : 
     991         161 : static CHIP_ERROR P256PublicKeyFromECKey(EC_KEY * ec_key, P256PublicKey & pubkey)
     992             : {
     993         161 :     ERR_clear_error();
     994         161 :     CHIP_ERROR error = CHIP_NO_ERROR;
     995             : 
     996         161 :     int nid            = NID_undef;
     997         161 :     ECName curve       = MapECName(pubkey.Type());
     998         161 :     EC_GROUP * group   = nullptr;
     999         161 :     size_t pubkey_size = 0;
    1000             : 
    1001         161 :     const EC_POINT * pubkey_ecp = EC_KEY_get0_public_key(ec_key);
    1002         161 :     VerifyOrExit(pubkey_ecp != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
    1003             : 
    1004         161 :     nid = _nidForCurve(curve);
    1005         161 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
    1006             : 
    1007         161 :     group = EC_GROUP_new_by_curve_name(nid);
    1008         161 :     VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
    1009             : 
    1010             :     pubkey_size =
    1011         161 :         EC_POINT_point2oct(group, pubkey_ecp, POINT_CONVERSION_UNCOMPRESSED, Uint8::to_uchar(pubkey), pubkey.Length(), nullptr);
    1012         161 :     pubkey_ecp = nullptr;
    1013             : 
    1014         161 :     VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INVALID_ARGUMENT);
    1015             : 
    1016         161 : exit:
    1017         161 :     if (group != nullptr)
    1018             :     {
    1019         161 :         EC_GROUP_free(group);
    1020         161 :         group = nullptr;
    1021             :     }
    1022             : 
    1023         161 :     _logSSLError();
    1024         161 :     return error;
    1025             : }
    1026             : 
    1027         124 : CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
    1028             : {
    1029         124 :     ERR_clear_error();
    1030             : 
    1031         124 :     Clear();
    1032             : 
    1033         124 :     CHIP_ERROR error = CHIP_NO_ERROR;
    1034         124 :     int result       = 0;
    1035         124 :     EC_KEY * ec_key  = nullptr;
    1036         124 :     ECName curve     = MapECName(mPublicKey.Type());
    1037             : 
    1038         124 :     int nid = _nidForCurve(curve);
    1039         124 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
    1040             : 
    1041         124 :     ec_key = EC_KEY_new_by_curve_name(nid);
    1042         124 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
    1043             : 
    1044         124 :     result = EC_KEY_generate_key(ec_key);
    1045         124 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1046             : 
    1047         124 :     error = P256PublicKeyFromECKey(ec_key, mPublicKey);
    1048         124 :     SuccessOrExit(error);
    1049             : 
    1050         124 :     from_EC_KEY(ec_key, &mKeypair);
    1051         124 :     mInitialized = true;
    1052         124 :     ec_key       = nullptr;
    1053             : 
    1054         124 : exit:
    1055         124 :     if (ec_key != nullptr)
    1056             :     {
    1057           0 :         EC_KEY_free(ec_key);
    1058           0 :         ec_key = nullptr;
    1059             :     }
    1060             : 
    1061         124 :     _logSSLError();
    1062         124 :     return error;
    1063             : }
    1064             : 
    1065         616 : CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const
    1066             : {
    1067         616 :     CHIP_ERROR error = CHIP_NO_ERROR;
    1068             : 
    1069         616 :     const EC_KEY * ec_key = to_const_EC_KEY(&mKeypair);
    1070             :     uint8_t privkey[kP256_PrivateKey_Length];
    1071             : 
    1072         616 :     int privkey_size          = 0;
    1073         616 :     const BIGNUM * privkey_bn = EC_KEY_get0_private_key(ec_key);
    1074         616 :     VerifyOrExit(privkey_bn != nullptr, error = CHIP_ERROR_INTERNAL);
    1075             : 
    1076         616 :     privkey_size = BN_bn2binpad(privkey_bn, privkey, sizeof(privkey));
    1077         616 :     privkey_bn   = nullptr;
    1078             : 
    1079         616 :     VerifyOrExit(privkey_size > 0, error = CHIP_ERROR_INTERNAL);
    1080         616 :     VerifyOrExit((size_t) privkey_size == sizeof(privkey), error = CHIP_ERROR_INTERNAL);
    1081             : 
    1082             :     {
    1083         616 :         size_t len = output.Length() == 0 ? output.Capacity() : output.Length();
    1084         616 :         Encoding::BufferWriter bbuf(output.Bytes(), len);
    1085         616 :         bbuf.Put(mPublicKey, mPublicKey.Length());
    1086         616 :         bbuf.Put(privkey, sizeof(privkey));
    1087         616 :         VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
    1088         616 :         output.SetLength(bbuf.Needed());
    1089             :     }
    1090             : 
    1091         616 : exit:
    1092         616 :     ClearSecretData(privkey, sizeof(privkey));
    1093         616 :     _logSSLError();
    1094         616 :     return error;
    1095             : }
    1096             : 
    1097        1382 : CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
    1098             : {
    1099        1382 :     Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length());
    1100             : 
    1101        1382 :     Clear();
    1102             : 
    1103        1382 :     BIGNUM * pvt_key     = nullptr;
    1104        1382 :     EC_GROUP * group     = nullptr;
    1105        1382 :     EC_POINT * key_point = nullptr;
    1106             : 
    1107        1382 :     EC_KEY * ec_key = nullptr;
    1108        1382 :     ECName curve    = MapECName(mPublicKey.Type());
    1109             : 
    1110        1382 :     ERR_clear_error();
    1111        1382 :     CHIP_ERROR error = CHIP_NO_ERROR;
    1112        1382 :     int result       = 0;
    1113        1382 :     int nid          = NID_undef;
    1114             : 
    1115        1382 :     const uint8_t * privkey = input.ConstBytes() + mPublicKey.Length();
    1116             : 
    1117        1382 :     VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
    1118        1382 :     bbuf.Put(input.ConstBytes(), mPublicKey.Length());
    1119        1382 :     VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
    1120             : 
    1121        1382 :     nid = _nidForCurve(curve);
    1122        1382 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
    1123             : 
    1124        1382 :     group = EC_GROUP_new_by_curve_name(nid);
    1125        1382 :     VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
    1126             : 
    1127        1382 :     key_point = EC_POINT_new(group);
    1128        1382 :     VerifyOrExit(key_point != nullptr, error = CHIP_ERROR_INTERNAL);
    1129             : 
    1130        1382 :     result = EC_POINT_oct2point(group, key_point, Uint8::to_const_uchar(mPublicKey), mPublicKey.Length(), nullptr);
    1131        1382 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1132             : 
    1133        1382 :     ec_key = EC_KEY_new_by_curve_name(nid);
    1134        1382 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
    1135             : 
    1136        1382 :     result = EC_KEY_set_public_key(ec_key, key_point);
    1137        1382 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1138             : 
    1139        1382 :     pvt_key = BN_bin2bn(privkey, kP256_PrivateKey_Length, nullptr);
    1140        1382 :     VerifyOrExit(pvt_key != nullptr, error = CHIP_ERROR_INTERNAL);
    1141             : 
    1142        1382 :     result = EC_KEY_set_private_key(ec_key, pvt_key);
    1143        1382 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1144             : 
    1145        1382 :     from_EC_KEY(ec_key, &mKeypair);
    1146        1382 :     mInitialized = true;
    1147        1382 :     ec_key       = nullptr;
    1148             : 
    1149        1382 : exit:
    1150        1382 :     if (ec_key != nullptr)
    1151             :     {
    1152           0 :         EC_KEY_free(ec_key);
    1153           0 :         ec_key = nullptr;
    1154             :     }
    1155             : 
    1156        1382 :     if (group != nullptr)
    1157             :     {
    1158        1382 :         EC_GROUP_free(group);
    1159        1382 :         group = nullptr;
    1160             :     }
    1161             : 
    1162        1382 :     if (pvt_key != nullptr)
    1163             :     {
    1164        1382 :         BN_free(pvt_key);
    1165        1382 :         pvt_key = nullptr;
    1166             :     }
    1167             : 
    1168        1382 :     if (key_point != nullptr)
    1169             :     {
    1170        1382 :         EC_POINT_free(key_point);
    1171        1382 :         key_point = nullptr;
    1172             :     }
    1173        1382 :     _logSSLError();
    1174        1382 :     return error;
    1175             : }
    1176             : 
    1177        2995 : void P256Keypair::Clear()
    1178             : {
    1179        2995 :     if (mInitialized)
    1180             :     {
    1181        1506 :         EC_KEY * ec_key = to_EC_KEY(&mKeypair);
    1182        1506 :         EC_KEY_free(ec_key);
    1183        1506 :         mInitialized = false;
    1184             :     }
    1185        2995 : }
    1186             : 
    1187        1489 : P256Keypair::~P256Keypair()
    1188             : {
    1189        1489 :     Clear();
    1190        1489 : }
    1191             : 
    1192          25 : CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
    1193             : {
    1194          25 :     ERR_clear_error();
    1195          25 :     CHIP_ERROR error     = CHIP_NO_ERROR;
    1196          25 :     int result           = 0;
    1197          25 :     int csr_length_local = 0;
    1198             : 
    1199          25 :     X509_REQ * x509_req = X509_REQ_new();
    1200          25 :     EVP_PKEY * evp_pkey = nullptr;
    1201             : 
    1202          25 :     EC_KEY * ec_key = to_EC_KEY(&mKeypair);
    1203             : 
    1204          25 :     X509_NAME * subject = X509_NAME_new();
    1205          25 :     VerifyOrExit(subject != nullptr, error = CHIP_ERROR_INTERNAL);
    1206             : 
    1207          25 :     VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
    1208             : 
    1209          25 :     result = X509_REQ_set_version(x509_req, 0);
    1210          25 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1211             : 
    1212          25 :     result = EC_KEY_check_key(ec_key);
    1213          25 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1214             : 
    1215          25 :     evp_pkey = EVP_PKEY_new();
    1216          25 :     VerifyOrExit(evp_pkey != nullptr, error = CHIP_ERROR_INTERNAL);
    1217             : 
    1218          25 :     result = EVP_PKEY_set1_EC_KEY(evp_pkey, ec_key);
    1219          25 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1220             : 
    1221          25 :     result = X509_REQ_set_pubkey(x509_req, evp_pkey);
    1222          25 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1223             : 
    1224             :     // TODO: mbedTLS CSR parser fails if the subject name is not set (or if empty).
    1225             :     //       CHIP Spec doesn't specify the subject name that can be used.
    1226             :     //       Figure out the correct value and update this code.
    1227          25 :     result = X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC, Uint8::from_const_char("CSR"), -1, -1, 0);
    1228          25 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1229             : 
    1230          25 :     result = X509_REQ_set_subject_name(x509_req, subject);
    1231          25 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1232             : 
    1233          25 :     result = X509_REQ_sign(x509_req, evp_pkey, EVP_sha256());
    1234          25 :     VerifyOrExit(result > 0, error = CHIP_ERROR_INTERNAL);
    1235             : 
    1236          25 :     csr_length_local = i2d_X509_REQ(x509_req, nullptr);
    1237          25 :     VerifyOrExit(csr_length_local >= 0, error = CHIP_ERROR_INTERNAL);
    1238          25 :     VerifyOrExit(CanCastTo<size_t>(csr_length_local), error = CHIP_ERROR_BUFFER_TOO_SMALL);
    1239          25 :     VerifyOrExit(static_cast<size_t>(csr_length_local) <= csr_length, error = CHIP_ERROR_BUFFER_TOO_SMALL);
    1240          25 :     csr_length = static_cast<size_t>(i2d_X509_REQ(x509_req, &out_csr));
    1241             : 
    1242          25 : exit:
    1243          25 :     ec_key = nullptr;
    1244             : 
    1245          25 :     if (evp_pkey != nullptr)
    1246             :     {
    1247          25 :         EVP_PKEY_free(evp_pkey);
    1248          25 :         evp_pkey = nullptr;
    1249             :     }
    1250             : 
    1251          25 :     X509_NAME_free(subject);
    1252          25 :     subject = nullptr;
    1253             : 
    1254          25 :     X509_REQ_free(x509_req);
    1255             : 
    1256          25 :     _logSSLError();
    1257          25 :     return error;
    1258             : }
    1259             : 
    1260          44 : CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr, size_t csr_length, P256PublicKey & pubkey)
    1261             : {
    1262          44 :     ReturnErrorOnFailure(VerifyCertificateSigningRequestFormat(csr, csr_length));
    1263             : 
    1264          40 :     ERR_clear_error();
    1265          40 :     CHIP_ERROR error = CHIP_NO_ERROR;
    1266          40 :     int result       = 0;
    1267             : 
    1268          40 :     EVP_PKEY * evp_pkey = nullptr;
    1269          40 :     EC_KEY * ec_key     = nullptr;
    1270             : 
    1271          40 :     const unsigned char * csr_buf = Uint8::to_const_uchar(csr);
    1272          40 :     X509_REQ * x509_req           = d2i_X509_REQ(nullptr, &csr_buf, (int) csr_length);
    1273          40 :     VerifyOrExit(x509_req != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
    1274             : 
    1275          40 :     VerifyOrExit(X509_REQ_get_version(x509_req) == 0, error = CHIP_ERROR_INVALID_ARGUMENT);
    1276             : 
    1277          40 :     evp_pkey = X509_REQ_get_pubkey(x509_req);
    1278          40 :     VerifyOrExit(evp_pkey != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
    1279             : 
    1280          40 :     result = X509_REQ_verify(x509_req, evp_pkey);
    1281          40 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INVALID_ARGUMENT);
    1282             : 
    1283          37 :     ec_key = EVP_PKEY_get1_EC_KEY(evp_pkey);
    1284          37 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
    1285             : 
    1286          37 :     error = P256PublicKeyFromECKey(ec_key, pubkey);
    1287          37 :     SuccessOrExit(error);
    1288             : 
    1289          40 : exit:
    1290             : 
    1291          40 :     if (x509_req != nullptr)
    1292             :     {
    1293          40 :         X509_REQ_free(x509_req);
    1294             :     }
    1295             : 
    1296          40 :     if (ec_key != nullptr)
    1297             :     {
    1298          37 :         EC_KEY_free(ec_key);
    1299             :     }
    1300             : 
    1301          40 :     if (evp_pkey != nullptr)
    1302             :     {
    1303          40 :         EVP_PKEY_free(evp_pkey);
    1304             :     }
    1305          40 :     _logSSLError();
    1306          40 :     return error;
    1307             : }
    1308             : 
    1309             : #define init_point(_point_)                                                                                                        \
    1310             :     do                                                                                                                             \
    1311             :     {                                                                                                                              \
    1312             :         _point_ = EC_POINT_new(context->curve);                                                                                    \
    1313             :         VerifyOrReturnError(_point_ != nullptr, CHIP_ERROR_INTERNAL);                                                              \
    1314             :     } while (0)
    1315             : 
    1316             : #define init_bn(_bn_)                                                                                                              \
    1317             :     do                                                                                                                             \
    1318             :     {                                                                                                                              \
    1319             :         _bn_ = BN_new();                                                                                                           \
    1320             :         VerifyOrReturnError(_bn_ != nullptr, CHIP_ERROR_INTERNAL);                                                                 \
    1321             :     } while (0)
    1322             : 
    1323             : #define free_point(_point_)                                                                                                        \
    1324             :     do                                                                                                                             \
    1325             :     {                                                                                                                              \
    1326             :         if (_point_ != nullptr)                                                                                                    \
    1327             :         {                                                                                                                          \
    1328             :             EC_POINT_clear_free(static_cast<EC_POINT *>(_point_));                                                                 \
    1329             :         }                                                                                                                          \
    1330             :     } while (0)
    1331             : 
    1332             : #define free_bn(_bn_)                                                                                                              \
    1333             :     do                                                                                                                             \
    1334             :     {                                                                                                                              \
    1335             :         if (_bn_ != nullptr)                                                                                                       \
    1336             :         {                                                                                                                          \
    1337             :             BN_clear_free(static_cast<BIGNUM *>(_bn_));                                                                            \
    1338             :         }                                                                                                                          \
    1339             :     } while (0)
    1340             : 
    1341             : typedef struct Spake2p_Context
    1342             : {
    1343             :     EC_GROUP * curve;
    1344             :     BN_CTX * bn_ctx;
    1345             :     const EVP_MD * md_info;
    1346             : } Spake2p_Context;
    1347             : 
    1348        1404 : static inline Spake2p_Context * to_inner_spake2p_context(Spake2pOpaqueContext * context)
    1349             : {
    1350        1404 :     return SafePointerCast<Spake2p_Context *>(context);
    1351             : }
    1352             : 
    1353         145 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal()
    1354             : {
    1355         145 :     Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
    1356             : 
    1357         145 :     context->curve   = nullptr;
    1358         145 :     context->bn_ctx  = nullptr;
    1359         145 :     context->md_info = nullptr;
    1360             : 
    1361         145 :     context->curve = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
    1362         145 :     VerifyOrReturnError(context->curve != nullptr, CHIP_ERROR_INTERNAL);
    1363             : 
    1364         145 :     G = EC_GROUP_get0_generator(context->curve);
    1365         145 :     VerifyOrReturnError(G != nullptr, CHIP_ERROR_INTERNAL);
    1366             : 
    1367         145 :     context->bn_ctx = BN_CTX_secure_new();
    1368         145 :     VerifyOrReturnError(context->bn_ctx != nullptr, CHIP_ERROR_INTERNAL);
    1369             : 
    1370         145 :     context->md_info = EVP_sha256();
    1371         145 :     VerifyOrReturnError(context->md_info != nullptr, CHIP_ERROR_INTERNAL);
    1372             : 
    1373         145 :     init_point(M);
    1374         145 :     init_point(N);
    1375         145 :     init_point(X);
    1376         145 :     init_point(Y);
    1377         145 :     init_point(L);
    1378         145 :     init_point(V);
    1379         145 :     init_point(Z);
    1380         145 :     init_bn(w0);
    1381         145 :     init_bn(w1);
    1382         145 :     init_bn(xy);
    1383         145 :     init_bn(tempbn);
    1384         145 :     init_bn(order);
    1385             : 
    1386         145 :     const int error_openssl = EC_GROUP_get_order(context->curve, static_cast<BIGNUM *>(order), context->bn_ctx);
    1387         145 :     VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
    1388             : 
    1389         145 :     return CHIP_NO_ERROR;
    1390             : }
    1391             : 
    1392         214 : void Spake2p_P256_SHA256_HKDF_HMAC::Clear()
    1393             : {
    1394         214 :     VerifyOrReturn(state != CHIP_SPAKE2P_STATE::PREINIT);
    1395             : 
    1396         145 :     Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
    1397             : 
    1398         145 :     if (context->curve != nullptr)
    1399             :     {
    1400         145 :         EC_GROUP_clear_free(context->curve);
    1401             :     }
    1402             : 
    1403         145 :     if (context->bn_ctx != nullptr)
    1404             :     {
    1405         145 :         BN_CTX_free(context->bn_ctx);
    1406             :     }
    1407             : 
    1408         145 :     free_point(M);
    1409         145 :     free_point(N);
    1410         145 :     free_point(X);
    1411         145 :     free_point(Y);
    1412         145 :     free_point(L);
    1413         145 :     free_point(V);
    1414         145 :     free_point(Z);
    1415         145 :     free_bn(w0);
    1416         145 :     free_bn(w1);
    1417         145 :     free_bn(xy);
    1418         145 :     free_bn(tempbn);
    1419         145 :     free_bn(order);
    1420             : 
    1421         145 :     state = CHIP_SPAKE2P_STATE::PREINIT;
    1422             : }
    1423             : 
    1424          49 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len,
    1425             :                                               MutableByteSpan & out_span)
    1426             : {
    1427          49 :     HMAC_sha hmac;
    1428          49 :     VerifyOrReturnError(out_span.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
    1429          49 :     ReturnErrorOnFailure(hmac.HMAC_SHA256(key, key_len, in, in_len, out_span.data(), kSHA256_Hash_Length));
    1430          49 :     out_span = out_span.SubSpan(0, kSHA256_Hash_Length);
    1431          49 :     return CHIP_NO_ERROR;
    1432          49 : }
    1433             : 
    1434          24 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len,
    1435             :                                                     const uint8_t * in, size_t in_len)
    1436             : {
    1437          24 :     VerifyOrReturnError(mac_len == kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
    1438             : 
    1439             :     uint8_t computed_mac[kSHA256_Hash_Length];
    1440          24 :     MutableByteSpan computed_mac_span{ computed_mac };
    1441          24 :     ReturnErrorOnFailure(Mac(key, key_len, in, in_len, computed_mac_span));
    1442          24 :     VerifyOrReturnError(computed_mac_span.size() == mac_len, CHIP_ERROR_INTERNAL);
    1443             : 
    1444          24 :     VerifyOrReturnError(CRYPTO_memcmp(mac, computed_mac_span.data(), computed_mac_span.size()) == 0, CHIP_ERROR_INTERNAL);
    1445             : 
    1446          23 :     return CHIP_NO_ERROR;
    1447             : }
    1448             : 
    1449         145 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FELoad(const uint8_t * in, size_t in_len, void * fe)
    1450             : {
    1451         145 :     BIGNUM * const bn_fe = static_cast<BIGNUM *>(fe);
    1452             : 
    1453         145 :     Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
    1454             : 
    1455         145 :     VerifyOrReturnError(CanCastTo<boringssl_size_t_openssl_int>(in_len), CHIP_ERROR_INTERNAL);
    1456         145 :     BN_bin2bn(Uint8::to_const_uchar(in), static_cast<boringssl_size_t_openssl_int>(in_len), bn_fe);
    1457         145 :     const int error_openssl = BN_mod(bn_fe, bn_fe, (BIGNUM *) order, context->bn_ctx);
    1458         145 :     VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
    1459             : 
    1460         145 :     return CHIP_NO_ERROR;
    1461             : }
    1462             : 
    1463          47 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEWrite(const void * fe, uint8_t * out, size_t out_len)
    1464             : {
    1465          47 :     VerifyOrReturnError(CanCastTo<int>(out_len), CHIP_ERROR_INTERNAL);
    1466          47 :     const int bn_out_len = BN_bn2binpad(static_cast<const BIGNUM *>(fe), Uint8::to_uchar(out), static_cast<int>(out_len));
    1467          47 :     VerifyOrReturnError(bn_out_len == static_cast<int>(out_len), CHIP_ERROR_INTERNAL);
    1468             : 
    1469          47 :     return CHIP_NO_ERROR;
    1470             : }
    1471             : 
    1472          12 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe)
    1473             : {
    1474          12 :     const int error_openssl = BN_rand_range(static_cast<BIGNUM *>(fe), static_cast<BIGNUM *>(order));
    1475          12 :     VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
    1476             : 
    1477          12 :     return CHIP_NO_ERROR;
    1478             : }
    1479             : 
    1480          50 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEMul(void * fer, const void * fe1, const void * fe2)
    1481             : {
    1482          50 :     const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
    1483             : 
    1484          50 :     const int error_openssl = BN_mod_mul(static_cast<BIGNUM *>(fer), static_cast<const BIGNUM *>(fe1),
    1485          50 :                                          static_cast<const BIGNUM *>(fe2), static_cast<BIGNUM *>(order), context->bn_ctx);
    1486          50 :     VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
    1487             : 
    1488          50 :     return CHIP_NO_ERROR;
    1489             : }
    1490             : 
    1491         430 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointLoad(const uint8_t * in, size_t in_len, void * R)
    1492             : {
    1493         430 :     const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
    1494             : 
    1495             :     const int error_openssl =
    1496         430 :         EC_POINT_oct2point(context->curve, static_cast<EC_POINT *>(R), Uint8::to_const_uchar(in), in_len, context->bn_ctx);
    1497         430 :     VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
    1498             : 
    1499         410 :     return CHIP_NO_ERROR;
    1500             : }
    1501             : 
    1502         165 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * out, size_t out_len)
    1503             : {
    1504         165 :     const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
    1505             : 
    1506         165 :     const size_t ec_out_len = EC_POINT_point2oct(context->curve, static_cast<const EC_POINT *>(R), POINT_CONVERSION_UNCOMPRESSED,
    1507         165 :                                                  Uint8::to_uchar(out), out_len, context->bn_ctx);
    1508         165 :     VerifyOrReturnError(ec_out_len == out_len, CHIP_ERROR_INTERNAL);
    1509             : 
    1510         165 :     return CHIP_NO_ERROR;
    1511             : }
    1512             : 
    1513         170 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1)
    1514             : {
    1515         170 :     const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
    1516             : 
    1517         170 :     const int error_openssl = EC_POINT_mul(context->curve, static_cast<EC_POINT *>(R), nullptr, static_cast<const EC_POINT *>(P1),
    1518         170 :                                            static_cast<const BIGNUM *>(fe1), context->bn_ctx);
    1519         170 :     VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
    1520             : 
    1521         170 :     return CHIP_NO_ERROR;
    1522             : }
    1523             : 
    1524          70 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, const void * fe1, const void * P2,
    1525             :                                                       const void * fe2)
    1526             : {
    1527          70 :     CHIP_ERROR error   = CHIP_ERROR_INTERNAL;
    1528          70 :     int error_openssl  = 0;
    1529          70 :     EC_POINT * scratch = nullptr;
    1530             : 
    1531          70 :     Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
    1532             : 
    1533          70 :     scratch = EC_POINT_new(context->curve);
    1534          70 :     VerifyOrExit(scratch != nullptr, error = CHIP_ERROR_INTERNAL);
    1535             : 
    1536          70 :     SuccessOrExit(error = PointMul(scratch, P1, fe1));
    1537          70 :     SuccessOrExit(error = PointMul(R, P2, fe2));
    1538             : 
    1539          70 :     error_openssl = EC_POINT_add(context->curve, static_cast<EC_POINT *>(R), static_cast<EC_POINT *>(R),
    1540             :                                  static_cast<const EC_POINT *>(scratch), context->bn_ctx);
    1541          70 :     VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
    1542             : 
    1543          70 :     error = CHIP_NO_ERROR;
    1544          70 : exit:
    1545          70 :     EC_POINT_clear_free(scratch);
    1546          70 :     return error;
    1547             : }
    1548             : 
    1549          20 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R)
    1550             : {
    1551          20 :     const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
    1552             : 
    1553          20 :     const int error_openssl = EC_POINT_invert(context->curve, static_cast<EC_POINT *>(R), context->bn_ctx);
    1554          20 :     VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
    1555             : 
    1556          20 :     return CHIP_NO_ERROR;
    1557             : }
    1558             : 
    1559          40 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointCofactorMul(void * R)
    1560             : {
    1561             :     // Cofactor on P256 is 1 so this is a NOP
    1562          40 :     return CHIP_NO_ERROR;
    1563             : }
    1564             : 
    1565           4 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len)
    1566             : {
    1567           4 :     CHIP_ERROR error      = CHIP_ERROR_INTERNAL;
    1568           4 :     int error_openssl     = 0;
    1569           4 :     BIGNUM * w1_bn        = nullptr;
    1570           4 :     EC_POINT * Lout_point = nullptr;
    1571             : 
    1572           4 :     Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
    1573             : 
    1574           4 :     w1_bn = BN_new();
    1575           4 :     VerifyOrExit(w1_bn != nullptr, error = CHIP_ERROR_INTERNAL);
    1576             : 
    1577           4 :     Lout_point = EC_POINT_new(context->curve);
    1578           4 :     VerifyOrExit(Lout_point != nullptr, error = CHIP_ERROR_INTERNAL);
    1579             : 
    1580           4 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(w1in_len), error = CHIP_ERROR_INTERNAL);
    1581           4 :     BN_bin2bn(Uint8::to_const_uchar(w1in), static_cast<boringssl_size_t_openssl_int>(w1in_len), w1_bn);
    1582           4 :     error_openssl = BN_mod(w1_bn, w1_bn, (BIGNUM *) order, context->bn_ctx);
    1583           4 :     VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
    1584             : 
    1585           4 :     error_openssl = EC_POINT_mul(context->curve, Lout_point, w1_bn, nullptr, nullptr, context->bn_ctx);
    1586           4 :     VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
    1587             : 
    1588           4 :     *L_len = EC_POINT_point2oct(context->curve, Lout_point, POINT_CONVERSION_UNCOMPRESSED, Uint8::to_uchar(Lout), *L_len,
    1589             :                                 context->bn_ctx);
    1590           4 :     VerifyOrExit(*L_len != 0, error = CHIP_ERROR_INTERNAL);
    1591             : 
    1592           4 :     error = CHIP_NO_ERROR;
    1593           4 : exit:
    1594           4 :     BN_clear_free(w1_bn);
    1595           4 :     EC_POINT_clear_free(Lout_point);
    1596             : 
    1597           4 :     return error;
    1598             : }
    1599             : 
    1600          60 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R)
    1601             : {
    1602          60 :     const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
    1603             : 
    1604          60 :     const int error_openssl = EC_POINT_is_on_curve(context->curve, static_cast<EC_POINT *>(R), context->bn_ctx);
    1605          60 :     VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
    1606             : 
    1607          40 :     return CHIP_NO_ERROR;
    1608             : }
    1609             : 
    1610         291 : CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType)
    1611             : {
    1612         291 :     CHIP_ERROR err          = CHIP_NO_ERROR;
    1613         291 :     const uint8_t * certPtr = cert.data();
    1614         291 :     X509 * x509Cert         = nullptr;
    1615         291 :     bool extBasicPresent    = false;
    1616         291 :     bool extKeyUsagePresent = false;
    1617         291 :     bool extSKIDPresent     = false;
    1618         291 :     bool extAKIDPresent     = false;
    1619             : 
    1620         291 :     VerifyOrReturnError(!cert.empty() && CanCastTo<long>(cert.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1621             : 
    1622         290 :     x509Cert = d2i_X509(nullptr, &certPtr, static_cast<long>(cert.size()));
    1623         290 :     VerifyOrExit(x509Cert != nullptr, err = CHIP_ERROR_INTERNAL);
    1624             : 
    1625         290 :     VerifyOrExit(X509_get_version(x509Cert) == 2, err = CHIP_ERROR_INTERNAL);
    1626         288 :     VerifyOrExit(X509_get_serialNumber(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1627         288 :     VerifyOrExit(X509_get_signature_nid(x509Cert) == NID_ecdsa_with_SHA256, err = CHIP_ERROR_INTERNAL);
    1628         286 :     VerifyOrExit(X509_get_issuer_name(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1629         286 :     VerifyOrExit(X509_get_notBefore(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1630         286 :     VerifyOrExit(X509_get_notAfter(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1631         286 :     VerifyOrExit(X509_get_subject_name(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1632             : 
    1633             :     // Verify public key presence and format.
    1634             :     {
    1635         286 :         Crypto::P256PublicKey pubkey;
    1636         286 :         SuccessOrExit(err = ExtractPubkeyFromX509Cert(cert, pubkey));
    1637         286 :     }
    1638             : 
    1639        1312 :     for (int i = 0; i < X509_get_ext_count(x509Cert); i++)
    1640             :     {
    1641        1057 :         X509_EXTENSION * ex = X509_get_ext(x509Cert, i);
    1642        1057 :         ASN1_OBJECT * obj   = X509_EXTENSION_get_object(ex);
    1643        1057 :         bool isCritical     = X509_EXTENSION_get_critical(ex) == 1;
    1644             : 
    1645        1057 :         switch (OBJ_obj2nid(obj))
    1646             :         {
    1647         283 :         case NID_basic_constraints:
    1648         283 :             VerifyOrExit(isCritical && !extBasicPresent, err = CHIP_ERROR_INTERNAL);
    1649         279 :             extBasicPresent = true;
    1650             :             {
    1651         279 :                 bool isCA    = X509_get_extension_flags(x509Cert) & EXFLAG_CA;
    1652         279 :                 long pathLen = X509_get_pathlen(x509Cert);
    1653         279 :                 if (certType == AttestationCertType::kDAC)
    1654             :                 {
    1655         128 :                     VerifyOrExit(!isCA && pathLen == -1, err = CHIP_ERROR_INTERNAL);
    1656             :                 }
    1657         151 :                 else if (certType == AttestationCertType::kPAI)
    1658             :                 {
    1659         147 :                     VerifyOrExit(isCA && pathLen == 0, err = CHIP_ERROR_INTERNAL);
    1660             :                 }
    1661             :                 else
    1662             :                 {
    1663             :                     // For PAA, pathlen must be absent or equal to 1 (see Matter 1.1 spec 6.2.2.5)
    1664           4 :                     VerifyOrExit(isCA && (pathLen == -1 || pathLen == 1), err = CHIP_ERROR_INTERNAL);
    1665             :                 }
    1666             :             }
    1667         262 :             break;
    1668         262 :         case NID_key_usage:
    1669         262 :             VerifyOrExit(isCritical && !extKeyUsagePresent, err = CHIP_ERROR_INTERNAL);
    1670         258 :             extKeyUsagePresent = true;
    1671             :             {
    1672         258 :                 uint32_t keyUsage = X509_get_key_usage(x509Cert);
    1673         258 :                 if (certType == AttestationCertType::kDAC)
    1674             :                 {
    1675             :                     // SHALL only have the digitalSignature bit set.
    1676         119 :                     VerifyOrExit(keyUsage == X509v3_KU_DIGITAL_SIGNATURE, err = CHIP_ERROR_INTERNAL);
    1677             :                 }
    1678             :                 else
    1679             :                 {
    1680         139 :                     bool keyCertSignFlag = keyUsage & X509v3_KU_KEY_CERT_SIGN;
    1681         139 :                     bool crlSignFlag     = keyUsage & X509v3_KU_CRL_SIGN;
    1682         139 :                     bool otherFlags      = keyUsage &
    1683             :                         ~static_cast<uint32_t>(X509v3_KU_CRL_SIGN | X509v3_KU_KEY_CERT_SIGN | X509v3_KU_DIGITAL_SIGNATURE);
    1684         139 :                     VerifyOrExit(keyCertSignFlag && crlSignFlag && !otherFlags, err = CHIP_ERROR_INTERNAL);
    1685             :                 }
    1686             :             }
    1687         253 :             break;
    1688         253 :         case NID_subject_key_identifier:
    1689         253 :             VerifyOrExit(!isCritical && !extSKIDPresent, err = CHIP_ERROR_INTERNAL);
    1690         253 :             VerifyOrExit(X509_get0_subject_key_id(x509Cert)->length == kSubjectKeyIdentifierLength, err = CHIP_ERROR_INTERNAL);
    1691         253 :             extSKIDPresent = true;
    1692         253 :             break;
    1693         253 :         case NID_authority_key_identifier:
    1694         253 :             VerifyOrExit(!isCritical && !extAKIDPresent, err = CHIP_ERROR_INTERNAL);
    1695         253 :             VerifyOrExit(X509_get0_authority_key_id(x509Cert)->length == kAuthorityKeyIdentifierLength, err = CHIP_ERROR_INTERNAL);
    1696         253 :             extAKIDPresent = true;
    1697         253 :             break;
    1698           6 :         default:
    1699           6 :             break;
    1700             :         }
    1701             :     }
    1702             :     // Mandatory extensions for all certs.
    1703         255 :     VerifyOrExit(extBasicPresent && extKeyUsagePresent && extSKIDPresent, err = CHIP_ERROR_INTERNAL);
    1704             : 
    1705         249 :     if (certType == AttestationCertType::kDAC || certType == AttestationCertType::kPAI)
    1706             :     {
    1707             :         // Mandatory extension for DAC and PAI certs.
    1708         247 :         VerifyOrExit(extAKIDPresent, err = CHIP_ERROR_INTERNAL);
    1709             :     }
    1710             : 
    1711           2 : exit:
    1712         290 :     X509_free(x509Cert);
    1713             : 
    1714         290 :     return err;
    1715             : }
    1716             : 
    1717         112 : CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate,
    1718             :                                     size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen,
    1719             :                                     CertificateChainValidationResult & result)
    1720             : {
    1721         112 :     CHIP_ERROR err             = CHIP_NO_ERROR;
    1722         112 :     int status                 = 0;
    1723         112 :     X509_STORE_CTX * verifyCtx = nullptr;
    1724         112 :     X509_STORE * store         = nullptr;
    1725         112 :     STACK_OF(X509) * chain     = nullptr;
    1726         112 :     X509 * x509RootCertificate = nullptr;
    1727         112 :     X509 * x509CACertificate   = nullptr;
    1728         112 :     X509 * x509LeafCertificate = nullptr;
    1729             : 
    1730         112 :     result = CertificateChainValidationResult::kInternalFrameworkError;
    1731             : 
    1732         112 :     VerifyOrReturnError(rootCertificate != nullptr && rootCertificateLen != 0 && CanCastTo<long>(rootCertificateLen),
    1733             :                         (result = CertificateChainValidationResult::kRootArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
    1734         111 :     VerifyOrReturnError(leafCertificate != nullptr && leafCertificateLen != 0 && CanCastTo<long>(leafCertificateLen),
    1735             :                         (result = CertificateChainValidationResult::kLeafArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
    1736             : 
    1737         110 :     store = X509_STORE_new();
    1738         110 :     VerifyOrExit(store != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
    1739             : 
    1740         110 :     verifyCtx = X509_STORE_CTX_new();
    1741         110 :     VerifyOrExit(verifyCtx != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
    1742             : 
    1743         110 :     chain = sk_X509_new_null();
    1744         110 :     VerifyOrExit(chain != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
    1745             : 
    1746         110 :     VerifyOrExit(CanCastTo<long>(rootCertificateLen),
    1747             :                  (result = CertificateChainValidationResult::kRootArgumentInvalid, err = CHIP_ERROR_INVALID_ARGUMENT));
    1748         110 :     x509RootCertificate = d2i_X509(nullptr, &rootCertificate, static_cast<long>(rootCertificateLen));
    1749         110 :     VerifyOrExit(x509RootCertificate != nullptr,
    1750             :                  (result = CertificateChainValidationResult::kRootFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1751             : 
    1752         110 :     status = X509_STORE_add_cert(store, x509RootCertificate);
    1753         110 :     VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kInternalFrameworkError, err = CHIP_ERROR_INTERNAL));
    1754             : 
    1755         110 :     if (caCertificate != nullptr && caCertificateLen > 0)
    1756             :     {
    1757         106 :         VerifyOrExit(CanCastTo<long>(caCertificateLen),
    1758             :                      (result = CertificateChainValidationResult::kICAArgumentInvalid, err = CHIP_ERROR_INVALID_ARGUMENT));
    1759         106 :         x509CACertificate = d2i_X509(nullptr, &caCertificate, static_cast<long>(caCertificateLen));
    1760         106 :         VerifyOrExit(x509CACertificate != nullptr,
    1761             :                      (result = CertificateChainValidationResult::kICAFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1762             : 
    1763         106 :         status = static_cast<int>(sk_X509_push(chain, x509CACertificate));
    1764         106 :         VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kInternalFrameworkError, err = CHIP_ERROR_INTERNAL));
    1765             :     }
    1766             : 
    1767         110 :     VerifyOrExit(CanCastTo<long>(leafCertificateLen),
    1768             :                  (result = CertificateChainValidationResult::kLeafArgumentInvalid, err = CHIP_ERROR_INVALID_ARGUMENT));
    1769         110 :     x509LeafCertificate = d2i_X509(nullptr, &leafCertificate, static_cast<long>(leafCertificateLen));
    1770         110 :     VerifyOrExit(x509LeafCertificate != nullptr,
    1771             :                  (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1772             : 
    1773         110 :     status = X509_STORE_CTX_init(verifyCtx, store, x509LeafCertificate, chain);
    1774         110 :     VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kInternalFrameworkError, err = CHIP_ERROR_INTERNAL));
    1775             : 
    1776             :     // Set time used in the X509 certificate chain validation to the notBefore time of the leaf certificate.
    1777             :     // That way the X509_verify_cert() validates that intermediate and root certificates were
    1778             :     // valid at the time of the leaf certificate generation.
    1779             :     {
    1780         110 :         X509_VERIFY_PARAM * param = X509_STORE_CTX_get0_param(verifyCtx);
    1781             :         chip::ASN1::ASN1UniversalTime asn1Time;
    1782         110 :         char * asn1TimeStr = reinterpret_cast<char *>(X509_get_notBefore(x509LeafCertificate)->data);
    1783             :         uint32_t unixEpoch;
    1784             : 
    1785         110 :         VerifyOrExit(param != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
    1786             : 
    1787         110 :         VerifyOrExit(CHIP_NO_ERROR == asn1Time.ImportFrom_ASN1_TIME_string(CharSpan(asn1TimeStr, strlen(asn1TimeStr))),
    1788             :                      (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1789             : 
    1790         110 :         VerifyOrExit(asn1Time.ExportTo_UnixTime(unixEpoch),
    1791             :                      (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1792             : 
    1793         110 :         VerifyOrExit(CanCastTo<time_t>(unixEpoch),
    1794             :                      (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1795         110 :         X509_VERIFY_PARAM_set_time(param, static_cast<time_t>(unixEpoch));
    1796         110 :         X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_X509_STRICT);
    1797             :     }
    1798             : 
    1799         110 :     status = X509_verify_cert(verifyCtx);
    1800         110 :     VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kChainInvalid, err = CHIP_ERROR_CERT_NOT_TRUSTED));
    1801             : 
    1802          98 :     err    = CHIP_NO_ERROR;
    1803          98 :     result = CertificateChainValidationResult::kSuccess;
    1804             : 
    1805         110 : exit:
    1806         110 :     X509_free(x509LeafCertificate);
    1807         110 :     X509_free(x509CACertificate);
    1808         110 :     X509_free(x509RootCertificate);
    1809         110 :     sk_X509_free(chain);
    1810         110 :     X509_STORE_CTX_free(verifyCtx);
    1811         110 :     X509_STORE_free(store);
    1812             : 
    1813         110 :     return err;
    1814             : }
    1815             : 
    1816          14 : CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & candidateCertificate, const ByteSpan & issuerCertificate)
    1817             : {
    1818          14 :     CHIP_ERROR error                            = CHIP_NO_ERROR;
    1819          14 :     X509 * x509CandidateCertificate             = nullptr;
    1820          14 :     X509 * x509issuerCertificate                = nullptr;
    1821          14 :     const unsigned char * pCandidateCertificate = candidateCertificate.data();
    1822          14 :     const unsigned char * pIssuerCertificate    = issuerCertificate.data();
    1823          14 :     ASN1_TIME * candidateNotBeforeTime          = nullptr;
    1824          14 :     ASN1_TIME * issuerNotBeforeTime             = nullptr;
    1825          14 :     ASN1_TIME * issuerNotAfterTime              = nullptr;
    1826          14 :     int result                                  = 0;
    1827          14 :     int days                                    = 0;
    1828          14 :     int seconds                                 = 0;
    1829             : 
    1830          14 :     VerifyOrReturnError(!candidateCertificate.empty() && CanCastTo<long>(candidateCertificate.size()) &&
    1831             :                             !issuerCertificate.empty() && CanCastTo<long>(issuerCertificate.size()),
    1832             :                         CHIP_ERROR_INVALID_ARGUMENT);
    1833             : 
    1834          12 :     x509CandidateCertificate = d2i_X509(nullptr, &pCandidateCertificate, static_cast<long>(candidateCertificate.size()));
    1835          12 :     VerifyOrExit(x509CandidateCertificate != nullptr, error = CHIP_ERROR_NO_MEMORY);
    1836             : 
    1837          12 :     x509issuerCertificate = d2i_X509(nullptr, &pIssuerCertificate, static_cast<long>(issuerCertificate.size()));
    1838          12 :     VerifyOrExit(x509issuerCertificate != nullptr, error = CHIP_ERROR_NO_MEMORY);
    1839             : 
    1840          12 :     candidateNotBeforeTime = X509_get_notBefore(x509CandidateCertificate);
    1841          12 :     issuerNotBeforeTime    = X509_get_notBefore(x509issuerCertificate);
    1842          12 :     issuerNotAfterTime     = X509_get_notAfter(x509issuerCertificate);
    1843          12 :     VerifyOrExit(candidateNotBeforeTime && issuerNotBeforeTime && issuerNotAfterTime, error = CHIP_ERROR_INTERNAL);
    1844             : 
    1845          12 :     result = ASN1_TIME_diff(&days, &seconds, issuerNotBeforeTime, candidateNotBeforeTime);
    1846          12 :     VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
    1847          12 :     result = _compareDaysAndSeconds(days, seconds);
    1848             : 
    1849             :     // check if candidateCertificate is issued at or after tbeCertificate's notBefore timestamp
    1850          12 :     VerifyOrExit(result >= 0, error = CHIP_ERROR_CERT_EXPIRED);
    1851             : 
    1852           8 :     result = ASN1_TIME_diff(&days, &seconds, issuerNotAfterTime, candidateNotBeforeTime);
    1853           8 :     VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
    1854           8 :     result = _compareDaysAndSeconds(days, seconds);
    1855             : 
    1856             :     // check if candidateCertificate is issued at or before tbeCertificate's notAfter timestamp
    1857           8 :     VerifyOrExit(result <= 0, error = CHIP_ERROR_CERT_EXPIRED);
    1858             : 
    1859          12 : exit:
    1860          12 :     X509_free(x509CandidateCertificate);
    1861          12 :     X509_free(x509issuerCertificate);
    1862             : 
    1863          12 :     return error;
    1864             : }
    1865             : 
    1866          90 : CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate)
    1867             : {
    1868          90 :     CHIP_ERROR error                   = CHIP_NO_ERROR;
    1869          90 :     X509 * x509Certificate             = nullptr;
    1870          90 :     const unsigned char * pCertificate = certificate.data();
    1871          90 :     ASN1_TIME * time                   = nullptr;
    1872          90 :     int result                         = 0;
    1873             : 
    1874          90 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1875             : 
    1876          90 :     x509Certificate = d2i_X509(nullptr, &pCertificate, static_cast<long>(certificate.size()));
    1877          90 :     VerifyOrExit(x509Certificate != nullptr, error = CHIP_ERROR_NO_MEMORY);
    1878             : 
    1879          90 :     time = X509_get_notBefore(x509Certificate);
    1880          90 :     VerifyOrExit(time, error = CHIP_ERROR_INTERNAL);
    1881             : 
    1882          90 :     result = X509_cmp_current_time(time);
    1883             :     // check if certificate's notBefore timestamp is earlier than or equal to current time.
    1884          90 :     VerifyOrExit(result == -1, error = CHIP_ERROR_CERT_EXPIRED);
    1885             : 
    1886          89 :     time = X509_get_notAfter(x509Certificate);
    1887          89 :     VerifyOrExit(time, error = CHIP_ERROR_INTERNAL);
    1888             : 
    1889          89 :     result = X509_cmp_current_time(time);
    1890             :     // check if certificate's notAfter timestamp is later than current time.
    1891          89 :     VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
    1892             : 
    1893          90 : exit:
    1894          90 :     X509_free(x509Certificate);
    1895             : 
    1896          90 :     return error;
    1897             : }
    1898             : 
    1899         402 : CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey)
    1900             : {
    1901         402 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    1902         402 :     EC_KEY * ec_key                      = nullptr;
    1903         402 :     EVP_PKEY * pkey                      = nullptr;
    1904         402 :     X509 * x509certificate               = nullptr;
    1905         402 :     const unsigned char * pCertificate   = certificate.data();
    1906         402 :     const unsigned char ** ppCertificate = &pCertificate;
    1907         402 :     unsigned char * pPubkey              = pubkey;
    1908         402 :     unsigned char ** ppPubkey            = &pPubkey;
    1909             :     int pkeyLen;
    1910             : 
    1911         402 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1912             : 
    1913         402 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    1914         402 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    1915             : 
    1916         402 :     pkey = X509_get_pubkey(x509certificate);
    1917         402 :     VerifyOrExit(pkey != nullptr, err = CHIP_ERROR_INTERNAL);
    1918         402 :     VerifyOrExit(EVP_PKEY_base_id(pkey) == EVP_PKEY_EC, err = CHIP_ERROR_INTERNAL);
    1919         402 :     VerifyOrExit(EVP_PKEY_bits(pkey) == 256, err = CHIP_ERROR_INTERNAL);
    1920             : 
    1921         402 :     ec_key = EVP_PKEY_get1_EC_KEY(pkey);
    1922         402 :     VerifyOrExit(ec_key != nullptr, err = CHIP_ERROR_NO_MEMORY);
    1923         402 :     VerifyOrExit(EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) == NID_X9_62_prime256v1, err = CHIP_ERROR_INTERNAL);
    1924             : 
    1925         401 :     pkeyLen = i2d_PublicKey(pkey, nullptr);
    1926         401 :     VerifyOrExit(pkeyLen == static_cast<int>(pubkey.Length()), err = CHIP_ERROR_INTERNAL);
    1927             : 
    1928         401 :     VerifyOrExit(i2d_PublicKey(pkey, ppPubkey) == pkeyLen, err = CHIP_ERROR_INTERNAL);
    1929             : 
    1930         402 : exit:
    1931         402 :     EC_KEY_free(ec_key);
    1932         402 :     EVP_PKEY_free(pkey);
    1933         402 :     X509_free(x509certificate);
    1934             : 
    1935         402 :     return err;
    1936             : }
    1937             : 
    1938             : namespace {
    1939             : 
    1940         346 : CHIP_ERROR ExtractKIDFromX509Cert(bool isSKID, const ByteSpan & certificate, MutableByteSpan & kid)
    1941             : {
    1942         346 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    1943         346 :     X509 * x509certificate               = nullptr;
    1944         346 :     const unsigned char * pCertificate   = certificate.data();
    1945         346 :     const unsigned char ** ppCertificate = &pCertificate;
    1946         346 :     const ASN1_OCTET_STRING * kidString  = nullptr;
    1947             : 
    1948         346 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1949             : 
    1950         346 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    1951         346 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    1952             : 
    1953         346 :     kidString = isSKID ? X509_get0_subject_key_id(x509certificate) : X509_get0_authority_key_id(x509certificate);
    1954         346 :     VerifyOrExit(kidString != nullptr, err = CHIP_ERROR_NOT_FOUND);
    1955         344 :     VerifyOrExit(CanCastTo<size_t>(kidString->length), err = CHIP_ERROR_INVALID_ARGUMENT);
    1956         344 :     VerifyOrExit(kidString->length == kSubjectKeyIdentifierLength, err = CHIP_ERROR_WRONG_CERT_TYPE);
    1957         344 :     VerifyOrExit(static_cast<size_t>(kidString->length) <= kid.size(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
    1958             : 
    1959         344 :     memcpy(kid.data(), kidString->data, static_cast<size_t>(kidString->length));
    1960             : 
    1961         344 :     kid.reduce_size(static_cast<size_t>(kidString->length));
    1962             : 
    1963         346 : exit:
    1964         346 :     X509_free(x509certificate);
    1965             : 
    1966         346 :     return err;
    1967             : }
    1968             : 
    1969             : } // namespace
    1970             : 
    1971         237 : CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid)
    1972             : {
    1973         237 :     return ExtractKIDFromX509Cert(true, certificate, skid);
    1974             : }
    1975             : 
    1976         109 : CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid)
    1977             : {
    1978         109 :     return ExtractKIDFromX509Cert(false, certificate, akid);
    1979             : }
    1980             : 
    1981          19 : CHIP_ERROR ExtractCRLDistributionPointURIFromX509Cert(const ByteSpan & certificate, MutableCharSpan & cdpurl)
    1982             : {
    1983          19 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    1984          19 :     X509 * x509certificate               = nullptr;
    1985          19 :     const unsigned char * pCertificate   = certificate.data();
    1986          19 :     const unsigned char ** ppCertificate = &pCertificate;
    1987          19 :     STACK_OF(DIST_POINT) * crldp         = nullptr;
    1988          19 :     DIST_POINT * dp                      = nullptr;
    1989          19 :     GENERAL_NAMES * gens                 = nullptr;
    1990          19 :     GENERAL_NAME * gen                   = nullptr;
    1991          19 :     ASN1_STRING * uri                    = nullptr;
    1992          19 :     const char * urlptr                  = nullptr;
    1993          19 :     size_t len                           = 0;
    1994             : 
    1995          19 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1996             : 
    1997          18 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    1998          18 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    1999             : 
    2000             :     // CRL Distribution Point Extension is encoded as a sequence of DistributionPoint:
    2001             :     //     CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
    2002             :     //
    2003             :     // This implementation only supports a single DistributionPoint (sequence of size 1)
    2004             :     crldp =
    2005          18 :         reinterpret_cast<STACK_OF(DIST_POINT) *>(X509_get_ext_d2i(x509certificate, NID_crl_distribution_points, nullptr, nullptr));
    2006          18 :     VerifyOrExit(crldp != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2007          13 :     VerifyOrExit(sk_DIST_POINT_num(crldp) == 1, err = CHIP_ERROR_NOT_FOUND);
    2008             : 
    2009          10 :     dp = sk_DIST_POINT_value(crldp, 0);
    2010          10 :     VerifyOrExit(dp != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2011          10 :     VerifyOrExit(dp->distpoint != nullptr && dp->distpoint->type == 0, err = CHIP_ERROR_NOT_FOUND);
    2012             : 
    2013             :     // The DistributionPoint is a sequence of three optional elements:
    2014             :     //     DistributionPoint ::= SEQUENCE {
    2015             :     //         distributionPoint       [0]     DistributionPointName OPTIONAL,
    2016             :     //         reasons                 [1]     ReasonFlags OPTIONAL,
    2017             :     //         cRLIssuer               [2]     GeneralNames OPTIONAL }
    2018             :     //
    2019             :     // where the DistributionPointName is a CHOICE of:
    2020             :     //     DistributionPointName ::= CHOICE {
    2021             :     //         fullName                [0]     GeneralNames,
    2022             :     //         nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
    2023             :     //
    2024             :     // The URI should be encoded in the fullName element.
    2025             :     // This implementation only supports a single GeneralName in the fullName sequence:
    2026             :     //     GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
    2027          10 :     gens = dp->distpoint->name.fullname;
    2028          10 :     VerifyOrExit(sk_GENERAL_NAME_num(gens) == 1, err = CHIP_ERROR_NOT_FOUND);
    2029             : 
    2030             :     // The CDP URI is encoded as a uniformResourceIdentifier field of the GeneralName:
    2031             :     //     GeneralName ::= CHOICE {
    2032             :     //         otherName                       [0]     OtherName,
    2033             :     //         rfc822Name                      [1]     IA5String,
    2034             :     //         dNSName                         [2]     IA5String,
    2035             :     //         x400Address                     [3]     ORAddress,
    2036             :     //         directoryName                   [4]     Name,
    2037             :     //         ediPartyName                    [5]     EDIPartyName,
    2038             :     //         uniformResourceIdentifier       [6]     IA5String,
    2039             :     //         iPAddress                       [7]     OCTET STRING,
    2040             :     //         registeredID                    [8]     OBJECT IDENTIFIER }
    2041           9 :     gen = sk_GENERAL_NAME_value(gens, 0);
    2042           9 :     VerifyOrExit(gen->type == GEN_URI, err = CHIP_ERROR_NOT_FOUND);
    2043             : 
    2044           9 :     uri    = reinterpret_cast<ASN1_STRING *>(GENERAL_NAME_get0_value(gen, nullptr));
    2045           9 :     urlptr = reinterpret_cast<const char *>(ASN1_STRING_get0_data(uri));
    2046           9 :     VerifyOrExit(CanCastTo<size_t>(ASN1_STRING_length(uri)), err = CHIP_ERROR_NOT_FOUND);
    2047           9 :     len = static_cast<size_t>(ASN1_STRING_length(uri));
    2048           9 :     VerifyOrExit(
    2049             :         (len > strlen(kValidCDPURIHttpPrefix) && strncmp(urlptr, kValidCDPURIHttpPrefix, strlen(kValidCDPURIHttpPrefix)) == 0) ||
    2050             :             (len > strlen(kValidCDPURIHttpsPrefix) &&
    2051             :              strncmp(urlptr, kValidCDPURIHttpsPrefix, strlen(kValidCDPURIHttpsPrefix)) == 0),
    2052             :         err = CHIP_ERROR_NOT_FOUND);
    2053           8 :     err = CopyCharSpanToMutableCharSpan(CharSpan(urlptr, len), cdpurl);
    2054             : 
    2055          18 : exit:
    2056          18 :     sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
    2057          18 :     X509_free(x509certificate);
    2058             : 
    2059          18 :     return err;
    2060             : }
    2061             : 
    2062          19 : CHIP_ERROR ExtractCDPExtensionCRLIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & crlIssuer)
    2063             : {
    2064          19 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    2065          19 :     int result                           = 1;
    2066          19 :     X509 * x509certificate               = nullptr;
    2067          19 :     const unsigned char * pCertificate   = certificate.data();
    2068          19 :     const unsigned char ** ppCertificate = &pCertificate;
    2069          19 :     STACK_OF(DIST_POINT) * crldp         = nullptr;
    2070          19 :     DIST_POINT * dp                      = nullptr;
    2071          19 :     GENERAL_NAMES * gens                 = nullptr;
    2072          19 :     GENERAL_NAME * gen                   = nullptr;
    2073          19 :     X509_NAME * dirName                  = nullptr;
    2074          19 :     const uint8_t * pDirName             = nullptr;
    2075          19 :     size_t dirNameLen                    = 0;
    2076             : 
    2077          19 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    2078             : 
    2079          18 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    2080          18 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2081             : 
    2082             :     // CRL Distribution Point Extension is encoded as a sequence of DistributionPoint:
    2083             :     //     CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
    2084             :     //
    2085             :     // This implementation only supports a single DistributionPoint (sequence of size 1)
    2086             :     crldp =
    2087          18 :         reinterpret_cast<STACK_OF(DIST_POINT) *>(X509_get_ext_d2i(x509certificate, NID_crl_distribution_points, nullptr, nullptr));
    2088          18 :     VerifyOrExit(crldp != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2089          13 :     VerifyOrExit(sk_DIST_POINT_num(crldp) == 1, err = CHIP_ERROR_NOT_FOUND);
    2090             : 
    2091          10 :     dp = sk_DIST_POINT_value(crldp, 0);
    2092          10 :     VerifyOrExit(dp != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2093             : 
    2094             :     // The DistributionPoint is a sequence of three optional elements:
    2095             :     //     DistributionPoint ::= SEQUENCE {
    2096             :     //         distributionPoint       [0]     DistributionPointName OPTIONAL,
    2097             :     //         reasons                 [1]     ReasonFlags OPTIONAL,
    2098             :     //         cRLIssuer               [2]     GeneralNames OPTIONAL }
    2099             :     //
    2100             :     // the cRLIssuer is encoded as a GeneralNames, where:
    2101             :     //     GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
    2102             :     // This implementation only supports a single GeneralName element in the cRLIssuer sequence:
    2103          10 :     gens = dp->CRLissuer;
    2104          10 :     VerifyOrExit(sk_GENERAL_NAME_num(gens) == 1, err = CHIP_ERROR_NOT_FOUND);
    2105             : 
    2106             :     // In this implementation the cRLIssuer is expected to be encoded as a directoryName field of the GeneralName:
    2107             :     //     GeneralName ::= CHOICE {
    2108             :     //         otherName                       [0]     OtherName,
    2109             :     //         rfc822Name                      [1]     IA5String,
    2110             :     //         dNSName                         [2]     IA5String,
    2111             :     //         x400Address                     [3]     ORAddress,
    2112             :     //         directoryName                   [4]     Name,
    2113             :     //         ediPartyName                    [5]     EDIPartyName,
    2114             :     //         uniformResourceIdentifier       [6]     IA5String,
    2115             :     //         iPAddress                       [7]     OCTET STRING,
    2116             :     //         registeredID                    [8]     OBJECT IDENTIFIER }
    2117           4 :     gen = sk_GENERAL_NAME_value(gens, 0);
    2118           4 :     VerifyOrExit(gen->type == GEN_DIRNAME, err = CHIP_ERROR_NOT_FOUND);
    2119             : 
    2120           4 :     dirName = reinterpret_cast<X509_NAME *>(GENERAL_NAME_get0_value(gen, nullptr));
    2121           4 :     VerifyOrExit(dirName != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2122             : 
    2123             :     // Extract directoryName as a raw DER Encoded data
    2124           4 :     result = X509_NAME_get0_der(dirName, &pDirName, &dirNameLen);
    2125           4 :     VerifyOrExit(result == 1, err = CHIP_ERROR_INTERNAL);
    2126           4 :     err = CopySpanToMutableSpan(ByteSpan(pDirName, dirNameLen), crlIssuer);
    2127             : 
    2128          18 : exit:
    2129          18 :     sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
    2130          18 :     X509_free(x509certificate);
    2131             : 
    2132          18 :     return err;
    2133             : }
    2134             : 
    2135           3 : CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber)
    2136             : {
    2137           3 :     CHIP_ERROR err                        = CHIP_NO_ERROR;
    2138           3 :     X509 * x509certificate                = nullptr;
    2139           3 :     auto * pCertificate                   = Uint8::to_const_uchar(certificate.data());
    2140           3 :     const unsigned char ** ppCertificate  = &pCertificate;
    2141           3 :     const ASN1_INTEGER * serialNumberASN1 = nullptr;
    2142           3 :     size_t serialNumberLen                = 0;
    2143             : 
    2144           3 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    2145             : 
    2146           3 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    2147           3 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2148             : 
    2149           3 :     serialNumberASN1 = X509_get_serialNumber(x509certificate);
    2150           3 :     VerifyOrExit(serialNumberASN1 != nullptr, err = CHIP_ERROR_INTERNAL);
    2151           3 :     VerifyOrExit(serialNumberASN1->data != nullptr, err = CHIP_ERROR_INTERNAL);
    2152           3 :     VerifyOrExit(CanCastTo<size_t>(serialNumberASN1->length), err = CHIP_ERROR_INTERNAL);
    2153             : 
    2154           3 :     serialNumberLen = static_cast<size_t>(serialNumberASN1->length);
    2155           3 :     VerifyOrExit(serialNumberLen <= serialNumber.size(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
    2156             : 
    2157           3 :     memcpy(serialNumber.data(), serialNumberASN1->data, serialNumberLen);
    2158           3 :     serialNumber.reduce_size(serialNumberLen);
    2159             : 
    2160           3 : exit:
    2161           3 :     X509_free(x509certificate);
    2162             : 
    2163           3 :     return err;
    2164             : }
    2165             : 
    2166             : namespace {
    2167          12 : CHIP_ERROR ExtractRawDNFromX509Cert(bool extractSubject, const ByteSpan & certificate, MutableByteSpan & dn)
    2168             : {
    2169          12 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    2170          12 :     int result                           = 1;
    2171          12 :     X509 * x509certificate               = nullptr;
    2172          12 :     auto * pCertificate                  = Uint8::to_const_uchar(certificate.data());
    2173          12 :     const unsigned char ** ppCertificate = &pCertificate;
    2174          12 :     X509_NAME * distinguishedName        = nullptr;
    2175          12 :     const uint8_t * pDistinguishedName   = nullptr;
    2176          12 :     size_t distinguishedNameLen          = 0;
    2177             : 
    2178          12 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    2179             : 
    2180          12 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    2181          12 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2182             : 
    2183          12 :     if (extractSubject)
    2184             :     {
    2185           9 :         distinguishedName = X509_get_subject_name(x509certificate);
    2186             :     }
    2187             :     else
    2188             :     {
    2189           3 :         distinguishedName = X509_get_issuer_name(x509certificate);
    2190             :     }
    2191          12 :     VerifyOrExit(distinguishedName != nullptr, err = CHIP_ERROR_INTERNAL);
    2192             : 
    2193          12 :     result = X509_NAME_get0_der(distinguishedName, &pDistinguishedName, &distinguishedNameLen);
    2194          12 :     VerifyOrExit(result == 1, err = CHIP_ERROR_INTERNAL);
    2195          12 :     err = CopySpanToMutableSpan(ByteSpan(pDistinguishedName, distinguishedNameLen), dn);
    2196             : 
    2197          12 : exit:
    2198          12 :     X509_free(x509certificate);
    2199             : 
    2200          12 :     return err;
    2201             : }
    2202             : } // namespace
    2203             : 
    2204           9 : CHIP_ERROR ExtractSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject)
    2205             : {
    2206           9 :     return ExtractRawDNFromX509Cert(true, certificate, subject);
    2207             : }
    2208             : 
    2209           3 : CHIP_ERROR ExtractIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & issuer)
    2210             : {
    2211           3 :     return ExtractRawDNFromX509Cert(false, certificate, issuer);
    2212             : }
    2213             : 
    2214         321 : CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
    2215             : {
    2216         321 :     ASN1_OBJECT * commonNameObj = OBJ_txt2obj("2.5.4.3", 1);
    2217         321 :     ASN1_OBJECT * matterVidObj  = OBJ_txt2obj("1.3.6.1.4.1.37244.2.1", 1); // Matter VID OID - taken from Spec
    2218         321 :     ASN1_OBJECT * matterPidObj  = OBJ_txt2obj("1.3.6.1.4.1.37244.2.2", 1); // Matter PID OID - taken from Spec
    2219             : 
    2220         321 :     CHIP_ERROR err                     = CHIP_NO_ERROR;
    2221         321 :     X509 * x509certificate             = nullptr;
    2222         321 :     const unsigned char * pCertificate = certificate.data();
    2223         321 :     X509_NAME * subject                = nullptr;
    2224         321 :     int x509EntryCountIdx              = 0;
    2225         321 :     AttestationCertVidPid vidpidFromCN;
    2226             : 
    2227         321 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    2228             : 
    2229         321 :     x509certificate = d2i_X509(nullptr, &pCertificate, static_cast<long>(certificate.size()));
    2230         321 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2231             : 
    2232         321 :     subject = X509_get_subject_name(x509certificate);
    2233         321 :     VerifyOrExit(subject != nullptr, err = CHIP_ERROR_INTERNAL);
    2234             : 
    2235        1087 :     for (x509EntryCountIdx = 0; x509EntryCountIdx < X509_NAME_entry_count(subject); ++x509EntryCountIdx)
    2236             :     {
    2237         778 :         X509_NAME_ENTRY * name_entry = X509_NAME_get_entry(subject, x509EntryCountIdx);
    2238         778 :         VerifyOrExit(name_entry != nullptr, err = CHIP_ERROR_INTERNAL);
    2239         778 :         ASN1_OBJECT * object = X509_NAME_ENTRY_get_object(name_entry);
    2240         778 :         VerifyOrExit(object != nullptr, err = CHIP_ERROR_INTERNAL);
    2241             : 
    2242         778 :         DNAttrType attrType = DNAttrType::kUnspecified;
    2243         778 :         if (OBJ_cmp(object, commonNameObj) == 0)
    2244             :         {
    2245         320 :             attrType = DNAttrType::kCommonName;
    2246             :         }
    2247         458 :         else if (OBJ_cmp(object, matterVidObj) == 0)
    2248             :         {
    2249         284 :             attrType = DNAttrType::kMatterVID;
    2250             :         }
    2251         174 :         else if (OBJ_cmp(object, matterPidObj) == 0)
    2252             :         {
    2253         172 :             attrType = DNAttrType::kMatterPID;
    2254             :         }
    2255             : 
    2256         778 :         if (attrType != DNAttrType::kUnspecified)
    2257             :         {
    2258         776 :             ASN1_STRING * data_entry = X509_NAME_ENTRY_get_data(name_entry);
    2259         776 :             VerifyOrExit(data_entry != nullptr, err = CHIP_ERROR_INTERNAL);
    2260         776 :             unsigned char * str = ASN1_STRING_data(data_entry);
    2261         776 :             VerifyOrExit(str != nullptr, err = CHIP_ERROR_INTERNAL);
    2262         776 :             int len = ASN1_STRING_length(data_entry);
    2263         776 :             VerifyOrExit(CanCastTo<size_t>(len), err = CHIP_ERROR_INTERNAL);
    2264             : 
    2265         776 :             err = ExtractVIDPIDFromAttributeString(attrType, ByteSpan(str, static_cast<size_t>(len)), vidpid, vidpidFromCN);
    2266         776 :             SuccessOrExit(err);
    2267             :         }
    2268             :     }
    2269             : 
    2270             :     // If Matter Attributes were not found use values extracted from the CN Attribute,
    2271             :     // which might be uninitialized as well.
    2272         309 :     if (!vidpid.Initialized())
    2273             :     {
    2274          23 :         vidpid = vidpidFromCN;
    2275             :     }
    2276             : 
    2277         286 : exit:
    2278         321 :     ASN1_OBJECT_free(commonNameObj);
    2279         321 :     ASN1_OBJECT_free(matterVidObj);
    2280         321 :     ASN1_OBJECT_free(matterPidObj);
    2281         321 :     X509_free(x509certificate);
    2282             : 
    2283         321 :     return err;
    2284         321 : }
    2285             : 
    2286          12 : CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate, const ByteSpan * candidateCertificates,
    2287             :                                           size_t candidateCertificatesCount, ByteSpan & outCertificate)
    2288             : {
    2289          12 :     CHIP_ERROR err                        = CHIP_NO_ERROR;
    2290          12 :     X509 * x509ReferenceCertificate       = nullptr;
    2291          12 :     X509 * x509CandidateCertificate       = nullptr;
    2292          12 :     const uint8_t * pReferenceCertificate = referenceCertificate.data();
    2293          12 :     X509_NAME * referenceSubject          = nullptr;
    2294          12 :     X509_NAME * candidateSubject          = nullptr;
    2295             :     uint8_t referenceSKIDBuf[kSubjectKeyIdentifierLength];
    2296             :     uint8_t candidateSKIDBuf[kSubjectKeyIdentifierLength];
    2297          12 :     MutableByteSpan referenceSKID(referenceSKIDBuf);
    2298          12 :     MutableByteSpan candidateSKID(candidateSKIDBuf);
    2299             : 
    2300          12 :     ReturnErrorCodeIf(referenceCertificate.empty(), CHIP_ERROR_INVALID_ARGUMENT);
    2301             : 
    2302          10 :     outCertificate = referenceCertificate;
    2303             : 
    2304          10 :     ReturnErrorCodeIf(candidateCertificates == nullptr || candidateCertificatesCount == 0, CHIP_NO_ERROR);
    2305             : 
    2306           8 :     ReturnErrorOnFailure(ExtractSKIDFromX509Cert(referenceCertificate, referenceSKID));
    2307             : 
    2308           8 :     x509ReferenceCertificate = d2i_X509(nullptr, &pReferenceCertificate, static_cast<long>(referenceCertificate.size()));
    2309           8 :     VerifyOrExit(x509ReferenceCertificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2310             : 
    2311           8 :     referenceSubject = X509_get_subject_name(x509ReferenceCertificate);
    2312           8 :     VerifyOrExit(referenceSubject != nullptr, err = CHIP_ERROR_INTERNAL);
    2313             : 
    2314          25 :     for (size_t i = 0; i < candidateCertificatesCount; i++)
    2315             :     {
    2316          21 :         const ByteSpan candidateCertificate   = candidateCertificates[i];
    2317          21 :         const uint8_t * pCandidateCertificate = candidateCertificate.data();
    2318             : 
    2319          25 :         VerifyOrExit(!candidateCertificate.empty(), err = CHIP_ERROR_INVALID_ARGUMENT);
    2320             : 
    2321          21 :         SuccessOrExit(err = ExtractSKIDFromX509Cert(candidateCertificate, candidateSKID));
    2322             : 
    2323          21 :         x509CandidateCertificate = d2i_X509(nullptr, &pCandidateCertificate, static_cast<long>(candidateCertificate.size()));
    2324          21 :         VerifyOrExit(x509CandidateCertificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2325             : 
    2326          21 :         candidateSubject = X509_get_subject_name(x509CandidateCertificate);
    2327          21 :         VerifyOrExit(candidateSubject != nullptr, err = CHIP_ERROR_INTERNAL);
    2328             : 
    2329          21 :         if (referenceSKID.data_equal(candidateSKID) && X509_NAME_cmp(referenceSubject, candidateSubject) == 0)
    2330             :         {
    2331           4 :             outCertificate = candidateCertificate;
    2332           4 :             ExitNow();
    2333             :         }
    2334             : 
    2335          17 :         X509_free(x509CandidateCertificate);
    2336          17 :         x509CandidateCertificate = nullptr;
    2337             :     }
    2338             : 
    2339           4 : exit:
    2340           8 :     X509_free(x509ReferenceCertificate);
    2341           8 :     X509_free(x509CandidateCertificate);
    2342             : 
    2343           8 :     return err;
    2344             : }
    2345             : 
    2346             : } // namespace Crypto
    2347             : } // namespace chip

Generated by: LCOV version 1.14