Merge branch 'secure_cert_data_provider' into 'main'

components/esp-matter: config option for setting secure cert providers

See merge request app-frameworks/esp-matter!912
This commit is contained in:
Hrishikesh Dhayagude
2025-08-29 14:31:22 +08:00
13 changed files with 632 additions and 50 deletions
+3 -1
View File
@@ -112,7 +112,9 @@ variables:
- rm -rf ${ESP_MATTER_PATH}/../platform
- mkdir -p ${ESP_MATTER_PATH}/../platform
- cp -r ${CHIP_SUBMODULE_PATH}/src/platform/ESP32 $ESP_MATTER_PATH/../platform/ESP32_custom
- cp ${ESP_MATTER_PATH}/examples/common/external_platform/BUILD.gn $ESP_MATTER_PATH/../platform/ESP32_custom
# We have modified the ESP32SecureCertDataProvider.h file to include the ESP32FactoryDataProvider.h
# So copying all files from the external_platform directory.
- cp ${ESP_MATTER_PATH}/examples/common/external_platform/* $ESP_MATTER_PATH/../platform/ESP32_custom/
- cd ${ESP_MATTER_PATH}/examples/light
- cp sdkconfig.defaults sdkconfig.defaults.backup
- cp sdkconfig.defaults.ext_plat_ci sdkconfig.defaults
+11
View File
@@ -76,6 +76,11 @@ menu "ESP Matter"
help
An implementation which reads commissionable data information from the factory partition
config SEC_CERT_COMMISSIONABLE_DATA_PROVIDER
bool "Commissionable Data - Secure Cert"
help
An implementation which reads commissionable data information from the esp_secure_cert partition
config CUSTOM_COMMISSIONABLE_DATA_PROVIDER
bool "Commissionable Data - Custom"
help
@@ -101,6 +106,12 @@ menu "ESP Matter"
help
An implementation which reads device instance information from the factory partition
config SEC_CERT_DEVICE_INSTANCE_INFO_PROVIDER
bool "Device Instance Info - Secure Cert"
help
An implementation which reads unique id for generating rotating device identifier from
secure cert partition and all other device instance data from factory partition
config CUSTOM_DEVICE_INSTANCE_INFO_PROVIDER
bool "Device Instance Info - Custom"
help
+71 -33
View File
@@ -1,4 +1,4 @@
// Copyright 2023 Espressif Systems (Shanghai) PTE LTD
// Copyright 2023-2025 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.
@@ -15,23 +15,36 @@
#include <credentials/examples/DeviceAttestationCredsExample.h>
#include <esp_log.h>
#include <esp_matter_providers.h>
#ifdef CONFIG_CHIP_ENABLE_EXTERNAL_PLATFORM
#ifndef EXTERNAL_ESP32DEVICEINFOPROVIDER_HEADER
#error "Please define EXTERNAL_ESP32DEVICEINFOPROVIDER_HEADER in your external platform gn/cmake file"
#endif // !EXTERNAL_ESP32DEVICEINFOPROVIDER_HEADER
#ifndef EXTERNAL_ESP32FACTORYDATAPROVIDER_HEADER
#error "Please define EXTERNAL_ESP32FACTORYDATAPROVIDER_HEADER in your external platform gn/cmake file"
#endif // !EXTERNAL_ESP32FACTORYDATAPROVIDER_HEADER
#ifndef EXTERNAL_ESP32SECURECERTDACPROVIDER_HEADER
#error "Please define EXTERNAL_ESP32SECURECERTDACPROVIDER_HEADER in your external platform gn/cmake file"
#endif // !EXTERNAL_ESP32DEVICEINFOPROVIDER_HEADER
#ifndef EXTERNAL_ESP32SECURECERTDATAPROVIDER_HEADER
#error "Please define EXTERNAL_ESP32SECURECERTDATAPROVIDER_HEADER in your external platform gn/cmake file"
#endif // !EXTERNAL_ESP32SECURECERTDATAPROVIDER_HEADER
#include EXTERNAL_ESP32DEVICEINFOPROVIDER_HEADER
#include EXTERNAL_ESP32FACTORYDATAPROVIDER_HEADER
#include EXTERNAL_ESP32SECURECERTDACPROVIDER_HEADER
#include EXTERNAL_ESP32SECURECERTDATAPROVIDER_HEADER
#else // CONFIG_CHIP_ENABLE_EXTERNAL_PLATFORM
#include <platform/ESP32/ESP32DeviceInfoProvider.h>
#include <platform/ESP32/ESP32FactoryDataProvider.h>
#include <platform/ESP32/ESP32SecureCertDACProvider.h>
#include <platform/ESP32/ESP32SecureCertDataProvider.h>
#endif // !CONFIG_CHIP_ENABLE_EXTERNAL_PLATFORM
using namespace chip::DeviceLayer;
@@ -53,41 +66,41 @@ static ESP32DeviceInfoProvider device_info_provider;
static ESP32SecureCertDACProvider sec_cert_dac_provider;
#endif // CONFIG_SEC_CERT_DAC_PROVIDER
#if defined(CONFIG_SEC_CERT_COMMISSIONABLE_DATA_PROVIDER) || defined(CONFIG_SEC_CERT_DEVICE_INSTANCE_INFO_PROVIDER)
static ESP32SecureCertDataProvider secure_cert_data_provider;
#endif // CONFIG_SEC_CERT_COMMISSIONABLE_DATA_PROVIDER || CONFIG_SEC_CERT_DEVICE_INSTANCE_INFO_PROVIDER
#ifdef CONFIG_CUSTOM_DAC_PROVIDER
static DeviceAttestationCredentialsProvider *s_custom_dac_provider = NULL;
void set_custom_dac_provider(DeviceAttestationCredentialsProvider *provider)
{
s_custom_dac_provider = provider;
}
#endif
#endif // CONFIG_CUSTOM_DAC_PROVIDER
#ifdef 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
#endif // CONFIG_CUSTOM_COMMISSIONABLE_DATA_PROVIDER
#ifdef 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
#endif // CONFIG_CUSTOM_DEVICE_INSTANCE_INFO_PROVIDER
#ifdef 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
#endif // CONFIG_CUSTOM_DEVICE_INFO_PROVIDER
DeviceAttestationCredentialsProvider *get_dac_provider(void)
{
@@ -107,40 +120,65 @@ DeviceAttestationCredentialsProvider *get_dac_provider(void)
return NULL;
}
void setup_providers()
// helper function to set the commissionable data provider based on the config option
static void set_commissionable_data_provider(void)
{
CommissionableDataProvider *provider = NULL;
#ifdef CONFIG_FACTORY_COMMISSIONABLE_DATA_PROVIDER
SetCommissionableDataProvider(&factory_data_provider);
#endif // CONFIG_FACTORY_COMMISSIONABLE_DATA_PROVIDER
#ifdef CONFIG_CUSTOM_COMMISSIONABLE_DATA_PROVIDER
if (s_custom_commissionable_data_provider) {
SetCommissionableDataProvider(s_custom_commissionable_data_provider);
}
#endif // CONFIG_CUSTOM_COMMISSIONABLE_DATA_PROVIDER
provider = &factory_data_provider;
#elif defined(CONFIG_SEC_CERT_COMMISSIONABLE_DATA_PROVIDER)
provider = &secure_cert_data_provider;
#elif defined(CONFIG_CUSTOM_COMMISSIONABLE_DATA_PROVIDER)
provider = s_custom_commissionable_data_provider;
#endif
// We should do nothing if CONFIG_EXAMPLE_COMMISSIONABLE_DATA_PROVIDER is enabled as
// LegacyTemporaryCommissionableDataProvider is set in GenericConfigurationManagerImpl<ConfigClass>::Init()
#ifdef CONFIG_FACTORY_DEVICE_INSTANCE_INFO_PROVIDER
SetDeviceInstanceInfoProvider(&factory_data_provider);
#endif // CONFIG_FACTORY_DEVICE_INSTANCE_INFO_PROVIDER
#ifdef CONFIG_CUSTOM_DEVICE_INSTANCE_INFO_PROVIDER
if (s_custom_device_instance_info_provider) {
SetDeviceInstanceInfoProvider(s_custom_device_instance_info_provider);
if (provider) {
SetCommissionableDataProvider(provider);
}
}
// helper function to set the device instance info provider based on the config option
static void set_device_instance_info_provider(void)
{
DeviceInstanceInfoProvider *provider = NULL;
#ifdef CONFIG_FACTORY_DEVICE_INSTANCE_INFO_PROVIDER
provider = &factory_data_provider;
#elif defined(CONFIG_SEC_CERT_DEVICE_INSTANCE_INFO_PROVIDER)
provider = &secure_cert_data_provider;
#elif defined(CONFIG_CUSTOM_DEVICE_INSTANCE_INFO_PROVIDER)
provider = 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<ConfigClass>::Init()
#ifdef CONFIG_FACTORY_DEVICE_INFO_PROVIDER
SetDeviceInfoProvider(&device_info_provider);
#endif // CONFIG_FACTORY_DEVICE_INFO_PROVIDER
#ifdef CONFIG_CUSTOM_DEVICE_INFO_PROVIDER
if (s_custom_device_info_provider) {
SetDeviceInfoProvider(s_custom_device_info_provider);
if (provider) {
SetDeviceInstanceInfoProvider(provider);
}
}
// helper function to set the device info provider based on the config option
static void set_device_info_provider(void)
{
DeviceInfoProvider *provider = NULL;
#ifdef CONFIG_FACTORY_DEVICE_INFO_PROVIDER
provider = &device_info_provider;
#elif defined(CONFIG_CUSTOM_DEVICE_INFO_PROVIDER)
provider = s_custom_device_info_provider;
#endif
if (provider) {
SetDeviceInfoProvider(provider);
}
}
void setup_providers()
{
set_commissionable_data_provider();
set_device_instance_info_provider();
set_device_info_provider();
SetDeviceAttestationCredentialsProvider(get_dac_provider());
}
} // namespace esp_matter
} // namespace esp_matter
+47 -16
View File
@@ -1071,40 +1071,71 @@ 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. This uses the legacy commissionable data
provider and provides the test values. These test values are enclosed in ``CONFIG_ENABLE_TEST_SETUP_PARAMS`` option and enabled by default.
- ``Commissionable Data - Test``, the device will use the hardcoded Commissionable Data.
This uses the legacy commissionable data provider and provides the test values.
These test values are enclosed in ``CONFIG_ENABLE_TEST_SETUP_PARAMS`` option and enabled by default.
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.
- ``Commissionable Data - Factory``, the device will use commissionable data information from the factory
partition.This option is visible 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.
- ``Commissionable Data - Secure Cert``, the device will use commissionable data information from the secure cert
partition. This option is only visible when ``CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER`` and
``CONFIG_SEC_CERT_DAC_PROVIDER`` is enabled.
If you are using ``Factory`` or ``Custom`` commissionable data provides, then disable the ``CONFIG_ENABLE_TEST_SETUP_PARAMS`` option.
- ``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.
.. note::
If you are using ``Factory``, ``Secure Cert`` or ``Custom`` commissionable data provides, then disable the ``CONFIG_ENABLE_TEST_SETUP_PARAMS`` option.
- ``DAC Provider options`` in ``→ Component config → ESP Matter``
When selecting ``Attestation - Test``, the device will use the hardcoded Device Attestation Credentials.
- ``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.
- ``Attestation - Factory``, the device will use the Device Attestation Credentials in the factory partition
binary. This option is visible 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.
- ``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.
- ``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.
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.
- ``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.
- ``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 Instance Info - Secure Cert``, the device will use the unique identifier for generating the rotating
device identifier from the secure cert partition and all other details will be read from the factory partition.
This option is only visible when ``CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER`` and
``CONFIG_SEC_CERT_DAC_PROVIDER`` is enabled.
- ``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.
- ``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.
- ``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.
- ``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.6.3 Custom Providers
~~~~~~~~~~~~~~~~~~~~~~
@@ -1175,7 +1206,7 @@ Factory partition contains basic information like VID, PID, etc.
By default, the CD(Certification Declaration) is stored in the factory partition and we need to add the ``-cd`` option when generating the factory partition.
Alternatively, if youd like to embed the CD in the firmware, you can enable the
Alternatively, if you'd like to embed the CD in the firmware, you can enable the
``CONFIG_ENABLE_SET_CERT_DECLARATION_API`` option and use the ``SetCertificationDeclaration()`` API to set the CD.
You can refer to the reference implementation in :project_file: `light example <https://github.com/espressif/esp-matter/tree/main/examples/light>`__.
+36
View File
@@ -176,3 +176,39 @@ This is the example to generate factory images after pre-provisioning:
.. _`esp-matter-mfg-tool`: https://github.com/espressif/esp-matter-tools/tree/main/mfg_tool
.. _`ESP RainMaker OTA`: https://rainmaker.espressif.com/docs/ota.html
4.3.4 Recommended Providers to Use
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. note::
WARNING: These options are not recommended for devices that are already in field
or modules that reads data from the factory partition or some other source.
We recommend using the following providers:
- Commissionable data provider: secure cert
- Device attestation data provider: secure cert
- Device instance info provider: secure cert
Below are the configuration options that should be enabled.
These can be appended to ``sdkconfig.defaults``.
In the following example, we demonstrate a different approach that places the configurations in a separate file,
which is then used with the ``idf.py build`` command.
.. code-block:: bash
cat > sdkconfig.defaults.prod <<EOF
# Enable the implementations in the connectedhomeip repo
CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER=y
CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER=y
# Set the appropriate providers
CONFIG_SEC_CERT_DAC_PROVIDER=y
CONFIG_SEC_CERT_COMMISSIONABLE_DATA_PROVIDER=y
CONFIG_SEC_CERT_DEVICE_INSTANCE_INFO_PROVIDER=y
CONFIG_NONE_DEVICE_INFO_PROVIDER=y
EOF
idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults.prod" set-target esp32c3 build
@@ -87,6 +87,7 @@ buildconfig_header("custom_buildconfig") {
"EXTERNAL_ESP32DEVICEINFOPROVIDER_HEADER=<platform/ESP32_custom/ESP32DeviceInfoProvider.h>",
"EXTERNAL_ESP32FACTORYDATAPROVIDER_HEADER=<platform/ESP32_custom/ESP32FactoryDataProvider.h>",
"EXTERNAL_ESP32SECURECERTDACPROVIDER_HEADER=<platform/ESP32_custom/ESP32SecureCertDACProvider.h>",
"EXTERNAL_ESP32SECURECERTDATAPROVIDER_HEADER=<platform/ESP32_custom/ESP32SecureCertDataProvider.h>",
"CHIP_CONFIG_SOFTWARE_VERSION_NUMBER=${chip_config_software_version_number}",
"CHIP_DEVICE_CONFIG_MAX_DISCOVERED_IP_ADDRESSES=${chip_max_discovered_ip_addresses}",
]
@@ -0,0 +1 @@
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32SecureCertDataProvider.cpp
@@ -0,0 +1,62 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
*
* 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.
*/
/*
* ESP32FactoryDataProvider reads the commissionable data and device instance information from the factory partition.
* This implementation extends that behaviour to read the commissionable data from secure cert partition.
* It also extends the behaviour to read the unique id for generating rotating device identifier from the secure cert
* partition.
*
*/
#pragma once
#include <lib/core/CHIPError.h>
#include <lib/support/Span.h>
// original file includes from ESP32 directory and hence it won't be able to find the ESP32FactoryDataProvider.h
// so switching to the external_platform directory, till the connectedhomeip repo switches to quoted includes.
#include "ESP32FactoryDataProvider.h"
#include <esp_secure_cert_tlv_config.h>
namespace chip {
namespace DeviceLayer {
class ESP32SecureCertDataProvider : public ESP32FactoryDataProvider
{
public:
// CommissionableDataProvider implementation
CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
// GetRotatingDeviceIdUniqueId from GenericDeviceInstanceInfoProvider
CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
// esp-secure-cert partition contains two 32-byte fixed random values that are set during manufacturing
// and remain constant for the lifetime of the device. These are unique per device and can be used
// for device identification, serial numbers, or any other purpose requiring a device-specific identifier.
static constexpr uint32_t kFixedRandomValueLength = 32;
static CHIP_ERROR GetFixedRandom1(MutableByteSpan & randomBuf);
static CHIP_ERROR GetFixedRandom2(MutableByteSpan & randomBuf);
};
} // namespace DeviceLayer
} // namespace chip
@@ -82,6 +82,7 @@ buildconfig_header("custom_buildconfig") {
"EXTERNAL_ESP32DEVICEINFOPROVIDER_HEADER=<platform/ESP32_custom/ESP32DeviceInfoProvider.h>",
"EXTERNAL_ESP32FACTORYDATAPROVIDER_HEADER=<platform/ESP32_custom/ESP32FactoryDataProvider.h>",
"EXTERNAL_ESP32SECURECERTDACPROVIDER_HEADER=<platform/ESP32_custom/ESP32SecureCertDACProvider.h>",
"EXTERNAL_ESP32SECURECERTDATAPROVIDER_HEADER=<platform/ESP32_custom/ESP32SecureCertDataProvider.h>",
"CHIP_CONFIG_SOFTWARE_VERSION_NUMBER=${chip_config_software_version_number}",
"CHIP_DEVICE_CONFIG_MAX_DISCOVERED_IP_ADDRESSES=${chip_max_discovered_ip_addresses}",
]
@@ -0,0 +1,62 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
*
* 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.
*/
/*
* ESP32FactoryDataProvider reads the commissionable data and device instance information from the factory partition.
* This implementation extends that behaviour to read the commissionable data from secure cert partition.
* It also extends the behaviour to read the unique id for generating rotating device identifier from the secure cert
* partition.
*
*/
#pragma once
#include <lib/core/CHIPError.h>
#include <lib/support/Span.h>
// original file includes from ESP32 directory and hence it won't be able to find the ESP32FactoryDataProvider.h
// so switching to the external_platform directory, till the connectedhomeip repo switches to quoted includes.
#include "ESP32FactoryDataProvider.h"
#include <esp_secure_cert_tlv_config.h>
namespace chip {
namespace DeviceLayer {
class ESP32SecureCertDataProvider : public ESP32FactoryDataProvider
{
public:
// CommissionableDataProvider implementation
CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
// GetRotatingDeviceIdUniqueId from GenericDeviceInstanceInfoProvider
CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
// esp-secure-cert partition contains two 32-byte fixed random values that are set during manufacturing
// and remain constant for the lifetime of the device. These are unique per device and can be used
// for device identification, serial numbers, or any other purpose requiring a device-specific identifier.
static constexpr uint32_t kFixedRandomValueLength = 32;
static CHIP_ERROR GetFixedRandom1(MutableByteSpan & randomBuf);
static CHIP_ERROR GetFixedRandom2(MutableByteSpan & randomBuf);
};
} // namespace DeviceLayer
} // namespace chip
@@ -0,0 +1,188 @@
/*
*
* Copyright (c) 2025 Project CHIP Authors
*
* 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 <crypto/CHIPCryptoPAL.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ConfigurationManager.h>
#include <platform/ESP32/ESP32Config.h>
#include <platform/internal/GenericDeviceInstanceInfoProvider.h>
#include <ESP32ManufacturingDataProvider.h>
namespace chip {
namespace DeviceLayer {
const char * ESP32ManufacturingDataProvider::PrecedenceToString(Precedence precedence)
{
switch (precedence)
{
case Precedence::kFactoryFirst:
return "FactoryFirst";
case Precedence::kSecureCertFirst:
return "SecureCertFirst";
default:
return "Unknown";
}
}
ESP32ManufacturingDataProvider::ESP32ManufacturingDataProvider(Precedence precedence)
: CommissionableDataProvider()
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
, Internal::GenericDeviceInstanceInfoProvider<Internal::ESP32Config>(ConfigurationManagerImpl::GetDefaultInstance())
#endif
, mPrecedence(precedence)
{
// check data integrity of both factory and secure cert data, we should have at least one valid data provider
mFactoryDataValid = CheckFactoryDataIntegrity();
mSecureCertDataValid = CheckSecureCertDataIntegrity();
// should we really die here? can the non-Matter functionality still work?
VerifyOrReturn(mFactoryDataValid || mSecureCertDataValid,
ChipLogError(DeviceLayer, "No valid data found in factory or secure cert partition"));
SetProvidersAsPerPrecedence();
ChipLogDetail(DeviceLayer, "ESP32ManufacturingDataProvider initialized with precedence:%s",
PrecedenceToString(precedence));
}
ESP32ManufacturingDataProvider::Precedence ESP32ManufacturingDataProvider::GetPrecedence() const
{
return mPrecedence;
}
// check if the factory has valid data, if not, return false
bool ESP32ManufacturingDataProvider::CheckFactoryDataIntegrity()
{
uint16_t setupDiscriminator;
uint32_t iterationCount;
uint8_t saltBuf[chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length];
uint8_t verifierBuf[chip::Crypto::kSpake2p_VerifierSerialized_Length];
uint8_t uniqueIdSpan[ConfigurationManager::kRotatingDeviceIDUniqueIDLength];
MutableByteSpan salt(saltBuf);
MutableByteSpan verifier(verifierBuf);
size_t verifierLen;
MutableByteSpan uniqueId(uniqueIdSpan);
VerifyOrReturnValue(mPrecedence == Precedence::kFactoryFirst, false);
VerifyOrReturnValue(mFactoryDataProvider.GetSetupDiscriminator(setupDiscriminator) == CHIP_NO_ERROR, false);
VerifyOrReturnValue(mFactoryDataProvider.GetSpake2pIterationCount(iterationCount) == CHIP_NO_ERROR, false);
VerifyOrReturnValue(mFactoryDataProvider.GetSpake2pSalt(salt) == CHIP_NO_ERROR, false);
VerifyOrReturnValue(mFactoryDataProvider.GetSpake2pVerifier(verifier, verifierLen) == CHIP_NO_ERROR, false);
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID
VerifyOrReturnValue(mFactoryDataProvider.GetRotatingDeviceIdUniqueId(uniqueId) == CHIP_NO_ERROR, false);
#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID
return true;
}
// check if the secure cert has valid data, if not, return false
bool ESP32ManufacturingDataProvider::CheckSecureCertDataIntegrity()
{
uint16_t setupDiscriminator;
uint32_t iterationCount;
uint8_t saltBuf[chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length];
uint8_t verifierBuf[chip::Crypto::kSpake2p_VerifierSerialized_Length];
uint8_t uniqueIdSpan[ConfigurationManager::kRotatingDeviceIDUniqueIDLength];
MutableByteSpan salt(saltBuf);
MutableByteSpan verifier(verifierBuf);
size_t verifierLen;
MutableByteSpan uniqueId(uniqueIdSpan);
VerifyOrReturnValue(mSecureCertDataProvider.GetSetupDiscriminator(setupDiscriminator) == CHIP_NO_ERROR, false);
VerifyOrReturnValue(mSecureCertDataProvider.GetSpake2pIterationCount(iterationCount) == CHIP_NO_ERROR, false);
VerifyOrReturnValue(mSecureCertDataProvider.GetSpake2pSalt(salt) == CHIP_NO_ERROR, false);
VerifyOrReturnValue(mSecureCertDataProvider.GetSpake2pVerifier(verifier, verifierLen) == CHIP_NO_ERROR, false);
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID
VerifyOrReturnValue(mSecureCertDataProvider.GetRotatingDeviceIdUniqueId(uniqueId) == CHIP_NO_ERROR, false);
#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID
return true;
}
CHIP_ERROR ESP32ManufacturingDataProvider::SetProvidersAsPerPrecedence()
{
bool useFactoryData = false;
// we performed CheckFactoryDataIntegrity() and CheckSecureCertDataIntegrity() in constructor,
// so we can use the result here
switch (mPrecedence)
{
case Precedence::kFactoryFirst:
{
useFactoryData = mFactoryDataValid;
break;
}
case Precedence::kSecureCertFirst:
{
useFactoryData = !mSecureCertDataValid;
break;
}
default:
{
ChipLogError(DeviceLayer, "Invalid precedence");
return CHIP_ERROR_INVALID_ARGUMENT;
}
}
ChipLogProgress(DeviceLayer, "Using commissionable and device instance info providers from %s",
useFactoryData ? "factory" : "secure cert");
mCommissionableDataProvider = useFactoryData ? &mFactoryDataProvider : &mSecureCertDataProvider;
mDeviceInstanceInfoProvider = useFactoryData ? &mFactoryDataProvider : &mSecureCertDataProvider;
return CHIP_NO_ERROR;
}
CHIP_ERROR ESP32ManufacturingDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator)
{
return mCommissionableDataProvider->GetSetupDiscriminator(setupDiscriminator);
}
CHIP_ERROR ESP32ManufacturingDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount)
{
return mCommissionableDataProvider->GetSpake2pIterationCount(iterationCount);
}
CHIP_ERROR ESP32ManufacturingDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf)
{
return mCommissionableDataProvider->GetSpake2pSalt(saltBuf);
}
CHIP_ERROR ESP32ManufacturingDataProvider::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen)
{
return mCommissionableDataProvider->GetSpake2pVerifier(verifierBuf, verifierLen);
}
CHIP_ERROR ESP32ManufacturingDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan)
{
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID
return mDeviceInstanceInfoProvider->GetRotatingDeviceIdUniqueId(uniqueIdSpan);
#else
return CHIP_ERROR_NOT_IMPLEMENTED;
#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID
}
} // namespace DeviceLayer
} // namespace chip
@@ -0,0 +1,94 @@
/*
*
* Copyright (c) 2025 Project CHIP Authors
*
* 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 <platform/CommissionableDataProvider.h>
#include <platform/internal/GenericDeviceInstanceInfoProvider.h>
#include <platform/ESP32/ESP32FactoryDataProvider.h>
#include <platform/ESP32/ESP32SecureCertDataProvider.h>
namespace chip {
namespace DeviceLayer {
// This implementation is a wrapper around the factory and secure cert data providers
// It facilitates users to choose the precedence of the data that should be used.
// eg: First batch of modules were manufactured with unique data in the factory partition
// and the second batch of modules were manufactured with unique data in the secure cert partition
// This helps users to keep the backward compatibility with the existing code
// by falling back to the different set of data.
class ESP32ManufacturingDataProvider : public CommissionableDataProvider
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
, public Internal::GenericDeviceInstanceInfoProvider<Internal::ESP32Config>
#endif
{
public:
enum class Precedence : uint8_t
{
// Data is expected to be found in the factory partition first, if not
// fallback to the secure cert partition
kFactoryFirst,
// Data is expected to be found in the secure cert partition first, if not
// fallback to the factory partition
kSecureCertFirst
};
static const char * PrecedenceToString(Precedence precedence);
// Default precedence is FactoryFirst
ESP32ManufacturingDataProvider(Precedence precedence = Precedence::kFactoryFirst);
// Get the precedence of the data provider
Precedence GetPrecedence() const;
// CommissionableDataProvider implementation
CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
// not supported APIs but required to be implemented
CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override { return CHIP_ERROR_NOT_IMPLEMENTED; }
CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override { return CHIP_ERROR_NOT_IMPLEMENTED; }
CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override { return CHIP_ERROR_NOT_IMPLEMENTED; }
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
// DeviceInstanceInfoProvider implementation
CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
private:
Precedence mPrecedence;
bool mFactoryDataValid = false;
bool mSecureCertDataValid = false;
CommissionableDataProvider * mCommissionableDataProvider = nullptr;
DeviceInstanceInfoProvider * mDeviceInstanceInfoProvider = nullptr;
ESP32FactoryDataProvider mFactoryDataProvider;
ESP32SecureCertDataProvider mSecureCertDataProvider;
// Helper method to update provider pointers based on precedence
CHIP_ERROR SetProvidersAsPerPrecedence();
bool CheckFactoryDataIntegrity();
bool CheckSecureCertDataIntegrity();
};
} // namespace DeviceLayer
} // namespace chip
@@ -0,0 +1,55 @@
# ESP32 Manufacturing Data Provider
#### Overview
The ESP32ManufacturingDataProvider is a unified wrapper around ESP32's Factory Data Provider and Secure Cert Data Provider. It provides a flexible fallback mechanism for accessing manufacturing data from either the factory partition or the secure cert partition based on configurable precedence rules.
Example: Modules manufactured have data in the factory partition for manufacturing data, but now we are migrating to store the manufacturing data in the secure cert partition. We want to support both approaches in the same codebase.
#### How to use in your project
```cpp
#include <ESP32ManufacturingDataProvider.h>
{
// Create provider with default precedence (FactoryFirst)
// This checks the data in the factory partition first, and if it's not valid,
// it will check the data in the secure cert partition.
static chip::DeviceLayer::ESP32ManufacturingDataProvider provider;
// Set as the commissionable data provider using esp_matter functions
// Must be called before esp_matter::start()
set_custom_commissionable_data_provider(&provider);
set_custom_device_instance_info_provider(&provider);
}
```
NOTE: Please make sure that the `examples/common/manufacturing_data_provider` is added as the
source directory and include path in the `CMakeLists.txt` of the project.
#### How to change the precedence
Default precedence is `FactoryFirst`, so if you want to change it to `SecureCertFirst`, you can do so by passing the
precedence to the constructor.
```cpp
{
using namespace chip::DeviceLayer;
static ESP32ManufacturingDataProvider provider(ESP32ManufacturingDataProvider::Precedence::SecureCertFirst);
// Set as the commissionable data provider using esp_matter functions
// Must be called before esp_matter::start()
set_custom_commissionable_data_provider(&provider);
set_custom_device_instance_info_provider(&provider);
}
```
#### Configuration Requirements
Ensure both underlying providers are available by enabling these configs:
```
CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER=y
CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER=y
CONFIG_SEC_CERT_DAC_PROVIDER=y
```