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.

%run ./lpc55sxx_secure_boot.ipynb
env: JUPYTER_SPSDK=1
Created `%!` as an alias for `%execute`.
nxpimage -v utils binary-image convert -i lpcxpresso55s69_led_blinky.axf -f BIN -o workspace/lpcxpresso55s69_led_blinky.bin
INFO:spsdk.apps.nxpimage:
+==0x0000_0000= lpcxpresso55s69_led_blinky.axf ==+
|             Size: 8.8 kB; 8,820 B              |
|     The image loaded from: /Users/macbook-     |
|m1/spsdk_test/spsdk/examples/jupyter_examples/lp|
|c55sxx_secure_boot/lpcxpresso55s69_led_blinky.ax|
|                      f .                       |
|+==0x0000_0000= Segment 0 =====================+|
||            Size: 8.8 kB; 8,820 B             ||
|+==0x0000_2273=================================+|
+==0x0000_2273===================================+

Success. (Converted file: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/lpcxpresso55s69_led_blinky.bin created.)
nxpimage -v mbi get-templates -f lpc55s6x -o workspace/templates --force
Creating /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/templates/lpc55s6x_xip_plain.yaml template file.
Creating /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/templates/lpc55s6x_xip_crc.yaml template file.
Creating /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/templates/lpc55s6x_xip_signed.yaml template file.
Creating /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/templates/lpc55s6x_load_to_ram_crc.yaml template file.
Creating /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/templates/lpc55s6x_load_to_ram_signed.yaml template file.
nxpcrypto -v key generate -k rsa2048 -o workspace/rsa2048_key.pem --force
The key pair has been created: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/rsa2048_key.pub, /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/rsa2048_key.pem
nxpcrypto -v cert get-template -o workspace/root_cert_template.yml --force
INFO:spsdk.apps.nxpcertgen:Creating Certificate template...
The configuration template file has been created: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/root_cert_template.yml
nxpcrypto -v cert get-template -o workspace/chain_cert_template.yml --force
INFO:spsdk.apps.nxpcertgen:Creating Certificate template...
The configuration template file has been created: /Users/macbook-m1/spsdk_test/spsdk/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'}
nxpcrypto -v cert generate -c workspace/root_cert_template.yml -e DER -o workspace/ROT1_sha256_2048_65537_v3_ca_crt.der --force
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...
The certificate file has been created: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/ROT1_sha256_2048_65537_v3_ca_crt.der
nxpcrypto -v cert generate -c workspace/chain_cert_template.yml -e DER -o workspace/IMG1_1_sha256_2048_65537_v3_usr_key.pem --force
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...
The certificate file has been created: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/IMG1_1_sha256_2048_65537_v3_usr_key.pem
nxpimage -v cert-block get-template -f lpc55s6x -o workspace/cert_block_template.yaml --force
Creating /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/cert_block_template.yaml template file.
nxpimage -v cert-block export -c workspace/cert_block_lpc55s6x.yml -f lpc55s6x
Success. (Certificate Block: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/cert_block.bin created.)
nxpimage -v mbi export -c workspace/mbi_config_lpc55s6x.yml
INFO:spsdk.utils.crypto.rkht:ROTKH: 6bbb1ee8fecc197111850e11a6b78c988de1523a8c3f604339a3f1fac1db20ec
INFO:spsdk.utils.crypto.rkht:ROTKH: 6bbb1ee8fecc197111850e11a6b78c988de1523a8c3f604339a3f1fac1db20ec
RKHT: 6bbb1ee8fecc197111850e11a6b78c988de1523a8c3f604339a3f1fac1db20ec
Success. (Master Boot Image: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/lpc55s6x_mbi.bin created.)
pfr get-template -t cmpa -f lpc55s6x -o workspace/cmpa_lpc55s6x.yml --force
PFR cmpa configuration template has been created.
Result has been stored in: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/cmpa_lpc55s6x.yml
pfr get-template -t cfpa -f lpc55s6x -o workspace/cfpa_lpc55s6x.yml --force
PFR cfpa configuration template has been created.
Result has been stored in: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/cfpa_lpc55s6x.yml
CMPA config:
{   'description': {   'device': 'lpc55s6x',
                       'revision': '1b',
                       'type': 'CMPA',
                       'version': '2.0.0'},
    '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
WARNING:spsdk.utils.registers:Bitfield SECURE_BOOT_CFG_SEC_BOOT_EN_ENABLE_0 not found, trying backward compatibility mode with ENABLE_0 (185ms since start, registers.py:1230)
WARNING:spsdk.utils.registers:Bitfield SECURE_BOOT_CFG_SKIP_DICE_DISABLE_0 not found, trying backward compatibility mode with DISABLE_0 (185ms since start, registers.py:1230)
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
Success. (PFR binary has been generated)
Result has been stored in: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/cmpa.bin
nxpdevscan
-------- Connected NXP SDIO Devices --------

-------- Connected NXP USB Devices --------

USB COMPOSITE DEVICE - NXP SEMICONDUCTOR INC.
Vendor ID: 0x1fc9
Product ID: 0x0021
Path: DevSrvsID:4294982445
Path Hash: 9b3224ce
Name: LPC55, RT6xx
Serial number: 

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

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

blhost -u lpc55 get-property current-version
Response status = 0 (0x0) Success.
Response word 1 = 1258487808 (0x4b030000)
Current Version = K3.0.0
blhost -u lpc55 set-property 29 1
Response status = 0 (0x0) Success.
blhost -u lpc55 write-memory 0x9E600 zero_1536.bin
?25lWriting memory  [####################################]  100%          ?25h
Response status = 0 (0x0) Success.
Response word 1 = 1536 (0x600)
blhost -u lpc55 set-property 29 0
Response status = 0 (0x0) Success.
pfr read -f lpc55s6x -u lpc55 -t cfpa -o workspace/cfpa.bin -y workspace/cfpa_parsed.yaml --show-diff
CFPA page address on lpc55s6x is 0x9de00
CFPA data stored to /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/cfpa.bin
Parsed config stored to /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/cfpa_parsed.yaml
Parsed CFPA from the processor
{   'description': {   'device': 'lpc55s6x',
                       'revision': '1b',
                       'type': 'CFPA',
                       'version': '2.0.0'},
    'settings': {   'CMPA_PROG_IN_PROGRESS': {'value': '0x5CC55AA5'},
                    'ROTKH_REVOKE': {'bitfields': {'RoTK0_EN': 'ENABLED'}},
                    'VERSION': {'value': '0x00001169'}}}
CFPA config:
{   'description': {   'device': 'lpc55s6x',
                       'revision': '1b',
                       'type': 'CFPA',
                       'version': '2.0.0'},
    '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': '0x116a'}}}
pfr -v generate-binary -c workspace/cfpa_lpc55s6x.yml -o workspace/cfpa.bin
WARNING:spsdk.utils.registers:Bitfield ROTKH_REVOKE_RoTK0_EN_ENABLED not found, trying backward compatibility mode with ENABLED (189ms since start, registers.py:1230)
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
Success. (PFR binary has been generated)
Result has been stored in: /Users/macbook-m1/spsdk_test/spsdk/examples/jupyter_examples/lpc55sxx_secure_boot/workspace/cfpa.bin
pfr write -u lpc55 -t cfpa -f lpc55s6x -b workspace/cfpa.bin
CFPA page address on lpc55s6x is 0x9de00
CFPA data written to device.
pfr write -u lpc55 -t cmpa -f lpc55s6x -b workspace/cmpa.bin
CMPA page address on lpc55s6x is 0x9e400
CMPA data written to device.
blhost -u lpc55 flash-erase-region 0 0x10000
Response status = 0 (0x0) Success.
blhost -u lpc55 write-memory 0 workspace/lpc55s6x_mbi.bin
?25lWriting memory  [####################################]  100%          ?25h
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.

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: 95078cd674e20cbeef9e67532ec7a84515059007506b1f769203a0057830f5a6
(OTP) MASTER KEY: c3c48b29b07c5e24a3478d1db07665c80c76af8bb22cb5bc60161dcb714eb9d2
Keys have been stored to: /Users/macbook-m1/spsdk_test/spsdk/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.

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
INFO:spsdk.utils.crypto.rkht:ROTKH: 6bbb1ee8fecc197111850e11a6b78c988de1523a8c3f604339a3f1fac1db20ec
Success. (Secure binary 2.1: /Users/macbook-m1/spsdk_test/spsdk/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.

# check if the device is connected and detected by PC
%! nxpdevscan
nxpdevscan
-------- Connected NXP SDIO Devices --------

-------- Connected NXP USB Devices --------

USB COMPOSITE DEVICE - NXP SEMICONDUCTOR INC.
Vendor ID: 0x1fc9
Product ID: 0x0021
Path: DevSrvsID:4294982445
Path Hash: 9b3224ce
Name: LPC55, RT6xx
Serial number: 

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

-------- Connected NXP SIO Devices --------
USB_CONNECTION = "-u lpc55" 
# choose com port or /dev
UART_CONNECTION = "-p com24"

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

%! blhost $CONNECTION get-property current-version
blhost -u lpc55 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.

## 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 lpc55 read-memory 0x0009E600 4
?25lReading memory  [####################################]  100%?25h
00 00 00 00
Response status = 0 (0x0) Success.
Response word 1 = 4 (0x4)
Read 4 of 4 bytes.
blhost -u lpc55 key-provisioning enroll
Response status = 0 (0x0) Success.
blhost -u lpc55 key-provisioning set_user_key 3 workspace/sbkek.bin
Response status = 0 (0x0) Success.
blhost -u lpc55 key-provisioning set_key 7 16
Response status = 0 (0x0) Success.
blhost -u lpc55 key-provisioning set_key 8 16
Response status = 0 (0x0) Success.
blhost -u lpc55 key-provisioning set_key 9 16
Response status = 0 (0x0) Success.
blhost -u lpc55 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.

%! blhost $CONNECTION receive-sb-file $SB2_PATH

# reset target
%! blhost $CONNECTION reset
blhost -u lpc55 receive-sb-file workspace/output.sb2
?25lSending SB file  [####################################]  100%          ERROR:spsdk.mboot.mcuboot:RX: Mboot: Data aborted by sender (16670ms since start, mcuboot.py:234)
?25h
Response status = 10101 (0x2775) ROM Loader: Signature Error.
blhost -u lpc55 reset
Response status = 10001 (0x2711) Security Violation.