LPC55Sxx Secure Firmware Update#
This notebook describes how to create secure container for firmware update on LPC55Sxx devices using the SPSDK command line utilities, it is based on the application note AN12283.
1. Secure Boot Setup#
We need to setup secure boot first. This is better described in “lpc55sx_secure_boot.ipynb” notebook. So, let’s execute it first.
Show code cell content
from spsdk.utils.jupyter_utils import YamlDiffWidget
%run ./lpc55sxx_secure_boot.ipynb
env: JUPYTER_SPSDK=1
Created `%!` as an alias for `%execute`.
nxpimage utils binary-image convert -i lpcxpresso55s69_led_blinky.axf -f BIN -o workspace/lpcxpresso55s69_led_blinky.bin
Success. (Converted file: workspace/lpcxpresso55s69_led_blinky.bin created.)
nxpimage mbi get-templates -f lpc55s69 -o workspace/ --force
Creating workspace/lpc55s69_xip_plain.yaml template file.
Creating workspace/lpc55s69_xip_crc.yaml template file.
Creating workspace/lpc55s69_xip_signed.yaml template file.
Creating workspace/lpc55s69_load_to_ram_crc.yaml template file.
Creating workspace/lpc55s69_load_to_ram_signed.yaml template file.
nxpimage mbi export -c inputs/mbi_config_lpc55s6x.yaml
RKTH: 60a4d31a7a08825285e3d3e961c850f41876c384e20cf7037664c6aebecc8b88
Success. (Master Boot Image: workspace/lpc55s6x_mbi.bin created.)
pfr get-template -t cmpa -f lpc55s69 -o workspace/cmpa_lpc55s6x.yaml --force
The PFR cmpa template for lpc55s69 has been saved into workspace/cmpa_lpc55s6x.yaml YAML file
pfr generate-binary -c inputs/cmpa_lpc55s6x.yaml -o workspace/cmpa.bin -e inputs/mbi_config_lpc55s6x.yaml
WARNING:spsdk.pfr.pfr:The DCFG_CC_SOCU_PIN register has been recomputed, because it has been used in configuration and the bitfield INVERSE_VALUE has not been specified (695ms since start, pfr.py:206)
WARNING:spsdk.pfr.pfr:The DCFG_CC_SOCU_DFLT register has been recomputed, because it has been used in configuration and the bitfield INVERSE_VALUE has not been specified (695ms since start, pfr.py:206)
Success. (PFR binary has been generated)
pfr get-template -t cfpa -f lpc55s69 -o workspace/cfpa_lpc55s6x.yaml --force
The PFR cfpa template for lpc55s69 has been saved into workspace/cfpa_lpc55s6x.yaml YAML file
nxpdevscan -u
-------- Connected NXP USB Devices --------
USB COMPOSITE DEVICE - NXP SEMICONDUCTOR INC.
Vendor ID: 0x1fc9
Product ID: 0x0021
Path: HID\VID_1FC9&PID_0021\9&3AA499EB&0&0000
Path Hash: 694e4de1
Name: lpc55s66 | lpc55s69 | lpc5526 | nhs52s04 | lpc5528 | lpc55s28 | lpc55s26
Serial number:
blhost -u lpc55s69 get-property current-version
Response status = 0 (0x0) Success.
Response word 1 = 1258487808 (0x4b030000)
Current Version = K3.0.0
blhost -u lpc55s69 set-property 29 1
Response status = 0 (0x0) Success.
blhost -u lpc55s69 write-memory 0x9E600 zero_1536.bin
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 1536 (0x600)
blhost -u lpc55s69 set-property 29 0
Response status = 0 (0x0) Success.
pfr read -f lpc55s69 -u lpc55s69 -t cfpa -o workspace/cfpa.bin -y workspace/cfpa_parsed.yaml
CFPA page address on lpc55s69 is 0x9de00
CFPA data stored to workspace/cfpa.bin
Parsed config stored to workspace/cfpa_parsed.yaml
pfr get-template -t cfpa -f lpc55s69 -o workspace/cfpa_lpc55s6x.yaml --force
The PFR cfpa template for lpc55s69 has been saved into workspace/cfpa_lpc55s6x.yaml YAML file
pfr write -u lpc55s69 -t cmpa -f lpc55s69 -b workspace/cmpa.bin
CMPA page address on lpc55s69 is 0x9e400
CMPA data written to device.
blhost -u lpc55s69 flash-erase-region 0 0x10000
Response status = 0 (0x0) Success.
blhost -u lpc55s69 write-memory 0 workspace/lpc55s6x_mbi.bin
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 10648 (0x2998)
2. SBKEK generation#
SBKEK is key (AES-256) used for encryption of the Secure Binary. We have to prepare it in plaint text and in binary form. We can use nxpimage sb21 get-sbkek tool for key generation.
WORKSPACE = "workspace/"
# we can specify key with -k option. If the key is not specified, random one will be generated.
%! nxpimage sb21 get-sbkek -o $WORKSPACE
SBKEK_PATH = WORKSPACE + "sbkek.txt"
SBKEK_BIN = WORKSPACE + "sbkek.bin"
nxpimage sb21 get-sbkek -o workspace/
WARNING:spsdk.utils.misc:The key source is not specified, the random value is used in size of 32 B. (752ms since start, misc.py:533)
SBKEK: 6ddec0bcf81ec722cf726811606177928d13f4ea67fb91e9082a37ed0e3f6b3c
(OTP) MASTER KEY: 860c818b83884764a71867a2f59d964e067370f9874c55daa7400ed3ea805f48
Keys have been stored to: workspace
3. Secure Binary preparation#
Secure Binary (SB) is a container in case of LPC55xx in version 2.1. It’s symmetrically encrypted using AES-256 and decrypted during boot and digitally signed. The SB configuration file contains the configuration commands that are processed after the SB2 file is loaded in the device. The image location is stated in the “sources” section of the .bd file. The SB key in the text file is used for encryption with the nxpimage command line tool.
In the example below we have prepared simple BD file with one section with two commands - erase and load.
YamlDiffWidget("inputs/lpc55sxx_secure_fw_update.diffc").html
import os
SB2_PATH = "workspace/output.sb"
%! nxpimage $VERBOSITY sb21 export -c inputs/sb2_config.yaml
assert os.path.exists(SB2_PATH)
nxpimage sb21 export -c inputs/sb2_config.yaml
RKTH: 60a4d31a7a08825285e3d3e961c850f41876c384e20cf7037664c6aebecc8b88
Success. (Secure binary 2.1: workspace/output.sb created.)
4. Device preparation#
Now it’s time to prepare the device (enroll keys, load pfr…). In this example we will use LPCXpresso55S69 Evaluation kit.
First step is to enter ISP mode, this could be achieved by either shorting J10 or by simultaneously pressing ISP button and reset button.
LPCXpresso55S69 supports UART and USB-HID interface for the ISP programming. In the picture below we used UART, if you want to use USB, connect the cable to high speed USB port.
We could use app nxpdevscan to check if the device is connected to the PC in ISP mode.
# check if the device is connected and detected by PC
%! nxpdevscan -u
nxpdevscan -u
-------- Connected NXP USB Devices --------
USB COMPOSITE DEVICE - NXP SEMICONDUCTOR INC.
Vendor ID: 0x1fc9
Product ID: 0x0021
Path: HID\VID_1FC9&PID_0021\9&3AA499EB&0&0000
Path Hash: 694e4de1
Name: nhs52s04 | lpc55s66 | lpc55s69 | lpc55s26 | lpc55s28 | lpc5526 | lpc5528
Serial number:
USB_CONNECTION = "-u lpc55s69"
# choose com port or /dev
UART_CONNECTION = "-p com21"
# comment if you want to use UART
# CONNECTION = USB_CONNECTION
CONNECTION = USB_CONNECTION
%! blhost $CONNECTION get-property current-version
blhost -u lpc55s69 get-property current-version
Response status = 0 (0x0) Success.
Response word 1 = 1258487808 (0x4b030000)
Current Version = K3.0.0
5. Key enrollment#
Key enrollment should be done only once in the device life cycle. We have to write KEK key that will be used for SB decryption and we will generate PUF keys for PRINCE encryption.
To detect if key provisioning was enrolled issue blhost command read-memory 0x0009E600 4. If the output is “95 95 95 95” it means that the key store is already enrolled.
## Check if the keystore is enrolled
%! blhost $CONNECTION read-memory 0x0009E600 4
## Key provisioning enroll uncomment in case it's not enrolled ###
%! blhost $CONNECTION key-provisioning enroll
### Write KEK for SB
%! blhost $CONNECTION key-provisioning set_user_key 3 $SBKEK_BIN
### Generate random key for PRINCE region 0 ###
%! blhost $CONNECTION key-provisioning set_key 7 16
### Generate random key for PRINCE region 1 ###
%! blhost $CONNECTION key-provisioning set_key 8 16
### Generate random key for PRINCE region 2 ###
%! blhost $CONNECTION key-provisioning set_key 9 16
### In case the key store has been enrolled comment if enrolling
# read keystore from internal flash
# %! blhost $CONNECTION key-provisioning read_key_nonvolatile 0
# # Write KEK for SB
# %! blhost $CONNECTION key-provisioning set_user_key 3 $SBKEK_BIN
# ### Now write the keystore to internal flash
%! blhost $CONNECTION key-provisioning write_key_nonvolatile 0
blhost -u lpc55s69 read-memory 0x0009E600 4
Reading memory
00 00 00 00
Response status = 0 (0x0) Success.
Response word 1 = 4 (0x4)
Read 4 of 4 bytes.
blhost -u lpc55s69 key-provisioning enroll
Response status = 0 (0x0) Success.
blhost -u lpc55s69 key-provisioning set_user_key 3 workspace/sbkek.bin
Response status = 0 (0x0) Success.
blhost -u lpc55s69 key-provisioning set_key 7 16
Response status = 0 (0x0) Success.
blhost -u lpc55s69 key-provisioning set_key 8 16
Response status = 0 (0x0) Success.
blhost -u lpc55s69 key-provisioning set_key 9 16
Response status = 0 (0x0) Success.
blhost -u lpc55s69 key-provisioning write_key_nonvolatile 0
Response status = 0 (0x0) Success.
6. Receive SB file#
Last step is to receive SB and then reset the chip to boot the image. Do not forget to remove the ISP jumper.
%! blhost $CONNECTION receive-sb-file $SB2_PATH
# reset target
%! blhost $CONNECTION reset
blhost -u lpc55s69 receive-sb-file workspace/output.sb
Sending SB file
Response status = 0 (0x0) Success.
blhost -u lpc55s69 reset
Response status = 0 (0x0) Success.