Secure Boot (AHAB) on i.MX 9
i.MX 91, i.MX 93 and i.MX 95 processors verify the boot image with
AHAB (Advanced High Assurance Boot), implemented by the EdgeLock Secure
Enclave (ELE). This page explains how AHAB works on Cargt SOMs and the steps
to sign an image. It does not replace NXP’s documentation: the processor’s
Security Reference Manual and the Code Signing Tool (CST) user guide are the
authoritative sources; see References. U-Boot’s own guide,
doc/imx/ahab/guides/mx8ulp_9x_secure_boot.txt in the U-Boot source, has
the full procedure.
Danger
Programming the SRK hash fuses and closing the device are permanent. A wrong SRK hash, or closing a device that does not boot a correctly signed image, leaves the SOM unable to boot, and it cannot be recovered. Practise on a SOM you can afford to lose, keep the signing keys offline, and contact Cargt before closing production parts.
Checking the Lifecycle
Current Cargt U-Boot builds do not include ahab_status (see the
warning in step 2), but the lifecycle can be read on any Cargt U-Boot. On i.MX 93, bits 9:0 of the FSB register at
0x4751041c hold the lifecycle (on i.MX 95 the register is at
0x47510414). This only reads the register. From an i.MX 93 00363 on the
00428 carrier:
u-boot=> md.l 0x4751041c 1
4751041c: 04018c08 ....
0x04018c08 & 0x3ff is 0x008, OEM Open. The i.MX 93 values are:
Value |
Lifecycle |
|---|---|
|
Blank |
|
Fab |
|
NXP Provisioned |
|
OEM Open (as shipped) |
|
OEM Closed |
|
Field Return OEM |
|
Field Return NXP |
|
OEM Locked |
|
Bricked |
The i.MX 95 uses different values (0x010 is OEM Open); see U-Boot’s
display_life_cycle() in arch/arm/mach-imx/ele_ahab.c.
How AHAB Works
The boot image (imx-boot) is a sequence of containers, each with a
header and a signature block. On i.MX 91 and i.MX 93:
Container |
Contents |
Signed by, checked by |
|---|---|---|
1 |
ELE firmware |
NXP; checked by the ELE ROM |
2 |
SPL (and the Cortex-M image, if any) |
You (OEM keys); checked by the ELE firmware |
3 |
ATF, OP-TEE and U-Boot proper |
You (OEM keys); checked by SPL through the ELE |
The i.MX 95 image also carries the OEI, System Manager and V2X firmware; see i.MX 95 Boot Firmware and System Manager and the image layout in U-Boot’s guide.
The OEM keys form a PKI tree. Its root is the Super Root Key (SRK) table: up to four SRK public keys. A hash of that table is programmed once into the SRK_HASH fuses, and the ELE compares every signed container’s SRK table against it. On i.MX 91 and i.MX 93 the hash is SHA-256 (256 bits, eight fuse words).
Warning
The i.MX 95 (B0 and later) uses AHAB 2.0, which works differently: the SRK hash is 512 bits, programmed into sixteen fuse words in banks 16 and 17, and signing needs CST 4.0.1 or later, or NXP’s Secure Provisioning SDK (SPSDK). The i.MX 91/93 steps below do not apply to it as written, and following them can leave an i.MX 95 SOM unable to boot once it is closed. Follow the i.MX 95 sections of U-Boot’s guide and NXP’s SPSDK example for the i.MX 95, and contact Cargt first.
The device lifecycle decides what happens when a check fails:
OEM Open (as shipped): the image is checked and failures are logged as events, but the device still boots. Use this state to test signed images.
OEM Closed: only correctly signed images boot. Changing to this state is irreversible.
Steps
These steps are for i.MX 91 and i.MX 93; see the warning above for the i.MX 95.
Get the Code Signing Tool from NXP (an NXP account is required), and generate the AHAB PKI tree with the scripts it provides. Then create the SRK table and the SRK hash fuse file with
srktool. Keep the private keys offline or in an HSM.Enable AHAB support in U-Boot. Add
CONFIG_AHAB_BOOT=yto the U-Boot configuration, for example with a configuration fragment in au-boot-imxbbappend in your layer. This adds theahab_*commands and makes SPL authenticate the U-Boot container through the ELE.Warning
In NXP’s U-Boot (
u-boot-imx2026.04),CONFIG_AHAB_BOOTalso changesbooti: it expects the kernel to be packaged as an AHAB OS container and fails withAuthenticate OS container is failedfor a plainImage, even in the OEM Open lifecycle. Cargt images boot a plainImage, so enablingCONFIG_AHAB_BOOTon its own stops the board from booting Linux. Enable it only together with packaging the kernel and device tree as an OS container (see Authenticating the Kernel).Current Cargt U-Boot builds (wrynose, October 2026) do not enable
CONFIG_AHAB_BOOT, so theahab_*andauth_cntrcommands are not available in them.Build the boot image.
imx-mkimage, run by theimx-bootrecipe, prints the container and signature block offsets that the CST needs. Fromimx-boot’slog.do_compilefor an i.MX 93 00363 build:Output: u-boot-atf-container.img ... CST: CONTAINER 0 offset: 0x0 CST: CONTAINER 0: Signature Block: offset is at 0x190 ... Output: flash.bin ... CST: CONTAINER 0 offset: 0x400 CST: CONTAINER 0: Signature Block: offset is at 0x490 append u-boot-atf-container.img at 348 KB, psize=1024
Sign the containers with the CST, using CSF description files that name your keys and the offsets from step 3. Sign
u-boot-atf-container.imgfirst, rebuildflash.binwith the signed container, then signflash.bin:./cst -i csf_uboot_atf.txt -o signed-u-boot-atf-container.img ./cst -i csf_boot_image.txt -o signed-flash.bin
Example CSF files are in U-Boot’s
doc/imx/ahab/csf_examples.Flash the signed image with UUU as usual; see Getting Started.
Program the SRK hash fuses (permanent). The fuse file from
srktoolholds eight 32-bit words:od -t x4 SRK_1_2_3_4_fuse.bin
On i.MX 93 they go in fuse bank 16, words 0 to 7, programmed from the U-Boot prompt with
fuse prog 16 <word> <value>, one command per word. For the i.MX 91, take the bank and words from its fuse map in the Security Reference Manual. Check every value twice before running these commands.Check for AHAB events. Boot the signed image and run
ahab_statusat the U-Boot prompt. It prints the lifecycle and the ELE’s event log, which records authentication problems since power-on. With the SRK hash fused and a correctly signed image, it reportsNo Events Found!.For comparison, this is an unsigned Cargt image on an i.MX 93 00363 (00428 carrier) in the OEM Open lifecycle. The board boots, but the ELE logs an event for the OEM container authentication request (
ELE_OEM_CNTN_AUTH_REQ):u-boot=> ahab_status Lifecycle: 0x00000008, OEM Open 0x0287eed6 IPC = MU APD (0x2) CMD = ELE_OEM_CNTN_AUTH_REQ (0x87) IND = ELE_NO_AUTHENTICATION_FAILURE_IND (0xEE) STA = ELE_SUCCESS_IND (0xD6)Any event means the device might not boot once closed. Do not continue until there are none.
ahab_dumpprints the ELE firmware’s raw debug log, which NXP support can interpret.Close the device (permanent, optional for development): run
ahab_closeat the U-Boot prompt and reboot.ahab_statusthen reportsOEM Closed.
Authenticating the Kernel
AHAB as described above covers the boot loader. To extend the chain of trust
to Linux, U-Boot can authenticate a signed OS container with auth_cntr.
Cargt U-Boot environments include the hooks: when sec_boot is yes,
bsp_bootcmd loads os_cntr_signed.bin and authenticates it with
auth_cntr before booting. You do not set sec_boot yourself: Cargt
U-Boot sets it at every boot, to yes when it is built with
CONFIG_AHAB_BOOT and to no otherwise. See U-Boot’s
doc/imx/ahab/guides/sign_os_cntr.txt.
For storing application keys, see Secure Key Storage (EdgeLock and OP-TEE).
Protect the U-Boot console as well; otherwise anyone with console access can
change bootcmd, or sec_boot for the current boot.