Matter SDK Coverage Report
Current view: top level - crypto - CHIPCryptoPALOpenSSL.cpp (source / functions) Coverage Total Hit
Test: SHA:eef3dff3495fc72e1a63ed53e147d1a295978be2 Lines: 98.8 % 1259 1244
Test Date: 2025-08-14 07:13:02 Functions: 98.8 % 81 80

            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         4355 : static int _nidForCurve(ECName name)
      94              : {
      95         4355 :     switch (name)
      96              :     {
      97         4355 :     case ECName::P256v1:
      98         4355 :         return EC_curve_nist2nid("P-256");
      99              :         break;
     100              : 
     101            0 :     default:
     102            0 :         return NID_undef;
     103              :         break;
     104              :     }
     105              : }
     106              : 
     107         4895 : static void _logSSLError()
     108              : {
     109         4895 :     unsigned long ssl_err_code = ERR_get_error();
     110         4898 :     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         4895 : }
     125              : 
     126         9582 : static const EVP_MD * _digestForType(DigestType digestType)
     127              : {
     128         9582 :     switch (digestType)
     129              :     {
     130         9582 :     case DigestType::SHA256:
     131         9582 :         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        15184 : 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        15184 :     EVP_CIPHER_CTX * context = nullptr;
     159        15184 :     int bytesWritten         = 0;
     160        15184 :     size_t ciphertext_length = 0;
     161        15184 :     const EVP_CIPHER * type  = nullptr;
     162              : #endif
     163        15184 :     CHIP_ERROR error = CHIP_NO_ERROR;
     164        15184 :     int result       = 1;
     165              : 
     166              :     // Placeholder location for avoiding null params for plaintexts when
     167              :     // size is zero.
     168        15184 :     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        15184 :     bool ciphertext_was_null = (ciphertext == nullptr);
     175              : 
     176        15184 :     if (plaintext_length == 0)
     177              :     {
     178            7 :         if (plaintext == nullptr)
     179              :         {
     180            5 :             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            7 :         if (ciphertext_was_null)
     185              :         {
     186            7 :             ciphertext = &placeholder_ciphertext[0];
     187              :         }
     188              :     }
     189              : 
     190        15184 :     VerifyOrExit((plaintext_length != 0) || ciphertext_was_null, error = CHIP_ERROR_INVALID_ARGUMENT);
     191        15184 :     VerifyOrExit(plaintext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     192        15184 :     VerifyOrExit(ciphertext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     193        15184 :     VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     194        15184 :     VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     195        15183 :     VerifyOrExit(CanCastTo<int>(nonce_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     196        15183 :     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        15183 :     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        15182 :     type = EVP_aes_128_ccm();
     217              : 
     218        15182 :     context = EVP_CIPHER_CTX_new();
     219        15182 :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
     220              : 
     221              :     // Pass in cipher
     222        15182 :     result = EVP_EncryptInit_ex(context, type, nullptr, nullptr, nullptr);
     223        15182 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     224              : 
     225              :     // Pass in nonce length.  Cast is safe because we checked with CanCastTo.
     226        15182 :     result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_IVLEN, static_cast<int>(nonce_length), nullptr);
     227        15182 :     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        15182 :     result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_TAG, static_cast<int>(tag_length), nullptr);
     231        15182 :     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        15182 :     result = EVP_EncryptInit_ex(context, nullptr, nullptr, key.As<Symmetric128BitsKeyByteArray>(), Uint8::to_const_uchar(nonce));
     236        15182 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     237              : 
     238              :     // Pass in plain text length
     239        15182 :     VerifyOrExit(CanCastTo<int>(plaintext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     240        15182 :     result = EVP_EncryptUpdate(context, nullptr, &bytesWritten, nullptr, static_cast<int>(plaintext_length));
     241        15182 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     242              : 
     243              :     // Pass in AAD
     244        15182 :     if (aad_length > 0 && aad != nullptr)
     245              :     {
     246        15026 :         VerifyOrExit(CanCastTo<int>(aad_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     247        15026 :         result = EVP_EncryptUpdate(context, nullptr, &bytesWritten, Uint8::to_const_uchar(aad), static_cast<int>(aad_length));
     248        15026 :         VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     249              :     }
     250              : 
     251              :     // Encrypt
     252        15182 :     VerifyOrExit(CanCastTo<int>(plaintext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     253        15182 :     result = EVP_EncryptUpdate(context, Uint8::to_uchar(ciphertext), &bytesWritten, Uint8::to_const_uchar(plaintext),
     254              :                                             static_cast<int>(plaintext_length));
     255        15182 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     256        15182 :     VerifyOrExit((ciphertext_was_null && bytesWritten == 0) || (bytesWritten >= 0), error = CHIP_ERROR_INTERNAL);
     257        15182 :     ciphertext_length = static_cast<unsigned int>(bytesWritten);
     258              : 
     259              :     // Finalize encryption
     260        15182 :     result = EVP_EncryptFinal_ex(context, ciphertext + ciphertext_length, &bytesWritten);
     261        15182 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     262        15182 :     VerifyOrExit(bytesWritten >= 0 && bytesWritten <= static_cast<int>(plaintext_length), error = CHIP_ERROR_INTERNAL);
     263              : 
     264              :     // Get tag
     265        15182 :     VerifyOrExit(CanCastTo<int>(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     266        15182 :     result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_GET_TAG, static_cast<int>(tag_length), Uint8::to_uchar(tag));
     267        15182 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     268              : #endif // CHIP_CRYPTO_BORINGSSL
     269              : 
     270        15184 : exit:
     271        15184 :     if (context != nullptr)
     272              :     {
     273              : #if CHIP_CRYPTO_BORINGSSL
     274              :         EVP_AEAD_CTX_free(context);
     275              : #else
     276        15182 :         EVP_CIPHER_CTX_free(context);
     277              : #endif // CHIP_CRYPTO_BORINGSSL
     278        15182 :         context = nullptr;
     279              :     }
     280              : 
     281        15184 :     return error;
     282              : }
     283              : 
     284        15035 : 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        15035 :     EVP_CIPHER_CTX * context = nullptr;
     294        15035 :     int bytesOutput          = 0;
     295        15035 :     const EVP_CIPHER * type  = nullptr;
     296              : #endif // CHIP_CRYPTO_BORINGSSL
     297        15035 :     CHIP_ERROR error = CHIP_NO_ERROR;
     298        15035 :     int result       = 1;
     299              : 
     300              :     // Placeholder location for avoiding null params for ciphertext when
     301              :     // size is zero.
     302        15035 :     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        15035 :     bool plaintext_was_null = (plaintext == nullptr);
     309              : 
     310        15035 :     if (ciphertext_length == 0)
     311              :     {
     312            5 :         if (ciphertext == nullptr)
     313              :         {
     314            4 :             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            5 :         if (plaintext_was_null)
     319              :         {
     320            5 :             plaintext = &placeholder_plaintext[0];
     321              :         }
     322              :     }
     323              : 
     324        15035 :     VerifyOrExit(ciphertext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     325        15035 :     VerifyOrExit(plaintext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     326        15035 :     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        15035 :     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        15035 :     VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     334        15035 :     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        15034 :     type = EVP_aes_128_ccm();
     347              : 
     348        15034 :     context = EVP_CIPHER_CTX_new();
     349        15034 :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
     350              : 
     351              :     // Pass in cipher
     352        15034 :     result = EVP_DecryptInit_ex(context, type, nullptr, nullptr, nullptr);
     353        15034 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     354              : 
     355              :     // Pass in nonce length
     356        15034 :     VerifyOrExit(CanCastTo<int>(nonce_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     357        15034 :     result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_IVLEN, static_cast<int>(nonce_length), nullptr);
     358        15034 :     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        15034 :     VerifyOrExit(CanCastTo<int>(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     364        15034 :     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        15034 :     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        15034 :     result = EVP_DecryptInit_ex(context, nullptr, nullptr, key.As<Symmetric128BitsKeyByteArray>(), Uint8::to_const_uchar(nonce));
     371        15034 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     372              : 
     373              :     // Pass in cipher text length
     374        15034 :     VerifyOrExit(CanCastTo<int>(ciphertext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     375        15034 :     result = EVP_DecryptUpdate(context, nullptr, &bytesOutput, nullptr, static_cast<int>(ciphertext_length));
     376        15034 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     377        15034 :     VerifyOrExit(bytesOutput <= static_cast<int>(ciphertext_length), error = CHIP_ERROR_INTERNAL);
     378              : 
     379              :     // Pass in aad
     380        15034 :     if (aad_length > 0 && aad != nullptr)
     381              :     {
     382        14911 :         VerifyOrExit(CanCastTo<int>(aad_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     383        14911 :         result = EVP_DecryptUpdate(context, nullptr, &bytesOutput, Uint8::to_const_uchar(aad), static_cast<int>(aad_length));
     384        14911 :         VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     385        14911 :         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        15034 :     VerifyOrExit(CanCastTo<int>(ciphertext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     390        15034 :     result = EVP_DecryptUpdate(context, Uint8::to_uchar(plaintext), &bytesOutput, Uint8::to_const_uchar(ciphertext),
     391              :                                             static_cast<int>(ciphertext_length));
     392        15034 :     if (plaintext_was_null)
     393              :     {
     394            5 :         VerifyOrExit(bytesOutput <= static_cast<int>(sizeof(placeholder_plaintext)), error = CHIP_ERROR_INTERNAL);
     395              :     }
     396        15034 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     397              : #endif // CHIP_CRYPTO_BORINGSSL
     398              : 
     399        15035 : exit:
     400        15035 :     if (context != nullptr)
     401              :     {
     402              : #if CHIP_CRYPTO_BORINGSSL
     403              :         EVP_AEAD_CTX_free(context);
     404              : #else
     405        15034 :         EVP_CIPHER_CTX_free(context);
     406              : #endif // CHIP_CRYPTO_BORINGSSL
     407              : 
     408        15034 :         context = nullptr;
     409              :     }
     410              : 
     411        15035 :     return error;
     412              : }
     413              : 
     414         4241 : 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         4241 :     VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     418         4241 :     VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     419              : 
     420         4241 :     SHA256(data, data_length, Uint8::to_uchar(out_buffer));
     421              : 
     422         4241 :     return CHIP_NO_ERROR;
     423              : }
     424              : 
     425          412 : 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          412 :     VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     429          412 :     VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     430              : 
     431          412 :     SHA1(data, data_length, Uint8::to_uchar(out_buffer));
     432              : 
     433          412 :     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         6420 : static inline void set_inner_hash_evp_md_ctx(HashSHA256OpaqueContext * context, EVP_MD_CTX * evp_ctx)
     443              : {
     444         6420 :     *SafePointerCast<EVP_MD_CTX **>(context) = evp_ctx;
     445         6420 : }
     446              : 
     447        18129 : static inline EVP_MD_CTX * to_inner_hash_evp_md_ctx(HashSHA256OpaqueContext * context)
     448              : {
     449        18129 :     return *SafePointerCast<EVP_MD_CTX **>(context);
     450              : }
     451              : 
     452         1340 : Hash_SHA256_stream::Hash_SHA256_stream()
     453              : {
     454         1340 :     set_inner_hash_evp_md_ctx(&mContext, nullptr);
     455         1340 : }
     456              : 
     457         1340 : Hash_SHA256_stream::~Hash_SHA256_stream()
     458              : {
     459         1340 :     Clear();
     460         1340 : }
     461              : 
     462         1334 : CHIP_ERROR Hash_SHA256_stream::Begin()
     463              : {
     464              : 
     465         1334 :     EVP_MD_CTX * mdctx = EVP_MD_CTX_new();
     466         1334 :     VerifyOrReturnError(mdctx != nullptr, CHIP_ERROR_INTERNAL);
     467              : 
     468         1334 :     set_inner_hash_evp_md_ctx(&mContext, mdctx);
     469              : 
     470         1334 :     const int result = EVP_DigestInit_ex(mdctx, _digestForType(DigestType::SHA256), nullptr);
     471              : 
     472         1334 :     VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
     473              : 
     474         1334 :     return CHIP_NO_ERROR;
     475              : }
     476              : 
     477         8234 : bool Hash_SHA256_stream::IsInitialized()
     478              : {
     479         8234 :     EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
     480         8234 :     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         8234 :     return EVP_MD_CTX_get0_md(mdctx) == _digestForType(DigestType::SHA256);
     490              : #endif
     491              : }
     492              : 
     493         2887 : CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data)
     494              : {
     495         2887 :     VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear());
     496              : 
     497         2887 :     EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
     498         2887 :     VerifyOrReturnError(mdctx != nullptr, CHIP_ERROR_INTERNAL);
     499              : 
     500         2887 :     const int result = EVP_DigestUpdate(mdctx, data.data(), data.size());
     501              : 
     502         2887 :     VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
     503              : 
     504         2887 :     return CHIP_NO_ERROR;
     505              : }
     506              : 
     507         2085 : CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer)
     508              : {
     509              : 
     510         2085 :     VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear());
     511              : 
     512         2085 :     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         2085 :     EVP_MD_CTX * previous_mdctx = EVP_MD_CTX_new();
     516         2085 :     VerifyOrReturnError(previous_mdctx != nullptr, CHIP_ERROR_INTERNAL);
     517         2085 :     const int copy_result = EVP_MD_CTX_copy_ex(previous_mdctx, mdctx);
     518         2085 :     VerifyOrReturnError(copy_result == 1, CHIP_ERROR_INTERNAL);
     519              : 
     520              :     // Pad + compute digest, then finalize context. It is restored next line to continue.
     521         2085 :     CHIP_ERROR result = Finish(out_buffer);
     522              : 
     523              :     // free the finalized context.
     524         2085 :     EVP_MD_CTX_free(mdctx);
     525              : 
     526              :     // Restore the backed up context, to be able to get intermediate digest again if needed
     527         2085 :     set_inner_hash_evp_md_ctx(&mContext, previous_mdctx);
     528              : 
     529         2085 :     return result;
     530              : }
     531              : 
     532         3264 : CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer)
     533              : {
     534              :     unsigned int size;
     535              : 
     536         3264 :     VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
     537         3262 :     VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear());
     538              : 
     539         3262 :     EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
     540              : 
     541         3262 :     const int result = EVP_DigestFinal_ex(mdctx, out_buffer.data(), &size);
     542              : 
     543         3262 :     VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
     544         3262 :     VerifyOrReturnError(size == kSHA256_Hash_Length, CHIP_ERROR_INTERNAL);
     545              : 
     546         3262 :     out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length);
     547              : 
     548         3262 :     return CHIP_NO_ERROR;
     549              : }
     550              : 
     551         1661 : void Hash_SHA256_stream::Clear()
     552              : {
     553         1661 :     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         1661 :     EVP_MD_CTX_free(mdctx);
     557         1661 :     set_inner_hash_evp_md_ctx(&mContext, nullptr);
     558              : 
     559         1661 :     OPENSSL_cleanse(this, sizeof(*this));
     560         1661 : }
     561              : 
     562         3993 : 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         3993 :     CHIP_ERROR error = CHIP_NO_ERROR;
     566         3993 :     int result       = 1;
     567              : 
     568         3993 :     EVP_PKEY_CTX * const context = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
     569         3993 :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_INTERNAL);
     570              : 
     571         3993 :     VerifyOrExit(secret != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     572         3993 :     VerifyOrExit(secret_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     573              : 
     574              :     // Salt is optional
     575         3993 :     if (salt_length > 0)
     576              :     {
     577         1113 :         VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     578              :     }
     579              : 
     580         3993 :     VerifyOrExit(info_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     581         3993 :     VerifyOrExit(info != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     582         3993 :     VerifyOrExit(out_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
     583         3993 :     VerifyOrExit(out_buffer != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     584              : 
     585         3993 :     result = EVP_PKEY_derive_init(context);
     586         3993 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     587              : 
     588         3993 :     result = EVP_PKEY_CTX_set_hkdf_md(context, EVP_sha256());
     589         3993 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     590              : 
     591         3993 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(secret_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     592         3993 :     result = EVP_PKEY_CTX_set1_hkdf_key(context, Uint8::to_const_uchar(secret),
     593              :                                         static_cast<boringssl_size_t_openssl_int>(secret_length));
     594         3993 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     595              : 
     596         3993 :     if (salt_length > 0 && salt != nullptr)
     597              :     {
     598         1113 :         VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(salt_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     599         1113 :         result = EVP_PKEY_CTX_set1_hkdf_salt(context, Uint8::to_const_uchar(salt),
     600              :                                              static_cast<boringssl_size_t_openssl_int>(salt_length));
     601         1113 :         VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     602              :     }
     603              : 
     604         3993 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(info_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     605              :     result =
     606         3993 :         EVP_PKEY_CTX_add1_hkdf_info(context, Uint8::to_const_uchar(info), static_cast<boringssl_size_t_openssl_int>(info_length));
     607         3993 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     608              : 
     609         3993 :     result = EVP_PKEY_CTX_hkdf_mode(context, EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND);
     610         3993 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     611              : 
     612              :     // Get the OKM (Output Key Material)
     613         3993 :     result = EVP_PKEY_derive(context, Uint8::to_uchar(out_buffer), &out_length);
     614         3993 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     615              : 
     616         3993 : exit:
     617         3993 :     if (context != nullptr)
     618              :     {
     619         3993 :         EVP_PKEY_CTX_free(context);
     620              :     }
     621         3993 :     return error;
     622              : }
     623              : 
     624          124 : 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          124 :     VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     628          124 :     VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
     629          124 :     VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     630          124 :     VerifyOrReturnError(message_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
     631          124 :     VerifyOrReturnError(out_length >= kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
     632          124 :     VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     633              : 
     634          124 :     CHIP_ERROR error         = CHIP_ERROR_INTERNAL;
     635          124 :     int error_openssl        = 0;
     636          124 :     unsigned int mac_out_len = 0;
     637              : 
     638          124 :     HMAC_CTX * mac_ctx = HMAC_CTX_new();
     639          124 :     VerifyOrExit(mac_ctx != nullptr, error = CHIP_ERROR_INTERNAL);
     640              : 
     641          124 :     VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(key_length), error = CHIP_ERROR_INVALID_ARGUMENT);
     642          124 :     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          124 :     VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
     645              : 
     646          124 :     error_openssl = HMAC_Update(mac_ctx, Uint8::to_const_uchar(message), message_length);
     647          124 :     VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
     648              : 
     649          124 :     mac_out_len   = static_cast<unsigned int>(CHIP_CRYPTO_HASH_LEN_BYTES);
     650          124 :     error_openssl = HMAC_Final(mac_ctx, Uint8::to_uchar(out_buffer), &mac_out_len);
     651          124 :     VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
     652              : 
     653          124 :     error = CHIP_NO_ERROR;
     654          124 : exit:
     655          124 :     HMAC_CTX_free(mac_ctx);
     656          124 :     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       151499 : CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length)
     710              : {
     711       151499 :     VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     712       151498 :     VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
     713              : 
     714       151497 :     VerifyOrReturnError(CanCastTo<boringssl_size_t_openssl_int>(out_length), CHIP_ERROR_INVALID_ARGUMENT);
     715       151497 :     const int result = RAND_priv_bytes(Uint8::to_uchar(out_buffer), static_cast<boringssl_size_t_openssl_int>(out_length));
     716       151497 :     VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
     717              : 
     718       151497 :     return CHIP_NO_ERROR;
     719              : }
     720              : 
     721         4355 : ECName MapECName(SupportedECPKeyTypes keyType)
     722              : {
     723         4355 :     switch (keyType)
     724              :     {
     725         4355 :     case SupportedECPKeyTypes::ECP256R1:
     726         4355 :         return ECName::P256v1;
     727            0 :     default:
     728            0 :         return ECName::None;
     729              :     }
     730              : }
     731              : 
     732         1832 : static inline void from_EC_KEY(EC_KEY * key, P256KeypairContext * context)
     733              : {
     734         1832 :     *SafePointerCast<EC_KEY **>(context) = key;
     735         1832 : }
     736              : 
     737         2182 : static inline EC_KEY * to_EC_KEY(P256KeypairContext * context)
     738              : {
     739         2182 :     return *SafePointerCast<EC_KEY **>(context);
     740              : }
     741              : 
     742          789 : static inline const EC_KEY * to_const_EC_KEY(const P256KeypairContext * context)
     743              : {
     744          789 :     return *SafePointerCast<const EC_KEY * const *>(context);
     745              : }
     746              : 
     747          317 : CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
     748              : {
     749          317 :     CHIP_ERROR error = CHIP_NO_ERROR;
     750          317 :     int nid          = NID_undef;
     751          317 :     EC_KEY * ec_key  = nullptr;
     752          317 :     ECDSA_SIG * sig  = nullptr;
     753          317 :     const BIGNUM * r = nullptr;
     754          317 :     const BIGNUM * s = nullptr;
     755              : 
     756          317 :     VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
     757              : 
     758              :     uint8_t digest[kSHA256_Hash_Length];
     759          315 :     memset(&digest[0], 0, sizeof(digest));
     760              : 
     761          315 :     ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
     762              : 
     763          315 :     ERR_clear_error();
     764              : 
     765              :     static_assert(P256ECDSASignature::Capacity() >= kP256_ECDSA_Signature_Length_Raw, "P256ECDSASignature must be large enough");
     766          315 :     VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
     767          315 :     nid = _nidForCurve(MapECName(mPublicKey.Type()));
     768          315 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
     769              : 
     770          315 :     ec_key = to_EC_KEY(&mKeypair);
     771          315 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
     772              : 
     773          315 :     sig = ECDSA_do_sign(Uint8::to_const_uchar(&digest[0]), static_cast<boringssl_size_t_openssl_int>(sizeof(digest)), ec_key);
     774          315 :     VerifyOrExit(sig != nullptr, error = CHIP_ERROR_INTERNAL);
     775          315 :     ECDSA_SIG_get0(sig, &r, &s);
     776          315 :     VerifyOrExit((r != nullptr) && (s != nullptr), error = CHIP_ERROR_INTERNAL);
     777          315 :     VerifyOrExit(CanCastTo<size_t>(BN_num_bytes(r)) && CanCastTo<size_t>(BN_num_bytes(s)), error = CHIP_ERROR_INTERNAL);
     778          315 :     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          315 :     VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
     784          315 :     VerifyOrExit(BN_bn2binpad(r, out_signature.Bytes() + 0u, kP256_FE_Length) == kP256_FE_Length, error = CHIP_ERROR_INTERNAL);
     785          315 :     VerifyOrExit(BN_bn2binpad(s, out_signature.Bytes() + kP256_FE_Length, kP256_FE_Length) == kP256_FE_Length,
     786              :                  error = CHIP_ERROR_INTERNAL);
     787              : 
     788          315 : exit:
     789          315 :     if (sig != nullptr)
     790              :     {
     791              :         // SIG owns the memory of r, s
     792          315 :         ECDSA_SIG_free(sig);
     793              :     }
     794              : 
     795          315 :     if (error != CHIP_NO_ERROR)
     796              :     {
     797            0 :         _logSSLError();
     798              :     }
     799              : 
     800          315 :     return error;
     801              : }
     802              : 
     803          137 : CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length,
     804              :                                                        const P256ECDSASignature & signature) const
     805              : {
     806          137 :     VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
     807              : 
     808              :     uint8_t digest[kSHA256_Hash_Length];
     809          135 :     memset(&digest[0], 0, sizeof(digest));
     810              : 
     811          135 :     ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
     812          135 :     return ECDSA_validate_hash_signature(&digest[0], sizeof(digest), signature);
     813              : }
     814              : 
     815         1977 : CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length,
     816              :                                                         const P256ECDSASignature & signature) const
     817              : {
     818         1977 :     ERR_clear_error();
     819         1977 :     CHIP_ERROR error     = CHIP_ERROR_INTERNAL;
     820         1977 :     int nid              = NID_undef;
     821         1977 :     EC_KEY * ec_key      = nullptr;
     822         1977 :     EC_POINT * key_point = nullptr;
     823         1977 :     EC_GROUP * ec_group  = nullptr;
     824         1977 :     ECDSA_SIG * ec_sig   = nullptr;
     825         1977 :     BIGNUM * r           = nullptr;
     826         1977 :     BIGNUM * s           = nullptr;
     827         1977 :     int result           = 0;
     828              : 
     829         1977 :     VerifyOrExit(hash != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     830         1976 :     VerifyOrExit(hash_length == kSHA256_Hash_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
     831         1975 :     VerifyOrExit(signature.Length() == kP256_ECDSA_Signature_Length_Raw, error = CHIP_ERROR_INVALID_ARGUMENT);
     832              : 
     833         1975 :     nid = _nidForCurve(MapECName(Type()));
     834         1975 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
     835              : 
     836         1975 :     ec_group = EC_GROUP_new_by_curve_name(nid);
     837         1975 :     VerifyOrExit(ec_group != nullptr, error = CHIP_ERROR_NO_MEMORY);
     838              : 
     839         1975 :     key_point = EC_POINT_new(ec_group);
     840         1975 :     VerifyOrExit(key_point != nullptr, error = CHIP_ERROR_NO_MEMORY);
     841              : 
     842         1975 :     result = EC_POINT_oct2point(ec_group, key_point, Uint8::to_const_uchar(*this), Length(), nullptr);
     843         1975 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     844              : 
     845         1975 :     ec_key = EC_KEY_new_by_curve_name(nid);
     846         1975 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_NO_MEMORY);
     847              : 
     848         1975 :     result = EC_KEY_set_public_key(ec_key, key_point);
     849         1975 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     850              : 
     851         1975 :     result = EC_KEY_check_key(ec_key);
     852         1975 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     853              : 
     854              :     // Build-up the signature object from raw <r,s> tuple
     855         1975 :     r = BN_bin2bn(Uint8::to_const_uchar(signature.ConstBytes()) + 0u, kP256_FE_Length, nullptr);
     856         1975 :     VerifyOrExit(r != nullptr, error = CHIP_ERROR_NO_MEMORY);
     857              : 
     858         1975 :     s = BN_bin2bn(Uint8::to_const_uchar(signature.ConstBytes()) + kP256_FE_Length, kP256_FE_Length, nullptr);
     859         1975 :     VerifyOrExit(s != nullptr, error = CHIP_ERROR_NO_MEMORY);
     860              : 
     861         1975 :     ec_sig = ECDSA_SIG_new();
     862         1975 :     VerifyOrExit(ec_sig != nullptr, error = CHIP_ERROR_NO_MEMORY);
     863              : 
     864         1975 :     result = ECDSA_SIG_set0(ec_sig, r, s);
     865         1975 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     866              : 
     867         1975 :     result = ECDSA_do_verify(Uint8::to_const_uchar(hash), static_cast<boringssl_size_t_openssl_int>(hash_length), ec_sig, ec_key);
     868         1975 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INVALID_SIGNATURE);
     869         1963 :     error = CHIP_NO_ERROR;
     870              : 
     871         1977 : exit:
     872         1977 :     _logSSLError();
     873         1977 :     if (ec_sig != nullptr)
     874              :     {
     875         1975 :         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         1975 :         r = nullptr;
     880         1975 :         s = nullptr;
     881              :     }
     882         1977 :     if (s != nullptr)
     883              :     {
     884            0 :         BN_clear_free(s);
     885              :     }
     886         1977 :     if (r != nullptr)
     887              :     {
     888            0 :         BN_clear_free(r);
     889              :     }
     890         1977 :     if (ec_key != nullptr)
     891              :     {
     892         1975 :         EC_KEY_free(ec_key);
     893              :     }
     894         1977 :     if (key_point != nullptr)
     895              :     {
     896         1975 :         EC_POINT_clear_free(key_point);
     897              :     }
     898         1977 :     if (ec_group != nullptr)
     899              :     {
     900         1975 :         EC_GROUP_free(ec_group);
     901              :     }
     902         1977 :     return error;
     903              : }
     904              : 
     905              : // helper function to populate octet key into EVP_PKEY out_evp_pkey. Caller must free out_evp_pkey
     906           26 : static CHIP_ERROR _create_evp_key_from_binary_p256_key(const P256PublicKey & key, EVP_PKEY ** out_evp_pkey)
     907              : {
     908              : 
     909           26 :     CHIP_ERROR error = CHIP_NO_ERROR;
     910           26 :     EC_KEY * ec_key  = nullptr;
     911           26 :     int result       = -1;
     912           26 :     EC_POINT * point = nullptr;
     913           26 :     EC_GROUP * group = nullptr;
     914           26 :     int nid          = NID_undef;
     915              : 
     916           26 :     VerifyOrExit(*out_evp_pkey == nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
     917              : 
     918           26 :     nid = _nidForCurve(MapECName(key.Type()));
     919           26 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INTERNAL);
     920              : 
     921           26 :     ec_key = EC_KEY_new_by_curve_name(nid);
     922           26 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
     923              : 
     924           26 :     group = EC_GROUP_new_by_curve_name(nid);
     925           26 :     VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
     926              : 
     927           26 :     point = EC_POINT_new(group);
     928           26 :     VerifyOrExit(point != nullptr, error = CHIP_ERROR_INTERNAL);
     929              : 
     930           26 :     result = EC_POINT_oct2point(group, point, Uint8::to_const_uchar(key), key.Length(), nullptr);
     931           26 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     932              : 
     933           26 :     result = EC_KEY_set_public_key(ec_key, point);
     934              : 
     935           26 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     936              : 
     937           26 :     *out_evp_pkey = EVP_PKEY_new();
     938           26 :     VerifyOrExit(*out_evp_pkey != nullptr, error = CHIP_ERROR_INTERNAL);
     939              : 
     940           26 :     result = EVP_PKEY_set1_EC_KEY(*out_evp_pkey, ec_key);
     941           26 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     942              : 
     943           26 : exit:
     944           26 :     if (ec_key != nullptr)
     945              :     {
     946           26 :         EC_KEY_free(ec_key);
     947           26 :         ec_key = nullptr;
     948              :     }
     949              : 
     950           26 :     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           26 :     if (point != nullptr)
     957              :     {
     958           26 :         EC_POINT_free(point);
     959           26 :         point = nullptr;
     960              :     }
     961              : 
     962           26 :     if (group != nullptr)
     963              :     {
     964           26 :         EC_GROUP_free(group);
     965           26 :         group = nullptr;
     966              :     }
     967              : 
     968           26 :     return error;
     969              : }
     970              : 
     971           26 : CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
     972              : {
     973           26 :     ERR_clear_error();
     974           26 :     CHIP_ERROR error      = CHIP_NO_ERROR;
     975           26 :     int result            = -1;
     976           26 :     EVP_PKEY * local_key  = nullptr;
     977           26 :     EVP_PKEY * remote_key = nullptr;
     978              : 
     979           26 :     EVP_PKEY_CTX * context = nullptr;
     980           26 :     size_t out_buf_length  = 0;
     981              : 
     982           26 :     EC_KEY * ec_key = EC_KEY_dup(to_const_EC_KEY(&mKeypair));
     983           26 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
     984              : 
     985           26 :     VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
     986              : 
     987           26 :     local_key = EVP_PKEY_new();
     988           26 :     VerifyOrExit(local_key != nullptr, error = CHIP_ERROR_INTERNAL);
     989              : 
     990           26 :     result = EVP_PKEY_set1_EC_KEY(local_key, ec_key);
     991           26 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
     992              : 
     993           26 :     error = _create_evp_key_from_binary_p256_key(remote_public_key, &remote_key);
     994           26 :     SuccessOrExit(error);
     995              : 
     996           26 :     context = EVP_PKEY_CTX_new(local_key, nullptr);
     997           26 :     VerifyOrExit(context != nullptr, error = CHIP_ERROR_INTERNAL);
     998              : 
     999           26 :     result = EVP_PKEY_derive_init(context);
    1000           26 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1001              : 
    1002           26 :     result = EVP_PKEY_derive_set_peer(context, remote_key);
    1003           26 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1004              : 
    1005           26 :     out_buf_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length();
    1006           26 :     result         = EVP_PKEY_derive(context, out_secret.Bytes(), &out_buf_length);
    1007           26 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1008           26 :     SuccessOrExit(error = out_secret.SetLength(out_buf_length));
    1009              : 
    1010           26 : exit:
    1011           26 :     if (ec_key != nullptr)
    1012              :     {
    1013           26 :         EC_KEY_free(ec_key);
    1014           26 :         ec_key = nullptr;
    1015              :     }
    1016              : 
    1017           26 :     if (local_key != nullptr)
    1018              :     {
    1019           26 :         EVP_PKEY_free(local_key);
    1020           26 :         local_key = nullptr;
    1021              :     }
    1022              : 
    1023           26 :     if (remote_key != nullptr)
    1024              :     {
    1025           26 :         EVP_PKEY_free(remote_key);
    1026           26 :         remote_key = nullptr;
    1027              :     }
    1028              : 
    1029           26 :     if (context != nullptr)
    1030              :     {
    1031           26 :         EVP_PKEY_CTX_free(context);
    1032           26 :         context = nullptr;
    1033              :     }
    1034              : 
    1035           26 :     _logSSLError();
    1036           26 :     return error;
    1037              : }
    1038              : 
    1039       417844 : void ClearSecretData(uint8_t * buf, size_t len)
    1040              : {
    1041       417844 :     OPENSSL_cleanse(buf, len);
    1042       417844 : }
    1043              : 
    1044          834 : bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n)
    1045              : {
    1046          834 :     return CRYPTO_memcmp(a, b, n) == 0;
    1047              : }
    1048              : 
    1049          207 : static CHIP_ERROR P256PublicKeyFromECKey(EC_KEY * ec_key, P256PublicKey & pubkey)
    1050              : {
    1051          207 :     ERR_clear_error();
    1052          207 :     CHIP_ERROR error = CHIP_NO_ERROR;
    1053              : 
    1054          207 :     int nid            = NID_undef;
    1055          207 :     ECName curve       = MapECName(pubkey.Type());
    1056          207 :     EC_GROUP * group   = nullptr;
    1057          207 :     size_t pubkey_size = 0;
    1058              : 
    1059          207 :     const EC_POINT * pubkey_ecp = EC_KEY_get0_public_key(ec_key);
    1060          207 :     VerifyOrExit(pubkey_ecp != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
    1061              : 
    1062          207 :     nid = _nidForCurve(curve);
    1063          207 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
    1064              : 
    1065          207 :     group = EC_GROUP_new_by_curve_name(nid);
    1066          207 :     VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
    1067              : 
    1068              :     pubkey_size =
    1069          207 :         EC_POINT_point2oct(group, pubkey_ecp, POINT_CONVERSION_UNCOMPRESSED, Uint8::to_uchar(pubkey), pubkey.Length(), nullptr);
    1070          207 :     pubkey_ecp = nullptr;
    1071              : 
    1072          207 :     VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INVALID_ARGUMENT);
    1073              : 
    1074          207 : exit:
    1075          207 :     if (group != nullptr)
    1076              :     {
    1077          207 :         EC_GROUP_free(group);
    1078          207 :         group = nullptr;
    1079              :     }
    1080              : 
    1081          207 :     _logSSLError();
    1082          207 :     return error;
    1083              : }
    1084              : 
    1085          160 : CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
    1086              : {
    1087          160 :     ERR_clear_error();
    1088              : 
    1089          160 :     Clear();
    1090              : 
    1091          160 :     CHIP_ERROR error = CHIP_NO_ERROR;
    1092          160 :     int result       = 0;
    1093          160 :     EC_KEY * ec_key  = nullptr;
    1094          160 :     ECName curve     = MapECName(mPublicKey.Type());
    1095              : 
    1096          160 :     int nid = _nidForCurve(curve);
    1097          160 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
    1098              : 
    1099          160 :     ec_key = EC_KEY_new_by_curve_name(nid);
    1100          160 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
    1101              : 
    1102          160 :     result = EC_KEY_generate_key(ec_key);
    1103          160 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1104              : 
    1105          160 :     error = P256PublicKeyFromECKey(ec_key, mPublicKey);
    1106          160 :     SuccessOrExit(error);
    1107              : 
    1108          160 :     from_EC_KEY(ec_key, &mKeypair);
    1109          160 :     mInitialized = true;
    1110          160 :     ec_key       = nullptr;
    1111              : 
    1112          160 : exit:
    1113          160 :     if (ec_key != nullptr)
    1114              :     {
    1115            0 :         EC_KEY_free(ec_key);
    1116            0 :         ec_key = nullptr;
    1117              :     }
    1118              : 
    1119          160 :     _logSSLError();
    1120          160 :     return error;
    1121              : }
    1122              : 
    1123          763 : CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const
    1124              : {
    1125          763 :     CHIP_ERROR error = CHIP_NO_ERROR;
    1126              : 
    1127          763 :     const EC_KEY * ec_key = to_const_EC_KEY(&mKeypair);
    1128              :     uint8_t privkey[kP256_PrivateKey_Length];
    1129              : 
    1130          763 :     int privkey_size          = 0;
    1131          763 :     const BIGNUM * privkey_bn = EC_KEY_get0_private_key(ec_key);
    1132          763 :     VerifyOrExit(privkey_bn != nullptr, error = CHIP_ERROR_INTERNAL);
    1133              : 
    1134          763 :     privkey_size = BN_bn2binpad(privkey_bn, privkey, sizeof(privkey));
    1135          763 :     privkey_bn   = nullptr;
    1136              : 
    1137          763 :     VerifyOrExit(privkey_size > 0, error = CHIP_ERROR_INTERNAL);
    1138          763 :     VerifyOrExit((size_t) privkey_size == sizeof(privkey), error = CHIP_ERROR_INTERNAL);
    1139              : 
    1140              :     {
    1141          763 :         size_t len = output.Length() == 0 ? output.Capacity() : output.Length();
    1142          763 :         Encoding::BufferWriter bbuf(output.Bytes(), len);
    1143          763 :         bbuf.Put(mPublicKey, mPublicKey.Length());
    1144          763 :         bbuf.Put(privkey, sizeof(privkey));
    1145          763 :         VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
    1146          763 :         output.SetLength(bbuf.Needed());
    1147              :     }
    1148              : 
    1149          763 : exit:
    1150          763 :     ClearSecretData(privkey, sizeof(privkey));
    1151          763 :     _logSSLError();
    1152          763 :     return error;
    1153              : }
    1154              : 
    1155         1672 : CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
    1156              : {
    1157         1672 :     Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length());
    1158              : 
    1159         1672 :     Clear();
    1160              : 
    1161         1672 :     BIGNUM * pvt_key     = nullptr;
    1162         1672 :     EC_GROUP * group     = nullptr;
    1163         1672 :     EC_POINT * key_point = nullptr;
    1164              : 
    1165         1672 :     EC_KEY * ec_key = nullptr;
    1166         1672 :     ECName curve    = MapECName(mPublicKey.Type());
    1167              : 
    1168         1672 :     ERR_clear_error();
    1169         1672 :     CHIP_ERROR error = CHIP_NO_ERROR;
    1170         1672 :     int result       = 0;
    1171         1672 :     int nid          = NID_undef;
    1172              : 
    1173         1672 :     const uint8_t * privkey = input.ConstBytes() + mPublicKey.Length();
    1174              : 
    1175         1672 :     VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
    1176         1672 :     bbuf.Put(input.ConstBytes(), mPublicKey.Length());
    1177         1672 :     VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
    1178              : 
    1179         1672 :     nid = _nidForCurve(curve);
    1180         1672 :     VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
    1181              : 
    1182         1672 :     group = EC_GROUP_new_by_curve_name(nid);
    1183         1672 :     VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
    1184              : 
    1185         1672 :     key_point = EC_POINT_new(group);
    1186         1672 :     VerifyOrExit(key_point != nullptr, error = CHIP_ERROR_INTERNAL);
    1187              : 
    1188         1672 :     result = EC_POINT_oct2point(group, key_point, Uint8::to_const_uchar(mPublicKey), mPublicKey.Length(), nullptr);
    1189         1672 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1190              : 
    1191         1672 :     ec_key = EC_KEY_new_by_curve_name(nid);
    1192         1672 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
    1193              : 
    1194         1672 :     result = EC_KEY_set_public_key(ec_key, key_point);
    1195         1672 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1196              : 
    1197         1672 :     pvt_key = BN_bin2bn(privkey, kP256_PrivateKey_Length, nullptr);
    1198         1672 :     VerifyOrExit(pvt_key != nullptr, error = CHIP_ERROR_INTERNAL);
    1199              : 
    1200         1672 :     result = EC_KEY_set_private_key(ec_key, pvt_key);
    1201         1672 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1202              : 
    1203         1672 :     from_EC_KEY(ec_key, &mKeypair);
    1204         1672 :     mInitialized = true;
    1205         1672 :     ec_key       = nullptr;
    1206              : 
    1207         1672 : exit:
    1208         1672 :     if (ec_key != nullptr)
    1209              :     {
    1210            0 :         EC_KEY_free(ec_key);
    1211            0 :         ec_key = nullptr;
    1212              :     }
    1213              : 
    1214         1672 :     if (group != nullptr)
    1215              :     {
    1216         1672 :         EC_GROUP_free(group);
    1217         1672 :         group = nullptr;
    1218              :     }
    1219              : 
    1220         1672 :     if (pvt_key != nullptr)
    1221              :     {
    1222         1672 :         BN_free(pvt_key);
    1223         1672 :         pvt_key = nullptr;
    1224              :     }
    1225              : 
    1226         1672 :     if (key_point != nullptr)
    1227              :     {
    1228         1672 :         EC_POINT_free(key_point);
    1229         1672 :         key_point = nullptr;
    1230              :     }
    1231         1672 :     _logSSLError();
    1232         1672 :     return error;
    1233              : }
    1234              : 
    1235         3646 : void P256Keypair::Clear()
    1236              : {
    1237         3646 :     if (mInitialized)
    1238              :     {
    1239         1832 :         EC_KEY * ec_key = to_EC_KEY(&mKeypair);
    1240         1832 :         EC_KEY_free(ec_key);
    1241         1832 :         mInitialized = false;
    1242              :     }
    1243         3646 : }
    1244              : 
    1245         1814 : P256Keypair::~P256Keypair()
    1246              : {
    1247         1814 :     Clear();
    1248         1814 : }
    1249              : 
    1250           35 : CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
    1251              : {
    1252           35 :     ERR_clear_error();
    1253           35 :     CHIP_ERROR error     = CHIP_NO_ERROR;
    1254           35 :     int result           = 0;
    1255           35 :     int csr_length_local = 0;
    1256              : 
    1257           35 :     X509_REQ * x509_req = X509_REQ_new();
    1258           35 :     EVP_PKEY * evp_pkey = nullptr;
    1259              : 
    1260           35 :     EC_KEY * ec_key = to_EC_KEY(&mKeypair);
    1261              : 
    1262           35 :     X509_NAME * subject = X509_NAME_new();
    1263           35 :     VerifyOrExit(subject != nullptr, error = CHIP_ERROR_INTERNAL);
    1264              : 
    1265           35 :     VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
    1266              : 
    1267           35 :     result = X509_REQ_set_version(x509_req, 0);
    1268           35 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1269              : 
    1270           35 :     result = EC_KEY_check_key(ec_key);
    1271           35 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1272              : 
    1273           35 :     evp_pkey = EVP_PKEY_new();
    1274           35 :     VerifyOrExit(evp_pkey != nullptr, error = CHIP_ERROR_INTERNAL);
    1275              : 
    1276           35 :     result = EVP_PKEY_set1_EC_KEY(evp_pkey, ec_key);
    1277           35 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1278              : 
    1279           35 :     result = X509_REQ_set_pubkey(x509_req, evp_pkey);
    1280           35 :     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           35 :     result = X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC, Uint8::from_const_char("CSR"), -1, -1, 0);
    1286           35 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1287              : 
    1288           35 :     result = X509_REQ_set_subject_name(x509_req, subject);
    1289           35 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
    1290              : 
    1291           35 :     result = X509_REQ_sign(x509_req, evp_pkey, EVP_sha256());
    1292           35 :     VerifyOrExit(result > 0, error = CHIP_ERROR_INTERNAL);
    1293              : 
    1294           35 :     csr_length_local = i2d_X509_REQ(x509_req, nullptr);
    1295           35 :     VerifyOrExit(csr_length_local >= 0, error = CHIP_ERROR_INTERNAL);
    1296           35 :     VerifyOrExit(CanCastTo<size_t>(csr_length_local), error = CHIP_ERROR_BUFFER_TOO_SMALL);
    1297           35 :     VerifyOrExit(static_cast<size_t>(csr_length_local) <= csr_length, error = CHIP_ERROR_BUFFER_TOO_SMALL);
    1298           35 :     csr_length = static_cast<size_t>(i2d_X509_REQ(x509_req, &out_csr));
    1299              : 
    1300           35 : exit:
    1301           35 :     ec_key = nullptr;
    1302              : 
    1303           35 :     if (evp_pkey != nullptr)
    1304              :     {
    1305           35 :         EVP_PKEY_free(evp_pkey);
    1306           35 :         evp_pkey = nullptr;
    1307              :     }
    1308              : 
    1309           35 :     X509_NAME_free(subject);
    1310           35 :     subject = nullptr;
    1311              : 
    1312           35 :     X509_REQ_free(x509_req);
    1313              : 
    1314           35 :     _logSSLError();
    1315           35 :     return error;
    1316              : }
    1317              : 
    1318           54 : CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr, size_t csr_length, P256PublicKey & pubkey)
    1319              : {
    1320           54 :     ReturnErrorOnFailure(VerifyCertificateSigningRequestFormat(csr, csr_length));
    1321              : 
    1322           50 :     ERR_clear_error();
    1323           50 :     CHIP_ERROR error = CHIP_NO_ERROR;
    1324           50 :     int result       = 0;
    1325              : 
    1326           50 :     EVP_PKEY * evp_pkey = nullptr;
    1327           50 :     EC_KEY * ec_key     = nullptr;
    1328              : 
    1329           50 :     const unsigned char * csr_buf = Uint8::to_const_uchar(csr);
    1330           50 :     X509_REQ * x509_req           = d2i_X509_REQ(nullptr, &csr_buf, (int) csr_length);
    1331           50 :     VerifyOrExit(x509_req != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
    1332              : 
    1333           50 :     VerifyOrExit(X509_REQ_get_version(x509_req) == 0, error = CHIP_ERROR_INVALID_ARGUMENT);
    1334              : 
    1335           50 :     evp_pkey = X509_REQ_get_pubkey(x509_req);
    1336           50 :     VerifyOrExit(evp_pkey != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
    1337              : 
    1338           50 :     result = X509_REQ_verify(x509_req, evp_pkey);
    1339           50 :     VerifyOrExit(result == 1, error = CHIP_ERROR_INVALID_ARGUMENT);
    1340              : 
    1341           47 :     ec_key = EVP_PKEY_get1_EC_KEY(evp_pkey);
    1342           47 :     VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
    1343              : 
    1344           47 :     error = P256PublicKeyFromECKey(ec_key, pubkey);
    1345           47 :     SuccessOrExit(error);
    1346              : 
    1347           50 : exit:
    1348              : 
    1349           50 :     if (x509_req != nullptr)
    1350              :     {
    1351           50 :         X509_REQ_free(x509_req);
    1352              :     }
    1353              : 
    1354           50 :     if (ec_key != nullptr)
    1355              :     {
    1356           47 :         EC_KEY_free(ec_key);
    1357              :     }
    1358              : 
    1359           50 :     if (evp_pkey != nullptr)
    1360              :     {
    1361           50 :         EVP_PKEY_free(evp_pkey);
    1362              :     }
    1363           50 :     _logSSLError();
    1364           50 :     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          230 : void Spake2p_P256_SHA256_HKDF_HMAC::Clear()
    1451              : {
    1452          230 :     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          309 : CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType)
    1671              : {
    1672          309 :     CHIP_ERROR err          = CHIP_NO_ERROR;
    1673          309 :     const uint8_t * certPtr = cert.data();
    1674          309 :     X509 * x509Cert         = nullptr;
    1675          309 :     bool extBasicPresent    = false;
    1676          309 :     bool extKeyUsagePresent = false;
    1677          309 :     bool extSKIDPresent     = false;
    1678          309 :     bool extAKIDPresent     = false;
    1679              : 
    1680          309 :     VerifyOrReturnError(!cert.empty() && CanCastTo<long>(cert.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1681              : 
    1682          308 :     x509Cert = d2i_X509(nullptr, &certPtr, static_cast<long>(cert.size()));
    1683          308 :     VerifyOrExit(x509Cert != nullptr, err = CHIP_ERROR_INTERNAL);
    1684              : 
    1685          308 :     VerifyOrExit(X509_get_version(x509Cert) == 2, err = CHIP_ERROR_INTERNAL);
    1686          306 :     VerifyOrExit(X509_get_serialNumber(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1687          306 :     VerifyOrExit(X509_get_signature_nid(x509Cert) == NID_ecdsa_with_SHA256, err = CHIP_ERROR_INTERNAL);
    1688          304 :     VerifyOrExit(X509_get_issuer_name(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1689          304 :     VerifyOrExit(X509_get_notBefore(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1690          304 :     VerifyOrExit(X509_get_notAfter(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1691          304 :     VerifyOrExit(X509_get_subject_name(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
    1692              : 
    1693              :     // Verify public key presence and format.
    1694              :     {
    1695          304 :         Crypto::P256PublicKey pubkey;
    1696          304 :         SuccessOrExit(err = ExtractPubkeyFromX509Cert(cert, pubkey));
    1697          304 :     }
    1698              : 
    1699         1390 :     for (int i = 0; i < X509_get_ext_count(x509Cert); i++)
    1700              :     {
    1701         1125 :         X509_EXTENSION * ex = X509_get_ext(x509Cert, i);
    1702         1125 :         ASN1_OBJECT * obj   = X509_EXTENSION_get_object(ex);
    1703         1125 :         bool isCritical     = X509_EXTENSION_get_critical(ex) == 1;
    1704              : 
    1705         1125 :         switch (OBJ_obj2nid(obj))
    1706              :         {
    1707          295 :         case NID_basic_constraints:
    1708          295 :             VerifyOrExit(isCritical && !extBasicPresent, err = CHIP_ERROR_INTERNAL);
    1709          291 :             extBasicPresent = true;
    1710              :             {
    1711          291 :                 bool isCA    = X509_get_extension_flags(x509Cert) & EXFLAG_CA;
    1712          291 :                 long pathLen = X509_get_pathlen(x509Cert);
    1713          291 :                 if (certType == AttestationCertType::kDAC)
    1714              :                 {
    1715          134 :                     VerifyOrExit(!isCA && pathLen == -1, err = CHIP_ERROR_INTERNAL);
    1716              :                 }
    1717          157 :                 else if (certType == AttestationCertType::kPAI)
    1718              :                 {
    1719          153 :                     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          274 :             break;
    1728          276 :         case NID_key_usage:
    1729          276 :             VerifyOrExit(isCritical && !extKeyUsagePresent, err = CHIP_ERROR_INTERNAL);
    1730          272 :             extKeyUsagePresent = true;
    1731              :             {
    1732          272 :                 uint32_t keyUsage = X509_get_key_usage(x509Cert);
    1733          272 :                 if (certType == AttestationCertType::kDAC)
    1734              :                 {
    1735              :                     // SHALL only have the digitalSignature bit set.
    1736          125 :                     VerifyOrExit(keyUsage == X509v3_KU_DIGITAL_SIGNATURE, err = CHIP_ERROR_INTERNAL);
    1737              :                 }
    1738              :                 else
    1739              :                 {
    1740          147 :                     bool keyCertSignFlag = keyUsage & X509v3_KU_KEY_CERT_SIGN;
    1741          147 :                     bool crlSignFlag     = keyUsage & X509v3_KU_CRL_SIGN;
    1742          147 :                     bool otherFlags      = keyUsage &
    1743              :                         ~static_cast<uint32_t>(X509v3_KU_CRL_SIGN | X509v3_KU_KEY_CERT_SIGN | X509v3_KU_DIGITAL_SIGNATURE);
    1744          147 :                     VerifyOrExit(keyCertSignFlag && crlSignFlag && !otherFlags, err = CHIP_ERROR_INTERNAL);
    1745              :                 }
    1746              :             }
    1747          267 :             break;
    1748          271 :         case NID_subject_key_identifier: {
    1749          271 :             VerifyOrExit(!isCritical && !extSKIDPresent, err = CHIP_ERROR_INTERNAL);
    1750          271 :             const ASN1_OCTET_STRING * pSKID = X509_get0_subject_key_id(x509Cert);
    1751          271 :             VerifyOrExit(pSKID != nullptr && pSKID->length == kSubjectKeyIdentifierLength, err = CHIP_ERROR_INTERNAL);
    1752          267 :             extSKIDPresent = true;
    1753          267 :             break;
    1754              :         }
    1755          267 :         case NID_authority_key_identifier: {
    1756          267 :             VerifyOrExit(!isCritical && !extAKIDPresent, err = CHIP_ERROR_INTERNAL);
    1757          267 :             const ASN1_OCTET_STRING * pAKID = X509_get0_authority_key_id(x509Cert);
    1758          267 :             VerifyOrExit(pAKID != nullptr && pAKID->length == kAuthorityKeyIdentifierLength, err = CHIP_ERROR_INTERNAL);
    1759          263 :             extAKIDPresent = true;
    1760          263 :             break;
    1761              :         }
    1762           16 :         default:
    1763           16 :             break;
    1764              :         }
    1765              :     }
    1766              :     // Mandatory extensions for all certs.
    1767          265 :     VerifyOrExit(extBasicPresent && extKeyUsagePresent && extSKIDPresent, err = CHIP_ERROR_INTERNAL);
    1768              : 
    1769          259 :     if (certType == AttestationCertType::kDAC || certType == AttestationCertType::kPAI)
    1770              :     {
    1771              :         // Mandatory extension for DAC and PAI certs.
    1772          257 :         VerifyOrExit(extAKIDPresent, err = CHIP_ERROR_INTERNAL);
    1773              :     }
    1774              : 
    1775            2 : exit:
    1776          308 :     X509_free(x509Cert);
    1777              : 
    1778          308 :     return err;
    1779              : }
    1780              : 
    1781          112 : CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate,
    1782              :                                     size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen,
    1783              :                                     CertificateChainValidationResult & result)
    1784              : {
    1785          112 :     CHIP_ERROR err             = CHIP_NO_ERROR;
    1786          112 :     int status                 = 0;
    1787          112 :     X509_STORE_CTX * verifyCtx = nullptr;
    1788          112 :     X509_STORE * store         = nullptr;
    1789          112 :     STACK_OF(X509) * chain     = nullptr;
    1790          112 :     X509 * x509RootCertificate = nullptr;
    1791          112 :     X509 * x509CACertificate   = nullptr;
    1792          112 :     X509 * x509LeafCertificate = nullptr;
    1793              : 
    1794          112 :     result = CertificateChainValidationResult::kInternalFrameworkError;
    1795              : 
    1796          112 :     VerifyOrReturnError(rootCertificate != nullptr && rootCertificateLen != 0 && CanCastTo<long>(rootCertificateLen),
    1797              :                         (result = CertificateChainValidationResult::kRootArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
    1798          111 :     VerifyOrReturnError(leafCertificate != nullptr && leafCertificateLen != 0 && CanCastTo<long>(leafCertificateLen),
    1799              :                         (result = CertificateChainValidationResult::kLeafArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
    1800              : 
    1801          110 :     store = X509_STORE_new();
    1802          110 :     VerifyOrExit(store != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
    1803              : 
    1804          110 :     verifyCtx = X509_STORE_CTX_new();
    1805          110 :     VerifyOrExit(verifyCtx != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
    1806              : 
    1807          110 :     chain = sk_X509_new_null();
    1808          110 :     VerifyOrExit(chain != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
    1809              : 
    1810          110 :     VerifyOrExit(CanCastTo<long>(rootCertificateLen),
    1811              :                  (result = CertificateChainValidationResult::kRootArgumentInvalid, err = CHIP_ERROR_INVALID_ARGUMENT));
    1812          110 :     x509RootCertificate = d2i_X509(nullptr, &rootCertificate, static_cast<long>(rootCertificateLen));
    1813          110 :     VerifyOrExit(x509RootCertificate != nullptr,
    1814              :                  (result = CertificateChainValidationResult::kRootFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1815              : 
    1816          110 :     status = X509_STORE_add_cert(store, x509RootCertificate);
    1817          110 :     VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kInternalFrameworkError, err = CHIP_ERROR_INTERNAL));
    1818              : 
    1819          110 :     if (caCertificate != nullptr && caCertificateLen > 0)
    1820              :     {
    1821          106 :         VerifyOrExit(CanCastTo<long>(caCertificateLen),
    1822              :                      (result = CertificateChainValidationResult::kICAArgumentInvalid, err = CHIP_ERROR_INVALID_ARGUMENT));
    1823          106 :         x509CACertificate = d2i_X509(nullptr, &caCertificate, static_cast<long>(caCertificateLen));
    1824          106 :         VerifyOrExit(x509CACertificate != nullptr,
    1825              :                      (result = CertificateChainValidationResult::kICAFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1826              : 
    1827          106 :         status = static_cast<int>(sk_X509_push(chain, x509CACertificate));
    1828          106 :         VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kInternalFrameworkError, err = CHIP_ERROR_INTERNAL));
    1829              :     }
    1830              : 
    1831          110 :     VerifyOrExit(CanCastTo<long>(leafCertificateLen),
    1832              :                  (result = CertificateChainValidationResult::kLeafArgumentInvalid, err = CHIP_ERROR_INVALID_ARGUMENT));
    1833          110 :     x509LeafCertificate = d2i_X509(nullptr, &leafCertificate, static_cast<long>(leafCertificateLen));
    1834          110 :     VerifyOrExit(x509LeafCertificate != nullptr,
    1835              :                  (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1836              : 
    1837          110 :     status = X509_STORE_CTX_init(verifyCtx, store, x509LeafCertificate, chain);
    1838          110 :     VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kInternalFrameworkError, err = CHIP_ERROR_INTERNAL));
    1839              : 
    1840              :     // Set time used in the X509 certificate chain validation to the notBefore time of the leaf certificate.
    1841              :     // That way the X509_verify_cert() validates that intermediate and root certificates were
    1842              :     // valid at the time of the leaf certificate generation.
    1843              :     {
    1844          110 :         X509_VERIFY_PARAM * param = X509_STORE_CTX_get0_param(verifyCtx);
    1845              :         chip::ASN1::ASN1UniversalTime asn1Time;
    1846          110 :         char * asn1TimeStr = reinterpret_cast<char *>(X509_get_notBefore(x509LeafCertificate)->data);
    1847              :         uint32_t unixEpoch;
    1848              : 
    1849          110 :         VerifyOrExit(param != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
    1850              : 
    1851          110 :         VerifyOrExit(CHIP_NO_ERROR == asn1Time.ImportFrom_ASN1_TIME_string(CharSpan(asn1TimeStr, strlen(asn1TimeStr))),
    1852              :                      (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1853              : 
    1854          110 :         VerifyOrExit(asn1Time.ExportTo_UnixTime(unixEpoch),
    1855              :                      (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1856              : 
    1857          110 :         VerifyOrExit(CanCastTo<time_t>(unixEpoch),
    1858              :                      (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
    1859          110 :         X509_VERIFY_PARAM_set_time(param, static_cast<time_t>(unixEpoch));
    1860          110 :         X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_X509_STRICT);
    1861              :     }
    1862              : 
    1863          110 :     status = X509_verify_cert(verifyCtx);
    1864          110 :     VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kChainInvalid, err = CHIP_ERROR_CERT_NOT_TRUSTED));
    1865              : 
    1866          100 :     err    = CHIP_NO_ERROR;
    1867          100 :     result = CertificateChainValidationResult::kSuccess;
    1868              : 
    1869          110 : exit:
    1870          110 :     X509_free(x509LeafCertificate);
    1871          110 :     X509_free(x509CACertificate);
    1872          110 :     X509_free(x509RootCertificate);
    1873          110 :     sk_X509_free(chain);
    1874          110 :     X509_STORE_CTX_free(verifyCtx);
    1875          110 :     X509_STORE_free(store);
    1876              : 
    1877          110 :     return err;
    1878              : }
    1879              : 
    1880           14 : CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & candidateCertificate, const ByteSpan & issuerCertificate)
    1881              : {
    1882           14 :     CHIP_ERROR error                            = CHIP_NO_ERROR;
    1883           14 :     X509 * x509CandidateCertificate             = nullptr;
    1884           14 :     X509 * x509issuerCertificate                = nullptr;
    1885           14 :     const unsigned char * pCandidateCertificate = candidateCertificate.data();
    1886           14 :     const unsigned char * pIssuerCertificate    = issuerCertificate.data();
    1887           14 :     ASN1_TIME * candidateNotBeforeTime          = nullptr;
    1888           14 :     ASN1_TIME * issuerNotBeforeTime             = nullptr;
    1889           14 :     ASN1_TIME * issuerNotAfterTime              = nullptr;
    1890           14 :     int result                                  = 0;
    1891           14 :     int days                                    = 0;
    1892           14 :     int seconds                                 = 0;
    1893              : 
    1894           14 :     VerifyOrReturnError(!candidateCertificate.empty() && CanCastTo<long>(candidateCertificate.size()) &&
    1895              :                             !issuerCertificate.empty() && CanCastTo<long>(issuerCertificate.size()),
    1896              :                         CHIP_ERROR_INVALID_ARGUMENT);
    1897              : 
    1898           12 :     x509CandidateCertificate = d2i_X509(nullptr, &pCandidateCertificate, static_cast<long>(candidateCertificate.size()));
    1899           12 :     VerifyOrExit(x509CandidateCertificate != nullptr, error = CHIP_ERROR_NO_MEMORY);
    1900              : 
    1901           12 :     x509issuerCertificate = d2i_X509(nullptr, &pIssuerCertificate, static_cast<long>(issuerCertificate.size()));
    1902           12 :     VerifyOrExit(x509issuerCertificate != nullptr, error = CHIP_ERROR_NO_MEMORY);
    1903              : 
    1904           12 :     candidateNotBeforeTime = X509_get_notBefore(x509CandidateCertificate);
    1905           12 :     issuerNotBeforeTime    = X509_get_notBefore(x509issuerCertificate);
    1906           12 :     issuerNotAfterTime     = X509_get_notAfter(x509issuerCertificate);
    1907           12 :     VerifyOrExit(candidateNotBeforeTime && issuerNotBeforeTime && issuerNotAfterTime, error = CHIP_ERROR_INTERNAL);
    1908              : 
    1909           12 :     result = ASN1_TIME_diff(&days, &seconds, issuerNotBeforeTime, candidateNotBeforeTime);
    1910           12 :     VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
    1911           12 :     result = _compareDaysAndSeconds(days, seconds);
    1912              : 
    1913              :     // check if candidateCertificate is issued at or after tbeCertificate's notBefore timestamp
    1914           12 :     VerifyOrExit(result >= 0, error = CHIP_ERROR_CERT_EXPIRED);
    1915              : 
    1916            8 :     result = ASN1_TIME_diff(&days, &seconds, issuerNotAfterTime, candidateNotBeforeTime);
    1917            8 :     VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
    1918            8 :     result = _compareDaysAndSeconds(days, seconds);
    1919              : 
    1920              :     // check if candidateCertificate is issued at or before tbeCertificate's notAfter timestamp
    1921            8 :     VerifyOrExit(result <= 0, error = CHIP_ERROR_CERT_EXPIRED);
    1922              : 
    1923           12 : exit:
    1924           12 :     X509_free(x509CandidateCertificate);
    1925           12 :     X509_free(x509issuerCertificate);
    1926              : 
    1927           12 :     return error;
    1928              : }
    1929              : 
    1930           92 : CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate)
    1931              : {
    1932           92 :     CHIP_ERROR error                   = CHIP_NO_ERROR;
    1933           92 :     X509 * x509Certificate             = nullptr;
    1934           92 :     const unsigned char * pCertificate = certificate.data();
    1935           92 :     ASN1_TIME * time                   = nullptr;
    1936           92 :     int result                         = 0;
    1937              : 
    1938           92 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1939              : 
    1940           92 :     x509Certificate = d2i_X509(nullptr, &pCertificate, static_cast<long>(certificate.size()));
    1941           92 :     VerifyOrExit(x509Certificate != nullptr, error = CHIP_ERROR_NO_MEMORY);
    1942              : 
    1943           92 :     time = X509_get_notBefore(x509Certificate);
    1944           92 :     VerifyOrExit(time, error = CHIP_ERROR_INTERNAL);
    1945              : 
    1946           92 :     result = X509_cmp_current_time(time);
    1947              :     // check if certificate's notBefore timestamp is earlier than or equal to current time.
    1948           92 :     VerifyOrExit(result == -1, error = CHIP_ERROR_CERT_EXPIRED);
    1949              : 
    1950           91 :     time = X509_get_notAfter(x509Certificate);
    1951           91 :     VerifyOrExit(time, error = CHIP_ERROR_INTERNAL);
    1952              : 
    1953           91 :     result = X509_cmp_current_time(time);
    1954              :     // check if certificate's notAfter timestamp is later than current time.
    1955           91 :     VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
    1956              : 
    1957           92 : exit:
    1958           92 :     X509_free(x509Certificate);
    1959              : 
    1960           92 :     return error;
    1961              : }
    1962              : 
    1963          422 : CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey)
    1964              : {
    1965          422 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    1966          422 :     EC_KEY * ec_key                      = nullptr;
    1967          422 :     EVP_PKEY * pkey                      = nullptr;
    1968          422 :     X509 * x509certificate               = nullptr;
    1969          422 :     const unsigned char * pCertificate   = certificate.data();
    1970          422 :     const unsigned char ** ppCertificate = &pCertificate;
    1971          422 :     unsigned char * pPubkey              = pubkey;
    1972          422 :     unsigned char ** ppPubkey            = &pPubkey;
    1973              :     int pkeyLen;
    1974              : 
    1975          422 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1976              : 
    1977          422 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    1978          422 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    1979              : 
    1980          422 :     pkey = X509_get_pubkey(x509certificate);
    1981          422 :     VerifyOrExit(pkey != nullptr, err = CHIP_ERROR_INTERNAL);
    1982          422 :     VerifyOrExit(EVP_PKEY_base_id(pkey) == EVP_PKEY_EC, err = CHIP_ERROR_INTERNAL);
    1983          422 :     VerifyOrExit(EVP_PKEY_bits(pkey) == 256, err = CHIP_ERROR_INTERNAL);
    1984              : 
    1985          422 :     ec_key = EVP_PKEY_get1_EC_KEY(pkey);
    1986          422 :     VerifyOrExit(ec_key != nullptr, err = CHIP_ERROR_NO_MEMORY);
    1987          422 :     VerifyOrExit(EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) == NID_X9_62_prime256v1, err = CHIP_ERROR_INTERNAL);
    1988              : 
    1989          421 :     pkeyLen = i2d_PublicKey(pkey, nullptr);
    1990          421 :     VerifyOrExit(pkeyLen == static_cast<int>(pubkey.Length()), err = CHIP_ERROR_INTERNAL);
    1991              : 
    1992          421 :     VerifyOrExit(i2d_PublicKey(pkey, ppPubkey) == pkeyLen, err = CHIP_ERROR_INTERNAL);
    1993              : 
    1994          422 : exit:
    1995          422 :     EC_KEY_free(ec_key);
    1996          422 :     EVP_PKEY_free(pkey);
    1997          422 :     X509_free(x509certificate);
    1998              : 
    1999          422 :     return err;
    2000              : }
    2001              : 
    2002              : namespace {
    2003              : 
    2004          387 : CHIP_ERROR ExtractKIDFromX509Cert(bool isSKID, const ByteSpan & certificate, MutableByteSpan & kid)
    2005              : {
    2006          387 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    2007          387 :     X509 * x509certificate               = nullptr;
    2008          387 :     const unsigned char * pCertificate   = certificate.data();
    2009          387 :     const unsigned char ** ppCertificate = &pCertificate;
    2010          387 :     const ASN1_OCTET_STRING * kidString  = nullptr;
    2011              : 
    2012          387 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    2013              : 
    2014          387 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    2015          387 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2016              : 
    2017          387 :     kidString = isSKID ? X509_get0_subject_key_id(x509certificate) : X509_get0_authority_key_id(x509certificate);
    2018          387 :     VerifyOrExit(kidString != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2019          385 :     VerifyOrExit(CanCastTo<size_t>(kidString->length), err = CHIP_ERROR_INVALID_ARGUMENT);
    2020          385 :     VerifyOrExit(kidString->length == kSubjectKeyIdentifierLength, err = CHIP_ERROR_WRONG_CERT_TYPE);
    2021          385 :     VerifyOrExit(static_cast<size_t>(kidString->length) <= kid.size(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
    2022              : 
    2023          385 :     memcpy(kid.data(), kidString->data, static_cast<size_t>(kidString->length));
    2024              : 
    2025          385 :     kid.reduce_size(static_cast<size_t>(kidString->length));
    2026              : 
    2027          387 : exit:
    2028          387 :     X509_free(x509certificate);
    2029              : 
    2030          387 :     return err;
    2031              : }
    2032              : 
    2033              : } // namespace
    2034              : 
    2035          251 : CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid)
    2036              : {
    2037          251 :     return ExtractKIDFromX509Cert(true, certificate, skid);
    2038              : }
    2039              : 
    2040          136 : CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid)
    2041              : {
    2042          136 :     return ExtractKIDFromX509Cert(false, certificate, akid);
    2043              : }
    2044              : 
    2045           19 : CHIP_ERROR ExtractCRLDistributionPointURIFromX509Cert(const ByteSpan & certificate, MutableCharSpan & cdpurl)
    2046              : {
    2047           19 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    2048           19 :     X509 * x509certificate               = nullptr;
    2049           19 :     const unsigned char * pCertificate   = certificate.data();
    2050           19 :     const unsigned char ** ppCertificate = &pCertificate;
    2051           19 :     STACK_OF(DIST_POINT) * crldp         = nullptr;
    2052           19 :     DIST_POINT * dp                      = nullptr;
    2053           19 :     GENERAL_NAMES * gens                 = nullptr;
    2054           19 :     GENERAL_NAME * gen                   = nullptr;
    2055           19 :     ASN1_STRING * uri                    = nullptr;
    2056           19 :     const char * urlptr                  = nullptr;
    2057           19 :     size_t len                           = 0;
    2058              : 
    2059           19 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    2060              : 
    2061           18 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    2062           18 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2063              : 
    2064              :     // CRL Distribution Point Extension is encoded as a sequence of DistributionPoint:
    2065              :     //     CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
    2066              :     //
    2067              :     // This implementation only supports a single DistributionPoint (sequence of size 1)
    2068              :     crldp =
    2069           18 :         reinterpret_cast<STACK_OF(DIST_POINT) *>(X509_get_ext_d2i(x509certificate, NID_crl_distribution_points, nullptr, nullptr));
    2070           18 :     VerifyOrExit(crldp != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2071           13 :     VerifyOrExit(sk_DIST_POINT_num(crldp) == 1, err = CHIP_ERROR_NOT_FOUND);
    2072              : 
    2073           10 :     dp = sk_DIST_POINT_value(crldp, 0);
    2074           10 :     VerifyOrExit(dp != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2075           10 :     VerifyOrExit(dp->distpoint != nullptr && dp->distpoint->type == 0, err = CHIP_ERROR_NOT_FOUND);
    2076              : 
    2077              :     // The DistributionPoint is a sequence of three optional elements:
    2078              :     //     DistributionPoint ::= SEQUENCE {
    2079              :     //         distributionPoint       [0]     DistributionPointName OPTIONAL,
    2080              :     //         reasons                 [1]     ReasonFlags OPTIONAL,
    2081              :     //         cRLIssuer               [2]     GeneralNames OPTIONAL }
    2082              :     //
    2083              :     // where the DistributionPointName is a CHOICE of:
    2084              :     //     DistributionPointName ::= CHOICE {
    2085              :     //         fullName                [0]     GeneralNames,
    2086              :     //         nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
    2087              :     //
    2088              :     // The URI should be encoded in the fullName element.
    2089              :     // This implementation only supports a single GeneralName in the fullName sequence:
    2090              :     //     GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
    2091           10 :     gens = dp->distpoint->name.fullname;
    2092           10 :     VerifyOrExit(sk_GENERAL_NAME_num(gens) == 1, err = CHIP_ERROR_NOT_FOUND);
    2093              : 
    2094              :     // The CDP URI is encoded as a uniformResourceIdentifier field of the GeneralName:
    2095              :     //     GeneralName ::= CHOICE {
    2096              :     //         otherName                       [0]     OtherName,
    2097              :     //         rfc822Name                      [1]     IA5String,
    2098              :     //         dNSName                         [2]     IA5String,
    2099              :     //         x400Address                     [3]     ORAddress,
    2100              :     //         directoryName                   [4]     Name,
    2101              :     //         ediPartyName                    [5]     EDIPartyName,
    2102              :     //         uniformResourceIdentifier       [6]     IA5String,
    2103              :     //         iPAddress                       [7]     OCTET STRING,
    2104              :     //         registeredID                    [8]     OBJECT IDENTIFIER }
    2105            9 :     gen = sk_GENERAL_NAME_value(gens, 0);
    2106            9 :     VerifyOrExit(gen->type == GEN_URI, err = CHIP_ERROR_NOT_FOUND);
    2107              : 
    2108            9 :     uri    = reinterpret_cast<ASN1_STRING *>(GENERAL_NAME_get0_value(gen, nullptr));
    2109            9 :     urlptr = reinterpret_cast<const char *>(ASN1_STRING_get0_data(uri));
    2110            9 :     VerifyOrExit(CanCastTo<size_t>(ASN1_STRING_length(uri)), err = CHIP_ERROR_NOT_FOUND);
    2111            9 :     len = static_cast<size_t>(ASN1_STRING_length(uri));
    2112            9 :     VerifyOrExit(
    2113              :         (len > strlen(kValidCDPURIHttpPrefix) && strncmp(urlptr, kValidCDPURIHttpPrefix, strlen(kValidCDPURIHttpPrefix)) == 0) ||
    2114              :             (len > strlen(kValidCDPURIHttpsPrefix) &&
    2115              :              strncmp(urlptr, kValidCDPURIHttpsPrefix, strlen(kValidCDPURIHttpsPrefix)) == 0),
    2116              :         err = CHIP_ERROR_NOT_FOUND);
    2117            8 :     err = CopyCharSpanToMutableCharSpan(CharSpan(urlptr, len), cdpurl);
    2118              : 
    2119           18 : exit:
    2120           18 :     sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
    2121           18 :     X509_free(x509certificate);
    2122              : 
    2123           18 :     return err;
    2124              : }
    2125              : 
    2126           19 : CHIP_ERROR ExtractCDPExtensionCRLIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & crlIssuer)
    2127              : {
    2128           19 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    2129           19 :     int result                           = 1;
    2130           19 :     X509 * x509certificate               = nullptr;
    2131           19 :     const unsigned char * pCertificate   = certificate.data();
    2132           19 :     const unsigned char ** ppCertificate = &pCertificate;
    2133           19 :     STACK_OF(DIST_POINT) * crldp         = nullptr;
    2134           19 :     DIST_POINT * dp                      = nullptr;
    2135           19 :     GENERAL_NAMES * gens                 = nullptr;
    2136           19 :     GENERAL_NAME * gen                   = nullptr;
    2137           19 :     X509_NAME * dirName                  = nullptr;
    2138           19 :     const uint8_t * pDirName             = nullptr;
    2139           19 :     size_t dirNameLen                    = 0;
    2140              : 
    2141           19 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    2142              : 
    2143           18 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    2144           18 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2145              : 
    2146              :     // CRL Distribution Point Extension is encoded as a sequence of DistributionPoint:
    2147              :     //     CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
    2148              :     //
    2149              :     // This implementation only supports a single DistributionPoint (sequence of size 1)
    2150              :     crldp =
    2151           18 :         reinterpret_cast<STACK_OF(DIST_POINT) *>(X509_get_ext_d2i(x509certificate, NID_crl_distribution_points, nullptr, nullptr));
    2152           18 :     VerifyOrExit(crldp != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2153           13 :     VerifyOrExit(sk_DIST_POINT_num(crldp) == 1, err = CHIP_ERROR_NOT_FOUND);
    2154              : 
    2155           10 :     dp = sk_DIST_POINT_value(crldp, 0);
    2156           10 :     VerifyOrExit(dp != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2157              : 
    2158              :     // The DistributionPoint is a sequence of three optional elements:
    2159              :     //     DistributionPoint ::= SEQUENCE {
    2160              :     //         distributionPoint       [0]     DistributionPointName OPTIONAL,
    2161              :     //         reasons                 [1]     ReasonFlags OPTIONAL,
    2162              :     //         cRLIssuer               [2]     GeneralNames OPTIONAL }
    2163              :     //
    2164              :     // the cRLIssuer is encoded as a GeneralNames, where:
    2165              :     //     GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
    2166              :     // This implementation only supports a single GeneralName element in the cRLIssuer sequence:
    2167           10 :     gens = dp->CRLissuer;
    2168           10 :     VerifyOrExit(sk_GENERAL_NAME_num(gens) == 1, err = CHIP_ERROR_NOT_FOUND);
    2169              : 
    2170              :     // In this implementation the cRLIssuer is expected to be encoded as a directoryName field of the GeneralName:
    2171              :     //     GeneralName ::= CHOICE {
    2172              :     //         otherName                       [0]     OtherName,
    2173              :     //         rfc822Name                      [1]     IA5String,
    2174              :     //         dNSName                         [2]     IA5String,
    2175              :     //         x400Address                     [3]     ORAddress,
    2176              :     //         directoryName                   [4]     Name,
    2177              :     //         ediPartyName                    [5]     EDIPartyName,
    2178              :     //         uniformResourceIdentifier       [6]     IA5String,
    2179              :     //         iPAddress                       [7]     OCTET STRING,
    2180              :     //         registeredID                    [8]     OBJECT IDENTIFIER }
    2181            4 :     gen = sk_GENERAL_NAME_value(gens, 0);
    2182            4 :     VerifyOrExit(gen->type == GEN_DIRNAME, err = CHIP_ERROR_NOT_FOUND);
    2183              : 
    2184            4 :     dirName = reinterpret_cast<X509_NAME *>(GENERAL_NAME_get0_value(gen, nullptr));
    2185            4 :     VerifyOrExit(dirName != nullptr, err = CHIP_ERROR_NOT_FOUND);
    2186              : 
    2187              :     // Extract directoryName as a raw DER Encoded data
    2188            4 :     result = X509_NAME_get0_der(dirName, &pDirName, &dirNameLen);
    2189            4 :     VerifyOrExit(result == 1, err = CHIP_ERROR_INTERNAL);
    2190            4 :     err = CopySpanToMutableSpan(ByteSpan(pDirName, dirNameLen), crlIssuer);
    2191              : 
    2192           18 : exit:
    2193           18 :     sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
    2194           18 :     X509_free(x509certificate);
    2195              : 
    2196           18 :     return err;
    2197              : }
    2198              : 
    2199           25 : CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber)
    2200              : {
    2201           25 :     CHIP_ERROR err                        = CHIP_NO_ERROR;
    2202           25 :     X509 * x509certificate                = nullptr;
    2203           25 :     auto * pCertificate                   = Uint8::to_const_uchar(certificate.data());
    2204           25 :     const unsigned char ** ppCertificate  = &pCertificate;
    2205           25 :     const ASN1_INTEGER * serialNumberASN1 = nullptr;
    2206           25 :     size_t serialNumberLen                = 0;
    2207              : 
    2208           25 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    2209              : 
    2210           25 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    2211           25 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2212              : 
    2213           25 :     serialNumberASN1 = X509_get_serialNumber(x509certificate);
    2214           25 :     VerifyOrExit(serialNumberASN1 != nullptr, err = CHIP_ERROR_INTERNAL);
    2215           25 :     VerifyOrExit(serialNumberASN1->data != nullptr, err = CHIP_ERROR_INTERNAL);
    2216           25 :     VerifyOrExit(CanCastTo<size_t>(serialNumberASN1->length), err = CHIP_ERROR_INTERNAL);
    2217              : 
    2218           25 :     serialNumberLen = static_cast<size_t>(serialNumberASN1->length);
    2219           25 :     VerifyOrExit(serialNumberLen <= serialNumber.size(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
    2220              : 
    2221           25 :     memcpy(serialNumber.data(), serialNumberASN1->data, serialNumberLen);
    2222           25 :     serialNumber.reduce_size(serialNumberLen);
    2223              : 
    2224           25 : exit:
    2225           25 :     X509_free(x509certificate);
    2226              : 
    2227           25 :     return err;
    2228              : }
    2229              : 
    2230              : namespace {
    2231           42 : CHIP_ERROR ExtractRawDNFromX509Cert(bool extractSubject, const ByteSpan & certificate, MutableByteSpan & dn)
    2232              : {
    2233           42 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
    2234           42 :     int result                           = 1;
    2235           42 :     X509 * x509certificate               = nullptr;
    2236           42 :     auto * pCertificate                  = Uint8::to_const_uchar(certificate.data());
    2237           42 :     const unsigned char ** ppCertificate = &pCertificate;
    2238           42 :     X509_NAME * distinguishedName        = nullptr;
    2239           42 :     const uint8_t * pDistinguishedName   = nullptr;
    2240           42 :     size_t distinguishedNameLen          = 0;
    2241              : 
    2242           42 :     VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
    2243              : 
    2244           42 :     x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
    2245           42 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2246              : 
    2247           41 :     if (extractSubject)
    2248              :     {
    2249           16 :         distinguishedName = X509_get_subject_name(x509certificate);
    2250              :     }
    2251              :     else
    2252              :     {
    2253           25 :         distinguishedName = X509_get_issuer_name(x509certificate);
    2254              :     }
    2255           41 :     VerifyOrExit(distinguishedName != nullptr, err = CHIP_ERROR_INTERNAL);
    2256              : 
    2257           41 :     result = X509_NAME_get0_der(distinguishedName, &pDistinguishedName, &distinguishedNameLen);
    2258           41 :     VerifyOrExit(result == 1, err = CHIP_ERROR_INTERNAL);
    2259           41 :     err = CopySpanToMutableSpan(ByteSpan(pDistinguishedName, distinguishedNameLen), dn);
    2260              : 
    2261           42 : exit:
    2262           42 :     X509_free(x509certificate);
    2263              : 
    2264           42 :     return err;
    2265              : }
    2266              : } // namespace
    2267              : 
    2268           17 : CHIP_ERROR ExtractSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject)
    2269              : {
    2270           17 :     return ExtractRawDNFromX509Cert(true, certificate, subject);
    2271              : }
    2272              : 
    2273           25 : CHIP_ERROR ExtractIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & issuer)
    2274              : {
    2275           25 :     return ExtractRawDNFromX509Cert(false, certificate, issuer);
    2276              : }
    2277              : 
    2278              : class ScopedASN1Object
    2279              : {
    2280              : public:
    2281          993 :     ScopedASN1Object(const char * string, int no_name) : obj(OBJ_txt2obj(string, no_name)) {}
    2282          993 :     ~ScopedASN1Object() { ASN1_OBJECT_free(obj); }
    2283              : 
    2284          993 :     explicit operator bool() const { return obj != nullptr; }
    2285         1438 :     ASN1_OBJECT * Get() const { return obj; }
    2286              : 
    2287              :     ScopedASN1Object(const ScopedASN1Object &)             = delete;
    2288              :     ScopedASN1Object & operator=(const ScopedASN1Object &) = delete;
    2289              : 
    2290              : private:
    2291              :     ASN1_OBJECT * obj = nullptr;
    2292              : };
    2293              : 
    2294          331 : CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
    2295              : {
    2296          331 :     ScopedASN1Object commonNameObj("2.5.4.3", 1);
    2297          331 :     VerifyOrReturnError(commonNameObj, CHIP_ERROR_NO_MEMORY);
    2298              : 
    2299          331 :     ScopedASN1Object matterVidObj("1.3.6.1.4.1.37244.2.1", 1); // Matter VID OID - taken from Spec
    2300          331 :     VerifyOrReturnError(matterVidObj, CHIP_ERROR_NO_MEMORY);
    2301              : 
    2302          331 :     ScopedASN1Object matterPidObj("1.3.6.1.4.1.37244.2.2", 1); // Matter PID OID - taken from Spec
    2303          331 :     VerifyOrReturnError(matterPidObj, CHIP_ERROR_NO_MEMORY);
    2304              : 
    2305          331 :     CHIP_ERROR err                     = CHIP_NO_ERROR;
    2306          331 :     X509 * x509certificate             = nullptr;
    2307          331 :     const unsigned char * pCertificate = certificate.data();
    2308          331 :     X509_NAME * subject                = nullptr;
    2309          331 :     int x509EntryCountIdx              = 0;
    2310          331 :     AttestationCertVidPid vidpidFromCN;
    2311              : 
    2312          331 :     VerifyOrExit(!certificate.empty() && CanCastTo<long>(certificate.size()), err = CHIP_ERROR_INVALID_ARGUMENT);
    2313              : 
    2314          330 :     x509certificate = d2i_X509(nullptr, &pCertificate, static_cast<long>(certificate.size()));
    2315          330 :     VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2316              : 
    2317          330 :     subject = X509_get_subject_name(x509certificate);
    2318          330 :     VerifyOrExit(subject != nullptr, err = CHIP_ERROR_INTERNAL);
    2319              : 
    2320         1111 :     for (x509EntryCountIdx = 0; x509EntryCountIdx < X509_NAME_entry_count(subject); ++x509EntryCountIdx)
    2321              :     {
    2322          795 :         X509_NAME_ENTRY * name_entry = X509_NAME_get_entry(subject, x509EntryCountIdx);
    2323          795 :         VerifyOrExit(name_entry != nullptr, err = CHIP_ERROR_INTERNAL);
    2324          795 :         ASN1_OBJECT * object = X509_NAME_ENTRY_get_object(name_entry);
    2325          795 :         VerifyOrExit(object != nullptr, err = CHIP_ERROR_INTERNAL);
    2326              : 
    2327          795 :         DNAttrType attrType = DNAttrType::kUnspecified;
    2328          795 :         if (OBJ_cmp(object, commonNameObj.Get()) == 0)
    2329              :         {
    2330          329 :             attrType = DNAttrType::kCommonName;
    2331              :         }
    2332          466 :         else if (OBJ_cmp(object, matterVidObj.Get()) == 0)
    2333              :         {
    2334          289 :             attrType = DNAttrType::kMatterVID;
    2335              :         }
    2336          177 :         else if (OBJ_cmp(object, matterPidObj.Get()) == 0)
    2337              :         {
    2338          175 :             attrType = DNAttrType::kMatterPID;
    2339              :         }
    2340              : 
    2341          795 :         if (attrType != DNAttrType::kUnspecified)
    2342              :         {
    2343          793 :             ASN1_STRING * data_entry = X509_NAME_ENTRY_get_data(name_entry);
    2344          793 :             VerifyOrExit(data_entry != nullptr, err = CHIP_ERROR_INTERNAL);
    2345          793 :             unsigned char * str = ASN1_STRING_data(data_entry);
    2346          793 :             VerifyOrExit(str != nullptr, err = CHIP_ERROR_INTERNAL);
    2347          793 :             int len = ASN1_STRING_length(data_entry);
    2348          793 :             VerifyOrExit(CanCastTo<size_t>(len), err = CHIP_ERROR_INTERNAL);
    2349              : 
    2350          793 :             err = ExtractVIDPIDFromAttributeString(attrType, ByteSpan(str, static_cast<size_t>(len)), vidpid, vidpidFromCN);
    2351          793 :             SuccessOrExit(err);
    2352              :         }
    2353              :     }
    2354              : 
    2355              :     // If Matter Attributes were not found use values extracted from the CN Attribute,
    2356              :     // which might be uninitialized as well.
    2357          316 :     if (!vidpid.Initialized())
    2358              :     {
    2359           25 :         vidpid = vidpidFromCN;
    2360              :     }
    2361              : 
    2362          291 : exit:
    2363          331 :     X509_free(x509certificate);
    2364              : 
    2365          331 :     return err;
    2366          331 : }
    2367              : 
    2368           12 : CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate, const ByteSpan * candidateCertificates,
    2369              :                                           size_t candidateCertificatesCount, ByteSpan & outCertificate)
    2370              : {
    2371           12 :     CHIP_ERROR err                        = CHIP_NO_ERROR;
    2372           12 :     X509 * x509ReferenceCertificate       = nullptr;
    2373           12 :     X509 * x509CandidateCertificate       = nullptr;
    2374           12 :     const uint8_t * pReferenceCertificate = referenceCertificate.data();
    2375           12 :     X509_NAME * referenceSubject          = nullptr;
    2376           12 :     X509_NAME * candidateSubject          = nullptr;
    2377              :     uint8_t referenceSKIDBuf[kSubjectKeyIdentifierLength];
    2378              :     uint8_t candidateSKIDBuf[kSubjectKeyIdentifierLength];
    2379           12 :     MutableByteSpan referenceSKID(referenceSKIDBuf);
    2380           12 :     MutableByteSpan candidateSKID(candidateSKIDBuf);
    2381              : 
    2382           12 :     VerifyOrReturnError(!referenceCertificate.empty(), CHIP_ERROR_INVALID_ARGUMENT);
    2383              : 
    2384           10 :     outCertificate = referenceCertificate;
    2385              : 
    2386           10 :     VerifyOrReturnError(candidateCertificates != nullptr && candidateCertificatesCount != 0, CHIP_NO_ERROR);
    2387              : 
    2388            8 :     ReturnErrorOnFailure(ExtractSKIDFromX509Cert(referenceCertificate, referenceSKID));
    2389              : 
    2390            8 :     x509ReferenceCertificate = d2i_X509(nullptr, &pReferenceCertificate, static_cast<long>(referenceCertificate.size()));
    2391            8 :     VerifyOrExit(x509ReferenceCertificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2392              : 
    2393            8 :     referenceSubject = X509_get_subject_name(x509ReferenceCertificate);
    2394            8 :     VerifyOrExit(referenceSubject != nullptr, err = CHIP_ERROR_INTERNAL);
    2395              : 
    2396           25 :     for (size_t i = 0; i < candidateCertificatesCount; i++)
    2397              :     {
    2398           21 :         const ByteSpan candidateCertificate   = candidateCertificates[i];
    2399           21 :         const uint8_t * pCandidateCertificate = candidateCertificate.data();
    2400              : 
    2401           25 :         VerifyOrExit(!candidateCertificate.empty(), err = CHIP_ERROR_INVALID_ARGUMENT);
    2402              : 
    2403           21 :         SuccessOrExit(err = ExtractSKIDFromX509Cert(candidateCertificate, candidateSKID));
    2404              : 
    2405           21 :         x509CandidateCertificate = d2i_X509(nullptr, &pCandidateCertificate, static_cast<long>(candidateCertificate.size()));
    2406           21 :         VerifyOrExit(x509CandidateCertificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
    2407              : 
    2408           21 :         candidateSubject = X509_get_subject_name(x509CandidateCertificate);
    2409           21 :         VerifyOrExit(candidateSubject != nullptr, err = CHIP_ERROR_INTERNAL);
    2410              : 
    2411           21 :         if (referenceSKID.data_equal(candidateSKID) && X509_NAME_cmp(referenceSubject, candidateSubject) == 0)
    2412              :         {
    2413            4 :             outCertificate = candidateCertificate;
    2414            4 :             ExitNow();
    2415              :         }
    2416              : 
    2417           17 :         X509_free(x509CandidateCertificate);
    2418           17 :         x509CandidateCertificate = nullptr;
    2419              :     }
    2420              : 
    2421            4 : exit:
    2422            8 :     X509_free(x509ReferenceCertificate);
    2423            8 :     X509_free(x509CandidateCertificate);
    2424              : 
    2425            8 :     return err;
    2426              : }
    2427              : 
    2428              : } // namespace Crypto
    2429              : } // namespace chip
        

Generated by: LCOV version 2.0-1