Matter SDK Coverage Report
Current view: top level - crypto - CHIPCryptoPALOpenSSL.cpp (source / functions) Coverage Total Hit
Test: SHA:2a48c1efeab1c0f76f3adb3a0940b0f7de706453 Lines: 99.2 % 998 990
Test Date: 2026-01-31 08:14:20 Functions: 100.0 % 68 68

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

Generated by: LCOV version 2.0-1