KW45xx and K32W1xx Secure Boot#
This notebook describes how to how to set up a basic secure boot on KW45xx and K32W1xx devices using the SPSDK command line utilities.
Secure Boot ensures authenticity, integrity and confidentiality of any software during the boot process and ensures that the intended secure level is reached. Secure Boot ensures that only properly signed (Original equipment manufacturer (OEM)-authentic) code can be executed on a device, protecting debug access is of utmost importance. Secure boot provides guarantee that unauthorized code cannot be executed on a given product.
At the end of this example, the signed application will be provided and the chip will be secured for that reason only application signed by key’s owner can boot.
Here is the necessary steps to achieve this goal:
plain application
root of trust
create secured imaged (created based on rot and plain)
switch device to proper life cycle
load secure image
verification
1. Prerequisites#
SPSDK is needed with examples extension.
pip install spsdk[examples]
(Please refer to the installation documentation.)This example uses KW45xx-EVK/K32W1xx-EVK board
Let’s prepare also workspace and variables.
WORKSPACE = "workspace/" # change this to path to your workspace
INPUTS = "inputs/"
# verbosity of commands, might be -v or -vv for debug or blank for no additional info
VERBOSITY = "-v"
# choose family (kw45b41z8, kw45b41z5 or k32w148)
FAMILY = "kw45b41z8"
MBI_USER_CONFIG = "inputs/kw45xx_xip_signed.yaml"
2. Root of Trust Keys Preparation#
To create a signed image, you need to establish a Root of Trust (RoT) at the beginning, which will be used later to sign the image.
The EVK board (KW45xx-EVK/K32W1xx) comes with pre-burned fuses containing the Root Key Table Hash (RKTH) in a fuse called CUST_PROD_OEMFW_AUTH_PUK, provided by NXP. The corresponding keys are stored in the EVK_keys folder.
Generally, you can generate Root of Trust Keys (RoTKs)/Super Root Keys (SRKs) and optionally an Image Signing Key (ISK). To generate these keys, use the nxpcrypto application (refer to How-to-get-keys-using-nxpcrypto). By default, the script creates 4 RoTKs and 1 ISK. At least one RoTK is mandatory.
Based on the loaded keys, a Root Key Table Hash (RKTH) value is calculated. This RKTH should be loaded into the device fuses, which is why the keys cannot be changed for the device once set.
3. Prepare Master Boot Image (MBI)#
In order to achieve secure boot, we will use signed mbi with by already prepared RoT keys.
The structure of signed MBI is following:
In order to generate MBI file, nxpimage tool is used. The process of creating MBI in SPSDK is following:
Get the certification block used in signed MBI
Get the configuration file that describes MBI setting
To start creating the configuration file, the template of that file could be used. The command is: ‘nxpimage mbi get-templates’
Modify the configuration file to reflect the project needs
Use the configuration by ‘nxpimage mbi export’ command to create the final MBI file
3.1 Preparing Certificate Block v2.1#
In order to create signed MBI the certification block that keeps the RoT info must be prepared.
In our case we have already prepared certification block to simplify the example (see Certification block configuration v2.1)
To learn how to create a certificate blok check the whole example is presented in dedicated notebook (see How-to-get-cert-block).
3.2 Preparing MBI configuration file#
Let’s begin by creating a template configuration file using the nxpimage mbi get-templates
command. To simplify this example, we have already prepared a certificate block, which can be found in the kw45xx_xip_signed.yaml file. Below, we’ll compare the differences between the template and our customized example to highlight the additions we’ve made.
nxpimage mbi get-templates -f kw45b41z8 -o workspace/ --force
Creating workspace/kw45b41z8_xip_plain.yaml template file.
Creating workspace/kw45b41z8_xip_crc.yaml template file.
Creating workspace/kw45b41z8_xip_signed.yaml template file.
Creating workspace/kw45b41z8_xip_nxp_signed.yaml template file.
3.3 MBI generation#
We have created certificates, keys and proper configuration required for the creation of MBI file. Let’s create a MBI.
# Execute MBI export command with our configuration
! nxpimage mbi export -c $MBI_USER_CONFIG
# Just check the MBI file has been properly created
MBI_OUTPUT_FILE = WORKSPACE + "kw45xx_mbi_xip_signed_hello_world.bin"
assert os.path.exists(MBI_OUTPUT_FILE)
RKTH: 650d8097079ff27a3e8a2da14781b922fd8295b6c00bfa067f00e87f1a16b8b304bf710d45cbd591e2e24be83183922c
Success. (Master Boot Image: workspace\kw45xx_mbi_xip_signed_hello_world.bin created.)
4. Device preparation#
Now it’s time to prepare the device. In this example we will use KW45xx-EVK/K32W1xx board.
Board preparation#
First step is to enter In System Programming (ISP) mode, this could be achieved by 3 scenarios:
Force ISP mode by HW pin
Put JP25 to (1-2)
Reset the board with SW4 pressed
Force ISP mode by debug mailbox command
Connect debug probe and use nxpdebugmbox ispmode -m 1 command
Native fall-down in case that no valid application is in chip
In case that chip has no valid application to boot, the ISP mode is activated natively
Use app nxpdevscan to check if the device is connected to the PC in ISP mode.
In our case, we already have burnt some fuses on EVK. Those KW45xx/K32Wxx EVK boards are distributed from NXP by already burned RoTKH information as has been already mentioned earlier.
# check if the device is connected and detected by PC
%! nxpdevscan
nxpdevscan
-------- Connected NXP USB Devices --------
-------- Connected NXP UART Devices --------
Port: COM10
Type: mboot device
-------- Connected NXP SIO Devices --------
-------- Connected NXP UUU Devices --------
# Choose com port got by nxpdevscan tool
UART_CONNECTION = "-p com10"
%! blhost $UART_CONNECTION get-property current-version
blhost -p com10 get-property current-version
Response status = 0 (0x0) Success.
Response word 1 = 1258488064 (0x4b030100)
Current Version = K3.1.0
5. Load MBI#
Last step is to uploads MBI file with image to device.
# 4.1 Erase all flash
%! blhost $UART_CONNECTION flash-erase-all
blhost -p com10 flash-erase-all
Response status = 0 (0x0) Success.
# 4.2 Uploads MBI
%! blhost $UART_CONNECTION write-memory 0x0 $MBI_OUTPUT_FILE
blhost -p com10 write-memory 0x0 workspace/kw45xx_mbi_xip_signed_hello_world.bin
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 2872 (0xb38)
# 4.3 Reset to board to verify that image successfully boot
%! blhost $UART_CONNECTION reset
blhost -p com10 reset
Response status = 0 (0x0) Success.
The application can boot. Right now the board is in OEM OPEN life cycle - every image can boot. You can check life cycle value by switching back to ISP mode and running command:
Here is description of lifecycles:
Let’s enable secure boot feature in next chapter and limit the booting only for images signed by oem owned keys.
6. Secure device#
Once the secure boot is enabled, which means that the life cycle is shifted to OEM Closed (0x1F), the signed image is loaded and only applications signed with these keys can boot.
Shifting the life cycle is done by writing the correct value to the fuse with address 0xa using the following command:
blhost $UART_CONNECTION fuse-program 0xa ‘{{1F}}’
WARNING: This step is a destructive operation (burning fuses). Remember that shifting the lifecycle is a one-time operation and cannot be reverted.
In the Closed lifecycle, only limited ISP commands are allowed (GetProperty, Reset, SetProperty, ReceiveSbFile). Test and debug ports are closed by default. If debug authentication is enabled, then the authentication process can be used to reopen debug ports.
Once the life cycle is shifted, we will achieve the goal: the signed application boots, and the chip is secured. From now on, only applications signed by OEM-owned keys can boot.
Moreover, firmware updates are only possible using the blhost receive-sb-file
command.
If you try to load an image that is signed by different keys, the application should not boot.