diff --git a/src/app/icd/server/BUILD.gn b/src/app/icd/server/BUILD.gn index f69c25015592af..b30b79d3d4a1d0 100644 --- a/src/app/icd/server/BUILD.gn +++ b/src/app/icd/server/BUILD.gn @@ -93,7 +93,6 @@ source_set("manager") { deps = [ ":icd-server-config" ] public_deps = [ - ":check-in-back-off", ":configuration-data", ":notifier", ":observer", @@ -106,6 +105,7 @@ source_set("manager") { if (chip_enable_icd_checkin) { public_deps += [ + ":check-in-back-off", ":monitoring-table", ":sender", "${chip_root}/src/app:app_config", diff --git a/src/app/icd/server/ICDManager.h b/src/app/icd/server/ICDManager.h index 4ec1dfe65231d3..19f5f0abeda955 100644 --- a/src/app/icd/server/ICDManager.h +++ b/src/app/icd/server/ICDManager.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -34,9 +33,10 @@ #include #if CHIP_CONFIG_ENABLE_ICD_CIP -#include // nogncheck -#include // nogncheck -#endif // CHIP_CONFIG_ENABLE_ICD_CIP +#include // nogncheck +#include // nogncheck +#include // nogncheck +#endif // CHIP_CONFIG_ENABLE_ICD_CIP namespace chip { namespace Crypto { diff --git a/src/app/icd/server/ICDMonitoringTable.cpp b/src/app/icd/server/ICDMonitoringTable.cpp index 8148a7fe33b237..c5543c74125f52 100644 --- a/src/app/icd/server/ICDMonitoringTable.cpp +++ b/src/app/icd/server/ICDMonitoringTable.cpp @@ -140,7 +140,6 @@ CHIP_ERROR ICDMonitoringEntry::SetKey(ByteSpan keyData) Crypto::Symmetric128BitsKeyByteArray keyMaterial; memcpy(keyMaterial, keyData.data(), sizeof(Crypto::Symmetric128BitsKeyByteArray)); - // TODO - Add function to set PSA key lifetime ReturnErrorOnFailure(symmetricKeystore->CreateKey(keyMaterial, aesKeyHandle)); CHIP_ERROR error = symmetricKeystore->CreateKey(keyMaterial, hmacKeyHandle); @@ -242,15 +241,22 @@ CHIP_ERROR ICDMonitoringTable::Get(uint16_t index, ICDMonitoringEntry & entry) c CHIP_ERROR ICDMonitoringTable::Find(NodeId id, ICDMonitoringEntry & entry) { - uint16_t index = 0; - while (index < this->Limit()) + uint16_t index; + ICDMonitoringEntry tempEntry(mSymmetricKeystore); + + for (index = 0; index < this->Limit(); index++) { - ReturnErrorOnFailure(this->Get(index++, entry)); - if (id == entry.checkInNodeID) + if (this->Get(index, tempEntry) != CHIP_NO_ERROR) + { + break; + } + if (id == tempEntry.checkInNodeID) { + entry = tempEntry; return CHIP_NO_ERROR; } } + entry.index = index; return CHIP_ERROR_NOT_FOUND; } @@ -263,16 +269,26 @@ CHIP_ERROR ICDMonitoringTable::Set(uint16_t index, const ICDMonitoringEntry & en VerifyOrReturnError(entry.keyHandleValid, CHIP_ERROR_INVALID_ARGUMENT); ICDMonitoringEntry e(this->mFabric, index); - e.checkInNodeID = entry.checkInNodeID; - e.monitoredSubject = entry.monitoredSubject; - e.clientType = entry.clientType; - e.index = index; + e.checkInNodeID = entry.checkInNodeID; + e.monitoredSubject = entry.monitoredSubject; + e.clientType = entry.clientType; + e.index = index; + e.symmetricKeystore = entry.symmetricKeystore; memcpy(e.aesKeyHandle.AsMutable(), entry.aesKeyHandle.As(), sizeof(Crypto::Symmetric128BitsKeyByteArray)); memcpy(e.hmacKeyHandle.AsMutable(), entry.hmacKeyHandle.As(), sizeof(Crypto::Symmetric128BitsKeyByteArray)); + ReturnErrorOnFailure(e.symmetricKeystore->PersistICDKey(e.aesKeyHandle)); + CHIP_ERROR error = e.symmetricKeystore->PersistICDKey(e.hmacKeyHandle); + if (error != CHIP_NO_ERROR) + { + // If setting the persistence of the HmacKeyHandle failed, we need to delete the AesKeyHandle to avoid a key leak + e.symmetricKeystore->DestroyKey(e.aesKeyHandle); + return error; + } + return e.Save(this->mStorage); } diff --git a/src/app/server/BUILD.gn b/src/app/server/BUILD.gn index 58524c3a648aab..4addf8eea938e3 100644 --- a/src/app/server/BUILD.gn +++ b/src/app/server/BUILD.gn @@ -54,7 +54,6 @@ static_library("server") { public_deps = [ "${chip_root}/src/app", "${chip_root}/src/app:test-event-trigger", - "${chip_root}/src/app/icd/server:check-in-back-off", "${chip_root}/src/app/icd/server:icd-server-config", "${chip_root}/src/app/icd/server:observer", "${chip_root}/src/lib/address_resolve", diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 27c850563f6e98..2f61197fcee2dd 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -72,14 +72,14 @@ #include #include -#include #if CHIP_CONFIG_ENABLE_ICD_SERVER #include // nogncheck #if CHIP_CONFIG_ENABLE_ICD_CIP #include // nogncheck -#endif -#endif +#include // nogncheck +#endif // CHIP_CONFIG_ENABLE_ICD_CIP +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER namespace chip { @@ -183,9 +183,11 @@ struct ServerInitParams Credentials::OperationalCertificateStore * opCertStore = nullptr; // Required, if not provided, the Server::Init() WILL fail. app::reporting::ReportScheduler * reportScheduler = nullptr; +#if CHIP_CONFIG_ENABLE_ICD_CIP // Optional. Support for the ICD Check-In BackOff strategy. Must be initialized before being provided. // If the ICD Check-In protocol use-case is supported and no strategy is provided, server will use the default strategy. app::ICDCheckInBackOffStrategy * icdCheckInBackOffStrategy = nullptr; +#endif // CHIP_CONFIG_ENABLE_ICD_CIP }; /** diff --git a/src/crypto/BUILD.gn b/src/crypto/BUILD.gn index 1fb8b94f39a82f..6f82c93c191fa8 100644 --- a/src/crypto/BUILD.gn +++ b/src/crypto/BUILD.gn @@ -67,6 +67,7 @@ source_set("public_headers") { public_deps = [ ":crypto_buildconfig", + "${chip_root}/src/app/icd/server:icd-server-config", "${chip_root}/src/lib/asn1", "${chip_root}/src/lib/core", "${chip_root}/src/lib/core:types", diff --git a/src/crypto/CHIPCryptoPALPSA.cpp b/src/crypto/CHIPCryptoPALPSA.cpp index 6eccb1dde8f1ab..99b947c18f5c78 100644 --- a/src/crypto/CHIPCryptoPALPSA.cpp +++ b/src/crypto/CHIPCryptoPALPSA.cpp @@ -263,6 +263,28 @@ void Hash_SHA256_stream::Clear() psa_hash_abort(toHashOperation(&mContext)); } +CHIP_ERROR FindFreeKeySlotInRange(psa_key_id_t & keyId, psa_key_id_t start, uint32_t range) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t end = start + range; + + VerifyOrReturnError(start >= PSA_KEY_ID_USER_MIN && end - 1 <= PSA_KEY_ID_USER_MAX, CHIP_ERROR_INVALID_ARGUMENT); + + for (keyId = start; keyId < end; keyId++) + { + psa_status_t status = psa_get_key_attributes(keyId, &attributes); + if (status == PSA_ERROR_INVALID_HANDLE) + { + return CHIP_NO_ERROR; + } + else if (status != PSA_SUCCESS) + { + return CHIP_ERROR_INTERNAL; + } + } + return CHIP_ERROR_NOT_FOUND; +} + CHIP_ERROR PsaKdf::Init(const ByteSpan & secret, const ByteSpan & salt, const ByteSpan & info) { psa_status_t status = PSA_SUCCESS; diff --git a/src/crypto/CHIPCryptoPALPSA.h b/src/crypto/CHIPCryptoPALPSA.h index 8fa3dc57a54024..508f2c4c3cd248 100644 --- a/src/crypto/CHIPCryptoPALPSA.h +++ b/src/crypto/CHIPCryptoPALPSA.h @@ -55,19 +55,58 @@ namespace Crypto { #define CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE 0x30000 #endif // CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE +/** + * @def CHIP_CONFIG_CRYPTO_PSA_KEY_ID_END + * + * @brief + * End of the PSA key identifier range used by Matter. + * + * This setting establishes the maximum limit for the key range specific to Matter, in order to + * prevent any overlap with other firmware components that also employ the PSA crypto API. + */ +#ifndef CHIP_CONFIG_CRYPTO_PSA_KEY_ID_END +#define CHIP_CONFIG_CRYPTO_PSA_KEY_ID_END 0x3FFFF +#endif // CHIP_CONFIG_CRYPTO_PSA_KEY_ID_END + +static_assert(PSA_KEY_ID_USER_MIN <= CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE && CHIP_CONFIG_CRYPTO_PSA_KEY_ID_END <= PSA_KEY_ID_USER_MAX, + "Matter specific PSA key range doesn't fit within PSA allowed range"); + +// Each ICD client requires storing two keys- AES and HMAC +static constexpr uint32_t kMaxICDClientKeys = 2 * CHIP_CONFIG_CRYPTO_PSA_ICD_MAX_CLIENTS; + +static_assert(kMaxICDClientKeys >= CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC * CHIP_CONFIG_MAX_FABRICS, + "Number of allocated ICD key slots is lower than maximum number of supported ICD clients"); + /** * @brief Defines subranges of the PSA key identifier space used by Matter. */ enum class KeyIdBase : psa_key_id_t { - Minimum = CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE, - Operational = Minimum, ///< Base of the PSA key ID range for Node Operational Certificate private keys - Maximum = Operational + kMaxValidFabricIndex, + Minimum = CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE, + Operational = Minimum, ///< Base of the PSA key ID range for Node Operational Certificate private keys + DACPrivKey = Operational + kMaxValidFabricIndex + 1, + ICDKeyRangeStart = DACPrivKey + 1, + Maximum = ICDKeyRangeStart + kMaxICDClientKeys, }; -static_assert(to_underlying(KeyIdBase::Minimum) >= PSA_KEY_ID_USER_MIN && to_underlying(KeyIdBase::Maximum) <= PSA_KEY_ID_USER_MAX, +static_assert(to_underlying(KeyIdBase::Minimum) >= CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE && + to_underlying(KeyIdBase::Maximum) <= CHIP_CONFIG_CRYPTO_PSA_KEY_ID_END, "PSA key ID base out of allowed range"); +/** + * @brief Finds first free persistent Key slot ID within range. + * + * @param[out] keyId Key ID handler to which free ID will be set. + * @param[in] start Starting ID in search range. + * @param[in] range Search range. + * + * @retval CHIP_NO_ERROR On success. + * @retval CHIP_ERROR_INTERNAL On PSA crypto API error. + * @retval CHIP_ERROR_NOT_FOUND On no free Key ID within range. + * @retval CHIP_ERROR_INVALID_ARGUMENT On search arguments out of PSA allowed range. + */ +CHIP_ERROR FindFreeKeySlotInRange(psa_key_id_t & keyId, psa_key_id_t start, uint32_t range); + /** * @brief Calculates PSA key ID for Node Operational Certificate private key for the given fabric. */ diff --git a/src/crypto/PSASessionKeystore.cpp b/src/crypto/PSASessionKeystore.cpp index 304fa10086daba..68f8029211e480 100644 --- a/src/crypto/PSASessionKeystore.cpp +++ b/src/crypto/PSASessionKeystore.cpp @@ -24,20 +24,18 @@ namespace Crypto { namespace { -class AesKeyAttributes +class KeyAttributesBase { public: - AesKeyAttributes() + KeyAttributesBase(psa_key_type_t type, psa_algorithm_t algorithm, psa_key_usage_t usageFlags, size_t bits) { - constexpr psa_algorithm_t kAlgorithm = PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8); - - psa_set_key_type(&mAttrs, PSA_KEY_TYPE_AES); - psa_set_key_algorithm(&mAttrs, kAlgorithm); - psa_set_key_usage_flags(&mAttrs, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); - psa_set_key_bits(&mAttrs, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 8); + psa_set_key_type(&mAttrs, type); + psa_set_key_algorithm(&mAttrs, algorithm); + psa_set_key_usage_flags(&mAttrs, usageFlags); + psa_set_key_bits(&mAttrs, bits); } - ~AesKeyAttributes() { psa_reset_key_attributes(&mAttrs); } + ~KeyAttributesBase() { psa_reset_key_attributes(&mAttrs); } const psa_key_attributes_t & Get() { return mAttrs; } @@ -45,49 +43,43 @@ class AesKeyAttributes psa_key_attributes_t mAttrs = PSA_KEY_ATTRIBUTES_INIT; }; -class HmacKeyAttributes +class AesKeyAttributes : public KeyAttributesBase { public: - HmacKeyAttributes() - { - psa_set_key_type(&mAttrs, PSA_KEY_TYPE_HMAC); - psa_set_key_algorithm(&mAttrs, PSA_ALG_HMAC(PSA_ALG_SHA_256)); - psa_set_key_usage_flags(&mAttrs, PSA_KEY_USAGE_SIGN_MESSAGE); - psa_set_key_bits(&mAttrs, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 8); - } - - ~HmacKeyAttributes() { psa_reset_key_attributes(&mAttrs); } - - const psa_key_attributes_t & Get() { return mAttrs; } - -private: - psa_key_attributes_t mAttrs = PSA_KEY_ATTRIBUTES_INIT; + AesKeyAttributes() : + KeyAttributesBase(PSA_KEY_TYPE_AES, PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8), + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY, + CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 8) + {} }; -class HkdfKeyAttributes +class HmacKeyAttributes : public KeyAttributesBase { public: - HkdfKeyAttributes() - { - psa_set_key_type(&mAttrs, PSA_KEY_TYPE_DERIVE); - psa_set_key_algorithm(&mAttrs, PSA_ALG_HKDF(PSA_ALG_SHA_256)); - psa_set_key_usage_flags(&mAttrs, PSA_KEY_USAGE_DERIVE); - } - - ~HkdfKeyAttributes() { psa_reset_key_attributes(&mAttrs); } - - const psa_key_attributes_t & Get() { return mAttrs; } + HmacKeyAttributes() : + KeyAttributesBase(PSA_KEY_TYPE_HMAC, PSA_ALG_HMAC(PSA_ALG_SHA_256), PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_COPY, + CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 8) + {} +}; -private: - psa_key_attributes_t mAttrs = PSA_KEY_ATTRIBUTES_INIT; +class HkdfKeyAttributes : public KeyAttributesBase +{ +public: + HkdfKeyAttributes() : KeyAttributesBase(PSA_KEY_TYPE_DERIVE, PSA_ALG_HKDF(PSA_ALG_SHA_256), PSA_KEY_USAGE_DERIVE, 0) {} }; +void SetKeyId(Symmetric128BitsKeyHandle & key, psa_key_id_t newKeyId) +{ + auto & KeyId = key.AsMutable(); + + KeyId = newKeyId; +} } // namespace CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Aes128KeyHandle & key) { // Destroy the old key if already allocated - psa_destroy_key(key.As()); + DestroyKey(key); AesKeyAttributes attrs; psa_status_t status = @@ -101,7 +93,7 @@ CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & ke CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Hmac128KeyHandle & key) { // Destroy the old key if already allocated - psa_destroy_key(key.As()); + DestroyKey(key); HmacKeyAttributes attrs; psa_status_t status = @@ -192,5 +184,39 @@ void PSASessionKeystore::DestroyKey(HkdfKeyHandle & key) keyId = PSA_KEY_ID_NULL; } +#if CHIP_CONFIG_ENABLE_ICD_CIP +CHIP_ERROR PSASessionKeystore::PersistICDKey(Symmetric128BitsKeyHandle & key) +{ + CHIP_ERROR err; + psa_key_id_t newKeyId = PSA_KEY_ID_NULL; + psa_key_attributes_t attrs; + + psa_get_key_attributes(key.As(), &attrs); + + // Exit early if key is already persistent + if (psa_get_key_lifetime(&attrs) == PSA_KEY_LIFETIME_PERSISTENT) + { + psa_reset_key_attributes(&attrs); + return CHIP_NO_ERROR; + } + + SuccessOrExit(err = Crypto::FindFreeKeySlotInRange(newKeyId, to_underlying(KeyIdBase::ICDKeyRangeStart), kMaxICDClientKeys)); + psa_set_key_lifetime(&attrs, PSA_KEY_LIFETIME_PERSISTENT); + psa_set_key_id(&attrs, newKeyId); + VerifyOrExit(psa_copy_key(key.As(), &attrs, &newKeyId) == PSA_SUCCESS, err = CHIP_ERROR_INTERNAL); + +exit: + DestroyKey(key); + psa_reset_key_attributes(&attrs); + + if (err == CHIP_NO_ERROR) + { + SetKeyId(key, newKeyId); + } + + return err; +} +#endif + } // namespace Crypto } // namespace chip diff --git a/src/crypto/PSASessionKeystore.h b/src/crypto/PSASessionKeystore.h index 1a55713b82d167..b4d2742ae069e8 100644 --- a/src/crypto/PSASessionKeystore.h +++ b/src/crypto/PSASessionKeystore.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include @@ -38,6 +39,9 @@ class PSASessionKeystore : public SessionKeystore AttestationChallenge & attestationChallenge) override; void DestroyKey(Symmetric128BitsKeyHandle & key) override; void DestroyKey(HkdfKeyHandle & key) override; +#if CHIP_CONFIG_ENABLE_ICD_CIP + CHIP_ERROR PersistICDKey(Symmetric128BitsKeyHandle & key) override; +#endif private: CHIP_ERROR DeriveSessionKeys(PsaKdf & kdf, Aes128KeyHandle & i2rKey, Aes128KeyHandle & r2iKey, diff --git a/src/crypto/SessionKeystore.h b/src/crypto/SessionKeystore.h index d668524ac93aed..654100fb95b28b 100644 --- a/src/crypto/SessionKeystore.h +++ b/src/crypto/SessionKeystore.h @@ -140,6 +140,17 @@ class SessionKeystore virtual CHIP_ERROR DeriveSessionKeys(const HkdfKeyHandle & secretKey, const ByteSpan & salt, const ByteSpan & info, Aes128KeyHandle & i2rKey, Aes128KeyHandle & r2iKey, AttestationChallenge & attestationChallenge) = 0; + + /** + * @brief Persistently store an ICD key. + * + * If input is already a persistent key handle, the function is a no-op and the original handle is returned. + * If input is a volatile key handle, key is persisted and the handle may be updated. + * + * If the method returns no error, the application is responsible for destroying the handle + * using the DestroyKey() method when the key is no longer needed. + */ + virtual CHIP_ERROR PersistICDKey(Symmetric128BitsKeyHandle & key) { return CHIP_NO_ERROR; } }; /** diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index 8936cc19c4f76d..7827f5a8c335f2 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -1667,6 +1667,22 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC 2 #endif +/** + * @def CHIP_CONFIG_CRYPTO_PSA_ICD_MAX_CLIENTS + * + * @brief + * Maximum number of ICD clients. Based on this number, platforms that utilize the + * PSA Crypto API should reserve key slot range. + * + * @note + * For platforms that utilize the PSA Crypto API, this configuration is used to + * compute the number of PSA key slots. It should remain unchanged during the device's lifetime, + * as alterations may lead to issues with backwards compatibility. + */ +#ifndef CHIP_CONFIG_CRYPTO_PSA_ICD_MAX_CLIENTS +#define CHIP_CONFIG_CRYPTO_PSA_ICD_MAX_CLIENTS 256 +#endif + /** * @def CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF * diff --git a/src/platform/nrfconnect/CHIPPlatformConfig.h b/src/platform/nrfconnect/CHIPPlatformConfig.h index 096bc3426c5fe3..7355d1a1834acb 100644 --- a/src/platform/nrfconnect/CHIPPlatformConfig.h +++ b/src/platform/nrfconnect/CHIPPlatformConfig.h @@ -59,6 +59,10 @@ #define CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE 0x30000 #endif // CHIP_CONFIG_CRYPTO_PSA_KEY_ID_BASE +#ifndef CHIP_CONFIG_CRYPTO_PSA_KEY_ID_END +#define CHIP_CONFIG_CRYPTO_PSA_KEY_ID_END 0x3FFFF +#endif // CHIP_CONFIG_CRYPTO_PSA_KEY_ID_END + // ==================== General Configuration Overrides ==================== #ifndef CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS @@ -142,6 +146,10 @@ #endif // CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC #endif // CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC +#ifndef CHIP_CONFIG_CRYPTO_PSA_ICD_MAX_CLIENTS +#define CHIP_CONFIG_CRYPTO_PSA_ICD_MAX_CLIENTS 256 +#endif + #ifndef CHIP_CONFIG_ENABLE_BDX_LOG_TRANSFER #ifdef CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER #define CHIP_CONFIG_ENABLE_BDX_LOG_TRANSFER CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER diff --git a/src/test_driver/nrfconnect/prj.conf b/src/test_driver/nrfconnect/prj.conf index 8c9c4433d56086..97b7787fe93ac8 100644 --- a/src/test_driver/nrfconnect/prj.conf +++ b/src/test_driver/nrfconnect/prj.conf @@ -76,6 +76,8 @@ CONFIG_STD_CPP17=y CONFIG_CHIP=y CONFIG_CHIP_CRYPTO_PSA=y CONFIG_CHIP_BUILD_TESTS=y +CONFIG_CHIP_ICD_LIT_SUPPORT=y +CONFIG_CHIP_ENABLE_ICD_SUPPORT=y CONFIG_CHIP_ENABLE_READ_CLIENT=y CONFIG_CHIP_DEVICE_VENDOR_ID=65521 CONFIG_CHIP_DEVICE_PRODUCT_ID=32768