Matter SDK Coverage Report
Current view: top level - crypto - CHIPCryptoPAL.h (source / functions) Coverage Total Hit
Test: SHA:7c9b1260e3daa86aae0d41b894469b295eee70e8 Lines: 98.0 % 98 96
Test Date: 2025-09-07 07:12:04 Functions: 87.2 % 109 95

            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              :  *      Header that exposes the platform agnostic CHIP crypto primitives
      21              :  */
      22              : 
      23              : #pragma once
      24              : 
      25              : #if CHIP_HAVE_CONFIG_H
      26              : #include <crypto/CryptoBuildConfig.h>
      27              : #endif // CHIP_HAVE_CONFIG_H
      28              : 
      29              : #include <system/SystemConfig.h>
      30              : 
      31              : #include <lib/core/CHIPError.h>
      32              : #include <lib/core/CHIPVendorIdentifiers.hpp>
      33              : #include <lib/core/DataModelTypes.h>
      34              : #include <lib/core/Optional.h>
      35              : #include <lib/support/Base64.h>
      36              : #include <lib/support/BufferReader.h>
      37              : #include <lib/support/CodeUtils.h>
      38              : #include <lib/support/SafePointerCast.h>
      39              : #include <lib/support/Span.h>
      40              : #include <lib/support/StringBuilder.h>
      41              : 
      42              : #include <stddef.h>
      43              : #include <string.h>
      44              : 
      45              : namespace chip {
      46              : namespace Crypto {
      47              : 
      48              : inline constexpr size_t kMax_x509_Certificate_Length = 600;
      49              : 
      50              : inline constexpr size_t kP256_FE_Length                        = 32;
      51              : inline constexpr size_t kP256_ECDSA_Signature_Length_Raw       = (2 * kP256_FE_Length);
      52              : inline constexpr size_t kP256_Point_Length                     = (2 * kP256_FE_Length + 1);
      53              : inline constexpr size_t kSHA256_Hash_Length                    = 32;
      54              : inline constexpr size_t kSHA1_Hash_Length                      = 20;
      55              : inline constexpr size_t kSubjectKeyIdentifierLength            = kSHA1_Hash_Length;
      56              : inline constexpr size_t kAuthorityKeyIdentifierLength          = kSHA1_Hash_Length;
      57              : inline constexpr size_t kMaxCertificateSerialNumberLength      = 20;
      58              : inline constexpr size_t kMaxCertificateDistinguishedNameLength = 200;
      59              : inline constexpr size_t kMaxCRLDistributionPointURLLength      = 100;
      60              : 
      61              : inline constexpr char kValidCDPURIHttpPrefix[]  = "http://";
      62              : inline constexpr char kValidCDPURIHttpsPrefix[] = "https://";
      63              : 
      64              : inline constexpr size_t CHIP_CRYPTO_GROUP_SIZE_BYTES      = kP256_FE_Length;
      65              : inline constexpr size_t CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES = kP256_Point_Length;
      66              : 
      67              : inline constexpr size_t CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES      = 16;
      68              : inline constexpr size_t CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES = 16;
      69              : 
      70              : inline constexpr size_t kMax_ECDH_Secret_Length     = kP256_FE_Length;
      71              : inline constexpr size_t kMax_ECDSA_Signature_Length = kP256_ECDSA_Signature_Length_Raw;
      72              : inline constexpr size_t kMAX_FE_Length              = kP256_FE_Length;
      73              : inline constexpr size_t kMAX_Point_Length           = kP256_Point_Length;
      74              : inline constexpr size_t kMAX_Hash_Length            = kSHA256_Hash_Length;
      75              : 
      76              : // Minimum required CSR length buffer length is relatively small since it's a single
      77              : // P256 key and no metadata/extensions are expected to be honored by the CA.
      78              : inline constexpr size_t kMIN_CSR_Buffer_Size = 255;
      79              : 
      80              : [[deprecated("This constant is no longer used by common code and should be replaced by kMIN_CSR_Buffer_Size. Checks that a CSR is "
      81              :              "<= kMAX_CSR_Buffer_size must be updated. This remains to keep valid buffers working from previous public API "
      82              :              "usage.")]] constexpr size_t kMAX_CSR_Buffer_Size = 255;
      83              : 
      84              : inline constexpr size_t CHIP_CRYPTO_HASH_LEN_BYTES = kSHA256_Hash_Length;
      85              : 
      86              : inline constexpr size_t kSpake2p_Min_PBKDF_Salt_Length  = 16;
      87              : inline constexpr size_t kSpake2p_Max_PBKDF_Salt_Length  = 32;
      88              : inline constexpr uint32_t kSpake2p_Min_PBKDF_Iterations = 1000;
      89              : inline constexpr uint32_t kSpake2p_Max_PBKDF_Iterations = 100000;
      90              : 
      91              : inline constexpr size_t kP256_PrivateKey_Length = CHIP_CRYPTO_GROUP_SIZE_BYTES;
      92              : inline constexpr size_t kP256_PublicKey_Length  = CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES;
      93              : 
      94              : inline constexpr size_t kAES_CCM128_Key_Length   = 128u / 8u;
      95              : inline constexpr size_t kAES_CCM128_Block_Length = kAES_CCM128_Key_Length;
      96              : inline constexpr size_t kAES_CCM128_Nonce_Length = 13;
      97              : inline constexpr size_t kAES_CCM128_Tag_Length   = 16;
      98              : inline constexpr size_t kHMAC_CCM128_Key_Length  = 128u / 8u;
      99              : 
     100              : inline constexpr size_t CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES = kAES_CCM128_Nonce_Length;
     101              : 
     102              : /* These sizes are hardcoded here to remove header dependency on underlying crypto library
     103              :  * in a public interface file. The validity of these sizes is verified by static_assert in
     104              :  * the implementation files.
     105              :  */
     106              : inline constexpr size_t kMAX_Spake2p_Context_Size     = 1024;
     107              : inline constexpr size_t kMAX_P256Keypair_Context_Size = 512;
     108              : 
     109              : inline constexpr size_t kEmitDerIntegerWithoutTagOverhead = 1; // 1 sign stuffer
     110              : inline constexpr size_t kEmitDerIntegerOverhead           = 3; // Tag + Length byte + 1 sign stuffer
     111              : 
     112              : inline constexpr size_t kMAX_Hash_SHA256_Context_Size = CHIP_CONFIG_SHA256_CONTEXT_SIZE;
     113              : 
     114              : inline constexpr size_t kSpake2p_WS_Length                 = kP256_FE_Length + 8;
     115              : inline constexpr size_t kSpake2p_VerifierSerialized_Length = kP256_FE_Length + kP256_Point_Length;
     116              : 
     117              : inline constexpr char kVIDPrefixForCNEncoding[]    = "Mvid:";
     118              : inline constexpr char kPIDPrefixForCNEncoding[]    = "Mpid:";
     119              : inline constexpr size_t kVIDandPIDHexLength        = sizeof(uint16_t) * 2;
     120              : inline constexpr size_t kMax_CommonNameAttr_Length = 64;
     121              : 
     122              : enum class FabricBindingVersion : uint8_t
     123              : {
     124              :     kVersion1 = 0x01 // Initial version using version 1.0 of the Matter Cryptographic Primitives.
     125              : };
     126              : 
     127              : // VidVerificationStatementVersion is on purpose different and non-overlapping with FabricBindingVersion.
     128              : enum class VidVerificationStatementVersion : uint8_t
     129              : {
     130              :     kVersion1 = 0x21 // Initial version using version 1.0 of the Matter Cryptographic Primitives.
     131              : };
     132              : 
     133              : inline constexpr uint8_t kFabricBindingVersionV1 = 1u;
     134              : 
     135              : inline constexpr size_t kVendorIdVerificationClientChallengeSize = 32u;
     136              : 
     137              : // VIDVerificationStatement := statement_version || vid_verification_signer_skid || vid_verification_statement_signature
     138              : inline constexpr size_t kVendorIdVerificationStatementV1Size =
     139              :     sizeof(uint8_t) + kSubjectKeyIdentifierLength + kP256_ECDSA_Signature_Length_Raw;
     140              : static_assert(
     141              :     kVendorIdVerificationStatementV1Size == 85,
     142              :     "Expected size of VendorIdVerificationStatement version 1 was computed incorrectly due to changes of fundamental constants");
     143              : 
     144              : // vendor_fabric_binding_message := fabric_binding_version (1 byte) || root_public_key || fabric_id || vendor_id
     145              : inline constexpr size_t kVendorFabricBindingMessageV1Size =
     146              :     sizeof(uint8_t) + CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES + sizeof(uint64_t) + sizeof(uint16_t);
     147              : static_assert(
     148              :     kVendorFabricBindingMessageV1Size == 76,
     149              :     "Expected size of VendorFabricBindingMessage version 1 was computed incorrectly due to changes of fundamental constants");
     150              : 
     151              : // vendor_id_verification_tbs := fabric_binding_version || client_challenge || attestation_challenge || fabric_index ||
     152              : // vendor_fabric_binding_message || <vid_verification_statement>
     153              : inline constexpr size_t kVendorIdVerificationTbsV1MaxSize = sizeof(uint8_t) + kVendorIdVerificationClientChallengeSize +
     154              :     CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES + sizeof(uint8_t) + kVendorFabricBindingMessageV1Size +
     155              :     kVendorIdVerificationStatementV1Size;
     156              : 
     157              : /*
     158              :  * Overhead to encode a raw ECDSA signature in X9.62 format in ASN.1 DER
     159              :  *
     160              :  * Ecdsa-Sig-Value ::= SEQUENCE {
     161              :  *     r       INTEGER,
     162              :  *     s       INTEGER
     163              :  * }
     164              :  *
     165              :  * --> SEQUENCE, universal constructed tag (0x30), length over 2 bytes, up to 255 (to support future larger sizes up to 512 bits)
     166              :  *   -> SEQ_OVERHEAD = 3 bytes
     167              :  * --> INTEGER, universal primitive tag (0x02), length over 1 byte, one extra byte worst case
     168              :  *     over max for 0x00 when MSB is set.
     169              :  *       -> INT_OVERHEAD = 3 bytes
     170              :  *
     171              :  * There is 1 sequence of 2 integers. Overhead is SEQ_OVERHEAD + (2 * INT_OVERHEAD) = 3 + (2 * 3) = 9.
     172              :  */
     173              : inline constexpr size_t kMax_ECDSA_X9Dot62_Asn1_Overhead = 9;
     174              : inline constexpr size_t kMax_ECDSA_Signature_Length_Der  = kMax_ECDSA_Signature_Length + kMax_ECDSA_X9Dot62_Asn1_Overhead;
     175              : 
     176              : static_assert(kMax_ECDH_Secret_Length >= kP256_FE_Length, "ECDH shared secret is too short for crypto suite");
     177              : static_assert(kMax_ECDSA_Signature_Length >= kP256_ECDSA_Signature_Length_Raw,
     178              :               "ECDSA signature buffer length is too short for crypto suite");
     179              : 
     180              : inline constexpr size_t kCompressedFabricIdentifierSize = 8;
     181              : 
     182              : /**
     183              :  * Spake2+ parameters for P256
     184              :  * Defined in https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html#name-ciphersuites
     185              :  */
     186              : const uint8_t spake2p_M_p256[] = {
     187              :     0x04, 0x88, 0x6e, 0x2f, 0x97, 0xac, 0xe4, 0x6e, 0x55, 0xba, 0x9d, 0xd7, 0x24, 0x25, 0x79, 0xf2, 0x99,
     188              :     0x3b, 0x64, 0xe1, 0x6e, 0xf3, 0xdc, 0xab, 0x95, 0xaf, 0xd4, 0x97, 0x33, 0x3d, 0x8f, 0xa1, 0x2f, 0x5f,
     189              :     0xf3, 0x55, 0x16, 0x3e, 0x43, 0xce, 0x22, 0x4e, 0x0b, 0x0e, 0x65, 0xff, 0x02, 0xac, 0x8e, 0x5c, 0x7b,
     190              :     0xe0, 0x94, 0x19, 0xc7, 0x85, 0xe0, 0xca, 0x54, 0x7d, 0x55, 0xa1, 0x2e, 0x2d, 0x20,
     191              : };
     192              : const uint8_t spake2p_N_p256[] = {
     193              :     0x04, 0xd8, 0xbb, 0xd6, 0xc6, 0x39, 0xc6, 0x29, 0x37, 0xb0, 0x4d, 0x99, 0x7f, 0x38, 0xc3, 0x77, 0x07,
     194              :     0x19, 0xc6, 0x29, 0xd7, 0x01, 0x4d, 0x49, 0xa2, 0x4b, 0x4f, 0x98, 0xba, 0xa1, 0x29, 0x2b, 0x49, 0x07,
     195              :     0xd6, 0x0a, 0xa6, 0xbf, 0xad, 0xe4, 0x50, 0x08, 0xa6, 0x36, 0x33, 0x7f, 0x51, 0x68, 0xc6, 0x4d, 0x9b,
     196              :     0xd3, 0x60, 0x34, 0x80, 0x8c, 0xd5, 0x64, 0x49, 0x0b, 0x1e, 0x65, 0x6e, 0xdb, 0xe7,
     197              : };
     198              : 
     199              : /**
     200              :  * Spake2+ state machine to ensure proper execution of the protocol.
     201              :  */
     202              : enum class CHIP_SPAKE2P_STATE : uint8_t
     203              : {
     204              :     PREINIT = 0, // Before any initialization
     205              :     INIT,        // First initialization
     206              :     STARTED,     // Prover & Verifier starts
     207              :     R1,          // Round one complete
     208              :     R2,          // Round two complete
     209              :     KC,          // Key confirmation complete
     210              : };
     211              : 
     212              : /**
     213              :  * Spake2+ role.
     214              :  */
     215              : enum class CHIP_SPAKE2P_ROLE : uint8_t
     216              : {
     217              :     VERIFIER = 0, // Accessory
     218              :     PROVER   = 1, // Commissioner
     219              : };
     220              : 
     221              : enum class SupportedECPKeyTypes : uint8_t
     222              : {
     223              :     ECP256R1 = 0,
     224              : };
     225              : 
     226              : enum class ECPKeyTarget : uint8_t
     227              : {
     228              :     ECDH  = 0,
     229              :     ECDSA = 1,
     230              : };
     231              : 
     232              : /** @brief Safely clears the first `len` bytes of memory area `buf`.
     233              :  * @param buf Pointer to a memory buffer holding secret data that must be cleared.
     234              :  * @param len Specifies secret data size in bytes.
     235              :  **/
     236              : void ClearSecretData(uint8_t * buf, size_t len);
     237              : 
     238              : /**
     239              :  * Helper for clearing a C array which auto-deduces the size.
     240              :  */
     241              : template <size_t N>
     242       416916 : void ClearSecretData(uint8_t (&buf)[N])
     243              : {
     244       416916 :     ClearSecretData(buf, N);
     245       416916 : }
     246              : 
     247              : /**
     248              :  * @brief Constant-time buffer comparison
     249              :  *
     250              :  * This function implements constant time memcmp. It's good practice
     251              :  * to use constant time functions for cryptographic functions.
     252              :  *
     253              :  * @param a Pointer to first buffer
     254              :  * @param b Pointer to Second buffer
     255              :  * @param n Number of bytes to compare
     256              :  * @return true if `n` first bytes of both buffers are equal, false otherwise
     257              :  */
     258              : bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n);
     259              : 
     260              : template <typename Sig>
     261              : class ECPKey
     262              : {
     263              : protected:
     264              :     // This base type can't be copied / assigned directly.
     265              :     // Sub-types should be either uncopyable or final.
     266        15633 :     ECPKey()                           = default;
     267              :     ECPKey(const ECPKey &)             = default;
     268         1668 :     ECPKey & operator=(const ECPKey &) = default;
     269              : 
     270              : public:
     271        15633 :     virtual ~ECPKey() = default;
     272              : 
     273              :     virtual SupportedECPKeyTypes Type() const  = 0;
     274              :     virtual size_t Length() const              = 0;
     275              :     virtual bool IsUncompressed() const        = 0;
     276              :     virtual operator const uint8_t *() const   = 0;
     277              :     virtual operator uint8_t *()               = 0;
     278              :     virtual const uint8_t * ConstBytes() const = 0;
     279              :     virtual uint8_t * Bytes()                  = 0;
     280              : 
     281          834 :     virtual bool Matches(const ECPKey<Sig> & other) const
     282              :     {
     283         1668 :         return (this->Length() == other.Length()) &&
     284         1668 :             IsBufferContentEqualConstantTime(this->ConstBytes(), other.ConstBytes(), this->Length());
     285              :     }
     286              : 
     287              :     virtual CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length, const Sig & signature) const = 0;
     288              :     virtual CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length,
     289              :                                                      const Sig & signature) const                                              = 0;
     290              : };
     291              : 
     292              : /**
     293              :  * @brief Helper class for holding sensitive data that should be erased from memory after use.
     294              :  *
     295              :  * The sensitive data buffer is a variable-length, fixed-capacity buffer class that securely erases
     296              :  * the contents of a buffer when the buffer is destroyed.
     297              :  */
     298              : template <size_t kCapacity>
     299              : class SensitiveDataBuffer
     300              : {
     301              : public:
     302         5964 :     ~SensitiveDataBuffer()
     303              :     {
     304              :         // Sanitize after use
     305         5964 :         ClearSecretData(mBytes);
     306         5964 :     }
     307         5962 :     SensitiveDataBuffer() {}
     308            1 :     SensitiveDataBuffer(const SensitiveDataBuffer & other) { *this = other; }
     309            1 :     SensitiveDataBuffer & operator=(const SensitiveDataBuffer & other)
     310              :     {
     311              :         // Guard self assignment
     312            1 :         if (this == &other)
     313            0 :             return *this;
     314              : 
     315            1 :         ClearSecretData(mBytes);
     316            1 :         SetLength(other.Length());
     317            1 :         ::memcpy(Bytes(), other.ConstBytes(), other.Length());
     318            1 :         return *this;
     319              :     }
     320              : 
     321              :     /**
     322              :      * @brief Set current length of the buffer
     323              :      * @return Error if new length is exceeds capacity of the buffer
     324              :      */
     325         4557 :     CHIP_ERROR SetLength(size_t length)
     326              :     {
     327         4557 :         VerifyOrReturnError(length <= kCapacity, CHIP_ERROR_INVALID_ARGUMENT);
     328         4556 :         mLength = length;
     329         4556 :         return CHIP_NO_ERROR;
     330              :     }
     331              : 
     332              :     /**
     333              :      * @brief Returns current length of the buffer
     334              :      */
     335         5264 :     size_t Length() const { return mLength; }
     336              : 
     337              :     /**
     338              :      * @brief Returns non-const pointer to start of the underlying buffer
     339              :      */
     340         6270 :     uint8_t * Bytes() { return &mBytes[0]; }
     341              : 
     342              :     /**
     343              :      * @brief Returns const pointer to start of the underlying buffer
     344              :      */
     345         7966 :     const uint8_t * ConstBytes() const { return &mBytes[0]; }
     346              : 
     347              :     /**
     348              :      * @brief Constructs span from the underlying buffer
     349              :      */
     350           23 :     ByteSpan Span() const { return ByteSpan(ConstBytes(), Length()); }
     351              : 
     352              :     /**
     353              :      * @brief Returns capacity of the buffer
     354              :      */
     355         2683 :     static constexpr size_t Capacity() { return kCapacity; }
     356              : 
     357              : private:
     358              :     uint8_t mBytes[kCapacity];
     359              :     size_t mLength = 0;
     360              : };
     361              : 
     362              : /**
     363              :  * @brief Helper class for holding fixed-sized sensitive data that should be erased from memory after use.
     364              :  *
     365              :  * The sensitive data buffer is a fixed-length, fixed-capacity buffer class that securely erases
     366              :  * the contents of a buffer when the buffer is destroyed.
     367              :  */
     368              : template <size_t kCapacity>
     369              : class SensitiveDataFixedBuffer
     370              : {
     371              : public:
     372              :     SensitiveDataFixedBuffer() = default;
     373              : 
     374            1 :     constexpr explicit SensitiveDataFixedBuffer(const uint8_t (&rawValue)[kCapacity])
     375              :     {
     376            1 :         memcpy(&mBytes[0], &rawValue[0], kCapacity);
     377            1 :     }
     378              : 
     379            1 :     constexpr explicit SensitiveDataFixedBuffer(const FixedByteSpan<kCapacity> & value)
     380              :     {
     381            1 :         memcpy(&mBytes[0], value.data(), kCapacity);
     382            1 :     }
     383              : 
     384       135414 :     ~SensitiveDataFixedBuffer()
     385              :     {
     386              :         // Sanitize after use
     387       135414 :         ClearSecretData(mBytes);
     388       135414 :     }
     389              : 
     390              :     /**
     391              :      * @brief Returns fixed length of the buffer
     392              :      */
     393              :     constexpr size_t Length() const { return kCapacity; }
     394              : 
     395              :     /**
     396              :      * @brief Returns non-const pointer to start of the underlying buffer
     397              :      */
     398         1617 :     uint8_t * Bytes() { return &mBytes[0]; }
     399              : 
     400              :     /**
     401              :      * @brief Returns const pointer to start of the underlying buffer
     402              :      */
     403           23 :     const uint8_t * ConstBytes() const { return &mBytes[0]; }
     404              : 
     405              :     /**
     406              :      * @brief Constructs fixed span from the underlying buffer
     407              :      */
     408            2 :     FixedByteSpan<kCapacity> Span() const { return FixedByteSpan<kCapacity>(mBytes); }
     409              : 
     410              :     /**
     411              :      * @brief Returns capacity of the buffer
     412              :      */
     413         1622 :     static constexpr size_t Capacity() { return kCapacity; }
     414              : 
     415              : private:
     416              :     uint8_t mBytes[kCapacity];
     417              : };
     418              : 
     419              : using P256ECDSASignature    = SensitiveDataBuffer<kMax_ECDSA_Signature_Length>;
     420              : using P256ECDHDerivedSecret = SensitiveDataBuffer<kMax_ECDH_Secret_Length>;
     421              : 
     422              : using IdentityProtectionKey     = SensitiveDataFixedBuffer<CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES>;
     423              : using IdentityProtectionKeySpan = FixedByteSpan<Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES>;
     424              : 
     425              : using AttestationChallenge = SensitiveDataFixedBuffer<CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES>;
     426              : 
     427              : class P256PublicKey final // final due to being copyable
     428              :     : public ECPKey<P256ECDSASignature>
     429              : {
     430              : public:
     431        14783 :     P256PublicKey() = default;
     432              : 
     433              :     template <size_t N>
     434            5 :     constexpr P256PublicKey(const uint8_t (&raw_value)[N])
     435            5 :     {
     436              :         static_assert(N == kP256_PublicKey_Length, "Can only array-initialize from proper bounds");
     437            5 :         memcpy(&bytes[0], &raw_value[0], N);
     438            5 :     }
     439              : 
     440              :     template <size_t N>
     441          845 :     constexpr P256PublicKey(const FixedByteSpan<N> & value)
     442          845 :     {
     443              :         static_assert(N == kP256_PublicKey_Length, "Can only initialize from proper sized byte span");
     444          845 :         memcpy(&bytes[0], value.data(), N);
     445          845 :     }
     446              : 
     447              :     template <size_t N>
     448          966 :     P256PublicKey & operator=(const FixedByteSpan<N> & value)
     449              :     {
     450              :         static_assert(N == kP256_PublicKey_Length, "Can only initialize from proper sized byte span");
     451          966 :         memcpy(&bytes[0], value.data(), N);
     452          966 :         return *this;
     453              :     }
     454              : 
     455         4361 :     SupportedECPKeyTypes Type() const override { return SupportedECPKeyTypes::ECP256R1; }
     456        16960 :     size_t Length() const override { return kP256_PublicKey_Length; }
     457         6517 :     operator uint8_t *() override { return bytes; }
     458         2717 :     operator const uint8_t *() const override { return bytes; }
     459         3395 :     const uint8_t * ConstBytes() const override { return &bytes[0]; }
     460           32 :     uint8_t * Bytes() override { return &bytes[0]; }
     461          834 :     bool IsUncompressed() const override
     462              :     {
     463          834 :         constexpr uint8_t kUncompressedPointMarker = 0x04;
     464              :         // SEC1 definition of an uncompressed point is (0x04 || X || Y) where X and Y are
     465              :         // raw zero-padded big-endian large integers of the group size.
     466          834 :         return (Length() == ((kP256_FE_Length * 2) + 1)) && (ConstBytes()[0] == kUncompressedPointMarker);
     467              :     }
     468              : 
     469              :     CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length,
     470              :                                             const P256ECDSASignature & signature) const override;
     471              :     CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length,
     472              :                                              const P256ECDSASignature & signature) const override;
     473              : 
     474              : private:
     475              :     uint8_t bytes[kP256_PublicKey_Length];
     476              : };
     477              : 
     478              : template <typename PK, typename Secret, typename Sig>
     479              : class ECPKeypair
     480              : {
     481              : protected:
     482              :     // This base type can't be copied / assigned directly.
     483              :     // Sub-types should be either uncopyable or final.
     484         1816 :     ECPKeypair()                               = default;
     485              :     ECPKeypair(const ECPKeypair &)             = default;
     486              :     ECPKeypair & operator=(const ECPKeypair &) = default;
     487              : 
     488              : public:
     489         1816 :     virtual ~ECPKeypair() = default;
     490              : 
     491              :     /** @brief Generate a new Certificate Signing Request (CSR).
     492              :      * @param csr Newly generated CSR in DER format
     493              :      * @param csr_length The caller provides the length of input buffer (csr). The function returns the actual length of generated
     494              :      *CSR.
     495              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     496              :      **/
     497              :     virtual CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const = 0;
     498              : 
     499              :     /**
     500              :      * @brief A function to sign a msg using ECDSA
     501              :      * @param msg Message that needs to be signed
     502              :      * @param msg_length Length of message
     503              :      * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
     504              :      * in raw <r,s> point form (see SEC1).
     505              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     506              :      **/
     507              :     virtual CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, Sig & out_signature) const = 0;
     508              : 
     509              :     /** @brief A function to derive a shared secret using ECDH
     510              :      * @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
     511              :      * ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
     512              :      * [https://www.secg.org/sec1-v2.pdf]
     513              :      * @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
     514              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     515              :      **/
     516              :     virtual CHIP_ERROR ECDH_derive_secret(const PK & remote_public_key, Secret & out_secret) const = 0;
     517              : 
     518              :     virtual const PK & Pubkey() const = 0;
     519              : };
     520              : 
     521              : struct alignas(size_t) P256KeypairContext
     522              : {
     523              :     uint8_t mBytes[kMAX_P256Keypair_Context_Size];
     524              : };
     525              : 
     526              : /**
     527              :  * A serialized P256 key pair is the concatenation of the public and private keys, in that order.
     528              :  */
     529              : using P256SerializedKeypair = SensitiveDataBuffer<kP256_PublicKey_Length + kP256_PrivateKey_Length>;
     530              : 
     531              : class P256KeypairBase : public ECPKeypair<P256PublicKey, P256ECDHDerivedSecret, P256ECDSASignature>
     532              : {
     533              : protected:
     534              :     // This base type can't be copied / assigned directly.
     535              :     // Sub-types should be either uncopyable or final.
     536         1816 :     P256KeypairBase()                                    = default;
     537              :     P256KeypairBase(const P256KeypairBase &)             = default;
     538              :     P256KeypairBase & operator=(const P256KeypairBase &) = default;
     539              : 
     540              : public:
     541              :     /**
     542              :      * @brief Initialize the keypair.
     543              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     544              :      **/
     545              :     virtual CHIP_ERROR Initialize(ECPKeyTarget key_target) = 0;
     546              : 
     547              :     /**
     548              :      * @brief Serialize the keypair.
     549              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     550              :      **/
     551              :     virtual CHIP_ERROR Serialize(P256SerializedKeypair & output) const = 0;
     552              : 
     553              :     /**
     554              :      * @brief Deserialize the keypair.
     555              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     556              :      **/
     557              :     virtual CHIP_ERROR Deserialize(P256SerializedKeypair & input) = 0;
     558              : };
     559              : 
     560              : class P256Keypair : public P256KeypairBase
     561              : {
     562              : public:
     563         1816 :     P256Keypair() = default;
     564              :     ~P256Keypair() override;
     565              : 
     566              :     // P256Keypair can't be copied / assigned.
     567              :     P256Keypair(const P256Keypair &)             = delete;
     568              :     P256Keypair & operator=(const P256Keypair &) = delete;
     569              : 
     570              :     /**
     571              :      * @brief Initialize the keypair.
     572              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     573              :      **/
     574              :     CHIP_ERROR Initialize(ECPKeyTarget key_target) override;
     575              : 
     576              :     /**
     577              :      * @brief Serialize the keypair.
     578              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     579              :      **/
     580              :     CHIP_ERROR Serialize(P256SerializedKeypair & output) const override;
     581              : 
     582              :     /**
     583              :      * @brief Deserialize the keypair.
     584              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     585              :      **/
     586              :     CHIP_ERROR Deserialize(P256SerializedKeypair & input) override;
     587              : 
     588              :     /**
     589              :      * @brief Generate a new Certificate Signing Request (CSR).
     590              :      * @param csr Newly generated CSR in DER format
     591              :      * @param csr_length The caller provides the length of input buffer (csr). The function returns the actual length of generated
     592              :      *CSR.
     593              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     594              :      **/
     595              :     CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const override;
     596              : 
     597              :     /**
     598              :      * @brief A function to sign a msg using ECDSA
     599              :      * @param msg Message that needs to be signed
     600              :      * @param msg_length Length of message
     601              :      * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
     602              :      * in raw <r,s> point form (see SEC1).
     603              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     604              :      **/
     605              :     CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const override;
     606              : 
     607              :     /**
     608              :      * @brief A function to derive a shared secret using ECDH
     609              :      *
     610              :      * This implements the CHIP_Crypto_ECDH(PrivateKey myPrivateKey, PublicKey theirPublicKey) cryptographic primitive
     611              :      * from the specification, using this class's private key from `mKeypair` as `myPrivateKey` and the remote
     612              :      * public key from `remote_public_key` as `theirPublicKey`.
     613              :      *
     614              :      * @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
     615              :      * ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
     616              :      * [https://www.secg.org/sec1-v2.pdf]
     617              :      * @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
     618              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     619              :      **/
     620              :     CHIP_ERROR ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const override;
     621              : 
     622              :     /**
     623              :      * @brief Loads a P256 keypair from raw private and public key byte spans.
     624              :      *
     625              :      * !!!!!! IMPORTANT !!!!!!!
     626              :      * Raw private keys SHOULD NOT be loaded directly without extreme care about ensuring they do not get retained in
     627              :      * memory (e.g. stack or heap) and have the shortest possible lifecycle. Please consider replacing basic example
     628              :      * usage of private key loading with delegation of signing to another part of the system that preferably has key
     629              :      * material isolation or protection.
     630              :      *
     631              :      * Combines the public and private key data into a serialized keypair format,
     632              :      * then deserializes it into this keypair object.
     633              :      *
     634              :      * @param private_key ByteSpan containing the raw private key bytes.
     635              :      * @param public_key ByteSpan containing the raw public key bytes.
     636              :      * @return CHIP_ERROR indicating success or failure of the operation.
     637              :      */
     638              :     CHIP_ERROR HazardousOperationLoadKeypairFromRaw(ByteSpan private_key, ByteSpan public_key);
     639              : 
     640              :     /** @brief Return public key for the keypair.
     641              :      **/
     642         1220 :     const P256PublicKey & Pubkey() const override { return mPublicKey; }
     643              : 
     644              : #if CHIP_WITH_NLFAULTINJECTION
     645            0 :     P256PublicKey & TestOnlyMutablePubkey() { return mPublicKey; }
     646              : #endif
     647              : 
     648              :     /** Release resources associated with this key pair */
     649              :     void Clear();
     650              : 
     651              : protected:
     652              : #if CHIP_WITH_NLFAULTINJECTION
     653              :     mutable P256PublicKey mPublicKey;
     654              : #else
     655              :     P256PublicKey mPublicKey;
     656              : #endif
     657              :     // P256PublicKey mPublicKey;
     658              :     mutable P256KeypairContext mKeypair;
     659              :     bool mInitialized = false;
     660              : };
     661              : 
     662              : /**
     663              :  * @brief Platform-specific symmetric key handle
     664              :  *
     665              :  * The class represents a key used by the Matter stack either in the form of raw key material or key
     666              :  * reference, depending on the platform. To achieve that, it contains an opaque context that can be
     667              :  * cast to a concrete representation used by the given platform.
     668              :  *
     669              :  * @note SymmetricKeyHandle is an abstract class to force child classes for each key handle type.
     670              :  *       SymmetricKeyHandle class implements all the necessary components for handles.
     671              :  */
     672              : template <size_t ContextSize>
     673              : class SymmetricKeyHandle
     674              : {
     675              : public:
     676              :     SymmetricKeyHandle(const SymmetricKeyHandle &) = delete;
     677              :     SymmetricKeyHandle(SymmetricKeyHandle &&)      = delete;
     678              :     void operator=(const SymmetricKeyHandle &)     = delete;
     679              :     void operator=(SymmetricKeyHandle &&)          = delete;
     680              : 
     681              :     /**
     682              :      * @brief Get internal context cast to the desired key representation
     683              :      */
     684              :     template <class T>
     685        30639 :     const T & As() const
     686              :     {
     687        30639 :         return *SafePointerCast<const T *>(&mContext);
     688              :     }
     689              : 
     690              :     /**
     691              :      * @brief Get internal context cast to the desired, mutable key representation
     692              :      */
     693              :     template <class T>
     694         7864 :     T & AsMutable()
     695              :     {
     696         7864 :         return *SafePointerCast<T *>(&mContext);
     697              :     }
     698              : 
     699              : protected:
     700       271529 :     SymmetricKeyHandle() = default;
     701       271693 :     ~SymmetricKeyHandle() { ClearSecretData(mContext.mOpaque); }
     702              : 
     703              : private:
     704              :     struct alignas(uintptr_t) OpaqueContext
     705              :     {
     706              :         uint8_t mOpaque[ContextSize] = {};
     707              :     } mContext;
     708              : };
     709              : 
     710              : using Symmetric128BitsKeyByteArray = uint8_t[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES];
     711              : 
     712              : /**
     713              :  * @brief Platform-specific 128-bit symmetric key handle
     714              :  */
     715              : class Symmetric128BitsKeyHandle : public SymmetricKeyHandle<CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES>
     716              : {
     717              : };
     718              : 
     719              : /**
     720              :  * @brief Platform-specific 128-bit AES key handle
     721              :  */
     722              : class Aes128KeyHandle final : public Symmetric128BitsKeyHandle
     723              : {
     724              : };
     725              : 
     726              : /**
     727              :  * @brief Platform-specific 128-bit HMAC key handle
     728              :  */
     729              : class Hmac128KeyHandle final : public Symmetric128BitsKeyHandle
     730              : {
     731              : };
     732              : 
     733              : /**
     734              :  * @brief Platform-specific HKDF key handle
     735              :  */
     736              : class HkdfKeyHandle final : public SymmetricKeyHandle<CHIP_CONFIG_HKDF_KEY_HANDLE_CONTEXT_SIZE>
     737              : {
     738              : };
     739              : 
     740              : /**
     741              :  * @brief Convert a raw ECDSA signature to ASN.1 signature (per X9.62) as used by TLS libraries.
     742              :  *
     743              :  * Errors are:
     744              :  *   - CHIP_ERROR_INVALID_ARGUMENT on any argument being invalid (e.g. nullptr), wrong sizes,
     745              :  *     wrong or unsupported format,
     746              :  *   - CHIP_ERROR_BUFFER_TOO_SMALL on running out of space at runtime.
     747              :  *   - CHIP_ERROR_INTERNAL on any unexpected processing error.
     748              :  *
     749              :  * @param[in] fe_length_bytes Field Element length in bytes (e.g. 32 for P256 curve)
     750              :  * @param[in] raw_sig Raw signature of <r,s> concatenated
     751              :  * @param[out] out_asn1_sig ASN.1 DER signature format output buffer. Size must have space for at least
     752              :  * kMax_ECDSA_X9Dot62_Asn1_Overhead. On CHIP_NO_ERROR, the out_asn1_sig buffer will be re-assigned
     753              :  * to have the correct size based on variable-length output.
     754              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     755              :  */
     756              : CHIP_ERROR EcdsaRawSignatureToAsn1(size_t fe_length_bytes, const ByteSpan & raw_sig, MutableByteSpan & out_asn1_sig);
     757              : 
     758              : /**
     759              :  * @brief Convert an ASN.1 DER signature (per X9.62) as used by TLS libraries to SEC1 raw format
     760              :  *
     761              :  * Errors are:
     762              :  *   - CHIP_ERROR_INVALID_ARGUMENT on any argument being invalid (e.g. nullptr), wrong sizes,
     763              :  *     wrong or unsupported format,
     764              :  *   - CHIP_ERROR_BUFFER_TOO_SMALL on running out of space at runtime.
     765              :  *   - CHIP_ERROR_INTERNAL on any unexpected processing error.
     766              :  *
     767              :  * @param[in] fe_length_bytes Field Element length in bytes (e.g. 32 for P256 curve)
     768              :  * @param[in] asn1_sig ASN.1 DER signature input
     769              :  * @param[out] out_raw_sig Raw signature of <r,s> concatenated format output buffer. Size must be at
     770              :  * least >= `2 * fe_length_bytes`. On CHIP_NO_ERROR, the out_raw_sig buffer will be re-assigned
     771              :  * to have the correct size (2 * fe_length_bytes).
     772              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     773              :  */
     774              : CHIP_ERROR EcdsaAsn1SignatureToRaw(size_t fe_length_bytes, const ByteSpan & asn1_sig, MutableByteSpan & out_raw_sig);
     775              : 
     776              : /**
     777              :  * @brief Utility to read a length field after a tag in a DER-encoded stream.
     778              :  * @param[in] reader Reader instance from which the input will be read
     779              :  * @param[out] length Length of the following element read from the stream
     780              :  * @return CHIP_ERROR_INVALID_ARGUMENT or CHIP_ERROR_BUFFER_TOO_SMALL on error, CHIP_NO_ERROR otherwise
     781              :  */
     782              : CHIP_ERROR ReadDerLength(chip::Encoding::LittleEndian::Reader & reader, size_t & length);
     783              : 
     784              : /**
     785              :  * @brief Utility to emit a DER-encoded INTEGER given a raw unsigned large integer
     786              :  *        in big-endian order. The `out_der_integer` span is updated to reflect the final
     787              :  *        variable length, including tag and length, and must have at least `kEmitDerIntegerOverhead`
     788              :  *        extra space in addition to the `raw_integer.size()`.
     789              :  * @param[in] raw_integer Bytes of a large unsigned integer in big-endian, possibly including leading zeroes
     790              :  * @param[out] out_der_integer Buffer to receive the DER-encoded integer
     791              :  * @return Returns CHIP_ERROR_INVALID_ARGUMENT or CHIP_ERROR_BUFFER_TOO_SMALL on error, CHIP_NO_ERROR otherwise.
     792              :  */
     793              : CHIP_ERROR ConvertIntegerRawToDer(const ByteSpan & raw_integer, MutableByteSpan & out_der_integer);
     794              : 
     795              : /**
     796              :  * @brief Utility to emit a DER-encoded INTEGER given a raw unsigned large integer
     797              :  *        in big-endian order. The `out_der_integer` span is updated to reflect the final
     798              :  *        variable length, excluding tag and length, and must have at least `kEmitDerIntegerWithoutTagOverhead`
     799              :  *        extra space in addition to the `raw_integer.size()`.
     800              :  * @param[in] raw_integer Bytes of a large unsigned integer in big-endian, possibly including leading zeroes
     801              :  * @param[out] out_der_integer Buffer to receive the DER-encoded integer
     802              :  * @return Returns CHIP_ERROR_INVALID_ARGUMENT or CHIP_ERROR_BUFFER_TOO_SMALL on error, CHIP_NO_ERROR otherwise.
     803              :  */
     804              : CHIP_ERROR ConvertIntegerRawToDerWithoutTag(const ByteSpan & raw_integer, MutableByteSpan & out_der_integer);
     805              : 
     806              : /**
     807              :  * @brief A function that implements AES-CCM encryption
     808              :  *
     809              :  * This implements the CHIP_Crypto_AEAD_GenerateEncrypt() cryptographic primitive
     810              :  * from the specification. For an empty plaintext, the user of the API can provide
     811              :  * an empty string, or a nullptr, and provide plaintext_length as 0. The output buffer,
     812              :  * ciphertext can also be an empty string, or a nullptr for this case.
     813              :  *
     814              :  * @param plaintext Plaintext to encrypt
     815              :  * @param plaintext_length Length of plain_text
     816              :  * @param aad Additional authentication data
     817              :  * @param aad_length Length of additional authentication data
     818              :  * @param key Encryption key
     819              :  * @param nonce Encryption nonce
     820              :  * @param nonce_length Length of encryption nonce
     821              :  * @param ciphertext Buffer to write ciphertext into. Caller must ensure this is large enough to hold the ciphertext
     822              :  * @param tag Buffer to write tag into. Caller must ensure this is large enough to hold the tag
     823              :  * @param tag_length Expected length of tag
     824              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     825              :  * */
     826              : CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
     827              :                            const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
     828              :                            uint8_t * tag, size_t tag_length);
     829              : 
     830              : /**
     831              :  * @brief A function that implements AES-CCM decryption
     832              :  *
     833              :  * This implements the CHIP_Crypto_AEAD_DecryptVerify() cryptographic primitive
     834              :  * from the specification. For an empty ciphertext, the user of the API can provide
     835              :  * an empty string, or a nullptr, and provide ciphertext_length as 0. The output buffer,
     836              :  * plaintext can also be an empty string, or a nullptr for this case.
     837              :  *
     838              :  * @param ciphertext Ciphertext to decrypt
     839              :  * @param ciphertext_length Length of ciphertext
     840              :  * @param aad Additional authentical data.
     841              :  * @param aad_length Length of additional authentication data
     842              :  * @param tag Tag to use to decrypt
     843              :  * @param tag_length Length of tag
     844              :  * @param key Decryption key
     845              :  * @param nonce Encryption nonce
     846              :  * @param nonce_length Length of encryption nonce
     847              :  * @param plaintext Buffer to write plaintext into
     848              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     849              :  **/
     850              : CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, const uint8_t * aad, size_t aad_length,
     851              :                            const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce,
     852              :                            size_t nonce_length, uint8_t * plaintext);
     853              : 
     854              : /**
     855              :  * @brief A function that implements AES-CTR encryption/decryption
     856              :  *
     857              :  * This implements the AES-CTR-Encrypt/Decrypt() cryptographic primitives per sections
     858              :  * 3.7.1 and 3.7.2 of the specification. For an empty input, the user of the API
     859              :  * can provide an empty string, or a nullptr, and provide input as 0.
     860              :  * The output buffer can also be an empty string, or a nullptr for this case.
     861              :  *
     862              :  * @param input Input text to encrypt/decrypt
     863              :  * @param input_length Length of ciphertext
     864              :  * @param key Decryption key
     865              :  * @param nonce Encryption nonce
     866              :  * @param nonce_length Length of encryption nonce
     867              :  * @param output Buffer to write output into
     868              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     869              :  **/
     870              : CHIP_ERROR AES_CTR_crypt(const uint8_t * input, size_t input_length, const Aes128KeyHandle & key, const uint8_t * nonce,
     871              :                          size_t nonce_length, uint8_t * output);
     872              : 
     873              : /**
     874              :  * @brief Generate a PKCS#10 CSR, usable for Matter, from a P256Keypair.
     875              :  *
     876              :  * This uses first principles ASN.1 encoding to avoid relying on the CHIPCryptoPAL backend
     877              :  * itself, other than to provide an implementation of a P256Keypair * that supports
     878              :  * at least `::Pubkey()` and `::ECDSA_sign_msg`. This allows using it with
     879              :  * OS/Platform-bridged private key handling, without requiring a specific
     880              :  * implementation of other bits like ASN.1.
     881              :  *
     882              :  * The CSR will have subject OU set to `CSA`. This is needed since omiting
     883              :  * subject altogether often trips CSR parsing code. The profile at the CA can
     884              :  * be configured to ignore CSR requested subject.
     885              :  *
     886              :  * @param keypair The key pair for which a CSR should be generated. Must not be null.
     887              :  * @param csr_span Span to hold the resulting CSR. Must have size at least kMIN_CSR_Buffer_Size.
     888              :  *                 Otherwise returns CHIP_ERROR_BUFFER_TOO_SMALL. It will get resized to
     889              :  *                 actual size needed on success.
     890              : 
     891              :  * @return Returns a CHIP_ERROR from P256Keypair or ASN.1 backend on error, CHIP_NO_ERROR otherwise
     892              :  **/
     893              : CHIP_ERROR GenerateCertificateSigningRequest(const P256Keypair * keypair, MutableByteSpan & csr_span);
     894              : 
     895              : /**
     896              :  * @brief Common code to validate ASN.1 format/size of a CSR, used by VerifyCertificateSigningRequest.
     897              :  *
     898              :  * Ensures it's not obviously malformed and doesn't have trailing garbage.
     899              :  *
     900              :  * @param csr CSR in DER format
     901              :  * @param csr_length The length of the CSR buffer
     902              :  * @return CHIP_ERROR_UNSUPPORTED_CERT_FORMAT on invalid format, CHIP_NO_ERROR otherwise.
     903              :  */
     904              : CHIP_ERROR VerifyCertificateSigningRequestFormat(const uint8_t * csr, size_t csr_length);
     905              : 
     906              : /**
     907              :  * @brief Verify the Certificate Signing Request (CSR). If successfully verified, it outputs the public key from the CSR.
     908              :  *
     909              :  * The CSR is valid if the format is correct, the signature validates with the embedded public
     910              :  * key, and there is no trailing garbage data.
     911              :  *
     912              :  * @param csr CSR in DER format
     913              :  * @param csr_length The length of the CSR
     914              :  * @param pubkey The public key from the verified CSR
     915              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     916              :  **/
     917              : CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr, size_t csr_length, P256PublicKey & pubkey);
     918              : 
     919              : /**
     920              :  * @brief A function that implements SHA-256 hash
     921              :  *
     922              :  * This implements the CHIP_Crypto_Hash() cryptographic primitive
     923              :  * in the the specification.
     924              :  *
     925              :  * @param data The data to hash
     926              :  * @param data_length Length of the data
     927              :  * @param out_buffer Pointer to buffer to write output into
     928              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     929              :  **/
     930              : 
     931              : CHIP_ERROR Hash_SHA256(const uint8_t * data, size_t data_length, uint8_t * out_buffer);
     932              : 
     933              : /**
     934              :  * @brief A function that implements SHA-1 hash
     935              :  * @param data The data to hash
     936              :  * @param data_length Length of the data
     937              :  * @param out_buffer Pointer to buffer to write output into
     938              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     939              :  **/
     940              : 
     941              : CHIP_ERROR Hash_SHA1(const uint8_t * data, size_t data_length, uint8_t * out_buffer);
     942              : 
     943              : /**
     944              :  * @brief A class that defines stream based implementation of SHA-256 hash
     945              :  *        It's expected that the object of this class can be safely copied.
     946              :  *        All implementations must check for std::is_trivially_copyable.
     947              :  **/
     948              : 
     949              : struct alignas(CHIP_CONFIG_SHA256_CONTEXT_ALIGN) HashSHA256OpaqueContext
     950              : {
     951              :     uint8_t mOpaque[kMAX_Hash_SHA256_Context_Size];
     952              : };
     953              : 
     954              : class Hash_SHA256_stream
     955              : {
     956              : public:
     957              :     Hash_SHA256_stream();
     958              :     ~Hash_SHA256_stream();
     959              : 
     960              :     /**
     961              :      * @brief Re-initialize digest computation to an empty context.
     962              :      *
     963              :      * @return CHIP_ERROR_INTERNAL on failure to initialize the context,
     964              :      *         CHIP_NO_ERROR otherwise.
     965              :      */
     966              :     CHIP_ERROR Begin();
     967              : 
     968              :     /**
     969              :      * @brief Add some data to the digest computation, updating internal state.
     970              :      *
     971              :      * @param[in] data The span of bytes to include in the digest update process.
     972              :      *
     973              :      * @return CHIP_ERROR_INTERNAL on failure to ingest the data, CHIP_NO_ERROR otherwise.
     974              :      */
     975              :     CHIP_ERROR AddData(const ByteSpan data);
     976              : 
     977              :     /**
     978              :      * @brief Get the intermediate padded digest for the current state of the stream.
     979              :      *
     980              :      * More data can be added before finish is called.
     981              :      *
     982              :      * @param[in,out] out_buffer Output buffer to receive the digest. `out_buffer` must
     983              :      * be at least `kSHA256_Hash_Length` bytes long. The `out_buffer` size
     984              :      * will be set to `kSHA256_Hash_Length` on success.
     985              :      *
     986              :      * @return CHIP_ERROR_INTERNAL on failure to compute the digest, CHIP_ERROR_BUFFER_TOO_SMALL
     987              :      *         if out_buffer is too small, CHIP_NO_ERROR otherwise.
     988              :      */
     989              :     CHIP_ERROR GetDigest(MutableByteSpan & out_buffer);
     990              : 
     991              :     /**
     992              :      * @brief Finalize the stream digest computation, getting the final digest.
     993              :      *
     994              :      * @param[in,out] out_buffer Output buffer to receive the digest. `out_buffer` must
     995              :      * be at least `kSHA256_Hash_Length` bytes long. The `out_buffer` size
     996              :      * will be set to `kSHA256_Hash_Length` on success.
     997              :      *
     998              :      * @return CHIP_ERROR_INTERNAL on failure to compute the digest, CHIP_ERROR_BUFFER_TOO_SMALL
     999              :      *         if out_buffer is too small, CHIP_NO_ERROR otherwise.
    1000              :      */
    1001              :     CHIP_ERROR Finish(MutableByteSpan & out_buffer);
    1002              : 
    1003              :     /**
    1004              :      * @brief Clear-out internal digest data to avoid lingering the state.
    1005              :      */
    1006              :     void Clear();
    1007              : 
    1008              : private:
    1009              :     // Check if the digest computation has been initialized; implement this if your backend needs it.
    1010              :     bool IsInitialized();
    1011              : 
    1012              :     HashSHA256OpaqueContext mContext;
    1013              : };
    1014              : 
    1015              : class HKDF_sha
    1016              : {
    1017              : public:
    1018              :     HKDF_sha()          = default;
    1019         3991 :     virtual ~HKDF_sha() = default;
    1020              : 
    1021              :     /**
    1022              :      * @brief A function that implements SHA-256 based HKDF
    1023              :      *
    1024              :      * This implements the CHIP_Crypto_KDF() cryptographic primitive
    1025              :      * in the the specification.
    1026              :      *
    1027              :      *  Error values are:
    1028              :      *   - CHIP_ERROR_INVALID_ARGUMENT: for any bad arguments or nullptr input on
    1029              :      *     any pointer.
    1030              :      *   - CHIP_ERROR_INTERNAL: for any unexpected error arising in the underlying
    1031              :      *     cryptographic layers.
    1032              :      *
    1033              :      * @param secret The secret to use as the key to the HKDF
    1034              :      * @param secret_length Length of the secret
    1035              :      * @param salt Optional salt to use as input to the HKDF
    1036              :      * @param salt_length Length of the salt
    1037              :      * @param info Optional info to use as input to the HKDF
    1038              :      * @param info_length Length of the info
    1039              :      * @param out_buffer Pointer to buffer to write output into.
    1040              :      * @param out_length Size of the underlying out_buffer. That length of output key material will be generated in out_buffer.
    1041              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1042              :      **/
    1043              : 
    1044              :     virtual CHIP_ERROR HKDF_SHA256(const uint8_t * secret, size_t secret_length, const uint8_t * salt, size_t salt_length,
    1045              :                                    const uint8_t * info, size_t info_length, uint8_t * out_buffer, size_t out_length);
    1046              : };
    1047              : 
    1048              : class HMAC_sha
    1049              : {
    1050              : public:
    1051              :     HMAC_sha()          = default;
    1052          124 :     virtual ~HMAC_sha() = default;
    1053              : 
    1054              :     /**
    1055              :      * @brief A function that implements SHA-256 based HMAC per FIPS1981.
    1056              :      *
    1057              :      * This implements the CHIP_Crypto_HMAC() cryptographic primitive
    1058              :      * in the the specification.
    1059              :      *
    1060              :      * The `out_length` must be at least kSHA256_Hash_Length, and only
    1061              :      * kSHA256_Hash_Length bytes are written to out_buffer.
    1062              :      *
    1063              :      * Error values are:
    1064              :      *   - CHIP_ERROR_INVALID_ARGUMENT: for any bad arguments or nullptr input on
    1065              :      *     any pointer.
    1066              :      *   - CHIP_ERROR_INTERNAL: for any unexpected error arising in the underlying
    1067              :      *     cryptographic layers.
    1068              :      *
    1069              :      * @param key The key to use for the HMAC operation
    1070              :      * @param key_length Length of the key
    1071              :      * @param message Message over which to compute the HMAC
    1072              :      * @param message_length Length of the message over which to compute the HMAC
    1073              :      * @param out_buffer Pointer to buffer into which to write the output.
    1074              :      * @param out_length Underlying size of the `out_buffer`.
    1075              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1076              :      **/
    1077              : 
    1078              :     virtual CHIP_ERROR HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length,
    1079              :                                    uint8_t * out_buffer, size_t out_length);
    1080              : 
    1081              :     /**
    1082              :      * @brief A function that implements SHA-256 based HMAC per FIPS1981.
    1083              :      *
    1084              :      * This implements the CHIP_Crypto_HMAC() cryptographic primitive
    1085              :      * in the the specification.
    1086              :      *
    1087              :      * The `out_length` must be at least kSHA256_Hash_Length, and only
    1088              :      * kSHA256_Hash_Length bytes are written to out_buffer.
    1089              :      *
    1090              :      * Error values are:
    1091              :      *   - CHIP_ERROR_INVALID_ARGUMENT: for any bad arguments or nullptr input on
    1092              :      *     any pointer.
    1093              :      *   - CHIP_ERROR_INTERNAL: for any unexpected error arising in the underlying
    1094              :      *     cryptographic layers.
    1095              :      *
    1096              :      * @param key The HMAC Key handle to use for the HMAC operation
    1097              :      * @param message Message over which to compute the HMAC
    1098              :      * @param message_length Length of the message over which to compute the HMAC
    1099              :      * @param out_buffer Pointer to buffer into which to write the output.
    1100              :      * @param out_length Underlying size of the `out_buffer`.
    1101              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1102              :      **/
    1103              :     virtual CHIP_ERROR HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length,
    1104              :                                    uint8_t * out_buffer, size_t out_length);
    1105              : };
    1106              : 
    1107              : /**
    1108              :  * @brief A cryptographically secure random number generator based on NIST SP800-90A
    1109              :  * @param out_buffer Buffer into which to write random bytes
    1110              :  * @param out_length Number of random bytes to generate
    1111              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1112              :  **/
    1113              : CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, size_t out_length);
    1114              : 
    1115              : /** @brief Entropy callback function
    1116              :  * @param data Callback-specific data pointer
    1117              :  * @param output Output data to fill
    1118              :  * @param len Length of output buffer
    1119              :  * @param olen The actual amount of data that was written to output buffer
    1120              :  * @return 0 if success
    1121              :  */
    1122              : typedef int (*entropy_source)(void * data, uint8_t * output, size_t len, size_t * olen);
    1123              : 
    1124              : /** @brief A function to add entropy sources to crypto library
    1125              :  *
    1126              :  * This function can be called multiple times to add multiple entropy sources. However,
    1127              :  * once the entropy source is added, it cannot be removed. Please make sure that the
    1128              :  * entropy source is valid for the lifetime of the application. Also, make sure that the
    1129              :  * same entropy source is not added multiple times, e.g.: by calling this function
    1130              :  * in class constructor or initialization function.
    1131              :  *
    1132              :  * @param fn_source Function pointer to the entropy source
    1133              :  * @param p_source  Data that should be provided when fn_source is called
    1134              :  * @param threshold Minimum required from source before entropy is released
    1135              :  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1136              :  **/
    1137              : CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold);
    1138              : 
    1139              : class PBKDF2_sha256
    1140              : {
    1141              : public:
    1142              :     PBKDF2_sha256()          = default;
    1143           10 :     virtual ~PBKDF2_sha256() = default;
    1144              : 
    1145              :     /** @brief Function to derive key using password. SHA256 hashing algorithm is used for calculating hmac.
    1146              :      * @param password password used for key derivation
    1147              :      * @param plen length of buffer containing password
    1148              :      * @param salt salt to use as input to the KDF
    1149              :      * @param slen length of salt
    1150              :      * @param iteration_count number of iterations to run
    1151              :      * @param key_length length of output key
    1152              :      * @param output output buffer where the key will be written
    1153              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1154              :      **/
    1155              :     virtual CHIP_ERROR pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen,
    1156              :                                      unsigned int iteration_count, uint32_t key_length, uint8_t * output);
    1157              : };
    1158              : 
    1159              : // TODO: Extract Spake2p to a separate header and replace the forward declaration with #include SessionKeystore.h
    1160              : class SessionKeystore;
    1161              : 
    1162              : /**
    1163              :  * The below class implements the draft 01 version of the Spake2+ protocol as
    1164              :  * defined in https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html.
    1165              :  *
    1166              :  * The following describes the protocol flows:
    1167              :  *
    1168              :  *     Commissioner                     Accessory
    1169              :  *     ------------                     ---------
    1170              :  *
    1171              :  *     Init
    1172              :  *     BeginProver
    1173              :  *     ComputeRoundOne  ------------->
    1174              :  *                                      Init
    1175              :  *                                      BeginVerifier
    1176              :  *                                  /-  ComputeRoundOne
    1177              :  *                      <-------------  ComputeRoundTwo
    1178              :  *     ComputeRoundTwo  ------------->
    1179              :  *     KeyConfirm                       KeyConfirm
    1180              :  *     GetKeys                          GetKeys
    1181              :  *
    1182              :  **/
    1183              : class Spake2p
    1184              : {
    1185              : public:
    1186              :     Spake2p(size_t fe_size, size_t point_size, size_t hash_size);
    1187          158 :     virtual ~Spake2p() = default;
    1188              : 
    1189              :     /**
    1190              :      * @brief Initialize Spake2+ with some context specific information.
    1191              :      *
    1192              :      * @param context     The context is arbitrary but should include information about the
    1193              :      *                    protocol being run, contain the transcript for negotiation, include
    1194              :      *                    the PKBDF parameters, etc.
    1195              :      * @param context_len The length of the context.
    1196              :      *
    1197              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1198              :      **/
    1199              :     virtual CHIP_ERROR Init(const uint8_t * context, size_t context_len);
    1200              : 
    1201              :     /**
    1202              :      * @brief Free Spake2+ underlying objects.
    1203              :      **/
    1204              :     virtual void Clear() = 0;
    1205              : 
    1206              :     /**
    1207              :      * @brief Start the Spake2+ process as a verifier (i.e. an accessory being provisioned).
    1208              :      *
    1209              :      * @param my_identity       The verifier identity. May be NULL if identities are not established.
    1210              :      * @param my_identity_len   The verifier identity length.
    1211              :      * @param peer_identity     The peer identity. May be NULL if identities are not established.
    1212              :      * @param peer_identity_len The peer identity length.
    1213              :      * @param w0in              The input w0 (a parameter baked into the device or computed with ComputeW0).
    1214              :      * @param w0in_len          The input w0 length.
    1215              :      * @param Lin               The input L (a parameter baked into the device or computed with ComputeL).
    1216              :      * @param Lin_len           The input L length.
    1217              :      *
    1218              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1219              :      **/
    1220              :     virtual CHIP_ERROR BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity,
    1221              :                                      size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin,
    1222              :                                      size_t Lin_len);
    1223              : 
    1224              :     /**
    1225              :      * @brief Start the Spake2+ process as a prover (i.e. a commissioner).
    1226              :      *
    1227              :      * @param my_identity       The prover identity. May be NULL if identities are not established.
    1228              :      * @param my_identity_len   The prover identity length.
    1229              :      * @param peer_identity     The peer identity. May be NULL if identities are not established.
    1230              :      * @param peer_identity_len The peer identity length.
    1231              :      * @param w0sin             The input w0s (an output from the PBKDF).
    1232              :      * @param w0sin_len         The input w0s length.
    1233              :      * @param w1sin             The input w1s (an output from the PBKDF).
    1234              :      * @param w1sin_len         The input w1s length.
    1235              :      *
    1236              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1237              :      **/
    1238              :     virtual CHIP_ERROR BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity,
    1239              :                                    size_t peer_identity_len, const uint8_t * w0sin, size_t w0sin_len, const uint8_t * w1sin,
    1240              :                                    size_t w1sin_len);
    1241              : 
    1242              :     /**
    1243              :      * @brief Compute the first round of the protocol.
    1244              :      *
    1245              :      * @param pab      X value from commissioner.
    1246              :      * @param pab_len  X length.
    1247              :      * @param out     The output first round Spake2+ contribution.
    1248              :      * @param out_len The output first round Spake2+ contribution length.
    1249              :      *
    1250              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1251              :      **/
    1252              :     virtual CHIP_ERROR ComputeRoundOne(const uint8_t * pab, size_t pab_len, uint8_t * out, size_t * out_len);
    1253              : 
    1254              :     /**
    1255              :      * @brief Compute the second round of the protocol.
    1256              :      *
    1257              :      * @param in      The peer first round Spake2+ contribution.
    1258              :      * @param in_len  The peer first round Spake2+ contribution length.
    1259              :      * @param out     The output second round Spake2+ contribution.
    1260              :      * @param out_len The output second round Spake2+ contribution length.
    1261              :      *
    1262              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1263              :      **/
    1264              :     virtual CHIP_ERROR ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len);
    1265              : 
    1266              :     /**
    1267              :      * @brief Confirm that each party computed the same keys.
    1268              :      *
    1269              :      * @param in     The peer second round Spake2+ contribution.
    1270              :      * @param in_len The peer second round Spake2+ contribution length.
    1271              :      *
    1272              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1273              :      **/
    1274              :     virtual CHIP_ERROR KeyConfirm(const uint8_t * in, size_t in_len);
    1275              : 
    1276              :     /**
    1277              :      * @brief Return the shared HKDF key.
    1278              :      *
    1279              :      * Returns the shared key established during the Spake2+ process, which can be used
    1280              :      * to derive application-specific keys using HKDF.
    1281              :      *
    1282              :      * @param keystore The session keystore for managing the HKDF key lifetime.
    1283              :      * @param key The output HKDF key.
    1284              :      *
    1285              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1286              :      **/
    1287              :     CHIP_ERROR GetKeys(SessionKeystore & keystore, HkdfKeyHandle & key);
    1288              : 
    1289              :     CHIP_ERROR InternalHash(const uint8_t * in, size_t in_len);
    1290              :     CHIP_ERROR WriteMN();
    1291              :     CHIP_ERROR GenerateKeys();
    1292              : 
    1293              :     /**
    1294              :      * @brief Load a field element.
    1295              :      *
    1296              :      *  @param in     The input big endian field element.
    1297              :      *  @param in_len The size of the input buffer in bytes.
    1298              :      *  @param fe     A pointer to an initialized implementation dependant field element.
    1299              :      *
    1300              :      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1301              :      **/
    1302              :     virtual CHIP_ERROR FELoad(const uint8_t * in, size_t in_len, void * fe) = 0;
    1303              : 
    1304              :     /**
    1305              :      * @brief Write a field element in big-endian format.
    1306              :      *
    1307              :      *  @param fe      The field element to write.
    1308              :      *  @param out     The output buffer.
    1309              :      *  @param out_len The length of the output buffer.
    1310              :      *
    1311              :      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1312              :      **/
    1313              :     virtual CHIP_ERROR FEWrite(const void * fe, uint8_t * out, size_t out_len) = 0;
    1314              : 
    1315              :     /**
    1316              :      * @brief Generate a field element.
    1317              :      *
    1318              :      *  @param fe  A pointer to an initialized implementation dependant field element.
    1319              :      *
    1320              :      *  @note The implementation must generate a random element from [0, q) where q is the curve order.
    1321              :      *
    1322              :      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1323              :      **/
    1324              :     virtual CHIP_ERROR FEGenerate(void * fe) = 0;
    1325              : 
    1326              :     /**
    1327              :      * @brief Multiply two field elements, fer = fe1 * fe2.
    1328              :      *
    1329              :      *  @param fer   A pointer to an initialized implementation dependant field element.
    1330              :      *  @param fe1  A pointer to an initialized implementation dependant field element.
    1331              :      *  @param fe2  A pointer to an initialized implementation dependant field element.
    1332              :      *
    1333              :      *  @note The result must be a field element (i.e. reduced by the curve order).
    1334              :      *
    1335              :      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1336              :      **/
    1337              :     virtual CHIP_ERROR FEMul(void * fer, const void * fe1, const void * fe2) = 0;
    1338              : 
    1339              :     /**
    1340              :      * @brief Load a point from 0x04 || X || Y format
    1341              :      *
    1342              :      * @param in     Input buffer
    1343              :      * @param in_len Input buffer length
    1344              :      * @param R      A pointer to an initialized implementation dependant point.
    1345              :      *
    1346              :      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1347              :      **/
    1348              :     virtual CHIP_ERROR PointLoad(const uint8_t * in, size_t in_len, void * R) = 0;
    1349              : 
    1350              :     /**
    1351              :      * @brief Write a point in 0x04 || X || Y format
    1352              :      *
    1353              :      * @param R       A pointer to an initialized implementation dependant point.
    1354              :      * @param out     Output buffer
    1355              :      * @param out_len Length of the output buffer
    1356              :      *
    1357              :      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1358              :      **/
    1359              :     virtual CHIP_ERROR PointWrite(const void * R, uint8_t * out, size_t out_len) = 0;
    1360              : 
    1361              :     /**
    1362              :      * @brief Scalar multiplication, R = fe1 * P1.
    1363              :      *
    1364              :      * @param R   Resultant point
    1365              :      * @param P1  Input point
    1366              :      * @param fe1  Input field element.
    1367              :      *
    1368              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1369              :      **/
    1370              :     virtual CHIP_ERROR PointMul(void * R, const void * P1, const void * fe1) = 0;
    1371              : 
    1372              :     /**
    1373              :      * @brief Scalar multiplication with addition, R = fe1 * P1 + fe2 * P2.
    1374              :      *
    1375              :      * @param R   Resultant point
    1376              :      * @param P1  Input point
    1377              :      * @param fe1  Input field element.
    1378              :      * @param P2  Input point
    1379              :      * @param fe2  Input field element.
    1380              :      *
    1381              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1382              :      **/
    1383              :     virtual CHIP_ERROR PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, const void * fe2) = 0;
    1384              : 
    1385              :     /**
    1386              :      * @brief Point inversion.
    1387              :      *
    1388              :      * @param R   Input/Output point to point_invert
    1389              :      *
    1390              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1391              :      **/
    1392              :     virtual CHIP_ERROR PointInvert(void * R) = 0;
    1393              : 
    1394              :     /**
    1395              :      * @brief Multiply a point by the curve cofactor.
    1396              :      *
    1397              :      * @param R   Input/Output point to point_invert
    1398              :      *
    1399              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1400              :      **/
    1401              :     virtual CHIP_ERROR PointCofactorMul(void * R) = 0;
    1402              : 
    1403              :     /*
    1404              :      *   @synopsis Check if a point is on the curve.
    1405              :      *
    1406              :      *   @param R   Input point to check.
    1407              :      *
    1408              :      *   @return CHIP_NO_ERROR if the point is valid, CHIP_ERROR otherwise.
    1409              :      */
    1410              :     virtual CHIP_ERROR PointIsValid(void * R) = 0;
    1411              : 
    1412              :     /*
    1413              :      *   @synopsis Compute w0sin mod p
    1414              :      *
    1415              :      *   @param w0out       Output field element w0
    1416              :      *   @param w0_len      Output field element length
    1417              :      *   @param w0sin       Input field element
    1418              :      *   @param w0sin_len   Input field element length
    1419              :      *
    1420              :      *   @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1421              :      **/
    1422              :     virtual CHIP_ERROR ComputeW0(uint8_t * w0out, size_t * w0_len, const uint8_t * w0sin, size_t w0sin_len) = 0;
    1423              : 
    1424              :     /*
    1425              :      *   @synopsis Compute w1in*G where w1in is w1sin mod p
    1426              :      *
    1427              :      *   @param Lout        Output point in 0x04 || X || Y format.
    1428              :      *   @param L_len       Output point length
    1429              :      *   @param w1sin       Input field element
    1430              :      *   @param w1sin_len   Input field element size
    1431              :      *
    1432              :      *   @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1433              :      **/
    1434              :     virtual CHIP_ERROR ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1sin, size_t w1sin_len) = 0;
    1435              : 
    1436              :     void * M;
    1437              :     void * N;
    1438              :     const void * G;
    1439              :     void * X;
    1440              :     void * Y;
    1441              :     void * L;
    1442              :     void * Z;
    1443              :     void * V;
    1444              :     void * w0;
    1445              :     void * w1;
    1446              :     void * xy;
    1447              :     void * order;
    1448              :     void * tempbn;
    1449              : 
    1450              : protected:
    1451              :     /**
    1452              :      * @brief Initialize underlying implementation curve, points, field elements, etc.
    1453              :      *
    1454              :      * @details The implementation needs to:
    1455              :      *     1. Initialize each of the points below and set the relevant pointers on the class:
    1456              :      *        a. M
    1457              :      *        b. N
    1458              :      *        c. G
    1459              :      *        d. X
    1460              :      *        e. Y
    1461              :      *        f. L
    1462              :      *        g. Z
    1463              :      *        h. V
    1464              :      *
    1465              :      *        As an example:
    1466              :      *           this.M = implementation_alloc_point();
    1467              :      *     2. Initialize each of the field elements below and set the relevant pointers on the class:
    1468              :      *        a. w0
    1469              :      *        b. w1
    1470              :      *        c. xy
    1471              :      *        d. tempbn
    1472              :      *     3. The hashing context should be initialized
    1473              :      *
    1474              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1475              :      **/
    1476              :     virtual CHIP_ERROR InitImpl() = 0;
    1477              : 
    1478              :     /**
    1479              :      * @brief Hash in_len bytes of in into the internal hash context.
    1480              :      *
    1481              :      * @param in     The input buffer.
    1482              :      * @param in_len Size of the input buffer in bytes.
    1483              :      *
    1484              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1485              :      **/
    1486              :     virtual CHIP_ERROR Hash(const uint8_t * in, size_t in_len) = 0;
    1487              : 
    1488              :     /**
    1489              :      * @brief Return the hash.
    1490              :      *
    1491              :      * @param out_span Output buffer. The size available must be >= the hash size. It gets resized
    1492              :      *                 to hash size on success.
    1493              :      *
    1494              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1495              :      **/
    1496              :     virtual CHIP_ERROR HashFinalize(MutableByteSpan & out_span) = 0;
    1497              : 
    1498              :     /**
    1499              :      * @brief Generate a message authentication code.
    1500              :      *
    1501              :      * @param key      The MAC key buffer.
    1502              :      * @param key_len  The size of the MAC key in bytes.
    1503              :      * @param in       The input buffer.
    1504              :      * @param in_len   The size of the input data to MAC in bytes.
    1505              :      * @param out_span The output MAC buffer span. Size must be >= the hash_size. Output size is updated to fit on success.
    1506              :      *
    1507              :      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
    1508              :      **/
    1509              :     virtual CHIP_ERROR Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len, MutableByteSpan & out_span) = 0;
    1510              : 
    1511              :     /**
    1512              :      * @brief Verify a message authentication code.
    1513              :      *
    1514              :      *  @param key     The MAC key buffer.
    1515              :      *  @param key_len The size of the MAC key in bytes.
    1516              :      *  @param mac     The input MAC buffer.
    1517              :      *  @param mac_len The size of the MAC in bytes.
    1518              :      *  @param in      The input buffer to verify.
    1519              :      *  @param in_len  The size of the input data to verify in bytes.
    1520              :      *
    1521              :      *  @return Returns a CHIP_ERROR when the MAC doesn't validate, CHIP_NO_ERROR otherwise.
    1522              :      **/
    1523              :     virtual CHIP_ERROR MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len, const uint8_t * in,
    1524              :                                  size_t in_len) = 0;
    1525              : 
    1526              :     /**
    1527              :      * @brief Derive an key of length out_len.
    1528              :      *
    1529              :      * @param ikm      The input key material buffer.
    1530              :      * @param ikm_len  The input key material length.
    1531              :      * @param salt     The optional salt. This may be NULL.
    1532              :      * @param salt_len The size of the salt in bytes.
    1533              :      * @param info     The info.
    1534              :      * @param info_len The size of the info in bytes.
    1535              :      * @param out      The output key
    1536              :      * @param out_len  The output key length
    1537              :      *
    1538              :      * @return Returns a CHIP_ERROR when the MAC doesn't validate, CHIP_NO_ERROR otherwise.
    1539              :      **/
    1540              :     virtual CHIP_ERROR KDF(const uint8_t * ikm, size_t ikm_len, const uint8_t * salt, size_t salt_len, const uint8_t * info,
    1541              :                            size_t info_len, uint8_t * out, size_t out_len) = 0;
    1542              : 
    1543              :     CHIP_SPAKE2P_ROLE role;
    1544              :     CHIP_SPAKE2P_STATE state = CHIP_SPAKE2P_STATE::PREINIT;
    1545              :     size_t fe_size;
    1546              :     size_t hash_size;
    1547              :     size_t point_size;
    1548              :     uint8_t Kcab[kMAX_Hash_Length];
    1549              :     uint8_t Kae[kMAX_Hash_Length];
    1550              :     uint8_t * Kca;
    1551              :     uint8_t * Kcb;
    1552              :     uint8_t * Ka;
    1553              :     uint8_t * Ke;
    1554              : };
    1555              : 
    1556              : struct alignas(size_t) Spake2pOpaqueContext
    1557              : {
    1558              :     uint8_t mOpaque[kMAX_Spake2p_Context_Size];
    1559              : };
    1560              : 
    1561              : class Spake2p_P256_SHA256_HKDF_HMAC : public Spake2p
    1562              : {
    1563              : public:
    1564          158 :     Spake2p_P256_SHA256_HKDF_HMAC() : Spake2p(kP256_FE_Length, kP256_Point_Length, kSHA256_Hash_Length)
    1565              :     {
    1566          158 :         memset(&mSpake2pContext, 0, sizeof(mSpake2pContext));
    1567          158 :     }
    1568              : 
    1569          158 :     ~Spake2p_P256_SHA256_HKDF_HMAC() override { Spake2p_P256_SHA256_HKDF_HMAC::Clear(); }
    1570              : 
    1571              :     void Clear() override;
    1572              :     CHIP_ERROR Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len, MutableByteSpan & out_span) override;
    1573              :     CHIP_ERROR MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len, const uint8_t * in,
    1574              :                          size_t in_len) override;
    1575              :     CHIP_ERROR FELoad(const uint8_t * in, size_t in_len, void * fe) override;
    1576              :     CHIP_ERROR FEWrite(const void * fe, uint8_t * out, size_t out_len) override;
    1577              :     CHIP_ERROR FEGenerate(void * fe) override;
    1578              :     CHIP_ERROR FEMul(void * fer, const void * fe1, const void * fe2) override;
    1579              : 
    1580              :     CHIP_ERROR PointLoad(const uint8_t * in, size_t in_len, void * R) override;
    1581              :     CHIP_ERROR PointWrite(const void * R, uint8_t * out, size_t out_len) override;
    1582              :     CHIP_ERROR PointMul(void * R, const void * P1, const void * fe1) override;
    1583              :     CHIP_ERROR PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, const void * fe2) override;
    1584              :     CHIP_ERROR PointInvert(void * R) override;
    1585              :     CHIP_ERROR PointCofactorMul(void * R) override;
    1586              :     CHIP_ERROR PointIsValid(void * R) override;
    1587              : 
    1588              :     CHIP_ERROR ComputeW0(uint8_t * w0out, size_t * w0_len, const uint8_t * w0sin, size_t w0sin_len) override;
    1589              :     CHIP_ERROR ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1sin, size_t w1sin_len) override;
    1590              : 
    1591              : protected:
    1592              :     CHIP_ERROR InitImpl() override;
    1593              :     CHIP_ERROR Hash(const uint8_t * in, size_t in_len) override;
    1594              :     CHIP_ERROR HashFinalize(MutableByteSpan & out_span) override;
    1595              :     CHIP_ERROR KDF(const uint8_t * secret, size_t secret_length, const uint8_t * salt, size_t salt_length, const uint8_t * info,
    1596              :                    size_t info_length, uint8_t * out, size_t out_length) override;
    1597              : 
    1598              : private:
    1599              :     CHIP_ERROR InitInternal();
    1600              :     Hash_SHA256_stream sha256_hash_ctx;
    1601              : 
    1602              :     Spake2pOpaqueContext mSpake2pContext;
    1603              : };
    1604              : 
    1605              : /**
    1606              :  * @brief Class used for verifying PASE secure sessions.
    1607              :  **/
    1608              : class Spake2pVerifier
    1609              : {
    1610              : public:
    1611              :     uint8_t mW0[kP256_FE_Length];
    1612              :     uint8_t mL[kP256_Point_Length];
    1613              : 
    1614              :     CHIP_ERROR Serialize(MutableByteSpan & outSerialized) const;
    1615              :     CHIP_ERROR Deserialize(const ByteSpan & inSerialized);
    1616              : 
    1617              :     /**
    1618              :      * @brief Generate the Spake2+ verifier.
    1619              :      *
    1620              :      * @param pbkdf2IterCount Iteration count for PBKDF2 function
    1621              :      * @param salt            Salt to be used for Spake2+ operation
    1622              :      * @param setupPin        Provided setup PIN (passcode)
    1623              :      *
    1624              :      * @return CHIP_ERROR     The result of Spake2+ verifier generation
    1625              :      */
    1626              :     CHIP_ERROR Generate(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin);
    1627              : 
    1628              :     /**
    1629              :      * @brief Compute the initiator values (w0s, w1s) used for PAKE input.
    1630              :      *
    1631              :      * @param pbkdf2IterCount Iteration count for PBKDF2 function
    1632              :      * @param salt            Salt to be used for Spake2+ operation
    1633              :      * @param setupPin        Provided setup PIN (passcode)
    1634              :      * @param ws              The output pair (w0s, w1s) stored sequentially
    1635              :      * @param ws_len          The output length
    1636              :      *
    1637              :      * @return CHIP_ERROR     The result from running PBKDF2
    1638              :      */
    1639              :     static CHIP_ERROR ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin, uint8_t * ws, uint32_t ws_len);
    1640              : };
    1641              : 
    1642              : /**
    1643              :  * @brief Serialized format of the Spake2+ Verifier components.
    1644              :  *
    1645              :  *  This is used when the Verifier should be presented in a serialized form.
    1646              :  *  For example, when it is generated using PBKDF function, when stored in the
    1647              :  *  memory or when sent over the wire.
    1648              :  *  The serialized format is concatentation of 'W0' and 'L' verifier components:
    1649              :  *      { Spake2pVerifier.mW0[kP256_FE_Length], Spake2pVerifier.mL[kP256_Point_Length] }
    1650              :  **/
    1651              : typedef uint8_t Spake2pVerifierSerialized[kSpake2p_VerifierSerialized_Length];
    1652              : 
    1653              : /**
    1654              :  * @brief Compute the compressed fabric identifier used for operational discovery service
    1655              :  *        records from a Node's root public key and Fabric ID. On success, out_compressed_fabric_id
    1656              :  *        will have a size of exactly kCompressedFabricIdentifierSize.
    1657              :  *
    1658              :  * Errors are:
    1659              :  *   - CHIP_ERROR_INVALID_ARGUMENT if root_public_key is invalid
    1660              :  *   - CHIP_ERROR_BUFFER_TOO_SMALL if out_compressed_fabric_id is too small for serialization
    1661              :  *   - CHIP_ERROR_INTERNAL on any unexpected crypto or data conversion errors.
    1662              :  *
    1663              :  * @param[in] root_public_key The root public key associated with the node's fabric
    1664              :  * @param[in] fabric_id The fabric ID associated with the node's fabric
    1665              :  * @param[out] out_compressed_fabric_id Span where output will be written. Its size must be >= kCompressedFabricIdentifierSize.
    1666              :  * @returns a CHIP_ERROR (see above) on failure or CHIP_NO_ERROR otherwise.
    1667              :  */
    1668              : CHIP_ERROR GenerateCompressedFabricId(const Crypto::P256PublicKey & root_public_key, uint64_t fabric_id,
    1669              :                                       MutableByteSpan & out_compressed_fabric_id);
    1670              : 
    1671              : /**
    1672              :  * @brief Compute the compressed fabric identifier used for operational discovery service
    1673              :  *        records from a Node's root public key and Fabric ID.  This is a conveniance
    1674              :  *        overload that writes to a uint64_t (CompressedFabricId) type.
    1675              :  *
    1676              :  * @param[in] rootPublicKey The root public key associated with the node's fabric
    1677              :  * @param[in] fabricId The fabric ID associated with the node's fabric
    1678              :  * @param[out] compressedFabricId output location for compressed fabric ID
    1679              :  * @returns a CHIP_ERROR on failure or CHIP_NO_ERROR otherwise.
    1680              :  */
    1681              : CHIP_ERROR GenerateCompressedFabricId(const Crypto::P256PublicKey & rootPublicKey, uint64_t fabricId,
    1682              :                                       uint64_t & compressedFabricId);
    1683              : 
    1684              : enum class CertificateChainValidationResult
    1685              : {
    1686              :     kSuccess = 0,
    1687              : 
    1688              :     kRootFormatInvalid   = 100,
    1689              :     kRootArgumentInvalid = 101,
    1690              : 
    1691              :     kICAFormatInvalid   = 200,
    1692              :     kICAArgumentInvalid = 201,
    1693              : 
    1694              :     kLeafFormatInvalid   = 300,
    1695              :     kLeafArgumentInvalid = 301,
    1696              : 
    1697              :     kChainInvalid = 400,
    1698              : 
    1699              :     kNoMemory = 500,
    1700              : 
    1701              :     kInternalFrameworkError = 600,
    1702              : };
    1703              : 
    1704              : CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate,
    1705              :                                     size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen,
    1706              :                                     CertificateChainValidationResult & result);
    1707              : 
    1708              : enum class AttestationCertType
    1709              : {
    1710              :     kPAA = 0,
    1711              :     kPAI = 1,
    1712              :     kDAC = 2,
    1713              : };
    1714              : 
    1715              : CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType);
    1716              : 
    1717              : /**
    1718              :  * @brief Generate a VendorFabricBindingMessage as used by the Fabric Table Vendor ID Verification Procedure.
    1719              :  *
    1720              :  * @param[in] fabricBindingVersion - Version of binding payload to generate. outputSpan size requirements are based on this.
    1721              :  * @param[in] rootPublicKey - Root public key for the fabric in question
    1722              :  * @param[in] fabricId - Fabric ID for the fabric in question
    1723              :  * @param[in] vendorId - Vendor ID for the fabric in question
    1724              :  * @param[inout] outputSpan - Span that will receive the binding message. Must be large enough for the
    1725              :  *                            payload (otherwise CHIP_ERROR_BUFFER_TOO_SMALL) and will be resized to fit.
    1726              :  * @return CHIP_NO_ERROR on success, otherwise another CHIP_ERROR value representative of the failure.
    1727              :  */
    1728              : CHIP_ERROR GenerateVendorFabricBindingMessage(FabricBindingVersion fabricBindingVersion, const P256PublicKey & rootPublicKey,
    1729              :                                               FabricId fabricId, uint16_t vendorId, MutableByteSpan & outputSpan);
    1730              : 
    1731              : /**
    1732              :  * @brief Generate the message to be signed for the Fabric Table Vendor ID Verification Procedure.
    1733              :  *
    1734              :  * The Fabric Binding Version value will be recovered from the vendorFabricBindingMessage.
    1735              :  *
    1736              :  * @param fabricIndex - Fabric Index for the fabric in question
    1737              :  * @param clientChallenge - Client challenge to use
    1738              :  * @param attestationChallenge - Attestation challenge to use
    1739              :  * @param vendorFabricBindingMessage - The VendorFabricBindingMessage previously computed for the fabric
    1740              :  * @param vidVerificationStatement - The VID Verification Statement to include in signature (may be empty)
    1741              :  * @param outputSpan - Span that will receive the to-be-signed message. Must be large enough for the
    1742              :  *                     payload (otherwise CHIP_ERROR_BUFFER_TOO_SMALL) and will be resized to fit.
    1743              :  * @return CHIP_NO_ERROR on success, otherwise another CHIP_ERROR value representative of the failure.
    1744              :  */
    1745              : CHIP_ERROR GenerateVendorIdVerificationToBeSigned(FabricIndex fabricIndex, const ByteSpan & clientChallenge,
    1746              :                                                   const ByteSpan & attestationChallenge,
    1747              :                                                   const ByteSpan & vendorFabricBindingMessage,
    1748              :                                                   const ByteSpan & vidVerificationStatement, MutableByteSpan & outputSpan);
    1749              : 
    1750              : /**
    1751              :  * @brief Validate notBefore timestamp of a certificate (candidateCertificate) against validity period of the
    1752              :  *        issuer certificate (issuerCertificate).
    1753              :  *
    1754              :  * Errors are:
    1755              :  *   - CHIP_ERROR_CERT_EXPIRED if the candidateCertificate timestamp does not satisfy the issuerCertificate's timestamp.
    1756              :  *   - CHIP_ERROR_INVALID_ARGUMENT when passing an invalid argument.
    1757              :  *   - CHIP_ERROR_INTERNAL on any unexpected crypto or data conversion errors.
    1758              :  *
    1759              :  *  @param candidateCertificate     A DER Certificate ByteSpan those notBefore timestamp to be evaluated.
    1760              :  *  @param issuerCertificate        A DER Certificate ByteSpan used to evaluate validity timestamp of the candidateCertificate.
    1761              :  *
    1762              :  *  @returns a CHIP_ERROR (see above) on failure or CHIP_NO_ERROR otherwise.
    1763              :  **/
    1764              : CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & candidateCertificate, const ByteSpan & issuerCertificate);
    1765              : 
    1766              : /**
    1767              :  * @brief Validate a certificate's validity date against current time.
    1768              :  *
    1769              :  * Errors are:
    1770              :  *   - CHIP_ERROR_CERT_EXPIRED if the certificate has expired.
    1771              :  *   - CHIP_ERROR_INVALID_ARGUMENT when passing an invalid argument.
    1772              :  *   - CHIP_ERROR_INTERNAL on any unexpected crypto or data conversion errors.
    1773              :  *
    1774              :  *  @param certificate A DER Certificate ByteSpan used as the validity reference to be checked against current time.
    1775              :  *
    1776              :  *  @returns a CHIP_ERROR (see above) on failure or CHIP_NO_ERROR otherwise.
    1777              :  **/
    1778              : CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate);
    1779              : 
    1780              : CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey);
    1781              : 
    1782              : /**
    1783              :  * @brief Extracts the Subject Key Identifier from an X509 Certificate.
    1784              :  **/
    1785              : CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid);
    1786              : 
    1787              : /**
    1788              :  * @brief Extracts the Authority Key Identifier from an X509 Certificate.
    1789              :  **/
    1790              : CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid);
    1791              : 
    1792              : /**
    1793              :  * @brief Extracts the CRL Distribution Point (CDP) extension from an X509 ASN.1 Encoded Certificate.
    1794              :  *        The returned value only covers the URI of the CDP. Only a single URI distribution point
    1795              :  *        GeneralName is supported, and only those that start with "http://" and "https://".
    1796              :  *
    1797              :  * @returns CHIP_ERROR_NOT_FOUND if not found or wrong format.
    1798              :  *          CHIP_NO_ERROR otherwise.
    1799              :  **/
    1800              : CHIP_ERROR ExtractCRLDistributionPointURIFromX509Cert(const ByteSpan & certificate, MutableCharSpan & cdpurl);
    1801              : 
    1802              : /**
    1803              :  * @brief Extracts the CRL Distribution Point (CDP) extension's cRLIssuer Name from an X509 ASN.1 Encoded Certificate.
    1804              :  *        The value is copied into buffer in a raw ASN.1 X.509 format. This format should be directly comparable
    1805              :  *        with the result of ExtractSubjectFromX509Cert().
    1806              :  *
    1807              :  * @returns CHIP_ERROR_NOT_FOUND if not found or wrong format.
    1808              :  *          CHIP_NO_ERROR otherwise.
    1809              :  **/
    1810              : CHIP_ERROR ExtractCDPExtensionCRLIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & crlIssuer);
    1811              : 
    1812              : /**
    1813              :  * @brief Extracts Serial Number from X509 Certificate.
    1814              :  **/
    1815              : CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber);
    1816              : 
    1817              : /**
    1818              :  * @brief Extracts Subject Distinguished Name from X509 Certificate. The value is copied into buffer in a raw ASN.1 X.509 format.
    1819              :  **/
    1820              : CHIP_ERROR ExtractSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject);
    1821              : 
    1822              : /**
    1823              :  * @brief Extracts Issuer Distinguished Name from X509 Certificate. The value is copied into buffer in a raw ASN.1 X.509 format.
    1824              :  **/
    1825              : CHIP_ERROR ExtractIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & issuer);
    1826              : 
    1827              : class PemEncoder
    1828              : {
    1829              : public:
    1830              :     /**
    1831              :      * @brief Construct a PEM encoder for element type `encodedElement` whose DER data is in `derBytes` span.
    1832              :      *
    1833              :      * LIFETIME: both encodedElement and derBytes lifetime must be >= PemEncoder lifetime.
    1834              :      *           PemEncoder references these while processing `NextLine()` calls.
    1835              :      *
    1836              :      * @param encodedElement - Element type string to include in header/footer (e.g. "CERTIFICATE"). Caller must provide correct
    1837              :      * uppercase.
    1838              :      * @param derBytes - Byte span containing data to encode. May be empty.
    1839              :      */
    1840            8 :     explicit PemEncoder(const char * encodedElement, ByteSpan derBytes) : mEncodedElement(encodedElement), mDerBytes(derBytes) {}
    1841              : 
    1842              :     // No copies.
    1843              :     PemEncoder(const PemEncoder &)             = delete;
    1844              :     PemEncoder & operator=(const PemEncoder &) = delete;
    1845              : 
    1846              :     /**
    1847              :      * @brief Returns the pointer to the next null-terminated line of the encoding, or nullptr if done.
    1848              :      *
    1849              :      * The returned pointer has the lifetime of this class and during that lifetime will always point
    1850              :      * to valid memory.
    1851              :      *
    1852              :      * When header/footer are written, the heading type (`encodedElement` value) such as
    1853              :      * `CERTIFICATE` is clamped so that the entire header line with `-----BEGIN ${encodedElement}-----`
    1854              :      * and footer line with `-----END ${encodedElement}-----` are not wider than 64 bytes. This
    1855              :      * will not happen in practice with the types of things this is meant to encode.
    1856              :      *
    1857              :      * Usage should be in a loop, for example:
    1858              :      *
    1859              :      *   std::vector<std::string> pemLines;
    1860              :      *
    1861              :      *   PemEncoder encoder("CERTIFICATE", TestCerts::sTestCert_PAA_FFF1_Cert);
    1862              :      *
    1863              :      *   const char* line = encoder.NextLine();
    1864              :      *   while (line)
    1865              :      *   {
    1866              :      *       pemLines.push_back(std::string{ line });
    1867              :      *       line = encoder.NextLine();
    1868              :      *   }
    1869              :      *
    1870              :      * @return a pointer to the internal line buffer for next line or nullptr when done.
    1871              :      */
    1872              :     const char * NextLine();
    1873              : 
    1874              : private:
    1875              :     static constexpr size_t kNumBytesPerLine = 48u;
    1876              :     static constexpr size_t kLineBufferSize  = 64u + 1u; // PEM expects 64 characters wide and a null terminator at least.
    1877              :     static_assert(kLineBufferSize == (BASE64_ENCODED_LEN(kNumBytesPerLine) + 1), "Internal incoherence of library configuration!");
    1878              : 
    1879              :     enum State : int
    1880              :     {
    1881              :         kPrintHeader = 0,
    1882              :         kPrintBody   = 1,
    1883              :         kPrintFooter = 2,
    1884              :         kDone        = 3,
    1885              :     };
    1886              : 
    1887              :     const char * mEncodedElement; // "CERTIFICATE", "EC PUBLIC KEY", etc. Must be capitalized by caller.
    1888              :     ByteSpan mDerBytes;
    1889              :     State mState           = State::kPrintHeader;
    1890              :     size_t mProcessedBytes = 0;
    1891              :     StringBuilder<kLineBufferSize> mStringBuilder{};
    1892              : };
    1893              : 
    1894              : // Utility class to take subject Key IDs (AKID/SKID) and convert them to DCL format ("A5:FF:00.....:DE:AD").
    1895              : class KeyIdStringifier
    1896              : {
    1897              : public:
    1898           10 :     KeyIdStringifier() = default;
    1899              : 
    1900              :     /**
    1901              :      * @brief Returns the null-terminated string buffer owned by the class containing converted KeyID.
    1902              :      *
    1903              :      * LIFETIME NOTE: The last returned value from KeyIdToHex is valid until the next call.
    1904              :      *
    1905              :      * This is optimized for standard 20-byte AKID/SKID but works for any length, truncating very long ones.
    1906              :      *
    1907              :      * @param keyIdBuffer - buffer of bytes of the key ID.
    1908              :      * @return pointer to class-owned storage of a null-terminated string in DCL format.
    1909              :      */
    1910           14 :     const char * KeyIdToHex(ByteSpan keyIdBuffer)
    1911              :     {
    1912           14 :         mStringBuilder.Reset();
    1913           14 :         if (keyIdBuffer.empty())
    1914              :         {
    1915            1 :             mStringBuilder.Add("<EMPTY KEY ID>");
    1916            1 :             return mStringBuilder.c_str();
    1917              :         }
    1918              : 
    1919           13 :         mStringBuilder.AddFormat("%02X", keyIdBuffer[0]);
    1920          228 :         for (size_t i = 1; i < keyIdBuffer.size(); ++i)
    1921              :         {
    1922          215 :             mStringBuilder.Add(":");
    1923          215 :             mStringBuilder.AddFormat("%02X", keyIdBuffer[i]);
    1924              :         }
    1925              : 
    1926           13 :         return mStringBuilder.AddMarkerIfOverflow().c_str();
    1927              :     }
    1928              : 
    1929              : private:
    1930              :     StringBuilder<(Crypto::kAuthorityKeyIdentifierLength * 3) + 1> mStringBuilder;
    1931              : };
    1932              : 
    1933              : /**
    1934              :  * @brief Checks for resigned version of the certificate in the list and returns it.
    1935              :  *
    1936              :  * The following conditions SHOULD be satisfied for the certificate to qualify as
    1937              :  * a resigned version of a reference certificate:
    1938              :  *   - SKID of the candidate and the reference certificate should match.
    1939              :  *   - SubjectDN of the candidate and the reference certificate should match.
    1940              :  *
    1941              :  * If no resigned version is found then reference certificate itself is returned.
    1942              :  *
    1943              :  *  @param referenceCertificate       A DER certificate.
    1944              :  *  @param candidateCertificates      A pointer to the list of DER Certificates, which should be searched
    1945              :  *                                    for the resigned version of `referenceCertificate`.
    1946              :  *  @param candidateCertificatesCount Number of certificates in the `candidateCertificates` list.
    1947              :  *  @param outCertificate             A reference to the certificate or it's resigned version if found.
    1948              :  *                                    Note that it points to either `referenceCertificate` or one of
    1949              :  *                                    `candidateCertificates`, but it doesn't copy data.
    1950              :  *
    1951              :  *  @returns error if there is certificate parsing/format issue or CHIP_NO_ERROR otherwise.
    1952              :  **/
    1953              : CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate, const ByteSpan * candidateCertificates,
    1954              :                                           size_t candidateCertificatesCount, ByteSpan & outCertificate);
    1955              : 
    1956              : /**
    1957              :  * Defines DN attribute types that can include endocing of VID/PID parameters.
    1958              :  */
    1959              : enum class DNAttrType
    1960              : {
    1961              :     kUnspecified = 0,
    1962              :     kCommonName  = 1,
    1963              :     kMatterVID   = 2,
    1964              :     kMatterPID   = 3,
    1965              : };
    1966              : 
    1967              : /**
    1968              :  *  @struct AttestationCertVidPid
    1969              :  *
    1970              :  *  @brief
    1971              :  *    A data structure representing Attestation Certificate VID and PID attributes.
    1972              :  */
    1973              : struct AttestationCertVidPid
    1974              : {
    1975              :     Optional<VendorId> mVendorId;
    1976              :     Optional<uint16_t> mProductId;
    1977              : 
    1978          693 :     bool Initialized() const { return (mVendorId.HasValue() || mProductId.HasValue()); }
    1979              : };
    1980              : 
    1981              : /**
    1982              :  * @brief Extracts VID and PID attributes from the DN Attribute string.
    1983              :  *        If attribute is not present the corresponding output value stays uninitialized.
    1984              :  *
    1985              :  * @return CHIP_ERROR_INVALID_ARGUMENT if wrong input is provided.
    1986              :  *         CHIP_ERROR_WRONG_CERT_DN if encoding of kMatterVID and kMatterPID attributes is wrong.
    1987              :  *         CHIP_NO_ERROR otherwise.
    1988              :  **/
    1989              : CHIP_ERROR ExtractVIDPIDFromAttributeString(DNAttrType attrType, const ByteSpan & attr,
    1990              :                                             AttestationCertVidPid & vidpidFromMatterAttr, AttestationCertVidPid & vidpidFromCNAttr);
    1991              : 
    1992              : /**
    1993              :  * @brief Extracts VID and PID attributes from the Subject DN of an X509 Certificate.
    1994              :  *        If attribute is not present the corresponding output value stays uninitialized.
    1995              :  **/
    1996              : CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & x509Cert, AttestationCertVidPid & vidpid);
    1997              : 
    1998              : /**
    1999              :  * @brief The set of credentials needed to operate group message security with symmetric keys.
    2000              :  */
    2001              : typedef struct GroupOperationalCredentials
    2002              : {
    2003              :     /// Validity start time in microseconds since 2000-01-01T00:00:00 UTC ("the Epoch")
    2004              :     uint64_t start_time;
    2005              :     /// Session Id
    2006              :     uint16_t hash;
    2007              :     /// Operational group key
    2008              :     uint8_t encryption_key[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES];
    2009              :     /// Privacy key
    2010              :     uint8_t privacy_key[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES];
    2011              : } GroupOperationalCredentials;
    2012              : 
    2013              : /**
    2014              :  * @brief Opaque context used to protect a symmetric key. The key operations must
    2015              :  *        be performed without exposing the protected key value.
    2016              :  */
    2017              : class SymmetricKeyContext
    2018              : {
    2019              : public:
    2020              :     /**
    2021              :      * @brief Returns the symmetric key hash
    2022              :      *
    2023              :      * TODO: Replace GetKeyHash() with DeriveGroupSessionId(SymmetricKeyContext &, uint16_t & session_id)
    2024              :      *
    2025              :      * @return Group Key Hash
    2026              :      */
    2027              :     virtual uint16_t GetKeyHash() = 0;
    2028              : 
    2029           11 :     virtual ~SymmetricKeyContext() = default;
    2030              :     /**
    2031              :      * @brief Perform the message encryption as described in 4.7.2. (Security Processing of Outgoing Messages)
    2032              :      * @param[in] plaintext     Outgoing message payload.
    2033              :      * @param[in] aad           Additional data (message header contents)
    2034              :      * @param[in] nonce         Nonce (Security Flags | Message Counter | Source Node ID)
    2035              :      * @param[out] mic          Outgoing Message Integrity Check
    2036              :      * @param[out] ciphertext   Outgoing encrypted payload. Must be at least as big as plaintext. The same buffer may be used both
    2037              :      * for ciphertext, and plaintext.
    2038              :      * @return CHIP_ERROR
    2039              :      */
    2040              :     virtual CHIP_ERROR MessageEncrypt(const ByteSpan & plaintext, const ByteSpan & aad, const ByteSpan & nonce,
    2041              :                                       MutableByteSpan & mic, MutableByteSpan & ciphertext) const = 0;
    2042              :     /**
    2043              :      * @brief Perform the message decryption as described in 4.7.3.(Security Processing of Incoming Messages)
    2044              :      * @param[in] ciphertext    Incoming encrypted payload
    2045              :      * @param[in] aad           Additional data (message header contents)
    2046              :      * @param[in] nonce         Nonce (Security Flags | Message Counter | Source Node ID)
    2047              :      * @param[in] mic           Incoming Message Integrity Check
    2048              :      * @param[out] plaintext     Incoming message payload. Must be at least as big as ciphertext. The same buffer may be used both
    2049              :      * for plaintext, and ciphertext.
    2050              :      * @return CHIP_ERROR
    2051              :      */
    2052              :     virtual CHIP_ERROR MessageDecrypt(const ByteSpan & ciphertext, const ByteSpan & aad, const ByteSpan & nonce,
    2053              :                                       const ByteSpan & mic, MutableByteSpan & plaintext) const = 0;
    2054              : 
    2055              :     /**
    2056              :      * @brief Perform privacy encoding as described in 4.8.2. (Privacy Processing of Outgoing Messages)
    2057              :      * @param[in] input         Message header to privacy encrypt
    2058              :      * @param[in] nonce         Privacy Nonce = session_id | mic
    2059              :      * @param[out] output       Message header obfuscated
    2060              :      * @return CHIP_ERROR
    2061              :      */
    2062              :     virtual CHIP_ERROR PrivacyEncrypt(const ByteSpan & input, const ByteSpan & nonce, MutableByteSpan & output) const = 0;
    2063              : 
    2064              :     /**
    2065              :      * @brief Perform privacy decoding as described in 4.8.3. (Privacy Processing of Incoming Messages)
    2066              :      * @param[in] input         Message header to privacy decrypt
    2067              :      * @param[in] nonce         Privacy Nonce = session_id | mic
    2068              :      * @param[out] output       Message header deobfuscated
    2069              :      * @return CHIP_ERROR
    2070              :      */
    2071              :     virtual CHIP_ERROR PrivacyDecrypt(const ByteSpan & input, const ByteSpan & nonce, MutableByteSpan & output) const = 0;
    2072              : 
    2073              :     /**
    2074              :      * @brief Release resources such as dynamic memory used to allocate this instance of the SymmetricKeyContext
    2075              :      */
    2076              :     virtual void Release() = 0;
    2077              : };
    2078              : 
    2079              : /**
    2080              :  *  @brief Derives the Operational Group Key using the Key Derivation Function (KDF) from the given epoch key.
    2081              :  * @param[in] epoch_key  The epoch key. Must be CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
    2082              :  * @param[in] compressed_fabric_id The compressed fabric ID for the fabric (big endian byte string)
    2083              :  * @param[out] out_key  Symmetric key used as the encryption key during message processing for group communication.
    2084              :  The buffer size must be at least CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
    2085              :  * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INTERNAL if the provided key is invalid.
    2086              :  **/
    2087              : CHIP_ERROR DeriveGroupOperationalKey(const ByteSpan & epoch_key, const ByteSpan & compressed_fabric_id, MutableByteSpan & out_key);
    2088              : 
    2089              : /**
    2090              :  *  @brief Derives the Group Session ID from a given operational group key using
    2091              :  *         the Key Derivation Function (Group Key Hash)
    2092              :  * @param[in] operational_key  The operational group key. Must be CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
    2093              :  * @param[out] session_id  Output of the Group Key Hash
    2094              :  * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INVALID_ARGUMENT if the provided key is invalid.
    2095              :  **/
    2096              : CHIP_ERROR DeriveGroupSessionId(const ByteSpan & operational_key, uint16_t & session_id);
    2097              : 
    2098              : /**
    2099              :  *  @brief Derives the Privacy Group Key using the Key Derivation Function (KDF) from the given epoch key.
    2100              :  * @param[in] epoch_key  The epoch key. Must be CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
    2101              :  * @param[out] out_key  Symmetric key used as the privacy key during message processing for group communication.
    2102              :  *                      The buffer size must be at least CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
    2103              :  * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INTERNAL if the provided key is invalid.
    2104              :  **/
    2105              : CHIP_ERROR DeriveGroupPrivacyKey(const ByteSpan & epoch_key, MutableByteSpan & out_key);
    2106              : 
    2107              : /**
    2108              :  *  @brief Derives the complete set of credentials needed for group security.
    2109              :  *
    2110              :  * This function will derive the Encryption Key, Group Key Hash (Session Id), and Privacy Key
    2111              :  * for the given Epoch Key and Compressed Fabric Id.
    2112              :  * @param[in] epoch_key  The epoch key. Must be CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
    2113              :  * @param[in] compressed_fabric_id The compressed fabric ID for the fabric (big endian byte string)
    2114              :  * @param[out] operational_credentials The set of Symmetric keys used during message processing for group communication.
    2115              :  * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INTERNAL if the provided key is invalid.
    2116              :  **/
    2117              : CHIP_ERROR DeriveGroupOperationalCredentials(const ByteSpan & epoch_key, const ByteSpan & compressed_fabric_id,
    2118              :                                              GroupOperationalCredentials & operational_credentials);
    2119              : } // namespace Crypto
    2120              : } // namespace chip
        

Generated by: LCOV version 2.0-1