Skip to content

Latest commit

 

History

History
69 lines (51 loc) · 5.67 KB

File metadata and controls

69 lines (51 loc) · 5.67 KB

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:

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 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 <certificate-name>.pem file passed as part of the build command (--certificate_path <path-to-certificate-name.pem>). 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 document.

  • keyCLIENT_PRIVATE_KEY_PEM: contents of <private-key-name>.pem file passed as part of the build command (--private_key_path <path-to-private-key-name.pem>). 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 Python script. The credentials header can be generated manually using the following command from the project's top level directory:

    python3 ./tools/scripts/generate_credentials_header.py \
        "<build_path>/helpers/provisioning" \
        --path-to-client-private-key-pem "<path-to-private-key-name.pem>" \
        --path-to-client-certificate-pem "<path-to-certificate-name.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 <build_path>/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:

FVP_Corstone_SSE-310 -a cpu0*=$TFM_BUILD_PATH/bl2.axf \
--data "$TFM_BUILD_PATH/tfm_s_signed.bin"@<S_IMAGE_LOAD_ADDRESS> \
--data "$BUILD_PATH/<application-name>_signed.bin"@<NS_IMAGE_LOAD_ADDRESS> \
--data "$TFM_BUILD_PATH/encrypted_provisioning_bundle.bin"@<S_PROVISIONING_BUNDLE_LOAD_ADDRESS> \
--data "$BUILD_PATH/helpers/provisioning/provisioning_data.bin"@<NS_PROVISIONING_BUNDLE_LOAD_ADDRESS>

$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