AHAB SIGN#

This Jupyter Notebook describes how to sign an already existing bootable image with ML-DSA keys. This example uses a complete U-Boot binary targeting i.MX95. To build a bootable image with ELE firmware and U-Boot bootloader, see the i.MX95 AHAB with U-Boot example.

1. Prerequisites#

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

  • This demo was tested with i.MX95 EVK board wih LPDDR5 memory and B0 revision.

1.1 Requirements#

  • PQC plugin for spsdk (pip install spsdk[pqc]).

  • A valid bootable image containing U-Boot, ELE firmware and other necessary binaries for i.MX95 (see i.MX95 AHAB with U-BOOT example, how to build it or download it from from official NXP website).

  • ML-DSA and ECC keys for signing the image (Generate with nxpcrypto tool - see Keys example).

from spsdk.utils.jupyter_utils import YamlDiffWidget

# 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
env: JUPYTER_SPSDK=1
Created `%!` as an alias for `%execute`.

2. AHAB signing#

2.1 AHAB sign template#

We can generate a template for signing using the nxpimage ahab get-template command with --sign or -s parameter. The command will generate a template which is YAML file that contains information about signature and/or encryption configuration.

nxpimage ahab get-template -f mimx9596 -o ahab_sign_template.yaml --sign

2.2 Signing the image#

AHAB image can be signed using the config file and command:

nxpimage ahab sign -c inputs/mx95_ahab_sign.yaml -b inputs/flash.bin -o outputs/flash_signed.bin -fs outputs/fuse-script

As you can see, you can also specify the directory where the fuse script will be saved using the -fs parameter.

YamlDiffWidget("inputs/mx95_ahab_sign.diffc").html
nxpimage ahab get-template -f mimx9596 -o workspace/ahab_sign_template.yaml -s --force 
Creating workspace/ahab_sign_template.yaml template file.

Configuration Differences

UNSIGNED_BOOTIMG = "inputs/flash.bin"
SIGNED_BOOTIMG = "outputs/flash_signed.bin"
AHAB_SIGN_CFG = "inputs/mx95_ahab_sign.yaml"
FUSE_SCRIPT_DIR = "outputs/fuse-script"

VERBOSITY = "-v"

# Sign the image
%! nxpimage $VERBOSITY ahab sign -c $AHAB_SIGN_CFG -b $UNSIGNED_BOOTIMG -o $SIGNED_BOOTIMG -fs $FUSE_SCRIPT_DIR -m serial_downloader --force
nxpimage -v ahab sign -c inputs/mx95_ahab_sign.yaml -b inputs/flash.bin -o outputs/flash_signed.bin -fs outputs/fuse-script -m serial_downloader --force 
INFO:spsdk.image.ahab.utils:Parsed Bootable image memory map: 
┌──0x0000_0000─ Bootable Image for mimx9596, Revision: latest ──┐
│                  Size: 2.7 MiB; 2,817,024 B                   │
│           Memory type: MemoryType.SERIAL_DOWNLOADER           │
│                        Pattern: zeros                         │
┌──0x0000_0000─ primary_image_container_set ──────────────────┐│
││                 Size: 886.0 kiB; 907,264 B                  ││
││          AHAB Image for mimx9596, Revision: latest          ││
││                       Pattern: zeros                        ││
││┌──0x0000_0000─ AHAB Containers ────────────────────────────┐││
│││                 Size: 48.0 kiB; 49,152 B                  │││
│││                   AHAB Containers block                   │││
│││                      Pattern: zeros                       │││
│││┌──0x0000_0000─ AHAB Container 0 ─────────────────────────┐│││
││││                 Size: 8.0 kiB; 8,227 B                  ││││
││││             AHAB Container for nxp_SWver:0              ││││
│││└──0x0000_2022────────────────────────────────────────────┘│││
│││                       Gap: 8.0 kiB                        │││
│││┌──0x0000_4000─ AHAB Container 1 ─────────────────────────┐│││
││││                       Size: 832 B                       ││││
││││             AHAB Container for nxp_SWver:0              ││││
│││└──0x0000_433f────────────────────────────────────────────┘│││
│││                       Gap: 15.2 kiB                       │││
│││┌──0x0000_8000─ AHAB Container 2 ─────────────────────────┐│││
││││                 Size: 6.9 kiB; 7,109 B                  ││││
││││             AHAB Container for oem_SWver:0              ││││
│││└──0x0000_9bc4────────────────────────────────────────────┘│││
││└──0x0000_bfff──────────────────────────────────────────────┘││
││┌──0x0000_c000─ Container 0 AHAB Data Image 0 ──────────────┐││
│││                 Size: 48.5 kiB; 49,696 B                  │││
│││AHAB encrypted data block for ele core and ele Image Type. │││
││└──0x0001_821f──────────────────────────────────────────────┘││
││                        Gap: 15.5 kiB                        ││
││┌──0x0001_c000─ Container 1 AHAB Data Image 0 ──────────────┐││
│││                 Size: 41.5 kiB; 42,496 B                  │││
│││ AHAB encrypted data block for v2x-1 core and v2x_primary  │││
│││                        Image Type.                        │││
││└──0x0002_65ff──────────────────────────────────────────────┘││
││                        Gap: 2.5 kiB                         ││
││┌──0x0002_7000─ Container 1 AHAB Data Image 1 ──────────────┐││
│││                 Size: 10.2 kiB; 10,496 B                  │││
│││AHAB encrypted data block for v2x-2 core and v2x_secondary │││
│││                        Image Type.                        │││
││└──0x0002_98ff──────────────────────────────────────────────┘││
││                         Gap: 768 B                          ││
││┌──0x0002_9c00─ Container 2 AHAB Data Image 0 ──────────────┐││
│││                Size: 316.0 kiB; 323,584 B                 │││
│││  AHAB data block for cortex-m33 core and oei Image Type.  │││
││└──0x0007_8bff──────────────────────────────────────────────┘││
││┌──0x0007_8c00─ Container 2 AHAB Data Image 1 ──────────────┐││
│││                         Size: 0 B                         │││
│││  AHAB data block for dummy core and oei_ddr Image Type.   │││
││└──0x0007_8bff──────────────────────────────────────────────┘││
││                        Gap: 64.0 kiB                        ││
││┌──0x0008_8c00─ Container 2 AHAB Data Image 2 ──────────────┐││
│││                  Size: 5.0 kiB; 5,120 B                   │││
│││  AHAB data block for cortex-m33 core and oei Image Type.  │││
││└──0x0008_9fff──────────────────────────────────────────────┘││
││┌──0x0008_a000─ Container 2 AHAB Data Image 3 ──────────────┐││
│││                Size: 165.0 kiB; 168,960 B                 │││
│││ AHAB data block for cortex-m33 core and executable Image  │││
│││                           Type.                           │││
││└──0x000b_33ff──────────────────────────────────────────────┘││
││┌──0x000b_3400─ Container 2 AHAB Data Image 4 ──────────────┐││
│││                 Size: 13.0 kiB; 13,312 B                  │││
│││ AHAB data block for cortex-m7-1 core and executable Image │││
│││                           Type.                           │││
││└──0x000b_67ff──────────────────────────────────────────────┘││
││┌──0x000b_6800─ Container 2 AHAB Data Image 5 ──────────────┐││
│││                Size: 156.0 kiB; 159,744 B                 │││
│││ AHAB data block for cortex-a55 core and executable Image  │││
│││                           Type.                           │││
││└──0x000d_d7ff──────────────────────────────────────────────┘││
││┌──0x000d_d800─ Container 2 AHAB Data Image 6 ──────────────┐││
│││                         Size: 0 B                         │││
│││  AHAB data block for cortex-m33 core and v2x_dummy Image  │││
│││                           Type.                           │││
││└──0x000d_d7ff──────────────────────────────────────────────┘││
│└──0x000d_d7ff────────────────────────────────────────────────┘│
┌──0x000d_d800─ secondary_image_container_set ────────────────┐│
││                 Size: 1.8 MiB; 1,909,760 B                  ││
││          AHAB Image for mimx9596, Revision: latest          ││
││                       Pattern: zeros                        ││
││┌──0x000d_d800─ AHAB Containers ────────────────────────────┐││
│││                 Size: 48.0 kiB; 49,152 B                  │││
│││                   AHAB Containers block                   │││
│││                      Pattern: zeros                       │││
│││┌──0x000d_d800─ AHAB Container 0 ─────────────────────────┐│││
││││                 Size: 6.4 kiB; 6,597 B                  ││││
││││             AHAB Container for oem_SWver:0              ││││
│││└──0x000d_f1c4────────────────────────────────────────────┘│││
││└──0x000e_97ff──────────────────────────────────────────────┘││
││┌──0x000e_9800─ Container 0 AHAB Data Image 0 ──────────────┐││
│││                 Size: 42.0 kiB; 43,008 B                  │││
│││ AHAB data block for cortex-a55 core and executable Image  │││
│││                           Type.                           │││
││└──0x000f_3fff──────────────────────────────────────────────┘││
││┌──0x000f_4000─ Container 0 AHAB Data Image 1 ──────────────┐││
│││                Size: 1.2 MiB; 1,223,680 B                 │││
│││ AHAB data block for cortex-a55 core and executable Image  │││
│││                           Type.                           │││
││└──0x0021_ebff──────────────────────────────────────────────┘││
││┌──0x0021_ec00─ Container 0 AHAB Data Image 2 ──────────────┐││
│││                Size: 580.0 kiB; 593,920 B                 │││
│││ AHAB data block for cortex-a55 core and executable Image  │││
│││                           Type.                           │││
││└──0x002a_fbff──────────────────────────────────────────────┘││
│└──0x002a_fbff────────────────────────────────────────────────┘│
└──0x002a_fbff──────────────────────────────────────────────────┘

INFO:spsdk.image.ahab.utils:Segment: Bootable image segment: Primary Image Container Set segment
INFO:spsdk.image.ahab.utils:Skipping signing of none OEM and non signed container
INFO:spsdk.image.ahab.utils:Skipping signing of none OEM and non signed container
INFO:spsdk.image.ahab.utils:On container at absolute offset 0x8000 (AHAB image offset 0x0 + container offset 0x8000) in image 
Name:      primary_image_container_set
Starts:    0x0
Ends:      0xdd7ff
Size:      Size: 886.0 kiB; 907,264 B
Alignment: 512 B
Execution Start Address: Not defined
Pattern:zeros
AHAB Image for mimx9596, Revision: latest
 Has been done following major updates:
signature_block:
  srk_assets:
    _srk_tables:
      original: [AHAB SRK TABLE, keys count: 4, AHAB SRK TABLE, keys count: 4]
      new: [AHAB SRK TABLE, keys count: 4, AHAB SRK TABLE, keys count: 4]
  signature:
    _signature_data:
      original: 009ac5ef8902b76a679533532d02aac677b20b3f0c68fa8e01b675716554d03f...(truncated to 32, total 132)
      new: Not available
  signature_2:
    _signature_data:
      original: 0f5f534892ecd8156f27cd4dca7748b79593aad211cedd11c51ee408cf80bac3...(truncated to 32, total 3309)
      new: Not available

INFO:spsdk.image.ahab.utils:Segment: Bootable image segment: Secondary Image Container Set segment
INFO:spsdk.image.ahab.utils:On container at absolute offset -0x1 (AHAB image offset -0x1 + container offset 0x0) in image 
Name:      secondary_image_container_set
Starts:    -0x1
Ends:      0x1d23fe
Size:      Size: 1.8 MiB; 1,909,760 B
Alignment: 512 B
Execution Start Address: Not defined
Pattern:zeros
AHAB Image for mimx9596, Revision: latest
 Has been done following major updates:
signature_block:
  srk_assets:
    _srk_tables:
      original: [AHAB SRK TABLE, keys count: 4, AHAB SRK TABLE, keys count: 4]
      new: [AHAB SRK TABLE, keys count: 4, AHAB SRK TABLE, keys count: 4]
  signature:
    _signature_data:
      original: 008d169d6b968b6a1602ea4cb90654e6a2da9bf5173920546a79c6754de59a74...(truncated to 32, total 132)
      new: Not available
  signature_2:
    _signature_data:
      original: f00bcb08d0030f204a9dc9484b9fbcf333387d54fd034225d1331fe520e3a6f0...(truncated to 32, total 3309)
      new: Not available

Signed image saved to outputs/flash_signed.bin
INFO:spsdk.image.ahab.ahab_container:Generated file containing SRK hash: outputs/fuse-script/ahab_oem2_srk0_hash.txt
INFO:spsdk.image.ahab.ahab_container:
Fuses info:

 --== Grouped register name: SRKH ==-- 
OTP ID: 128, Value: 0xAC7E9D91
OTP ID: 129, Value: 0x23AC7C1C
OTP ID: 130, Value: 0xE30BBABF
OTP ID: 131, Value: 0x90E70D54
OTP ID: 132, Value: 0x0F1AEFCE
OTP ID: 133, Value: 0x9998792D
OTP ID: 134, Value: 0xDE600650
OTP ID: 135, Value: 0xA144CF97
OTP ID: 136, Value: 0x8F5F329C
OTP ID: 137, Value: 0x97DD1B96
OTP ID: 138, Value: 0x98EEE8E5
OTP ID: 139, Value: 0x3C29B324
OTP ID: 140, Value: 0x708C2065
OTP ID: 141, Value: 0xE2CFF23D
OTP ID: 142, Value: 0xC94B8235
OTP ID: 143, Value: 0xD5C6C344

INFO:spsdk.image.ahab.ahab_container:Generated script for writing fuses for container 2: outputs/fuse-script/ahab_oem2_srk0_hash_nxpele.bcf
INFO:spsdk.image.ahab.ahab_container:Generated file containing SRK hash: outputs/fuse-script/ahab_oem2_srk1_hash.txt
INFO:spsdk.image.ahab.ahab_container:
Fuses info:

 --== Grouped register name: PQC_SRKH ==-- 
OTP ID: 448, Value: 0xA4C25CF9
OTP ID: 449, Value: 0x3A897E6B
OTP ID: 450, Value: 0x65B02428
OTP ID: 451, Value: 0x97674462
OTP ID: 452, Value: 0xBF41C13A
OTP ID: 453, Value: 0x86D9F03A
OTP ID: 454, Value: 0x2EF246AE
OTP ID: 455, Value: 0x7A347919
OTP ID: 456, Value: 0x555B5447
OTP ID: 457, Value: 0xE801DF23
OTP ID: 458, Value: 0x7C278F6D
OTP ID: 459, Value: 0xC8FBEA31
OTP ID: 460, Value: 0x76CA9A8E
OTP ID: 461, Value: 0x3CE47C57
OTP ID: 462, Value: 0x640A8572
OTP ID: 463, Value: 0x09ACB465

INFO:spsdk.image.ahab.ahab_container:Generated script for writing fuses for container 2: outputs/fuse-script/ahab_oem2_srk1_hash_nxpele.bcf
INFO:spsdk.image.ahab.ahab_container:Generated file containing SRK hash: outputs/fuse-script/ahab_oem0_srk0_hash.txt
INFO:spsdk.image.ahab.ahab_container:
Fuses info:

 --== Grouped register name: SRKH ==-- 
OTP ID: 128, Value: 0xAC7E9D91
OTP ID: 129, Value: 0x23AC7C1C
OTP ID: 130, Value: 0xE30BBABF
OTP ID: 131, Value: 0x90E70D54
OTP ID: 132, Value: 0x0F1AEFCE
OTP ID: 133, Value: 0x9998792D
OTP ID: 134, Value: 0xDE600650
OTP ID: 135, Value: 0xA144CF97
OTP ID: 136, Value: 0x8F5F329C
OTP ID: 137, Value: 0x97DD1B96
OTP ID: 138, Value: 0x98EEE8E5
OTP ID: 139, Value: 0x3C29B324
OTP ID: 140, Value: 0x708C2065
OTP ID: 141, Value: 0xE2CFF23D
OTP ID: 142, Value: 0xC94B8235
OTP ID: 143, Value: 0xD5C6C344

INFO:spsdk.image.ahab.ahab_container:Generated script for writing fuses for container 0: outputs/fuse-script/ahab_oem0_srk0_hash_nxpele.bcf
INFO:spsdk.image.ahab.ahab_container:Generated file containing SRK hash: outputs/fuse-script/ahab_oem0_srk1_hash.txt
INFO:spsdk.image.ahab.ahab_container:
Fuses info:

 --== Grouped register name: PQC_SRKH ==-- 
OTP ID: 448, Value: 0xA4C25CF9
OTP ID: 449, Value: 0x3A897E6B
OTP ID: 450, Value: 0x65B02428
OTP ID: 451, Value: 0x97674462
OTP ID: 452, Value: 0xBF41C13A
OTP ID: 453, Value: 0x86D9F03A
OTP ID: 454, Value: 0x2EF246AE
OTP ID: 455, Value: 0x7A347919
OTP ID: 456, Value: 0x555B5447
OTP ID: 457, Value: 0xE801DF23
OTP ID: 458, Value: 0x7C278F6D
OTP ID: 459, Value: 0xC8FBEA31
OTP ID: 460, Value: 0x76CA9A8E
OTP ID: 461, Value: 0x3CE47C57
OTP ID: 462, Value: 0x640A8572
OTP ID: 463, Value: 0x09ACB465

INFO:spsdk.image.ahab.ahab_container:Generated script for writing fuses for container 0: outputs/fuse-script/ahab_oem0_srk1_hash_nxpele.bcf
Exporting AHAB fuses to outputs/fuse-script.
outputs/fuse-script/ahab_oem2_srk0_hash.txt
outputs/fuse-script/ahab_oem2_srk0_hash_nxpele.bcf
outputs/fuse-script/ahab_oem2_srk1_hash.txt
outputs/fuse-script/ahab_oem2_srk1_hash_nxpele.bcf
outputs/fuse-script/ahab_oem0_srk0_hash.txt
outputs/fuse-script/ahab_oem0_srk0_hash_nxpele.bcf
outputs/fuse-script/ahab_oem0_srk1_hash.txt
outputs/fuse-script/ahab_oem0_srk1_hash_nxpele.bcf

3 Download image#

3.1 Download AHAB image#

Set the boot mode to Cortex-M Serial Downloader (1001 on EVK boot switch) and download the files using the UUU tool

%! nxpuuu $VERBOSITY write -f mimx9596 -b emmc $SIGNED_BOOTIMG
nxpuuu -v write -f mimx9596 -b emmc outputs/flash_signed.bin 
SDPS: boot -f outputs/flash_signed.bin


SDPV: write -f outputs/flash_signed.bin -skipspl


SDPV: jump


Success

4. Write fuses#

We need to write SRKH (Super Root Key Hash) to fuses. This can be done using the nxpele tool. When the signed AHAB image is exported, a “.bcf” script is generated.

Note that you need to burn SRKH and also PQC SRKH fuses in this example, because we are using ML-DSA65 keys.

The scripts can be executed using the nxpele batch command:

nxpele -f mimx9596 batch ./outputs/fuse-script/ahab_oem0_srk0_hash_nxpele.bcf

and

nxpele -f mimx9596 batch ./outputs/fuse-script/ahab_oem0_srk1_hash_nxpele.bcf

5. Boot and test#

Now change the boot mode to Cortex-M eMMC (1010 on EVK boot switch) and reset the board. Find the serial port that belongs to U-Boot console and interrupt the boot process. When the console is switched to the U-Boot menu, we can use the nxpele tool to communicate with the ELE.

%! nxpele -f mimx9596 -p COM3 -d uboot_serial get-info
nxpele -f mimx9596 -p COM3 -d uboot_serial get-info 
ELE get info ends successfully:
Command:              0xda
Version:              3
Length:               256
SoC ID:               MX95 - 0x9500
SoC version:          B000
Life Cycle:           OEM_CLSD - 0x0040
SSSM state:           4
Attest API version:   0
UUID:                 c9d88ddf5ace444da168dd2a520630e1
SHA256 ROM PATCH:     72d02b666a524aca0a3162accb4c8de7af33083fc2faefb249d87c7de1437c81
SHA256 FW:            9fdfd92f6f1a6e222362b4a9b5110a964df304a66f91e343d25c3be6a88b75c9
Advanced information:
  OEM SRKH:           41a3ab5e956ff6649e843f2686ada51840415d2fa2b6508960098d5bf6f41f27eafeff21a88f3c4b2ccf08895c1440f4b2675fb0bfe5675333b5fcbb3fba9a45
  CSAL state:         EdgeLock secure enclave random context initialization succeed - 0x02
  TRNG state:         TRNG entropy is valid and ready to be read - 0x03
  OEM PQC SRKH:       643dcc626197897115d7cce1ec079c479399af59cd46b9b45b6578fabe86d20e788683151239d8128c4f8ccc871ea86c9d8ee58b6e03e9bf8fdbde6b21b5bd09