From 534fc4885a3cfe5bc99a097d5907073f37a8d3f3 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Sat, 6 May 2023 15:19:19 +0800 Subject: [PATCH] esp-matter: Add custom providers support --- components/esp_matter/Kconfig | 78 ++++++++ components/esp_matter/esp_matter_core.cpp | 24 +-- .../esp_matter/esp_matter_dac_provider.cpp | 166 ------------------ .../esp_matter/esp_matter_dac_provider.h | 35 ---- .../esp_matter/esp_matter_providers.cpp | 122 +++++++++++++ components/esp_matter/esp_matter_providers.h | 61 +++++++ .../esp_matter/secure_cert_dac_provider.cpp | 144 +++++++++++++++ .../esp_matter/secure_cert_dac_provider.h | 41 +++++ docs/en/certification.rst | 22 +-- docs/en/developing.rst | 83 ++++++++- 10 files changed, 525 insertions(+), 251 deletions(-) delete mode 100644 components/esp_matter/esp_matter_dac_provider.cpp delete mode 100644 components/esp_matter/esp_matter_dac_provider.h create mode 100644 components/esp_matter/esp_matter_providers.cpp create mode 100644 components/esp_matter/esp_matter_providers.h create mode 100644 components/esp_matter/secure_cert_dac_provider.cpp create mode 100644 components/esp_matter/secure_cert_dac_provider.h diff --git a/components/esp_matter/Kconfig b/components/esp_matter/Kconfig index ec9cac0b1..ea6d7ea8c 100644 --- a/components/esp_matter/Kconfig +++ b/components/esp_matter/Kconfig @@ -35,8 +35,86 @@ menu "ESP Matter" help An implementation which reads attestation information from the esp_secure_cert partition + config CUSTOM_DAC_PROVIDER + bool "Attestation - Custom" + help + A custom implementation of DAC provider + endchoice + choice ESP_MATTER_COMMISSIONABLE_DATA_PROVIDER + prompt "Commissionable Data Provider options" + default EXAMPLE_COMMISSIONABLE_DATA_PROVIDER + help + This option determines which commissionable data provider will be used. + + config EXAMPLE_COMMISSIONABLE_DATA_PROVIDER + bool "Commissionable Data - Test" + help + An example Commissionable Data Provider which provides commissionable data information + + config FACTORY_COMMISSIONABLE_DATA_PROVIDER + bool "Commissionable Data - Factory" + depends on ENABLE_ESP32_FACTORY_DATA_PROVIDER + help + An implementation which reads commissionable data information from the factory partition + + config CUSTOM_COMMISSIONABLE_DATA_PROVIDER + bool "Commissionable Data - Custom" + help + A custom implementation of Commissionable Data provider + + endchoice + + choice ESP_MATTER_DEVICE_INSTANCE_INFO_PROVIDER + prompt "Device Instance Info Provider options" + default EXAMPLE_DEVICE_INSTANCE_INFO_PROVIDER + help + This option determines which device instance info provider will be used. + + config EXAMPLE_DEVICE_INSTANCE_INFO_PROVIDER + bool "Device Instance Info - Test" + help + An example Device Instance Info Provider which provides device instance information + + config FACTORY_DEVICE_INSTANCE_INFO_PROVIDER + bool "Device Instance Info - Factory" + depends on ENABLE_ESP32_FACTORY_DATA_PROVIDER && ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER + help + An implementation which reads device instance information from the factory partition + + config CUSTOM_DEVICE_INSTANCE_INFO_PROVIDER + bool "Device Instance Info - Custom" + help + A custom implementation of Device Instance Info provider + + endchoice + + choice ESP_MATTER_DEVICE_INFO_PROVIDER + prompt "Device Info Provider options" + default NONE_DEVICE_INFO_PROVIDER + help + This option determines which device info provider will be used. + + config NONE_DEVICE_INFO_PROVIDER + bool "Device Info - None" + help + Do not set the Device Info Provider + + config FACTORY_DEVICE_INFO_PROVIDER + bool "Device Info - Factory" + depends on ENABLE_ESP32_FACTORY_DATA_PROVIDER && ENABLE_ESP32_DEVICE_INFO_PROVIDER + help + An implementation which reads device information from the factory partition + + config CUSTOM_DEVICE_INFO_PROVIDER + bool "Device Info - Custom" + help + A custom implementation of Device Info provider + + endchoice + + config ESP_MATTER_MAX_DYNAMIC_ENDPOINT_COUNT int "Maximum dynamic endpoints" range 1 255 diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index fcecbed99..bd155d5db 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -37,13 +37,11 @@ #include #include #include -#include -#include #include #include #include -#include #include +#include using chip::CommandId; using chip::DataVersion; @@ -73,13 +71,6 @@ static bool esp_matter_started = false; namespace esp_matter { namespace { -#if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER -chip::DeviceLayer::ESP32FactoryDataProvider factory_data_provider; -#endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER - -#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER -chip::DeviceLayer::ESP32DeviceInfoProvider device_info_provider; -#endif void PostEvent(uint16_t eventType) { @@ -906,18 +897,7 @@ static esp_err_t chip_init(event_callback_t callback, intptr_t callback_arg) return ESP_FAIL; } -#if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER - SetCommissionableDataProvider(&factory_data_provider); -#if CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER - SetDeviceInstanceInfoProvider(&factory_data_provider); -#endif // CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER -#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER - SetDeviceInfoProvider(&device_info_provider); -#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER -#endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER - - SetDeviceAttestationCredentialsProvider(get_dac_provider()); - + setup_providers(); ConnectivityMgr().SetBLEAdvertisingEnabled(true); // ConnectivityMgr().SetWiFiAPMode(ConnectivityManager::kWiFiAPMode_Enabled); if (PlatformMgr().StartEventLoopTask() != CHIP_NO_ERROR) { diff --git a/components/esp_matter/esp_matter_dac_provider.cpp b/components/esp_matter/esp_matter_dac_provider.cpp deleted file mode 100644 index 895398bf0..000000000 --- a/components/esp_matter/esp_matter_dac_provider.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2022 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include -#include -#include -#include -#include - -#define TAG "dac_provider" - -#if CONFIG_SEC_CERT_DAC_PROVIDER - -namespace chip { -namespace DeviceLayer { - -using namespace chip::Credentials; -using namespace chip::DeviceLayer::Internal; - -namespace { -static constexpr uint32_t kDACPrivateKeySize = 32; -static constexpr uint32_t kDACPublicKeySize = 65; -static constexpr uint8_t kPrivKeyOffset = 7; -static constexpr uint8_t kPubKeyOffset = 56; - -CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) -{ - Crypto::P256SerializedKeypair serializedKeypair; - ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size())); - memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size()); - memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); - return keypair.Deserialize(serializedKeypair); -} -} // namespace - -class SecureCertDACProvider: public Credentials::DeviceAttestationCredentialsProvider -{ -public: - SecureCertDACProvider() : Credentials::DeviceAttestationCredentialsProvider() {} - - CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override - { - size_t certSize; - ReturnErrorOnFailure( - ESP32Config::ReadConfigValueBin(ESP32Config::kConfigKey_CertDeclaration, outBuffer.data(), outBuffer.size(), certSize)); - outBuffer.reduce_size(certSize); - return CHIP_NO_ERROR; - } - - CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override - { - // We do not provide any FirmwareInformation. - out_firmware_info_buffer.reduce_size(0); - return CHIP_NO_ERROR; - } - - CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override - { - char *dac_cert = NULL; - uint32_t dac_len = 0; - - esp_err_t err = esp_secure_cert_get_device_cert(&dac_cert, &dac_len); - if (err == ESP_OK && dac_cert != NULL && dac_len != 0) - { - ESP_FAULT_ASSERT(err == ESP_OK && dac_cert != NULL && dac_len != 0); - VerifyOrReturnError(dac_len <= kMaxDERCertLength, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT, esp_secure_cert_free_ca_cert(dac_cert)); - VerifyOrReturnError(dac_len <= outBuffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL, esp_secure_cert_free_ca_cert(dac_cert)); - memcpy(outBuffer.data(), dac_cert, outBuffer.size()); - outBuffer.reduce_size(dac_len); - esp_secure_cert_free_device_cert(dac_cert); - return CHIP_NO_ERROR; - } - - ESP_LOGE(TAG, "esp_secure_cert_get_device_cert failed err:%d", err); - return CHIP_ERROR_INCORRECT_STATE; - } - - CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override - { - char *pai_cert = NULL; - uint32_t pai_len = 0; - - esp_err_t err = esp_secure_cert_get_ca_cert(&pai_cert, &pai_len); - if (err == ESP_OK && pai_cert != NULL && pai_len != 0) - { - ESP_FAULT_ASSERT(err == ESP_OK && pai_cert != NULL && pai_len != 0); - VerifyOrReturnError(pai_len <= kMaxDERCertLength, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT, esp_secure_cert_free_ca_cert(pai_cert)); - VerifyOrReturnError(pai_len <= outBuffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL, esp_secure_cert_free_ca_cert(pai_cert)); - memcpy(outBuffer.data(), pai_cert, outBuffer.size()); - outBuffer.reduce_size(pai_len); - esp_secure_cert_free_ca_cert(pai_cert); - return CHIP_NO_ERROR; - } - - ESP_LOGE(TAG, "esp_secure_cert_get_ca_cert failed err:%d", err); - return CHIP_ERROR_INCORRECT_STATE; - } - - CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override - { - Crypto::P256ECDSASignature signature; - Crypto::P256Keypair keypair; - char *sc_keypair = NULL; - uint32_t sc_keypair_len = 0; - - VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(IsSpanUsable(messageToSign), CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); - - esp_err_t err = esp_secure_cert_get_priv_key(&sc_keypair, &sc_keypair_len); - if (err == ESP_OK && sc_keypair != NULL && sc_keypair_len != 0) - { - ESP_FAULT_ASSERT(err == ESP_OK && sc_keypair != NULL && sc_keypair_len != 0); - - CHIP_ERROR chipError = LoadKeypairFromRaw(ByteSpan(reinterpret_cast(sc_keypair + kPrivKeyOffset), kDACPrivateKeySize), - ByteSpan(reinterpret_cast(sc_keypair + kPubKeyOffset), kDACPublicKeySize), keypair); - VerifyOrReturnError(chipError == CHIP_NO_ERROR, chipError, esp_secure_cert_free_priv_key(sc_keypair)); - - chipError = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature); - VerifyOrReturnError(chipError == CHIP_NO_ERROR, chipError, esp_secure_cert_free_priv_key(sc_keypair)); - - esp_secure_cert_free_priv_key(sc_keypair); - chipError = CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); - return chipError; - } - - ESP_LOGE(TAG, "esp_secure_cert_get_priv_key failed err:%d", err); - return CHIP_ERROR_INCORRECT_STATE; - } -}; -} // namespace DeviceLayer -} // namespace chip - -#endif // CONFIG_SEC_CERT_DAC_PROVIDER - -namespace esp_matter { - -// TODO: Need some method or mechanism to use the custom implementation along with the above three -chip::Credentials::DeviceAttestationCredentialsProvider * get_dac_provider(void) -{ -#if CONFIG_SEC_CERT_DAC_PROVIDER - static chip::DeviceLayer::SecureCertDACProvider instance; - return &instance; -#elif CONFIG_FACTORY_PARTITION_DAC_PROVIDER - static chip::DeviceLayer::ESP32FactoryDataProvider instance; - return &instance; -#else // CONFIG_EXAMPLE_DAC_PROVIDER - return chip::Credentials::Examples::GetExampleDACProvider(); -#endif -} - -} // namespace esp_matter diff --git a/components/esp_matter/esp_matter_dac_provider.h b/components/esp_matter/esp_matter_dac_provider.h deleted file mode 100644 index defe43ab5..000000000 --- a/components/esp_matter/esp_matter_dac_provider.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2022 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#include - -namespace esp_matter { - -/** - * @brief Get the DAC Provider implementation based on the configuration option - * - * If CONFIG_EXAMPLE_DAC_PROVIDER option is enabled then implementation which uses test data is used. - * - * If CONFIG_FACTORY_PARTITION_DAC_PROVIDER option is enabled then implementation which reads attestation - * information from factory partition is used. - * - * If CONFIG_SEC_CERT_DAC_PROVIDER option is enabled then implementation which reads attestation information - * from the esp_secure_cert partition is used. - * - * @return Pointer to the object of type DeviceAttestationCredentialsProvider - */ -chip::Credentials::DeviceAttestationCredentialsProvider * get_dac_provider(void); - -} // namespace esp_matter diff --git a/components/esp_matter/esp_matter_providers.cpp b/components/esp_matter/esp_matter_providers.cpp new file mode 100644 index 000000000..48f956e01 --- /dev/null +++ b/components/esp_matter/esp_matter_providers.cpp @@ -0,0 +1,122 @@ +// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +using namespace chip::DeviceLayer; +using namespace chip::Credentials; + +constexpr char TAG[] = "esp_matter_providers"; + +namespace esp_matter { + +#if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER +static ESP32FactoryDataProvider factory_data_provider; +#endif + +#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER +static ESP32DeviceInfoProvider device_info_provider; + +#endif + +#if CONFIG_CUSTOM_DAC_PROVIDER +static DeviceAttestationCredentialsProvider *s_custom_dac_provider = NULL; + +void set_custom_dac_provider(DeviceAttestationCredentialsProvider *provider) +{ + s_custom_dac_provider = provider; +} +#endif + +#if CONFIG_CUSTOM_COMMISSIONABLE_DATA_PROVIDER +static CommissionableDataProvider *s_custom_commissionable_data_provider = NULL; + +void set_custom_commissionable_data_provider(CommissionableDataProvider *provider) +{ + s_custom_commissionable_data_provider = provider; +} +#endif + +#if CONFIG_CUSTOM_DEVICE_INSTANCE_INFO_PROVIDER +static DeviceInstanceInfoProvider *s_custom_device_instance_info_provider = NULL; + +void set_custom_device_instance_info_provider(DeviceInstanceInfoProvider *provider) +{ + s_custom_device_instance_info_provider = provider; +} +#endif + +#if CONFIG_CUSTOM_DEVICE_INFO_PROVIDER +static DeviceInfoProvider *s_custom_device_info_provider = NULL; + +void set_custom_device_info_provider(DeviceInfoProvider *provider) +{ + s_custom_device_info_provider = provider; +} +#endif + +static DeviceAttestationCredentialsProvider *get_dac_provider(void) +{ +#if CONFIG_SEC_CERT_DAC_PROVIDER + static SecureCertDACProvider instance; + return &instance; +#elif CONFIG_FACTORY_PARTITION_DAC_PROVIDER + return &factory_data_provider; +#elif CONFIG_CUSTOM_DAC_PROVIDER + if (s_custom_dac_provider) { + return s_custom_dac_provider; + } else { + ESP_LOGE(TAG, "custom_dac_provider cannot be NULL"); + } +#endif + return chip::Credentials::Examples::GetExampleDACProvider(); +} + +void setup_providers() +{ +#if CONFIG_FACTORY_COMMISSIONABLE_DATA_PROVIDER + SetCommissionableDataProvider(&factory_data_provider); +#elif CONFIG_CUSTOM_COMMISSIONABLE_DATA_PROVIDER + if (s_custom_commissionable_data_provider) { + SetCommissionableDataProvider(s_custom_commissionable_data_provider); + } +#endif + // We should do nothing if CONFIG_EXAMPLE_COMMISSIONABLE_DATA_PROVIDER is enabled as + // LegacyTemporaryCommissionableDataProvider is set in GenericConfigurationManagerImpl::Init() + +#if CONFIG_FACTORY_DEVICE_INSTANCE_INFO_PROVIDER + SetDeviceInstanceInfoProvider(&factory_data_provider); +#elif CONFIG_CUSTOM_DEVICE_INSTANCE_INFO_PROVIDER + if (s_custom_device_instance_info_provider) { + SetDeviceInstanceInfoProvider(s_custom_device_instance_info_provider); + } +#endif + // We should do nothing if CONFIG_EXAMPLE_DEVICE_INSTANCE_INFO_PROVIDER is enabled as + // GenericDeviceInstanceInfoProvider is set in GenericConfigurationManagerImpl::Init() + +#if CONFIG_FACTORY_DEVICE_INFO_PROVIDER + SetDeviceInfoProvider(&device_info_provider); +#elif CONFIG_CUSTOM_DEVICE_INFO_PROVIDER + if (s_custom_device_info_provider) { + SetDeviceInfoProvider(s_custom_device_info_provider); + } +#endif + SetDeviceAttestationCredentialsProvider(get_dac_provider()); +} + +} // namespace esp_matter diff --git a/components/esp_matter/esp_matter_providers.h b/components/esp_matter/esp_matter_providers.h new file mode 100644 index 000000000..afdda8f36 --- /dev/null +++ b/components/esp_matter/esp_matter_providers.h @@ -0,0 +1,61 @@ +// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include +#include +#include + +namespace esp_matter { + +/** + * @brief Set the custom DAC provider + * + * This should be called before esp_matter::start(). + */ +#if CONFIG_CUSTOM_DAC_PROVIDER +void set_custom_dac_provider(chip::Credentials::DeviceAttestationCredentialsProvider *provider); +#endif + +/** + * @brief Set the custom commissionable data provider + * + * This should be called before esp_matter::start(). + */ +#if CONFIG_CUSTOM_COMMISSIONABLE_DATA_PROVIDER +void set_custom_commissionable_data_provider(chip::DeviceLayer::CommissionableDataProvider *provider); +#endif + +/** + * @brief Set the custom device instance info provider + * + * This should be called before esp_matter::start(). + */ +#if CONFIG_CUSTOM_DEVICE_INSTANCE_INFO_PROVIDER +void set_custom_device_instance_info_provider(chip::DeviceLayer::DeviceInstanceInfoProvider *provider); +#endif + +/** + * @brief Set the custom device info provider + * + * This should be called before esp_matter::start(). + */ +#if CONFIG_CUSTOM_DEVICE_INFO_PROVIDER +void set_custom_device_info_provider(chip::DeviceLayer::DeviceInfoProvider *provider); +#endif + +void setup_providers(); +} // namespace esp_matter diff --git a/components/esp_matter/secure_cert_dac_provider.cpp b/components/esp_matter/secure_cert_dac_provider.cpp new file mode 100644 index 000000000..af9614d94 --- /dev/null +++ b/components/esp_matter/secure_cert_dac_provider.cpp @@ -0,0 +1,144 @@ +// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include + +#define TAG "dac_provider" + +#if CONFIG_SEC_CERT_DAC_PROVIDER + +namespace chip { +namespace DeviceLayer { + +using namespace chip::Credentials; +using namespace chip::DeviceLayer::Internal; + +namespace { +static constexpr uint32_t kDACPrivateKeySize = 32; +static constexpr uint32_t kDACPublicKeySize = 65; +static constexpr uint8_t kPrivKeyOffset = 7; +static constexpr uint8_t kPubKeyOffset = 56; + +CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair &keypair) +{ + Crypto::P256SerializedKeypair serializedKeypair; + ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size())); + memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size()); + memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); + return keypair.Deserialize(serializedKeypair); +} +} // namespace + +CHIP_ERROR SecureCertDACProvider::GetCertificationDeclaration(MutableByteSpan &outBuffer) +{ + size_t certSize; + ReturnErrorOnFailure(ESP32Config::ReadConfigValueBin(ESP32Config::kConfigKey_CertDeclaration, outBuffer.data(), + outBuffer.size(), certSize)); + outBuffer.reduce_size(certSize); + return CHIP_NO_ERROR; +} + +CHIP_ERROR SecureCertDACProvider::GetFirmwareInformation(MutableByteSpan &out_firmware_info_buffer) +{ + // We do not provide any FirmwareInformation. + out_firmware_info_buffer.reduce_size(0); + return CHIP_NO_ERROR; +} + +CHIP_ERROR SecureCertDACProvider::GetDeviceAttestationCert(MutableByteSpan &outBuffer) +{ + char *dac_cert = NULL; + uint32_t dac_len = 0; + + esp_err_t err = esp_secure_cert_get_device_cert(&dac_cert, &dac_len); + if (err == ESP_OK && dac_cert != NULL && dac_len != 0) { + ESP_FAULT_ASSERT(err == ESP_OK && dac_cert != NULL && dac_len != 0); + VerifyOrReturnError(dac_len <= kMaxDERCertLength, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT, + esp_secure_cert_free_ca_cert(dac_cert)); + VerifyOrReturnError(dac_len <= outBuffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL, + esp_secure_cert_free_ca_cert(dac_cert)); + memcpy(outBuffer.data(), dac_cert, outBuffer.size()); + outBuffer.reduce_size(dac_len); + esp_secure_cert_free_device_cert(dac_cert); + return CHIP_NO_ERROR; + } + + ESP_LOGE(TAG, "esp_secure_cert_get_device_cert failed err:%d", err); + return CHIP_ERROR_INCORRECT_STATE; +} + +CHIP_ERROR SecureCertDACProvider::GetProductAttestationIntermediateCert(MutableByteSpan &outBuffer) +{ + char *pai_cert = NULL; + uint32_t pai_len = 0; + + esp_err_t err = esp_secure_cert_get_ca_cert(&pai_cert, &pai_len); + if (err == ESP_OK && pai_cert != NULL && pai_len != 0) { + ESP_FAULT_ASSERT(err == ESP_OK && pai_cert != NULL && pai_len != 0); + VerifyOrReturnError(pai_len <= kMaxDERCertLength, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT, + esp_secure_cert_free_ca_cert(pai_cert)); + VerifyOrReturnError(pai_len <= outBuffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL, + esp_secure_cert_free_ca_cert(pai_cert)); + memcpy(outBuffer.data(), pai_cert, outBuffer.size()); + outBuffer.reduce_size(pai_len); + esp_secure_cert_free_ca_cert(pai_cert); + return CHIP_NO_ERROR; + } + + ESP_LOGE(TAG, "esp_secure_cert_get_ca_cert failed err:%d", err); + return CHIP_ERROR_INCORRECT_STATE; +} + +CHIP_ERROR SecureCertDACProvider::SignWithDeviceAttestationKey(const ByteSpan &messageToSign, + MutableByteSpan &outSignBuffer) +{ + Crypto::P256ECDSASignature signature; + Crypto::P256Keypair keypair; + char *sc_keypair = NULL; + uint32_t sc_keypair_len = 0; + + VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(IsSpanUsable(messageToSign), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); + + esp_err_t err = esp_secure_cert_get_priv_key(&sc_keypair, &sc_keypair_len); + if (err == ESP_OK && sc_keypair != NULL && sc_keypair_len != 0) { + ESP_FAULT_ASSERT(err == ESP_OK && sc_keypair != NULL && sc_keypair_len != 0); + + CHIP_ERROR chipError = LoadKeypairFromRaw( + ByteSpan(reinterpret_cast(sc_keypair + kPrivKeyOffset), kDACPrivateKeySize), + ByteSpan(reinterpret_cast(sc_keypair + kPubKeyOffset), kDACPublicKeySize), keypair); + VerifyOrReturnError(chipError == CHIP_NO_ERROR, chipError, esp_secure_cert_free_priv_key(sc_keypair)); + + chipError = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature); + VerifyOrReturnError(chipError == CHIP_NO_ERROR, chipError, esp_secure_cert_free_priv_key(sc_keypair)); + + esp_secure_cert_free_priv_key(sc_keypair); + chipError = CopySpanToMutableSpan(ByteSpan{signature.ConstBytes(), signature.Length()}, outSignBuffer); + return chipError; + } + + ESP_LOGE(TAG, "esp_secure_cert_get_priv_key failed err:%d", err); + return CHIP_ERROR_INCORRECT_STATE; +} +} // namespace DeviceLayer +} // namespace chip + +#endif // CONFIG_SEC_CERT_DAC_PROVIDER diff --git a/components/esp_matter/secure_cert_dac_provider.h b/components/esp_matter/secure_cert_dac_provider.h new file mode 100644 index 000000000..a8f07927c --- /dev/null +++ b/components/esp_matter/secure_cert_dac_provider.h @@ -0,0 +1,41 @@ +// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include + +#if CONFIG_SEC_CERT_DAC_PROVIDER +namespace chip { +namespace DeviceLayer { + +class SecureCertDACProvider : public Credentials::DeviceAttestationCredentialsProvider +{ +public: + SecureCertDACProvider() : Credentials::DeviceAttestationCredentialsProvider() {} + + CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override; + + CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override; + + CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override; + + CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override; + + CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override; +}; + +} // namespace DeviceLayer +} // namespace chip +#endif // CONFIG_SEC_CERT_DAC_PROVIDER diff --git a/docs/en/certification.rst b/docs/en/certification.rst index d666f8fae..d9199f478 100644 --- a/docs/en/certification.rst +++ b/docs/en/certification.rst @@ -146,27 +146,7 @@ Run automated chip-tool tests and verify that the pairing commands are using the 3.2.3 Menuconfig Options ~~~~~~~~~~~~~~~~~~~~~~~~ -Here are the menuconfig options related to the usage of factory partition binary. - -- ``Use ESP32 Factory Data Provider`` in ``→ Component config → CHIP Device Layer → Commissioning options`` - - When enabling this option, the app will use the discriminator and spake2+ verifier in the factory partition binary instead of the hardcoded test ones. - -- ``Use ESP32 Device Instance Info Provider`` in ``→ Component config → CHIP Device Layer → Commissioning options`` - - When enabling this option, the app will read vendor name, vendor id, product name, product id, product url, product label, hardware version string, and unique id of rotating device id from the factory partition binary. - -- ``Use ESP32 Device Info Provider`` in ``→ Component config → CHIP Device Layer → Commissioning options`` - - When enabling this option, the app will read supported locales, supported calendar types, fixed labels, and user labels from the factory partition binary instead of using the hardcode ones. - -- ``DAC Provider options`` in ``→ Component config → ESP Matter`` - - When selecting ``Attestation - Test``, the app will use the hardcoded PAI certificate, DAC, DAC private key, and CD. - - When selecting ``Attestation - Factory``, the app will use the PAI certificate, DAC, DAC private key, and CD in the factory partition binary. - - When selecting ``Attestation - Secure Cert``, the app will use the PAI certificate, DAC, DAC private key, and CD in the secure cert partition. This option is for the `Pre-Provisioned Modules `__. And the original vendor ID and product ID should be added to the CD file for the Pre-Provisioned Modules. Please contact your Espressif contact person for more information. +Please consult the `factory data providers <./developing.html#factory-data-providers>`__ and adjust the menucofig options accordingly for the certification test. 3.3 Matter OTA Image Generation ------------------------------- diff --git a/docs/en/developing.rst b/docs/en/developing.rst index 13bd9b3f8..1b772bfa0 100644 --- a/docs/en/developing.rst +++ b/docs/en/developing.rst @@ -869,7 +869,7 @@ This section introduces the Matter controller example. Now this example supports 2.4.5.1 Starting with device console ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -After you flash the controller example to the device, you can use `device console `__ to commission and send commands to the end-device. All of the controller commands start with *matter esp controller*. +After you flash the controller example to the device, you can use `device console <./developing.html#device-console>`__ to commission and send commands to the end-device. All of the controller commands start with *matter esp controller*. 2.4.5.2 Pairing commands ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -965,10 +965,77 @@ The ``group-settings`` command is used for setting group information of the cont matter esp controller group-settings bind-keyset matter esp controller group-settings unbind-keyset -2.5 Using esp_secure_cert partition +2.5 Factory Data Providers +-------------------------- + +2.5.1 Providers Introduction +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +There are four factory data providers, each with its own implementation, that need to be configured. These providers supply the device with necessary factory data, which is then read by the device according to their respective implementations. + +- ``Commissionable Data Provider`` + + This particular provider is responsible for retrieving commissionable data, which includes information such as setup-discriminator, spake2p-iteration-count, spake2p-salt, spake2p-verifier, and setup-passcode. + +- ``Device Attestation Credentials(DAC) Provider`` + + This particular provider is responsible for retrieving device attestation credentials, which includes information such as CD, firmware-information, DAC, and PAI certificate. And it can also sign message with the DAC private key. + +- ``Device Instance Info Provider`` + + This particular provider is responsible for retrieving device instance information, which includes vendor-name, vendor-id, product-name, product-id, product-url, product-label, hardware-version-string, hardware-version, rotating-device-id-unique-id, serial-number, manufacturing-data, and part-number. + +- ``Device Info Provider`` + + This particular provider is responsible for retrieving device information, which includes fixed-labels, user-labels, supported-locales, and supported-calendar-types. + +2.5.2 Configuration Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Different implementations of the four providers can be chosen in meuconfig: + +- ``Commissionable Data Provider options`` in ``→ Component config → ESP Matter`` + + When selecting ``Commissionable Data - Test``, the device will use the hardcoded Commissionable Data. + + When selecting ``Commissionable Data - Factory``, the device will use commissionable data information from the factory partition. This option is visable only when ``CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER`` is selected. + + When selecting ``Commissionable Data - Custom``, the device will use the custom defined commissionable data provider to obtain commissionable data information. ``esp_matter::set_custom_commissionable_data_provider()`` should be called before ``esp_matter::start()`` to set the custom provider. + +- ``DAC Provider options`` in ``→ Component config → ESP Matter`` + + When selecting ``Attestation - Test``, the device will use the hardcoded Device Attestation Credentials. + + When selecting ``Attestation - Factory``, the device will use the Device Attestation Credentials in the factory partition binary. This option is visable only when ``CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER`` is selected. + + When selecting ``Attestation - Secure Cert``, the device will use the Device Attestation Credentials in the secure cert partition. This option is for the `Pre-Provisioned Modules <./production.html#pre-provisioned-modules>`__. And the original vendor ID and product ID should be added to the CD file for the Pre-Provisioned Modules. Please contact your Espressif contact person for more information. + + When selecting ``Attestation - Custom``, the device will use the custom defined DAC provider to obtain the Device Attestation Credentials. ``esp_matter::set_custom_dac_provider()`` should be called before ``esp_matter::start()`` to set the custom provider. + +- ``Device Instance Info Provider options`` in ``→ Component config → ESP Matter`` + + When selecting ``Device Instance Info - Test``, the device will use the hardcoded Device Instance Information. + + When selecting ``Device Instance Info - Factory``, the device will use device instance information from the factory partition. This option is visable only when ``CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER`` and ``ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER`` is selected. + + When selecting ``Device Instance Info - Custom``, the device will use custom defined Device Instance Info Provider to obtain the Device Instance Information. ``esp_matter::set_custom_device_instance_info_provider`` should be called before ``esp_matter::start()`` to set the custom provider. + +- ``Device Info Provider options`` in ``→ Component config → ESP Matter`` + + When selecting ``Device Info - None``, the device will not use any device information provider. It should be selected when there are not related clusters on the device. + + When selecting ``Device Info - Factory``, the device will use device information from the factory partition. This option is visable only when ``CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER`` and ``ENABLE_ESP32_DEVICE_INFO_PROVIDER`` is selected. + + When selecting ``Device Info - Custom``, the device will use custom defined Device Info Provider to obtain the Device Information. ``esp_matter::set_custom_device_info_provider`` should be called before ``esp_matter::start()`` to set the custom provider. + +2.5.3 Custom Providers +~~~~~~~~~~~~~~~~~~~~~~ + +In order to use custom providers, you need to define implementations of the four base classes of the providers and override the functions within them. And the custom providers should be set before ``esp_matter::start()`` is called. + +2.6 Using esp_secure_cert partition ----------------------------------- -2.5.1 Configuration Options +2.6.1 Configuration Options ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Build the firmware with below configuration options @@ -984,9 +1051,11 @@ Build the firmware with below configuration options # Enable some options which reads CD and other basic info from the factory partition CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER=y CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER=y + CONFIG_FACTORY_COMMISSIONABLE_DATA_PROVIDER=y + CONFIG_FACTORY_DEVICE_INSTANCE_INFO_PROVIDER=y -2.5.2 Certification Declaration +2.6.2 Certification Declaration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you do not have an certification declaration file then you can generate the test CD with the help of below mentioned steps. @@ -1012,7 +1081,7 @@ For more info about the arguments, please check `here