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 https://www.nxp.com/docs/en/application-note/AN12283.pdf.

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.

[1]:
%run ./lpc55sxx_secure_boot.ipynb
Created `%!` as an alias for `%execute`.
nxpimage -v utils binary-image convert -i lpcxpresso55s69_led_blinky.axf -f BIN workspace/lpcxpresso55s69_led_blinky.bin
Success. (Converted file: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\lpcxpresso55s69_led_blinky.bin created.)
WARNING:spsdk.utils.images:Elf file support is experimental. Take that with care. (1987ms since start, images.py:531)
INFO:spsdk.apps.nxpimage:
+==0x0000_0000= lpcxpresso55s69_led_blinky.axf ==+
|                  Size: 8.8 kB                  |
|The image loaded from: c:/repos/spsdk_master/exa|
|mples/jupyter_examples/lpc55sxx_secure_boot/lpcx|
|          presso55s69_led_blinky.axf .          |
|+==0x0000_0000= Segment 0 =====================+|
||                 Size: 8.8 kB                 ||
|+==0x0000_2273=================================+|
+==0x0000_2273===================================+

nxpimage -v mbi get-templates -f lpc55s6x workspace/templates
Skip creating c:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\templates\lpc55s6x_int_xip_plain.yaml, this file already exists.
Skip creating c:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\templates\lpc55s6x_int_xip_crc.yaml, this file already exists.
Skip creating c:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\templates\lpc55s6x_int_xip_signed.yaml, this file already exists.
Skip creating c:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\templates\lpc55s6x_ram_crc.yaml, this file already exists.
Skip creating c:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\templates\lpc55s6x_ram_signed.yaml, this file already exists.
nxpcrypto -v key generate -k rsa2048 workspace/rsa2048_key.pem --force
The key pair has been created: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\rsa2048_key.pub, C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\rsa2048_key.pem
INFO:spsdk.apps.nxpkeygen:Generating RSA private key...
INFO:spsdk.apps.nxpkeygen:Generating RSA corresponding public key...
INFO:spsdk.apps.nxpkeygen:Saving RSA key pair...
nxpcrypto -v cert get-template workspace/root_cert_template.yml --force
The configuration template file has been created: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\root_cert_template.yml
INFO:spsdk.apps.nxpcertgen:Creating Certificate template...
nxpcrypto -v cert get-template workspace/chain_cert_template.yml --force
The configuration template file has been created: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\chain_cert_template.yml
Root Certificate config:
{   'duration': 3650,
    'extensions': {'BASIC_CONSTRAINTS': {'ca': True, 'path_length': 0}},
    'issuer': {   'COMMON_NAME': 'NXP',
                  'COUNTRY_NAME': 'CZ',
                  'LOCALITY_NAME': 'Roznov pod Radhostem',
                  'ORGANIZATION_NAME': 'SPSDK Team',
                  'STATE_OR_PROVINCE_NAME': 'Morava',
                  'STREET_ADDRESS': '1.maje 1009'},
    'issuer_private_key': 'workspace/rsa2048_key.pem',
    'serial_number': 12346578,
    'subject': {   'COMMON_NAME': 'NXP',
                   'COUNTRY_NAME': 'CZ',
                   'LOCALITY_NAME': 'Roznov pod Radhostem',
                   'ORGANIZATION_NAME': 'SPSDK Team',
                   'STATE_OR_PROVINCE_NAME': 'Morava',
                   'STREET_ADDRESS': '1.maje 1009'},
    'subject_public_key': 'workspace/rsa2048_key.pub'}
Chain certificate config:
{   'duration': 3650,
    'extensions': {'BASIC_CONSTRAINTS': {'ca': False, 'path_length': 0}},
    'issuer': {   'COMMON_NAME': 'NXP',
                  'COUNTRY_NAME': 'CZ',
                  'LOCALITY_NAME': 'Roznov pod Radhostem',
                  'ORGANIZATION_NAME': 'SPSDK Team',
                  'STATE_OR_PROVINCE_NAME': 'Morava',
                  'STREET_ADDRESS': '1.maje 1009'},
    'issuer_private_key': 'workspace/rsa2048_key.pem',
    'serial_number': 12346578,
    'subject': {   'COMMON_NAME': 'NXP - SPSDK',
                   'COUNTRY_NAME': 'CZ',
                   'LOCALITY_NAME': 'Roznov pod Radhostem',
                   'ORGANIZATION_NAME': 'SPSDK Team',
                   'POSTAL_CODE': '756 61',
                   'STATE_OR_PROVINCE_NAME': 'Morava',
                   'STREET_ADDRESS': '1.maje 1009'},
    'subject_public_key': 'workspace/rsa2048_key.pub'}
INFO:spsdk.apps.nxpcertgen:Creating Certificate template...
nxpcrypto -v cert generate -c workspace/root_cert_template.yml -e DER -o workspace/ROT1_sha256_2048_65537_v3_ca_crt.der --force
The certificate file has been created: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\ROT1_sha256_2048_65537_v3_ca_crt.der
INFO:spsdk.apps.nxpcertgen:Generating Certificate...
INFO:spsdk.apps.nxpcertgen:Loading configuration from yml file...
INFO:spsdk.apps.nxpcertgen:Saving the generated certificate to the specified path...
INFO:spsdk.apps.nxpcertgen:Certificate generated successfully...
nxpcrypto -v cert generate -c workspace/chain_cert_template.yml -e DER -o workspace/IMG1_1_sha256_2048_65537_v3_usr_key.pem --force
The certificate file has been created: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\IMG1_1_sha256_2048_65537_v3_usr_key.pem
INFO:spsdk.apps.nxpcertgen:Generating Certificate...
INFO:spsdk.apps.nxpcertgen:Loading configuration from yml file...
INFO:spsdk.apps.nxpcertgen:Saving the generated certificate to the specified path...
INFO:spsdk.apps.nxpcertgen:Certificate generated successfully...
nxpimage -v mbi export workspace/mbi_config_lpc55s6x.yml
Success. (Master Boot Image: c:/repos/spsdk_master/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/lpc55s6x_mbi.bin created.)
INFO:spsdk.image.mbi_mixin:RKTH: ee14c7f74e66cf0b3909c5359af483ed7b73b31e60c2389177fde48194f7651d
pfr get-template -t cmpa -d lpc55s6x -o workspace/cmpa_lpc55s6x.yml
PFR cmpa configuration template has been created.
Result has been stored in: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\cmpa_lpc55s6x.yml
pfr get-template -t cfpa -d lpc55s6x -o workspace/cfpa_lpc55s6x.yml
PFR cfpa configuration template has been created.
Result has been stored in: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\cfpa_lpc55s6x.yml
CMPA config:
{   'description': {   'device': 'lpc55s6x',
                       'revision': '1b',
                       'type': 'CMPA',
                       'version': '1.9.1+sp.ear1'},
    'settings': {   'BOOT_CFG': {   'bitfields': {   'BOOT_FAILURE_PIN': '0x00',
                                                     'BOOT_SPEED': 'SYSTEM_SPEED_CODE',
                                                     'DEFAULT_ISP_MODE': 'AUTO_ISP',
                                                     'USB_SPEED': 'USB_SPEED_0'}},
                    'CUSTOMER_DEFINED0': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED1': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED10': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED11': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED12': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED13': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED14': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED15': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED16': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED17': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED18': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED19': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED2': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED20': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED21': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED22': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED23': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED24': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED25': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED26': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED27': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED28': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED29': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED3': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED30': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED31': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED32': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED33': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED34': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED35': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED36': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED37': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED38': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED39': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED4': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED40': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED41': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED42': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED43': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED44': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED45': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED46': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED47': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED48': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED49': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED5': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED50': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED51': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED52': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED53': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED54': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED55': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED6': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED7': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED8': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED9': {'value': '0x00000000'},
                    'DCFG_CC_SOCU_DFLT': {   'bitfields': {   'CPU1_DBGEN': 'DISABLED',
                                                              'CPU1_NIDEN': 'DISABLED',
                                                              'DBGEN': 'DISABLED',
                                                              'FA_ME_CMD_EN': 'DISABLED',
                                                              'ISP_CMD_EN': 'DISABLED',
                                                              'NIDEN': 'DISABLED',
                                                              'SPIDEN': 'DISABLED',
                                                              'SPNIDEN': 'DISABLED',
                                                              'TAPEN': 'DISABLED'}},
                    'DCFG_CC_SOCU_PIN': {   'bitfields': {   'CPU1_DBGEN': 'USE_DAP',
                                                             'CPU1_NIDEN': 'USE_DAP',
                                                             'DBGEN': 'USE_DAP',
                                                             'FA_ME_CMD_EN': 'USE_DAP',
                                                             'ISP_CMD_EN': 'USE_DAP',
                                                             'NIDEN': 'USE_DAP',
                                                             'SPIDEN': 'USE_DAP',
                                                             'SPNIDEN': 'USE_DAP',
                                                             'TAPEN': 'USE_DAP',
                                                             'UUID_CHECK': 'DISABLED'}},
                    'PRINCE_BASE_ADDR': {   'bitfields': {   'ADDR0_PRG': '0x0',
                                                             'ADDR1_PRG': '0x0',
                                                             'ADDR2_PRG': '0x0',
                                                             'LOCK_REG0': 'UNLOCK',
                                                             'LOCK_REG1': 'UNLOCK',
                                                             'REG0_ERASE_CHECK_EN': 'DISABLE',
                                                             'REG1_ERASE_CHECK_EN': 'DISABLE',
                                                             'REG2_ERASE_CHECK_EN': 'DISABLE'}},
                    'PRINCE_SR_0': {'value': '0x00000000'},
                    'PRINCE_SR_1': {'value': '0x00000000'},
                    'PRINCE_SR_2': {'value': '0x00000000'},
                    'ROTKH': {   'value': '0000000000000000000000000000000000000000000000000000000000000000'},
                    'SDIO_CFG': {'value': '0x00000000'},
                    'SECURE_BOOT_CFG': {   'bitfields': {   'BLOCK_ENROLL': 'ALLOW',
                                                            'BLOCK_SET_KEY': 'ALLOW',
                                                            'DICE_CUST_CFG': 'NOT_INCLUDE',
                                                            'DICE_INC_NXP_CFG': 'NOT_INCLUDE',
                                                            'DICE_INC_SEC_EPOCH': '0x0',
                                                            'RSA4K': 'RSA2048',
                                                            'SEC_BOOT_EN': 'SECURE_BOOT_CFG_SEC_BOOT_EN_ENABLE_0',
                                                            'SKIP_DICE': 'SECURE_BOOT_CFG_SKIP_DICE_DISABLE_0',
                                                            'TZM_IMAGE_TYPE': 'HEADER'}},
                    'SPI_FLASH_CFG': {   'bitfields': {   'SPI_RECOVERY_BOOT_EN': '0x0'}},
                    'USB_ID': {   'bitfields': {   'USB_PRODUCT_ID': '0x0000',
                                                   'USB_VENDOR_ID': '0x0000'}},
                    'VENDOR_USAGE': {'bitfields': {'VENDOR_USAGE': '0x0000'}},
                    'XTAL_16MHZ_CAPABANK_TRIM': {   'bitfields': {   'PCB_XIN_PARA_CAP_PF_X100': '0x00',
                                                                     'PCB_XOUT_PARA_CAP_PF_X100': '0x00',
                                                                     'TRIM_VALID': 'NOT_TRIM',
                                                                     'XTAL_LOAD_CAP_IEC_PF_X100': '0x00'}},
                    'XTAL_32KHZ_CAPABANK_TRIM': {   'bitfields': {   'PCB_XIN_PARA_CAP_PF_X100': '0x00',
                                                                     'PCB_XOUT_PARA_CAP_PF_X100': '0x00',
                                                                     'TRIM_VALID': 'NOT_TRIM',
                                                                     'XTAL_LOAD_CAP_IEC_PF_X100': '0x00'}}}}
pfr -v generate-binary -c workspace/cmpa_lpc55s6x.yml -o workspace/cmpa.bin -e workspace/mbi_config_lpc55s6x.yml
Success. (PFR binary has been generated.
Result has been stored in: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\cmpa.bin
WARNING:spsdk.utils.registers:Bitfield SECURE_BOOT_CFG_SEC_BOOT_EN_ENABLE_0 not found, trying backward compatibility mode with ENABLE_0 (1260ms since start, registers.py:1201)
WARNING:spsdk.utils.registers:Bitfield SECURE_BOOT_CFG_SKIP_DICE_DISABLE_0 not found, trying backward compatibility mode with DISABLE_0 (1260ms since start, registers.py:1201)
INFO:spsdk.pfr.pfrc:OK: Brick condition not fulfilled
INFO:spsdk.pfr.pfrc:OK: Brick condition not fulfilled
INFO:spsdk.pfr.pfrc:OK: Brick condition not fulfilled
INFO:spsdk.utils.crypto.rkht:ROTKH: ee14c7f74e66cf0b3909c5359af483ed7b73b31e60c2389177fde48194f7651d
nxpdevscan
-------- Connected NXP USB Devices --------

LPC-LINK2 CMSIS-DAP V5.224 - NXP Semiconductors
Vendor ID: 0x1fc9
Product ID: 0x0090
Path: HID\VID_1FC9&PID_0090&MI_00\7&36E95AFB&0&0000
Path Hash: 77e5c391
Name:
Serial number: NRA2AQHR

LPC-LINK2 DATA PORT - NXP Semiconductors
Vendor ID: 0x1fc9
Product ID: 0x0090
Path: HID\VID_1FC9&PID_0090&MI_04\7&25C3B40A&0&0000
Path Hash: c297936f
Name:
Serial number: NRA2AQHR

LPCSIO - NXP Semiconductors
Vendor ID: 0x1fc9
Product ID: 0x0090
Path: HID\VID_1FC9&PID_0090&MI_03\7&38F3D048&0&0000
Path Hash: 5f15a706
Name:
Serial number: NRA2AQHR

-------- Connected NXP UART Devices --------

Port: COM25
Type: mboot device

-------- Connected NXP SIO Devices --------

LIBUSBSIO - NXP Semiconductors, LPCSIO
Vendor ID: 0x1fc9
Product ID: 0x0090
Path: HID\VID_1FC9&PID_0090&MI_03\7&38F3D048&0&0000
Path Hash: 5f15a706
Serial number: NRA2AQHR
Interface number: 3
Release number: 256

blhost -p com25 get-property current-version
Response status = 0 (0x0) Success.
Response word 1 = 1258487808 (0x4b030000)
Current Version = K3.0.0
blhost -p com25 set-property 29 1
Response status = 0 (0x0) Success.
blhost -p com25 write-memory 0x9E600 zero_1536.bin
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 1536 (0x600)
blhost -p com25 set-property 29 0
Response status = 0 (0x0) Success.
pfr read -d lpc55s6x -p com25 -t cfpa -o workspace/cfpa.bin -y workspace/cfpa_parsed.yaml --show-diff
CFPA page address on lpc55s6x is 0x9de00
CFPA data stored to C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\cfpa.bin
Parsed config stored to C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\cfpa_parsed.yaml
Parsed CFPA from the processor
{   'description': {   'device': 'lpc55s6x',
                       'revision': '1b',
                       'type': 'CFPA',
                       'version': '1.9.1+sp.ear1'},
    'settings': {   'CMPA_PROG_IN_PROGRESS': {'value': '0x5CC55AA5'},
                    'ROTKH_REVOKE': {'bitfields': {'RoTK0_EN': 'ENABLED'}},
                    'VERSION': {'value': '0x00000002'}}}
CFPA config:
{   'description': {   'device': 'lpc55s6x',
                       'revision': '1b',
                       'type': 'CFPA',
                       'version': '1.9.1+sp.ear1'},
    'settings': {   'CMPA_PROG_IN_PROGRESS': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED0': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED1': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED10': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED11': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED12': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED13': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED14': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED15': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED16': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED17': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED18': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED19': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED2': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED20': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED21': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED22': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED23': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED24': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED25': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED26': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED27': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED28': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED29': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED3': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED30': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED31': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED32': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED33': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED34': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED35': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED36': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED37': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED38': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED39': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED4': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED40': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED41': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED42': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED43': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED44': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED45': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED46': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED47': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED48': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED49': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED5': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED50': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED51': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED52': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED53': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED54': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED55': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED6': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED7': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED8': {'value': '0x00000000'},
                    'CUSTOMER_DEFINED9': {'value': '0x00000000'},
                    'DCFG_CC_SOCU_NS_DFLT': {   'bitfields': {   'CPU1_DBGEN': 'DISABLED',
                                                                 'CPU1_NIDEN': 'DISABLED',
                                                                 'DBGEN': 'DISABLED',
                                                                 'FA_ME_CMD_EN': 'DISABLED',
                                                                 'ISP_CMD_EN': 'DISABLED',
                                                                 'NIDEN': 'DISABLED',
                                                                 'SPIDEN': 'DISABLED',
                                                                 'SPNIDEN': 'DISABLED',
                                                                 'TAPEN': 'DISABLED'}},
                    'DCFG_CC_SOCU_NS_PIN': {   'bitfields': {   'CPU1_DBGEN': 'USE_DAP',
                                                                'CPU1_NIDEN': 'USE_DAP',
                                                                'DBGEN': 'USE_DAP',
                                                                'FA_ME_CMD_EN': 'USE_DAP',
                                                                'ISP_CMD_EN': 'USE_DAP',
                                                                'NIDEN': 'USE_DAP',
                                                                'SPIDEN': 'USE_DAP',
                                                                'SPNIDEN': 'USE_DAP',
                                                                'TAPEN': 'USE_DAP',
                                                                'UUID_CHECK': 'DISABLED'}},
                    'ENABLE_FA_MODE': {'value': '0x00000000'},
                    'HEADER': {'value': '0x00000000'},
                    'IMAGE_KEY_REVOKE': {'value': '0x00000000'},
                    'NS_FW_Version': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY0': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY1': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY10': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY11': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY2': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY3': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY4': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY5': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY6': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY7': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY8': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_BODY9': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_HEADER0': {'value': '0x00000000'},
                    'PRINCE_REGION0_IV_HEADER1': {   'bitfields': {   'INDEX': '0x0',
                                                                      'SIZE': '0x0',
                                                                      'TYPE': '0x0'}},
                    'PRINCE_REGION1_IV_BODY0': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY1': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY10': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY11': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY2': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY3': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY4': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY5': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY6': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY7': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY8': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_BODY9': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_HEADER0': {'value': '0x00000000'},
                    'PRINCE_REGION1_IV_HEADER1': {   'bitfields': {   'INDEX': '0x0',
                                                                      'SIZE': '0x0',
                                                                      'TYPE': '0x0'}},
                    'PRINCE_REGION2_IV_BODY0': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY1': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY10': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY11': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY2': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY3': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY4': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY5': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY6': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY7': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY8': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_BODY9': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_HEADER0': {'value': '0x00000000'},
                    'PRINCE_REGION2_IV_HEADER1': {   'bitfields': {   'INDEX': '0x0',
                                                                      'SIZE': '0x0',
                                                                      'TYPE': '0x0'}},
                    'ROTKH_REVOKE': {   'bitfields': {   'RoTK0_EN': 'ROTKH_REVOKE_RoTK0_EN_ENABLED',
                                                         'RoTK1_EN': 'INVALID',
                                                         'RoTK2_EN': 'INVALID',
                                                         'RoTK3_EN': 'INVALID'}},
                    'S_FW_Version': {'value': '0x00000000'},
                    'VENDOR_USAGE': {   'bitfields': {   'DBG_VENDOR_USAGE': '0x0000'}},
                    'VERSION': {'value': '0x3'}}}
pfr -v generate-binary -c workspace/cfpa_lpc55s6x.yml -o workspace/cfpa.bin
Success. (PFR binary has been generated.
Result has been stored in: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\cfpa.bin
WARNING:spsdk.utils.registers:Bitfield ROTKH_REVOKE_RoTK0_EN_ENABLED not found, trying backward compatibility mode with ENABLED (1844ms since start, registers.py:1201)
INFO:spsdk.pfr.pfrc:OK: Brick condition not fulfilled
INFO:spsdk.pfr.pfrc:OK: Brick condition not fulfilled
INFO:spsdk.pfr.pfrc:OK: Brick condition not fulfilled
INFO:spsdk.pfr.pfrc:OK: Brick condition not fulfilled
INFO:spsdk.pfr.pfrc:OK: Brick condition not fulfilled
pfr write -p com25 -t cfpa -d lpc55s6x -b workspace/cfpa.bin
CFPA page address on lpc55s6x is 0x9de00
CFPA data written to device.
pfr write -p com25 -t cmpa -d lpc55s6x -b workspace/cmpa.bin
CMPA page address on lpc55s6x is 0x9e400
CMPA data written to device.
blhost -p com25 flash-erase-region 0 0x10000
Response status = 0 (0x0) Success.
blhost -p com25 write-memory 0 workspace/lpc55s6x_mbi.bin
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 11064 (0x2b38)

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.

[2]:
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/
SBKEK: af39c2f536cdd56b91a6b64334672fba08200fcdcf7715e40884a855742101e5
(OTP) MASTER KEY: e8df82db763cb8ae442097665ed9524d1ab7187515789bebce3f34dc36a7e196
Keys have been stored to: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace

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.

[3]:
import os


BD_FILE_PATH = WORKSPACE + "signed.bd"
SB2_PATH = WORKSPACE + "output.sb2"


bd = """options {
 flags = 0x8; // for sb2.1 use only 0x8 encrypted + signed
 buildNumber = 0x1;
 productVersion = "1.00.00";
 componentVersion = "1.00.00";
 secureBinaryVersion = "2.1";
}
sources
{
 inputFile = extern(0);
}
section (0)
{
 erase 0..0x00010000;
 load inputFile > 0x0;
}"""

# write configuration to file
with open(BD_FILE_PATH, "w+") as bd_file:
    bd_file.write(bd)

assert os.path.exists(SBKEK_PATH)
assert os.path.exists(SBKEK_BIN)

%! nxpimage $VERBOSITY sb21 export -k $SBKEK_PATH -c $BD_FILE_PATH -o $SB2_PATH -s $PRIVATE_KEY_PATH -S $ROOT_0_CERT_PATH -S $CHAIN_CERT_0 -R $ROOT_0_CERT_PATH $BIN_OUTPUT_PATH

assert os.path.exists(SB2_PATH)

nxpimage -v sb21 export -k workspace/sbkek.txt -c workspace/signed.bd -o workspace/output.sb2 -s workspace/rsa2048_key.pem -S workspace/ROT1_sha256_2048_65537_v3_ca_crt.der -S workspace/IMG1_1_sha256_2048_65537_v3_usr_key.pem -R workspace/ROT1_sha256_2048_65537_v3_ca_crt.der workspace/lpc55s6x_mbi.bin
Success. (Secure binary 2.1: C:\repos\spsdk_master\examples\jupyter_examples\lpc55sxx_secure_boot\workspace\output.sb2 created.)

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.

lpc55s69

We could use app nxpdevscan to check if the device is connected to the PC in ISP mode.

[4]:
# check if the device is connected and detected by PC
%! nxpdevscan
nxpdevscan
-------- Connected NXP USB Devices --------

LPC-LINK2 CMSIS-DAP V5.224 - NXP Semiconductors
Vendor ID: 0x1fc9
Product ID: 0x0090
Path: HID\VID_1FC9&PID_0090&MI_00\7&36E95AFB&0&0000
Path Hash: 77e5c391
Name:
Serial number: NRA2AQHR

LPC-LINK2 DATA PORT - NXP Semiconductors
Vendor ID: 0x1fc9
Product ID: 0x0090
Path: HID\VID_1FC9&PID_0090&MI_04\7&25C3B40A&0&0000
Path Hash: c297936f
Name:
Serial number: NRA2AQHR

LPCSIO - NXP Semiconductors
Vendor ID: 0x1fc9
Product ID: 0x0090
Path: HID\VID_1FC9&PID_0090&MI_03\7&38F3D048&0&0000
Path Hash: 5f15a706
Name:
Serial number: NRA2AQHR

-------- Connected NXP UART Devices --------

Port: COM25
Type: mboot device

-------- Connected NXP SIO Devices --------

LIBUSBSIO - NXP Semiconductors, LPCSIO
Vendor ID: 0x1fc9
Product ID: 0x0090
Path: HID\VID_1FC9&PID_0090&MI_03\7&38F3D048&0&0000
Path Hash: 5f15a706
Serial number: NRA2AQHR
Interface number: 3
Release number: 256

[5]:
USB_CONNECTION = "-u lpc55"
# choose com port or /dev
UART_CONNECTION = "-p com25"

# comment if you want to use UART
CONNECTION = UART_CONNECTION
# CONNECTION = UART_CONNECTION

%! blhost $CONNECTION get-property current-version
blhost -p com25 get-property current-version
Response status = 0 (0x0) Success.
Response word 1 = 1258487808 (0x4b030000)
Current Version = K3.0.0

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.

[6]:
## 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 -p com25 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 -p com25 key-provisioning enroll
Response status = 0 (0x0) Success.
blhost -p com25 key-provisioning set_user_key 3 workspace/sbkek.bin
Response status = 0 (0x0) Success.
blhost -p com25 key-provisioning set_key 7 16
Response status = 0 (0x0) Success.
blhost -p com25 key-provisioning set_key 8 16
Response status = 0 (0x0) Success.
blhost -p com25 key-provisioning set_key 9 16
Response status = 0 (0x0) Success.
blhost -p com25 key-provisioning write_key_nonvolatile 0
Response status = 0 (0x0) Success.

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.

[7]:
%! blhost $CONNECTION receive-sb-file $SB2_PATH

# reset target
%! blhost $CONNECTION reset
blhost -p com25 receive-sb-file workspace/output.sb2
Sending SB file
Response status = 0 (0x0) Success.
blhost -p com25 reset
Response status = 0 (0x0) Success.