From 9aa522a2abcd46ccf581f43b6f697d1e8767b361 Mon Sep 17 00:00:00 2001 From: Ahmed Ismail Date: Fri, 23 Feb 2024 16:41:15 +0000 Subject: [PATCH] device-provisioning: Add process documentation Signed-off-by: Ahmed Ismail --- docs/device_provisioning.md | 70 +++++++++++++++++++++++++++++ docs/keyword_detection.md | 7 +-- docs/speech_recognition.md | 7 +-- release_changes/202402261206.change | 1 + 4 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 docs/device_provisioning.md create mode 100644 release_changes/202402261206.change diff --git a/docs/device_provisioning.md b/docs/device_provisioning.md new file mode 100644 index 00000000..6fc38241 --- /dev/null +++ b/docs/device_provisioning.md @@ -0,0 +1,70 @@ +# Device Provisioning + +## Introduction +Device provisioning is composed of sequential steps, The main idea is to provide a unique identity for each device along with storing the authenticated identity in a secure space to safeguard against potential attacks by adversaries. In the context of the AWS IoT Core, these take the form of an **AWS IoT client certificate** stored in the device's protected storage and a **private key** imported to PSA Crypto. + +## How it works +The device provisioning binary (`provisioning_data.bin`) is built from a C source file that contains an instance of a provisioning bundle struct (`ProvisioningParamsBundle_t`) as shown below: + +```c +const ProvisioningParamsBundle_t provisioningBundle = +{ + .provisioningMagic1 = PROVISIONING_MAGIC, + .provisioningParams = + { + .pucJITPCertificate = keyJITR_DEVICE_CERTIFICATE_AUTHORITY_PEM, + .pucClientCertificate = keyCLIENT_CERTIFICATE_PEM, + .pucClientPrivateKey = keyCLIENT_PRIVATE_KEY_PEM + }, + .codeSigningPublicKey = keyCODE_SIGNING_PUBLIC_KEY_PEM, + .provisioningMagic2 = PROVISIONING_MAGIC +}; +``` + +* `PROVISIONING_MAGIC`: a configurable value that can be set in [provisioning_config.h](../applications/helpers/provisioning/provisioning_config.h) header file, the `PROVISIONING_MAGIC` value is checked at the beginning of the provisioning process to make sure that the provided bundle parameters are genuine. + +* `keyJITR_DEVICE_CERTIFICATE_AUTHORITY_PEM`: contents of a *.pem file representing a Just-in-Time Registration of Device Certificate. This is not supported by the FRI as device certificates are generated prior to connecting to AWS IoT Core, hence this value is defined as an empty string. + +* `keyCLIENT_CERTIFICATE_PEM`: contents of `.pem` file passed as part of the build command (`--certificate_path `). This is needed as AWS IoT Core authenticates device connections with the help of X.509 certificates. For more information on how to generate a X.509 certificate, please check [setting_up_aws_connectivity.md](./setting_up_aws_connectivity.md) document. + +* `keyCLIENT_PRIVATE_KEY_PEM`: contents of `.pem` file passed as part of the build command (`--private_key_path `). This is used along with the certificate to validate the identity of the device. + +* `keyCODE_SIGNING_PUBLIC_KEY_PEM`: contents of `image_ns_signing_public_key.pem` which is the public key component of the key pair generated by TF-M during the build process. This is needed to validate the authenticity of an OTA update image by verifying the associated signature. + +* `keyJITR_DEVICE_CERTIFICATE_AUTHORITY_PEM`, `keyCLIENT_CERTIFICATE_PEM`, `keyCLIENT_PRIVATE_KEY_PEM`, and `keyCODE_SIGNING_PUBLIC_KEY_PEM` are used to generate the credentials header during the build process using [generate_credentials_header.py](../tools/scripts/generate_credentials_header.py) python script. +The credentials header can be generated manually using the following command from the project's top level directory: + + ```sh + python3 ./tools/scripts/generate_credentials_header.py \ + "/helpers/provisioning" \ + --path-to-client-private-key-pem "" \ + --path-to-client-certificate-pem "" \ + --path-to-code-signing-public-key-pem "$TFM_KEYS_PATH/image_ns_signing_public_key.pem" + ``` + + where `$TFM_KEYS_PATH` is the path TF-M keys are generated in (`$BUILD_PATH/iot_reference_arm_corstone3xx/components/security/trusted_firmware-m/integration/trusted_firmware-m-build-prefix/src/trusted_firmware-m-build-build/api_ns/image_signing/keys/`). + +The provisioning binary `provisioning_data.bin` is built into `/helpers/provisioning` subdirectory where the binary is used to provision the device with the client certificate, associated private and public key pair, and the optional Just-in-Time registration certificate. If the private or public key is unavailable in storage, a new key pair is generated. + +The `provisioning_data.bin` binary has to be loaded to `NS_PROVISIONING_BUNDLE_LOAD_ADDRESS` (platform dependant address specified at `bsp/CMakeLists.txt`) so that when the application runs, it detects that the non-secure provisioning bundle is present and writes the credentials into the protected storage. This step is done automatically as part of merging the output application binaries which takes place during the the build process through `iot_reference_arm_corstone3xx_tf_m_merge_images` CMake function. + +This step can also be done manually at run time by using the following command: + +```sh +FVP_Corstone_SSE-310 -a cpu0*=$TFM_BUILD_PATH/bl2.axf \ +--data "$TFM_BUILD_PATH/tfm_s_signed.bin"@ \ +--data "$BUILD_PATH/_signed.bin"@ \ +--data "$TFM_BUILD_PATH/encrypted_provisioning_bundle.bin"@ \ +--data "$BUILD_PATH/helpers/provisioning/provisioning_data.bin"@ +``` + +`$BUILD_PATH` is the path which is passed through `--path` option as part of the build command. + +`$TFM_BUILD_PATH` is the path where TF-M binaries are generated (`$BUILD_PATH/iot_reference_arm_corstone3xx/components/security/trusted_firmware-m/integration/trusted_firmware-m-build-prefix/src/trusted_firmware-m-build-build/api_ns/bin`). + +### Note: + +If the contents of the certificate or private key `.pem` files used for building the application (passed with `--certificate_path` and `--private_key_path`) have changed, rebuild the non-secure provisioning binary using the following command: +```sh +cmake --build build -j -- provisioning_data +``` diff --git a/docs/keyword_detection.md b/docs/keyword_detection.md index 725a713a..740916d2 100644 --- a/docs/keyword_detection.md +++ b/docs/keyword_detection.md @@ -61,12 +61,7 @@ Or, run the command below to perform a clean build: ## Provisioning the device credentials into Protected Storage -During the build process a ```provisioning_data.bin``` is built into the ```build/applications/keyword_detection/provisioning_data``` directory. -This binary contains the device credentials (private key and certificate). - -If the content of the .pem files that were used during the build process (passed with ```--certificate_path``` and ```--private_key_path```) changed, then ```cmake --build build -j -- provisioning_data``` rebuilds this provisioning binary. - -The binary has to be loaded to the ```0x210FF000``` address so the ```keyword-detection``` can detect that a provisioning bundle is present and writes the credentials into the Protected Storage. (The run.sh script automatically does this.) +Check [Device Provisioning](./device_provisioning.md) for detailed information. ## Running the application diff --git a/docs/speech_recognition.md b/docs/speech_recognition.md index 95497785..87ee04c1 100644 --- a/docs/speech_recognition.md +++ b/docs/speech_recognition.md @@ -38,12 +38,7 @@ Or, run the command below to perform a clean build: ``` ## Provisioning the device credentials into Protected Storage -During the build process a ```provisioning_data.bin``` is built into the ```build/applications/speech_recognition/provisioning_data``` directory. -This binary contains the device credentials (private key and certificate). - -If the content of the .pem files that were used during the build process (passed with ```--certificate_path``` and ```--private_key_path```) changed, then ```cmake --build build -j -- provisioning_data``` rebuilds this provisioning binary. - -The binary has to be loaded to the ```0x210FF000``` address so the ```speech-recognition``` can detect that a provisioning bundle is present and writes the credentials into the Protected Storage. (The run.sh script automatically does this.) +Check [Device Provisioning](./device_provisioning.md) for detailed information. ## Running the application diff --git a/release_changes/202402261206.change b/release_changes/202402261206.change new file mode 100644 index 00000000..1c3b4df6 --- /dev/null +++ b/release_changes/202402261206.change @@ -0,0 +1 @@ +device-provisioning: Add process documentation.