Matter SDK Coverage Report
Current view: top level - crypto - CHIPCryptoPALOpenSSL.cpp (source / functions) Coverage Total Hit
Test: SHA:f84fe08d06f240e801b5d923f8a938a9938ca110 Lines: 98.8 % 1252 1237
Test Date: 2025-02-22 08:08:07 Functions: 98.7 % 77 76

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

Generated by: LCOV version 2.0-1