diff --git a/components/esp_matter/CMakeLists.txt b/components/esp_matter/CMakeLists.txt index 503a4ac8c..7de9e8b46 100644 --- a/components/esp_matter/CMakeLists.txt +++ b/components/esp_matter/CMakeLists.txt @@ -71,7 +71,7 @@ set(INCLUDE_DIRS_LIST "." "${MATTER_SDK_PATH}/src" "${ZAP_GENERATED_PATH}/../") -set(REQUIRES_LIST chip bt esp_matter_console nvs_flash app_update esp32_mbedtls esp_system route_hook) +set(REQUIRES_LIST chip bt esp_matter_console nvs_flash app_update esp_secure_cert_mgr esp32_mbedtls esp_system route_hook) if ("${IDF_TARGET}" STREQUAL "esp32h2") list(APPEND REQUIRES_LIST openthread esp_matter_openthread) diff --git a/components/esp_matter/Kconfig b/components/esp_matter/Kconfig index 91d143499..91f99e127 100644 --- a/components/esp_matter/Kconfig +++ b/components/esp_matter/Kconfig @@ -12,4 +12,28 @@ menu "ESP Matter" help The NVS Partition name for ESP Matter to store the NONVOLATILE attribues + choice ESP_MATTER_DAC_PROVIDER + prompt "DAC Provider options" + default EXAMPLE_DAC_PROVIDER + help + This option determines which attestation credentials provider will be used. + + config EXAMPLE_DAC_PROVIDER + bool "Attestation - Test" + help + An example DAC Provider which provides test attestation information + + config FACTORY_PARTITION_DAC_PROVIDER + depends on ENABLE_ESP32_FACTORY_DATA_PROVIDER + bool "Attestation - Factory" + help + An implementation which reads attestation information from the factory partition + + config SEC_CERT_DAC_PROVIDER + bool "Attestation - Secure Cert" + help + An implementation which reads attestation information from the esp_secure_cert partition + + endchoice + endmenu diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index a3e9c5d6e..ca4b056eb 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -41,6 +40,7 @@ #endif #include #include +#include using chip::CommandId; using chip::DataVersion; @@ -49,7 +49,6 @@ using chip::kInvalidCommandId; using chip::kInvalidClusterId; using chip::kInvalidEndpointId; using chip::Credentials::SetDeviceAttestationCredentialsProvider; -using chip::Credentials::Examples::GetExampleDACProvider; using chip::DeviceLayer::ChipDeviceEvent; using chip::DeviceLayer::ConfigurationMgr; using chip::DeviceLayer::ConnectivityManager; @@ -876,20 +875,15 @@ static esp_err_t chip_init(event_callback_t callback) return ESP_FAIL; } -/* TODO: Remove the examples DAC provider once we have a concrete - * way to generate attestation credentials. - */ - #if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER - SetDeviceAttestationCredentialsProvider(&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 -#else // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER - SetDeviceAttestationCredentialsProvider(GetExampleDACProvider()); #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER + SetDeviceAttestationCredentialsProvider(get_dac_provider()); + 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 new file mode 100644 index 000000000..a2db8ca19 --- /dev/null +++ b/components/esp_matter/esp_matter_dac_provider.cpp @@ -0,0 +1,160 @@ +// 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 + +#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) + { + ESP_LOGE(TAG, "esp_secure_cert_get_device_cert failed err:%u", err); + return CHIP_ERROR_INCORRECT_STATE; + } + + memcpy(outBuffer.data(), dac_cert, dac_len); + outBuffer.reduce_size(dac_len); + + return CHIP_NO_ERROR; + } + + 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) + { + ESP_LOGE(TAG, "esp_secure_cert_get_ca_cert failed err:%u", err); + return CHIP_ERROR_INCORRECT_STATE; + } + + memcpy(outBuffer.data(), pai_cert, pai_len); + outBuffer.reduce_size(pai_len); + + esp_secure_cert_free_priv_key(pai_cert); + + return CHIP_NO_ERROR; + } + + 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) + { + ESP_LOGE(TAG, "esp_secure_cert_get_priv_key failed err:%u", err); + return CHIP_ERROR_INCORRECT_STATE; + } + + CHIP_ERROR chipError = LoadKeypairFromRaw(ByteSpan(reinterpret_cast(sc_keypair + kPrivKeyOffset), kDACPrivateKeySize), + ByteSpan(reinterpret_cast(sc_keypair + kPubKeyOffset), kDACPublicKeySize), keypair); + SuccessOrExit(chipError); + + chipError = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature); + SuccessOrExit(chipError); + + chipError = CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); + + exit: + esp_secure_cert_free_priv_key(sc_keypair); + return chipError; + } +}; +} // 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 new file mode 100644 index 000000000..defe43ab5 --- /dev/null +++ b/components/esp_matter/esp_matter_dac_provider.h @@ -0,0 +1,35 @@ +// 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/idf_component.yml b/components/esp_matter/idf_component.yml new file mode 100644 index 000000000..4dfeb124b --- /dev/null +++ b/components/esp_matter/idf_component.yml @@ -0,0 +1,6 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/esp_secure_cert_mgr: "^2.0.4" + ## Required IDF version + idf: + version: ">=4.4.2" diff --git a/examples/light/partitions.csv b/examples/light/partitions.csv index f0215a98a..23795d153 100644 --- a/examples/light/partitions.csv +++ b/examples/light/partitions.csv @@ -1,7 +1,8 @@ # Name, Type, SubType, Offset, Size, Flags # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table -sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition +esp_secure_cert, 0x3F, ,0xd000, 0x2000, , # Never mark this as an encrypted partition nvs, data, nvs, 0x10000, 0x6000, +nvs_keys, data, nvs_keys,, 0x1000, otadata, data, ota, , 0x2000 phy_init, data, phy, , 0x1000, ota_0, app, ota_0, 0x20000, 0x1E0000, diff --git a/examples/light/partitions_h2.csv b/examples/light/partitions_h2.csv index 7d1b2a4f8..29f199567 100644 --- a/examples/light/partitions_h2.csv +++ b/examples/light/partitions_h2.csv @@ -1,7 +1,8 @@ # Name, Type, SubType, Offset, Size, Flags # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table -sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition +esp_secure_cert, 0x3F, ,0xd000, 0x2000, , # Never mark this as an encrypted partition nvs, data, nvs, 0x10000, 0x6000, +nvs_keys, data, nvs_keys, , 0x1000, phy_init, data, phy, , 0x1000, # Temporarily disable ota for ESP32-H2 because the use of flash need to be optimized. factory, app, factory, , 0x1C0000, diff --git a/examples/light/sdkconfig.defaults b/examples/light/sdkconfig.defaults index b9e7c2afa..343834af3 100644 --- a/examples/light/sdkconfig.defaults +++ b/examples/light/sdkconfig.defaults @@ -16,6 +16,7 @@ CONFIG_LWIP_IPV6_AUTOCONFIG=y # Use a custom partition table CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0xC000 # Enable chip shell CONFIG_ENABLE_CHIP_SHELL=y @@ -30,3 +31,6 @@ CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000 # disable softap by default CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n + +# Disable DS Peripheral +# CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL is not set diff --git a/examples/light_switch/partitions.csv b/examples/light_switch/partitions.csv index f0215a98a..23795d153 100644 --- a/examples/light_switch/partitions.csv +++ b/examples/light_switch/partitions.csv @@ -1,7 +1,8 @@ # Name, Type, SubType, Offset, Size, Flags # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table -sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition +esp_secure_cert, 0x3F, ,0xd000, 0x2000, , # Never mark this as an encrypted partition nvs, data, nvs, 0x10000, 0x6000, +nvs_keys, data, nvs_keys,, 0x1000, otadata, data, ota, , 0x2000 phy_init, data, phy, , 0x1000, ota_0, app, ota_0, 0x20000, 0x1E0000, diff --git a/examples/light_switch/partitions_h2.csv b/examples/light_switch/partitions_h2.csv index 7d1b2a4f8..29f199567 100644 --- a/examples/light_switch/partitions_h2.csv +++ b/examples/light_switch/partitions_h2.csv @@ -1,7 +1,8 @@ # Name, Type, SubType, Offset, Size, Flags # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table -sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition +esp_secure_cert, 0x3F, ,0xd000, 0x2000, , # Never mark this as an encrypted partition nvs, data, nvs, 0x10000, 0x6000, +nvs_keys, data, nvs_keys, , 0x1000, phy_init, data, phy, , 0x1000, # Temporarily disable ota for ESP32-H2 because the use of flash need to be optimized. factory, app, factory, , 0x1C0000, diff --git a/examples/light_switch/sdkconfig.defaults b/examples/light_switch/sdkconfig.defaults index 4ffcc80ce..c1f860434 100644 --- a/examples/light_switch/sdkconfig.defaults +++ b/examples/light_switch/sdkconfig.defaults @@ -16,6 +16,7 @@ CONFIG_LWIP_IPV6_AUTOCONFIG=y # Use a custom partition table CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0xC000 # Testing Options CONFIG_USE_TEST_SETUP_PIN_CODE=20212020 @@ -34,3 +35,6 @@ CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000 # disable softap by default CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n + +# Disable DS Peripheral +# CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL is not set