diff --git a/config/nrfconnect/chip-module/Kconfig b/config/nrfconnect/chip-module/Kconfig
index b664bfa867..ba726adab2 100644
--- a/config/nrfconnect/chip-module/Kconfig
+++ b/config/nrfconnect/chip-module/Kconfig
@@ -206,6 +206,11 @@ choice CHIP_FACTORY_DATA_CERT_SOURCE
endchoice
+config CHIP_FACTORY_DATA_GENERATE_CD
+ bool "Generates Certification Declaration to the output build directory"
+ help
+ Generates the new Certification Declaration and stores it to the output build directory.
+
if CHIP_FACTORY_DATA_CERT_SOURCE_USER
config CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT
@@ -230,6 +235,7 @@ endif # CHIP_FACTORY_DATA_CERT_SOURCE_USER
# Configs for SPAKE2+ generation
config CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER
bool "Generate SPAKE2+ verifier"
+ default y
help
Enables the generation of the SPAKE2+ verifier for the configured SPAKE2+
passcode, iteration count and salt.
diff --git a/config/nrfconnect/chip-module/generate_factory_data.cmake b/config/nrfconnect/chip-module/generate_factory_data.cmake
index dc1794562d..3c286fc21d 100644
--- a/config/nrfconnect/chip-module/generate_factory_data.cmake
+++ b/config/nrfconnect/chip-module/generate_factory_data.cmake
@@ -48,14 +48,25 @@ string(APPEND script_args "--hw_ver ${CONFIG_CHIP_DEVICE_HARDWARE_VERSION}\n")
string(APPEND script_args "--hw_ver_str \"${CONFIG_CHIP_DEVICE_HARDWARE_VERSION_STRING}\"\n")
# check if Rotating Device Id Unique Id should be generated
-if(NOT CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID)
- if(NOT DEFINED CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID)
- message(FATAL_ERROR "CHIP_DEVICE_ROTATING_DEVICE_UID was not provided. To generate it use CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID=y")
+if(CONFIG_CHIP_ROTATING_DEVICE_ID)
+ if(NOT CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID)
+ if(NOT DEFINED CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID)
+ message(FATAL_ERROR "CHIP_DEVICE_ROTATING_DEVICE_UID was not provided. To generate it use CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID=y")
+ else()
+ string(APPEND script_args "--rd_uid \"${CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID}\"\n")
+ endif()
else()
- string(APPEND script_args "--rd_uid \"${CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID}\"\n")
+ string(APPEND script_args "--generate_rd_uid\n")
endif()
-else()
- string(APPEND script_args "--generate_rd_uid\n")
+endif()
+
+if(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED OR CONFIG_CHIP_FACTORY_DATA_GENERATE_CD)
+ find_program(chip_cert_exe NAMES chip-cert REQUIRED)
+ string(APPEND script_args "--chip_cert_path ${chip_cert_exe}\n")
+endif()
+
+if(CONFIG_CHIP_FACTORY_DATA_GENERATE_CD)
+ string(APPEND script_args "--gen_cd\n")
endif()
# for development purpose user can use default certs instead of generating or providing them
@@ -77,10 +88,8 @@ elseif(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_USER)
string(APPEND script_args "--dac_cert \"${CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT}\"\n")
string(APPEND script_args "--dac_key \"${CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_KEY}\"\n")
string(APPEND script_args "--pai_cert \"${CONFIG_CHIP_FACTORY_DATA_USER_CERTS_PAI_CERT}\"\n")
-else()
- find_program(chip_cert_exe NAMES chip-cert REQUIRED)
- string(APPEND script_args "--gen_cd\n")
- string(APPEND script_args "--chip_cert_path ${chip_cert_exe}\n")
+elseif(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED)
+ string(APPEND script_args "--gen_certs\n")
endif()
# add Password-Authenticated Key Exchange parameters
@@ -90,8 +99,14 @@ string(APPEND script_args "--discriminator ${CONFIG_CHIP_DEVICE_DISCRIMINATOR}\n
string(APPEND script_args "--passcode ${CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE}\n")
string(APPEND script_args "--include_passcode\n")
string(APPEND script_args "--overwrite\n")
-string(APPEND script_args "--product_finish ${CONFIG_CHIP_DEVICE_PRODUCT_FINISH}\n")
+# check if spake2 verifier should be generated using script
+if(NOT CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER)
+ # Spake2 verifier should be provided using kConfig
+ string(APPEND script_args "--spake2_verifier \"${CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER}\"\n")
+endif()
+# Product appearance
+string(APPEND script_args "--product_finish ${CONFIG_CHIP_DEVICE_PRODUCT_FINISH}\n")
if(CONFIG_CHIP_DEVICE_PRODUCT_COLOR)
string(APPEND script_args "--product_color ${CONFIG_CHIP_DEVICE_PRODUCT_COLOR}\n")
endif()
@@ -100,12 +115,6 @@ if(CONFIG_CHIP_FACTORY_DATA_GENERATE_ONBOARDING_CODES)
string(APPEND script_args "--generate_onboarding\n")
endif()
-# check if spake2 verifier should be generated using script
-if(NOT CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER)
- # Spake2 verifier should be provided using kConfig
- string(APPEND script_args "--spake2_verifier \"${CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER}\"\n")
-endif()
-
if(CONFIG_CHIP_DEVICE_ENABLE_KEY)
# Add optional EnableKey that triggers user-specific action.
string(APPEND script_args "--enable_key \"${CONFIG_CHIP_DEVICE_ENABLE_KEY}\"\n")
diff --git a/docs/guides/nrfconnect_factory_data_configuration.md b/docs/guides/nrfconnect_factory_data_configuration.md
index 7244234735..d72d292b9f 100644
--- a/docs/guides/nrfconnect_factory_data_configuration.md
+++ b/docs/guides/nrfconnect_factory_data_configuration.md
@@ -30,29 +30,30 @@ data secure by applying hardware write protection.
-- [Configuring factory data for the nRF Connect examples](#configuring-factory-data-for-the-nrf-connect-examples)
- - [Overview](#overview)
- - [Factory data component table](#factory-data-component-table)
- - [Factory data format](#factory-data-format)
- - [Appearance field description](#appearance-field-description)
- - [Enabling factory data support](#enabling-factory-data-support)
- - [Generating factory data](#generating-factory-data)
- - [Creating the factory data JSON file with the first script](#creating-the-factory-data-json-file-with-the-first-script)
- - [How to set user data](#how-to-set-user-data)
- - [How to handle user data](#how-to-handle-user-data)
- - [Verifying using the JSON Schema tool](#verifying-using-the-json-schema-tool)
- - [Option 1: Using the php-json-schema tool](#option-1-using-the-php-json-schema-tool)
- - [Option 2: Using a website validator](#option-2-using-a-website-validator)
- - [Option 3: Using the nRF Connect Python script](#option-3-using-the-nrf-connect-python-script)
- - [Generating onboarding codes](#generating-onboarding-codes)
- - [Enabling onboarding codes generation within the build system](#enabling-onboarding-codes-generation-within-the-build-system)
- - [Preparing factory data partition on a device](#preparing-factory-data-partition-on-a-device)
- - [Creating a factory data partition with the second script](#creating-a-factory-data-partition-with-the-second-script)
- - [Building an example with factory data](#building-an-example-with-factory-data)
- - [Providing factory data parameters as a build argument list](#providing-factory-data-parameters-as-a-build-argument-list)
- - [Setting factory data parameters using interactive Kconfig interfaces](#setting-factory-data-parameters-using-interactive-kconfig-interfaces)
- - [Programming factory data](#programming-factory-data)
- - [Using own factory data implementation](#using-own-factory-data-implementation)
+- [Configuring factory data for the nRF Connect examples](#configuring-factory-data-for-the-nrf-connect-examples)
+ - [Overview](#overview)
+ - [Factory data component table](#factory-data-component-table)
+ - [Factory data format](#factory-data-format)
+ - [Appearance field description](#appearance-field-description)
+ - [Enabling factory data support](#enabling-factory-data-support)
+ - [Generating factory data](#generating-factory-data)
+ - [Creating the factory data JSON file with the first script](#creating-the-factory-data-json-file-with-the-first-script)
+ - [How to set user data](#how-to-set-user-data)
+ - [How to handle user data](#how-to-handle-user-data)
+ - [Verifying using the JSON Schema tool](#verifying-using-the-json-schema-tool)
+ - [Option 1: Using the php-json-schema tool](#option-1-using-the-php-json-schema-tool)
+ - [Option 2: Using a website validator](#option-2-using-a-website-validator)
+ - [Option 3: Using the nRF Connect Python script](#option-3-using-the-nrf-connect-python-script)
+ - [Generating onboarding codes](#generating-onboarding-codes)
+ - [Enabling onboarding codes generation within the build system](#enabling-onboarding-codes-generation-within-the-build-system)
+ - [Preparing factory data partition on a device](#preparing-factory-data-partition-on-a-device)
+ - [Creating a factory data partition with the second script](#creating-a-factory-data-partition-with-the-second-script)
+ - [Building an example with factory data](#building-an-example-with-factory-data)
+ - [Providing factory data parameters as a build argument list](#providing-factory-data-parameters-as-a-build-argument-list)
+ - [Setting factory data parameters using interactive Kconfig interfaces](#setting-factory-data-parameters-using-interactive-kconfig-interfaces)
+ - [Default Kconfig values and developing aspects](#default-kconfig-values-and-developing-aspects)
+ - [Programming factory data](#programming-factory-data)
+ - [Using own factory data implementation](#using-own-factory-data-implementation)
@@ -272,6 +273,7 @@ To use this script, complete the following steps:
```
--chip_cert_path
+ --gen_certs
```
> **Note:** To generate new certificates, you need the `chip-cert`
@@ -293,7 +295,7 @@ To use this script, complete the following steps:
--rd_uid
```
- - Generate a new ID and provide it ():
+ - (optional) Generate a new ID and provide it:
```
--generate_rd_uid
@@ -328,6 +330,17 @@ To use this script, complete the following steps:
--product_color
```
+ j. (optional) Generate Certification Declaration for testing purposes
+
+ ```
+ --chip_cert_path
+ --gen_cd
+ ```
+
+ > **Note:** To generate new Certification Declaration, you need the `chip-cert`
+ > executable. See the note at the end of this section to learn how to get
+ > it.
+
4. Run the script using the prepared list of arguments:
```
@@ -794,6 +807,38 @@ snippet:
> interfaces, read the
> [Kconfig documentation](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/build/kconfig/menuconfig.html).
+### Default Kconfig values and developing aspects
+
+Each factory data parameter has its default value reflected in the Kconfig.
+The list below shows some Kconfig settings that are configured in the nRF Connect build system and have an impact on the application.
+You can modify them to achieve the desired behavior of your application.
+
+* The device uses the test certificates located in the `credentials/development/attestation/` directory, which are generated using all default values.
+ If you want to change the default `vendor_id`, `product_id`, `vendor_name`, or `device_name` and generate new test certificates, add the `CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED=y` Kconfig option.
+ Remember to build the `chip-cert` application and add it to the system PATH.
+
+ For developing a production-ready product, you need to write the certificates obtained during the certification process.
+ To do this, add the `CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_USER=y` Kconfig option and set the appropriate paths for the following Kconfig options:
+
+ * `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT`
+ * `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_KEY`
+ * `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_PAI_CERT`
+
+* By default, the SPAKE2+ verifier is generated during each example's build. This means that this value will change automatically if you change any of the following parameters:
+
+ * `CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE`
+ * `CONFIG_CHIP_DEVICE_SPAKE2_SALT`
+ * `CONFIG_CHIP_DEVICE_SPAKE2_IT`
+
+ You can disable the generation of the SPAKE2+ verifier by setting the `CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER=n` Kconfig option.
+ Then, you will need to provide the externally-generated SPAKE2+ verifier using the `CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER` Kconfig value.
+
+* Generating the rotating device ID unique ID is disabled by default, but you can enable it by setting the `CONFIG_CHIP_ROTATING_DEVICE_ID=y` and `CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID=y` Kconfig values.
+ Moreover, if you set the `CONFIG_CHIP_ROTATING_DEVICE_ID` Kconfig option to `y` and disable the `CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID` Kconfig option, you will need to provide it manually using the `CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID` Kconfig value.
+
+* You can generate the test Certification Declaration by using the `CONFIG_CHIP_FACTORY_DATA_GENERATE_CD=y` Kconfig option.
+ Remember to build the `chip-cert` application and add it to the system PATH.
+
## Programming factory data
diff --git a/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py b/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py
index 6c2af9dc89..7cddb766a9 100644
--- a/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py
+++ b/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py
@@ -102,7 +102,8 @@ def gen_test_certs(chip_cert_exe: str,
generate_cd: bool = False,
cd_type: int = 1,
paa_cert_path: str = None,
- paa_key_path: str = None):
+ paa_key_path: str = None,
+ generate_all_certs: bool = False):
"""
Generate Matter certificates according to given Vendor ID and Product ID using the chip-cert executable.
To use own Product Attestation Authority certificate provide paa_cert_path and paa_key_path arguments.
@@ -120,6 +121,7 @@ def gen_test_certs(chip_cert_exe: str,
/credentials/test/attestation directory.
paa_key_path (str, optional): provide PAA key path. Defaults to None - a path will be set to
/credentials/test/attestation directory.
+ generate_all_certs: Generate the new DAC and PAI certificates
Returns:
dictionary: ["PAI_CERT": (str),
@@ -136,9 +138,10 @@ def gen_test_certs(chip_cert_exe: str,
attestation_certs = namedtuple("attestation_certs", ["dac_cert", "dac_key", "pai_cert"])
- log.info("Generating new certificates using chip-cert...")
-
if generate_cd:
+
+ log.info("Generating new Certification Declaration using chip-cert...")
+
# generate Certification Declaration
cmd = [chip_cert_exe, "gen-cd",
"--key", CD_KEY_PATH,
@@ -162,47 +165,52 @@ def gen_test_certs(chip_cert_exe: str,
"DAC_KEY": output + "/DAC_key"
}
- # generate PAI
- cmd = [chip_cert_exe, "gen-att-cert",
- "-t", "i",
- "-c", device_name,
- "-V", hex(vendor_id),
- "-C", PAA_PATH,
- "-K", PAA_KEY_PATH,
- "-o", new_certificates["PAI_CERT"] + ".pem",
- "-O", new_certificates["PAI_KEY"] + ".pem",
- "-l", str(10000),
- ]
- subprocess.run(cmd)
-
- # generate DAC
- cmd = [chip_cert_exe, "gen-att-cert",
- "-t", "d",
- "-c", device_name,
- "-V", hex(vendor_id),
- "-P", hex(product_id),
- "-C", new_certificates["PAI_CERT"] + ".pem",
- "-K", new_certificates["PAI_KEY"] + ".pem",
- "-o", new_certificates["DAC_CERT"] + ".pem",
- "-O", new_certificates["DAC_KEY"] + ".pem",
- "-l", str(10000),
- ]
- subprocess.run(cmd)
-
- # convert to .der files
- for cert_k, cert_v in new_certificates.items():
- action_type = "convert-cert" if cert_k.find("CERT") != -1 else "convert-key"
- log.info(cert_v + ".der")
- cmd = [chip_cert_exe, action_type,
- cert_v + ".pem",
- cert_v + ".der",
- "--x509-der",
+ if generate_all_certs:
+ log.info("Generating new PAI and DAC certificates using chip-cert...")
+
+ # generate PAI
+ cmd = [chip_cert_exe, "gen-att-cert",
+ "-t", "i",
+ "-c", device_name,
+ "-V", hex(vendor_id),
+ "-C", PAA_PATH,
+ "-K", PAA_KEY_PATH,
+ "-o", new_certificates["PAI_CERT"] + ".pem",
+ "-O", new_certificates["PAI_KEY"] + ".pem",
+ "-l", str(10000),
+ ]
+ subprocess.run(cmd)
+
+ # generate DAC
+ cmd = [chip_cert_exe, "gen-att-cert",
+ "-t", "d",
+ "-c", device_name,
+ "-V", hex(vendor_id),
+ "-P", hex(product_id),
+ "-C", new_certificates["PAI_CERT"] + ".pem",
+ "-K", new_certificates["PAI_KEY"] + ".pem",
+ "-o", new_certificates["DAC_CERT"] + ".pem",
+ "-O", new_certificates["DAC_KEY"] + ".pem",
+ "-l", str(10000),
]
subprocess.run(cmd)
- return attestation_certs(new_certificates["DAC_CERT"] + ".der",
- new_certificates["DAC_KEY"] + ".der",
- new_certificates["PAI_CERT"] + ".der")
+ # convert to .der files
+ for cert_k, cert_v in new_certificates.items():
+ action_type = "convert-cert" if cert_k.find("CERT") != -1 else "convert-key"
+ log.info(cert_v + ".der")
+ cmd = [chip_cert_exe, action_type,
+ cert_v + ".pem",
+ cert_v + ".der",
+ "--x509-der",
+ ]
+ subprocess.run(cmd)
+
+ return attestation_certs(new_certificates["DAC_CERT"] + ".der",
+ new_certificates["DAC_KEY"] + ".der",
+ new_certificates["PAI_CERT"] + ".der")
+
+ return attestation_certs(None, None, None)
class FactoryDataGenerator:
@@ -234,8 +242,8 @@ def _validate_args(self):
raise AssertionError("Provided wrong user data, this is not a JSON format! {}".format(e))
assert self._args.spake2_verifier or self._args.passcode, \
"Cannot find Spake2+ verifier, to generate a new one please provide passcode (--passcode)"
- assert (self._args.chip_cert_path or (self._args.dac_cert and self._args.pai_cert and self._args.dac_key)), \
- "Cannot find paths to DAC or PAI certificates .der files. To generate a new ones please provide a path to chip-cert executable (--chip_cert_path)"
+ assert ((self._args.gen_certs and self._args.chip_cert_path) or (self._args.dac_cert and self._args.pai_cert and self._args.dac_key)), \
+ "Cannot find paths to DAC or PAI certificates .der files. To generate a new ones please provide a path to chip-cert executable (--chip_cert_path) and add --gen_certs argument"
assert self._args.output.endswith(".json"), \
"Output path doesn't contain .json file path. ({})".format(self._args.output)
assert not (self._args.passcode in INVALID_PASSCODES), \
@@ -273,23 +281,27 @@ def generate_json(self):
# convert salt to bytestring to be coherent with Spake2+ verifier type
spake_2_salt = self._args.spake2_salt
- if self._args.chip_cert_path:
- certs = gen_test_certs(self._args.chip_cert_path,
- self._args.output[:self._args.output.rfind("/")],
- self._args.vendor_id,
- self._args.product_id,
- self._args.vendor_name + "_" + self._args.product_name,
- self._args.gen_cd,
- self._args.cd_type,
- self._args.paa_cert,
- self._args.paa_key)
- dac_cert = certs.dac_cert
- pai_cert = certs.pai_cert
- dac_key = certs.dac_key
- else:
+ certs = gen_test_certs(self._args.chip_cert_path,
+ self._args.output[:self._args.output.rfind("/")],
+ self._args.vendor_id,
+ self._args.product_id,
+ self._args.vendor_name + "_" + self._args.product_name,
+ self._args.gen_cd,
+ self._args.cd_type,
+ self._args.paa_cert,
+ self._args.paa_key,
+ self._args.gen_certs)
+
+ dac_cert = certs.dac_cert
+ pai_cert = certs.pai_cert
+ dac_key = certs.dac_key
+
+ if not dac_cert:
dac_cert = self._args.dac_cert
- dac_key = self._args.dac_key
+ if not pai_cert:
pai_cert = self._args.pai_cert
+ if not dac_key:
+ dac_key = self._args.dac_key
# try to read DAC public and private keys
dac_priv_key = get_raw_private_key_der(dac_key, self._args.dac_key_password)
@@ -364,6 +376,7 @@ def _add_entry(self, name: str, value: any):
def _generate_spake2_verifier(self):
""" If verifier has not been provided in arguments list it should be generated via external script """
+ log.info("Generating SPAKE2+ Verifier...")
return generate_verifier(self._args.passcode, self._args.spake2_salt, self._args.spake2_it)
def _generate_rotating_device_uid(self):
@@ -479,6 +492,8 @@ def base64_str(s): return base64.b64decode(s)
"This option requires a path to chip-cert executable."
"By default you can find chip-cert in connectedhomeip/src/tools/chip-cert directory "
"and build it there."))
+ optional_arguments.add_argument("--gen_certs", action="store_true",
+ help="Generate a new DAC nad PAI certificates")
optional_arguments.add_argument("--dac_cert", type=str,
help="[.der] Provide the path to .der file containing DAC certificate.")
optional_arguments.add_argument("--dac_key", type=str,