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
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