DICE flow using LPC55s3x#

DICE (Device Identifier Composition Engine) is a security technology that provides a hardware-based root of trust for devices. It ensures that the device’s identity and integrity are securely established and maintained throughout its lifecycle. DICE is used to create a unique device identifier and cryptographic keys that are tied to the device’s hardware, enabling secure boot, attestation, and other security features.

DICE attestation system consists of 3 pieces:

  • Verification service (performing the attestation)

  • PC host application (connecting the service and the target MCU)

  • DICE-enabled application (creating DICE response)

For working with DICE, SPSDK offers a DICE attester host tool named nxpdice.
Along the CLI, there are also APIs available in module spsdk.dice.

1. Prerequisites#

  • SPSDK is needed with examples extension. pip install spsdk[examples] (Please refer to the installation documentation.)

  • This Jupyter Notebook works without a board

2. DICE Attestation flow overview#

  1. OEM sets up their Root of Trust (RoT) by having up to 4 keys for signing MBI/SB images

  2. OEM develops their application and apply secure boot setting with DICE enabled

  3. OEM takes gets the RKTH from MBI/SB generation (from nxpimage output)

    • (this will be simplified in next version, where nxpdice will re-compute RKTH from config file)

  4. The RKTH is then used to generate NXP_CUST_DICE_CA_PUK using nxpdice

  5. In a secure environment, OEM runs a release version of their FW

    • This needs to be a final release version as the user application is a part of DICE computation

  6. In a secure environment, OEM retrieves a DICE response from the target and uses the output for register new version of FW, RTF, and HAD

    • These values serve as reference for DICE attestation

  7. During final device lifecycle, OEM obtains a DICE response to a challenge and verifies it via verification service

    • Challenge vector must match

    • DICE response contains devices unique CUST_DIE_DICE_CA_PUK signed by NXP_CUST_DICE_CA_PRK (service verifies the signature)

    • Service verifies that the DIE_PUK hasn’t changed for a particular version of the FW

    • Service verifies the response signature using the CUST_DIE_DICE_CA_PUK

    • RTF must match (using the reference registered earlier)

    • HAD may differ, differences shall be audited by OEM

3. Setting the DICE target#

SPSDK supports two types of DICE targets:

  • model

  • real device

3.1 Models setup#

Models are mainly for testing the verification service, but may be used as a showcase without a need to real HW.
Models are simply set of directories, each representing a “device”.
On top of that, there are some common settings that may be overwritten (mainly to simulate error conditions)

The following command will create a models directory with 3 device models inside named “com90, com91, com92”

Note: on Windows machine you can’t create folders called “com1” - “com10”

If you wish to continue with models, leave the variable MODELS below set.

# This env variable sets colored logger output to STDOUT
# Execute this cell to enable execution of the ! line magic
%env JUPYTER_SPSDK=1
%alias execute echo %l && %l
%alias_magic ! execute

MODELS_DIR = "models"
%! nxpdice create-models --models-dir $MODELS_DIR --number 3 --prefix com9
env: JUPYTER_SPSDK=1
Created `%!` as an alias for `%execute`.
nxpdice create-models --models-dir models --number 3 --prefix com9
Creating root models folder: models
Root model directory created
Creating device model: com90
Creating device model: com91
Creating device model: com92

3.2 HW setup#

Make sure the board is in the ISP mode

Make a note of the UART (COM) port of the target board (COM_PORT variable below)
When in doubt use SPSDK’s nxpdevscan --port command to see all available devices in ISP mode.

%! nxpdevscan --port
nxpdevscan --port 
-------- Connected NXP UART Devices --------

Port: COM7
Type: mboot device
VERBOSITY = ""  # use --debug or --verbose for more details
FAMILY = "--family lpc55s36"

MODELS = "--models-dir models"  # leave this value empty is you wish to work with a real device instead of a model

# Set the real device COM port or name of a device model (com9x from above)
COM_PORT = "com90"

CONN = f"-p {COM_PORT}"

4. Setting the DICE verification service#

SPSDK supports a offline and online verification services:

  • offline service is using local database (SQLite).

  • online service is a REST API appication and SPSDK offers a client for this app

    • to use the online service please follow the instructions https://bitbucket.sw.nxp.com/projects/SPSDK/repos/dice-verification-service/browse

In this example we’ll continue with the offline (local) service. To switch to the online service just uncomment the line below.

SERVICE = "--database dice.sqlite3"
# SERVICE = "--service-url http://localhost:8000"

4.1 Registering NXP_CUST_DICE_CA_PUK public key#

Make sure the device is reset before starting. This operation can be executed only once between resets.

if MODELS:
    print("No need to reset a model")
else:
    %! blhost $VERBOSITY $CONN reset
No need to reset a model

For generating the NXP_CUST_DICE_CA_PUK we need RKTH. The following command will trigger the key generation on the target. After that it will register the CA key in the verification service.

RKTH = "3f1f71ccd8dfcbcff3e445c21f003a974f8c40ce9aa7d8c567416b9ab45d1655"
%! nxpdice $VERBOSITY register-ca-puk $SERVICE $CONN $FAMILY $MODELS --rkth $RKTH
nxpdice  register-ca-puk --database dice.sqlite3 -p com90 --family lpc55s3x --models-dir models --rkth 3f1f71ccd8dfcbcff3e445c21f003a974f8c40ce9aa7d8c567416b9ab45d1655 
Registering NXP_CUST_DICE_CA_PUK: 8905f3e06e4542d5eea1821a53a4631857a79b64d7d5d2f3380afb3f87333bcdc1ac5e813c097b6fac20dc3c95dcf94ecc6943a79fb13760c69df89a453e7ac1
DICE CA PUK set successfully.

4.2 Registering new version of FW, RTF, and HAD#

Value of RTF (Runtime fingerprint) and HAD (hardware attestation data) are very difficult to compute on the PC side, therefore we use real-life data gathered from the target. To do that, we use regular DICE response data. Difference is in the verification service which is not trying to verify the response, but rather uses the data inside the response to register the values.

%! nxpdice $VERBOSITY register-version $SERVICE $CONN $FAMILY $MODELS 
nxpdice  register-version --database dice.sqlite3 -p com90 --family lpc55s3x --models-dir models 
FW Version, RTF, and HAD registered successfully.

5. Verifying DICE response#

Verification is handled on a challenge-response basis. The response is created by a DICE-enabled user application.

In this example we’ll use an application that supports MBoot/BLHost.

For provisioning the target, singing and loading the application please use SEC tool.

The following command will perform the following steps:

  • get a unique challenge from the verfication

  • send the challenge to DICE-enabled user application

  • get a response from the target

  • send the response to the verification service

  • displays the result of verification

%! nxpdice $VERBOSITY verify  $SERVICE $CONN $FAMILY $MODELS
nxpdice  verify  --database dice.sqlite3 -p com90 --family lpc55s3x --models-dir models 
Submitting DICE Response:
RTF      : 2620ef95a94458eba0fe820a4af075afcf53d77005f63c6d730e777300e96e09
HAD      : 0ff0035500000022ffffffff000000000000dc000000018f000000000000000000000000000000000000000000000000
DIE_PUK  : b13626e31d3e9fc8e806ca226e9e3962f275a104f4e8c220935f0a70fd5d4ac430914781dab060479fb895f266cdfebed891bd8a1792dcea74abd614a573ba5f
CA_SIGN  : c25956e12701b9b5bd65ae3432f2b90133e9f293abcc71dd0ddc418c50b182aaa40cc4792197e47470a25765bee636ba484876c80249174324b7b8893d1c87f5
UUID     : 5f7fe9c5b8d15d80e0b4b3f64129e772
Version  : 00000001
Challenge: c6ce7dadb057beb6511a6dbb1739b1371821636e0d5523f1f4c5068d7cc5e040
DIE_SIGN : 33df078be2d082a6850b0047ffd2745ac0fb7dc4b0c9a01e212f5214edae8f77c4e093434ef59aba34bcbdac1da91a1f0e1521527ccbb157510addf146512817
DICE response verified successfully.

6. Injecting error states using models#

Models are configured by a set of YAML files located in folder referenced by variable MODELS (by default “models”)

The top level config file contains CUST_DIE_DICE_CA keys, FW version, and expected values for RTF and HAD.

Each “device” has it’s own config file containing DIE keys and UUID. This config file allows to override everything from the “top-level” config in introduce various error conditions. Such as: changing CUST_DIE_DICE_CA_PUK key to cause CA signature failure; setting invalid value of FW version or RTF or Challenge; etc.

if not MODELS:
    raise UserWarning("This demo works only with models")

MODELS = "--models-dir err_models"  # path to models containing an error
%! nxpdice $VERBOSITY verify  $SERVICE -p com91 $FAMILY $MODELS
nxpdice  verify  --database dice.sqlite3 -p com91 --family lpc55s3x --models-dir err_models 
Submitting DICE Response:
RTF      : 2620ef95a94458eba0fe820a4af075afcf53d77005f63c6d730e777300e96e09
HAD      : 0000000000000022ffffffff000000000000dc000000018f000000000000000000000000000000000000000000000000
DIE_PUK  : 6e5218e7fd651d23950e4ff564311e41468ff75b7b1fcda67c0311a2657a8e648dc00307d20e9512fe8001f66e53db8613067d1c4b9d3f60bdbd01e70ec83b00
CA_SIGN  : 2bd89656f1efcd8ee0933b71a275c72e9578914310bcb3ecccb46cf97b345ee2edbfa2e7c19a6c1c09438c1bd8ba768fa845c78b07c4f79de8f95012428cf4a5
UUID     : 7bb61d72b1d3235d84bf6d52987dc69d
Version  : 00000001
Challenge: 8a2d47fe679ab894dbd6a97dfd1425a321e6e4504221d8abb313fc61a286d146
DIE_SIGN : 1d8e5e8271e47b854e4d6b78e4ca27b38527102777b67b35c4af0eb2ff179137812a697e5d898a1e5f8da6193277f8154689460b80ede10d29d23ca85bef9e15
HAD difference detected!
Expected: 0ff0035500000022ffffffff000000000000dc000000018f000000000000000000000000000000000000000000000000
Actual  : 0000000000000022ffffffff000000000000dc000000018f000000000000000000000000000000000000000000000000
+-------------------------------------------------------------------------------------------------------------------------+
|                                                HAD differences breakdown                                                |
+-------------+----------------------------+------------+------------+----------------------------------------------------+
|   Register  |         Bit-field          |  Expected  |   Actual   | Description                                        |
+-------------+----------------------------+------------+------------+----------------------------------------------------+
| ELS_AS_CFG0 |        CFG_LC_STATE        | 0b01010101 | 0b00000000 | LC state configuration bit.                        |
+-------------+----------------------------+------------+------------+----------------------------------------------------+
| ELS_AS_CFG0 | CFG_BOD_VBAT_RESET_ENABLED |     1      |     0      | When BOD VDDMAIN analog detector is turned on and  |
|             |                            |            |            | BOD VDDMAIN reset is enabled, this bit indicates   |
|             |                            |            |            | state 1.                                           |
+-------------+----------------------------+------------+------------+----------------------------------------------------+
| ELS_AS_CFG0 | CFG_BOD_CORE_RESET_ENABLED |     1      |     0      | When BOD CORE analog detector is turned on and BOD |
|             |                            |            |            | CORE reset is enabled, this bit indicates state 1. |
+-------------+----------------------------+------------+------------+----------------------------------------------------+
| ELS_AS_CFG0 |   CFG_FLASH_BANK0_ENABLE   |   0b1111   |   0b0000   | The state of FLASHBANK_ENABLE0 register            |
|             |                            |            |            | (0x4000_0450) reflects to this register as below.  |
+-------------+----------------------------+------------+------------+----------------------------------------------------+
| ELS_AS_CFG0 |   CFG_FLASH_BANK1_ENABLE   |   0b1111   |   0b0000   | The state of FLASHBANK_ENABLE1 register            |
|             |                            |            |            | (0x4000_0454) reflects to this register as below:  |
+-------------+----------------------------+------------+------------+----------------------------------------------------+
DICE response verified successfully.