Secure Boot on IMX93 with AHAB¶
This page explains the bootloader authentication on Welma, for machines with i.MX applications processors that support Advanced High Assurance Boot (AHAB), typically machine sm2s-imx93-mbep5.
References:
- EdgeLock Secure Enclave (ELE) API Reference Guide (Rev.2 04/2023)
- i.MX 93 Applications Processor Security Reference Manual (Rev.4 12/2023)
- i.MX 93 Application Processor Reference Manual (Rev.5 05/2024)
- AN12312 Secure Booot on AHAB Supported Devices (rev.1 14/08/2023)
- Code Signing Tool User's Guide (rev 3.3.2 04/2023)
- U-Boot's documentation: introduction ahab
- U-Boot's documentation: mx8ulp/9x secure boot
Acronyms:
- CSF: Command Sequencer File
- CST: Code-Signing Tool
- AHAB: Advanced High Assurance Boot
- IVT: Initial Vector Table
- SPL: Second Program Loader
- SRK: Super Root Key
imx-boot structure¶
The built image is named imx-boot
, it consists of 3 containers and is
structured as follows:
Compared to HABv4, AHAB does not use CSF binaries. The SRK table and Signature
for container headers and image information is inserted into the Signature Block
region of the imx-boot
binary.
All 3 containers must be signed to successfully boot into U-Boot with AHAB enabled. 1st container is proprietary binary and it comes signed already. We only have to sign 2nd and 3rd containers.
The idea is generally the same as what's done for HABv4 - imx-boot's do_compile log is parsed to figure out correct offsets. Those offsets are later used to generate CSF files used as input to CST.
i.MX93 supports ECC and RSA keys, however PSS needs to be used as signature algorithm when RSA keys are chosen. However, it was decided to use the EC keys, as they're suggested default.
Secure boot stages¶
The secure boot process involves multiple stages of verification, each using specific assets and cryptographic algorithms. The default cryptographic algorithm used is EC P384, SHA-384 as signature hashing algorithm, and SHA256 as digest algorithm.
ELE FW is the image inside of the 1st container of imx-boot
.
It's being authenticated first, and, if successful, ELE jumps to ELE FW
that handles the rest of the boot process.
ELE FW is NXP proprietary binary and comes pre-signed with NXP keys.
-
ELE FW Authentication: This comes from NXP and is a proprietary binary
-
Assets:
-
"NXP header and signature" (image above):
- SRK TABLE: table of the public keys
- Signature: signature that signs Container Headers, Signature Headers and SRK Table
-
ELE FW
-
-
Authentication:
- The A35 ROM loads ELE FW into internal RAM.
- The ELE ROM code authenticates the ELE FW signature.
- ELE switches from ROM to authenticated FW.
- ELE authenticates OEM container header
- The container header are loaded to target RAM (A35 in singleboot (our) case)
- ELE authenticates container header currently being processed and returns status response to boot core.
-
-
SPL Image Authentication:
-
Assets contained:
- u-boot-spl
-
Authentication:
- SRK Table (inside of BL2 header and signature) is verified against the NXP/OEM SRK fuses.
- The container signature is verified against the SRK.
-
-
FIT Image Loading: The SPL loads the contents of the 3rd container (BL3) into external RAM. The 3rd container packages the next components which are U-boot binary with device tree blob, ARM trusted firmware, and OP-TEE binary.
-
The ROM Code starts u-boot SPL.
-
BL3 container authentication:
-
Assets contained in BL3 container:
- bl31.bin (ATF)
- u-boot
- tee.bin (OP-TEE)
-
Authentication:
- SRK Table (inside of BL3 header and signature) is verified against the NXP/OEM SRK fuses.
- The container signature is verified against the SRK.
-
-
Execution of U-Boot:
- The SPL passes control to ATF, OP-TEE and U-Boot.
Setting up your Secure Boot¶
This section will guide you through the process of building and running an image with secure boot.
It is assumed the following context:
- IMX machine (eg: sm2s-imx93-mbep5)
- Default Welma partition layout
- Default Welma AHAB development keys used in the Yocto build
- Production keys owned by a separate entity (other than the development team)
Building your Image¶
This section explains what you need to do to support secure boot on a new board. Welma supported boards already have all this.
Welma requirements:
-
machine.conf:
- Set
BOOT_SIGNING_MECHANISM = "imx"
- Set
BOOT_SIGNING_MECHANISM_VERSION = "ahab"
- Set
-
In
local.conf
- Activate secure boot by defining
WELMA_SECURE_BOOT = "1"
(this is the default) - Adjust or keep the default values for
WELMA_KEY_SWK1_PUB
andWELMA_KEY_SWK1_PRIV
- Activate secure boot by defining
-
Other variables:
WELMA_KEYS_DIR
: Directory of the public keys used for the SRK tableIMG_KEY
: Path to IMGK. Must be named%_crt.pem
and have its related private key in../keys/%.key.pem
. (default: one of the development keys).
-
imx-boot:
- Have the
uboot-offsets-sd
file generated and deployed. It is produced by a patch to U-Boot. It indicates nodtb U-Boot's size and U-Boot's FDT size. These parameters are later inserted intoimx-boot-offsets-sd
. - Have the
imx-boot-offsets-sd
file generated and deployed. It indicates which blocks of imx-boot shall be authenticated. - Have
WELMA_KEY_SWK1_PUB
injected (executeimx-uboot-tool-ahab
). - Have imx-boot signed with the selected keys and embed all necessary
certificates (execute
imx-sign
).
- Have the
-
u-boot:
- Activate AHAB, FIT signature and legacy image format (
CONFIG_AHAB_BOOT
,CONFIG_FIT_SIGNATURE
) - Ensure another patch to U-Boot allowing to use
hexvalue
option forfdt
command to U-Boot is applied - Deactivate the HAB authentication of the kernel FIT image because it is replaced by the regular U-Boot mechanism.
- Disable the U-Boot command line or restrict its access by a password, because it would allow an attacker to bypass the secure boot mechanism.
- Activate AHAB, FIT signature and legacy image format (
-
In SYSRO and APPRO: have your programs not start other programs located in SYSRW, as this filesystem is not covered by secure boot. Keep in mind that
/home
is located in SYSRW and make sure that files such as~/.profile
,~/.bashrc
, etc. do not get executed automatically if they were created by an attacker.
The following files are output in DEPLOYDIR
:
${DEPLOYDIR}/fuse-bootcmd.scr
${DEPLOYDIR}/imx-boot-tools/imx-boot-offsets-sd
Signing your Image with Production Keys¶
Input:
-
Generated by the build:
- imx-boot
- imx-boot-offsets-sd
- fitImage (BOOT)
- .verity images (SYSRO, APPRO)
-
Production Keys: SWK1.priv, SWK1.crt
Ouput (signed images provisioned with necessary public keys):
- imx-boot
- BOOT vfat partition
- SYSRO and APPRO verity partitions
Steps:
-
Inject SWK1.crt into imx-boot
- Execute
imx-uboot-tool-ahab
(will extractu-boot-dtb
from imx-boot; inject SWK1.crt intou-boot-dtb
; replaceu-boot-dtb
in imx-boot)
- Execute
Note
Some padding is added to dt.dtb
, used to provide enough space
in dt.dtb
for it to be injected with the SWK1 pubkey.
Controlled from yocto build by the variable WELMA_DTB_PADDING
.
Currently set to 4096 (should be at least 3072 in case of
sha256,rsa4096 hash sign algos).
welma-signing-tools/imx/imx-uboot-tool-ahab inject-pubkey \
--imx-boot imx-boot \
--offsets-file imx-boot-offsets-sd \
--cert SWK1.crt \
--uboot-pubkey-algo sha256,rsa4096
-
Sign fitImage:
-
Create the BOOT partition (vfat) populated with the signed fitImage, using
mkdosfs
&mcopy
-
Sign .verity images:
Fusing your Products¶
-
Prepare the hash of the SRK table to be fused: Sign imx-boot
-
Disable JTAG
Scripts to use to generate the needed keys and signatures¶
The files are located in the repository welma-signing-tools
. It contains three
scripts:
imx-keygen
: This script will create a set of keys to be used to sign the bootloader. The default key for AHAB is EC p384 with 30 years of validity. The--remove-passphrase
option is mandatory for AHAB version of the script.imx-sign
: This takes the binary to sign, secure boot version (habv4 or ahab), the CSF files templates, the directory containing the keys and the mkimage log files generated at build time. It then generates a new signed binary file to be flashed on the board.imx-srk-table-gen
: This script is used to generate the eFuses dump. It copies necessary key and certificate files, runs the SRK tool to generate fuse binaries, and create s a boot environment file with commands to program the fuses. It also provides a formatted output of the fuse programming commands for manual use.
Those scripts can be called within Yocto or externally.
Yocto Build variables¶
In order to activate the needed feature the build must be modified to include
WELMA_SECURE_BOOT = "1"
in the local.conf
file. It is possible to override
some default variables for signing.
The following variables in the build process can be overridden in your
local.conf
file:
-
WELMA_KEYS_DIR
: This variable is used to define the path to the keys. The default value for sm2s-imx93-mbep5 MACHINE is${STAGING_DATADIR_NATIVE}/default-dev-keys-ahab
. -
CSF_TEMPLATE
: This variable is used to define the path to the CSF templates. The default value is${STAGING_DATADIR_NATIVE}/templates
. -
IMG_KEY
: This variable is used to define the path to the sign key, relative toWELMA_KEYS_DIR
. The default value for sm2s-imx93-mbep5 MACHINE is./crts/SRK1_sha384_secp384r1_v3_usr_crt.pem
.
Burning the eFuses¶
During the Yoco build, a file named fuse-bootcmd.scr
is created.
It is installed in the DEPLOYDIR
.
Warning
These commands are writing to One-Time Programmable (OTP) eFuses.
Each eFuse is one bit, and the registers are 32 bits. These eFuses
can only be written to once. However, while a bit is 0
, it can be
set to 1
even if the full 32-bit word has been written. Be absolutely
certain that you want to write to the OTP before running these commands.
Once a bit is set to 1
, the data cannot be changed or erased.
Before closing the device, ensure there are no pending events by running
the ahab_status
command.
In U-Boot download the script using tftp:
u-boot=> setenv ipaddr 10.0.0.2 && setenv serverip 10.0.0.1
u-boot=> tftp fuse-bootcmd.scr
Using ethernet@42890000 device
TFTP from server 10.0.0.1; our IP address is 10.0.0.2
Filename 'fuse-bootcmd.scr'.
Load address: 0x80400000
Loading: #
545.9 KiB/s
done
Bytes transferred = 1119 (45f hex)
u-boot=> source $loadaddr
## Executing script at 80400000
New commands available:
run mfg_fuse_rot_otp
run mfg_close_device
WARNING! THESE COMMANDS ARE WRITING TO OTP REGISTERS AND CAN BE RUN ONLY ONCE ON A PART
BE SURE YOU REALLY WANT TO WRITE OTP BEFORE RUNNING THESE COMMANDS
BEFORE CLOSING DEVICE CHECK LACK OF EVENTS WITH COMMAND hab_status
It is possible to check the values written in the fuses with fuse sense
in U-Boot:
u-boot=> fuse sense 16 0 8
Sensing bank 16:
Word 0x00000000: a0dc1592 13632529 e3b8625f 75dd7454
Word 0x00000004: 7f4595e0 a9bb9995 25fc6ad4 6d6d22a9
Offline signing of imx-boot¶
In order to sign imx-boot with other keys than the default ones after a Yocto build, two scripts need to be called:
imx-srk-table-gen
will create the fuse table for the new keysimx-sign
will sign the binary file with the new keys
Pre-requisites:
- python3
- have
srktool
andcst
inPATH
.
Inputs:
- imx-boot
- private and public keys
- offset file (
imx-boot-offsets-sd
)
Outputs:
- imx-boot (provisioned with public keys and signed)
- u-boot fuse commands
Example:
$ imx-srk-table-gen --keys /path/to/SRK*_crt.pem \
--srk-table /path/to/srk_table \
--srk-fuse-instructions-uboot /path/to/fuse-bootcmd.env \
--sb-version ahab
$ imx-sign \
--sb-version ahab \
--imgk /path/to/SRK1_sha384_secp384r1_v3_usr_crt.pem \
--srk-table /path/to/srk_table \
--template /path/to/template_csf_ahab.txt \
--bootloader /path/to/imx-boot \
--output /path/to/imx-boot.signed \
--imx-boot-offsets /path/to/imx-boot-offsets-sd
Test cases¶
The following test cases are designed to verify the secure boot process. The main objective is to ensure that there are no Advanced High Assurance Boot (AHAB) events that might indicate a security breach or a failure in the secure boot process.
To check for AHAB events, we stop the U-Boot execution and launch the
ahab_status
command. This command displays the AHAB events that occurred
during the boot process. A successful test case will show no AHAB events.
Note
These test cases are performed on a non-closed device. In a non-closed device, the secure boot is not fully enforced, allowing for testing and debugging.
U-Boot signed with matching keys¶
This is the nominal case, where the keys used have been properly fused. In this case there will be no AHAB events.
- Case of a non-closed device:
- Case of a closed device:
(information upcoming in a future version of this document)
Unsigned U-Boot or signed with a wrong key¶
When U-Boot is unsigned or signed with an incorrect key, HAB events are
triggered. These events indicate a failure in the secure boot process. The
ahab_status
command will show an AHAB event with a indicator either of:
ELE_NO_AUTHENTICATION_FAILURE_IND
(U-Boot was not signed at all)ELE_BAD_KEY_HASH_FAILURE_IND
- ...
Example:
=> ahab_status
Lifecycle: 0x00000008, OEM Open
0x0287fad6
IPC = MU APD (0x2)
CMD = ELE_OEM_CNTN_AUTH_REQ (0x87)
IND = ELE_BAD_KEY_HASH_FAILURE_IND (0xFA)
STA = ELE_SUCCESS_IND (0xD6)
0x0287fad6
IPC = MU APD (0x2)
CMD = ELE_OEM_CNTN_AUTH_REQ (0x87)
IND = ELE_BAD_KEY_HASH_FAILURE_IND (0xFA)
STA = ELE_SUCCESS_IND (0xD6)
Note
For more information, see EdgeLock Secure Enclave (ELE) API Reference Guide for possible IND (indication) fields (section 4.3 "Response Indication") or possibe CMD (command) fields (section 3 "Messages").
Badly signed or corrupted imx-boot on a closed device¶
In case the device has been closed, no boot can occur if the keys are not good, or if the imx-boot image is corrupted in some way. In this case, u-boot will not be started and the result is:
(information upcoming in a future version of this document)
In this case, to fix your device, do a first installation with a properly signed imx-boot.