Secure Boot on IMX with HABv4¶
This pages explains the bootloader authentication on Welma, for machines with i.MX applications processors that support High Assurance Boot version 4 (HAB4), typically machine sm2s-imx8plus-mbep5.
References:
- NXP AN4581: i.MX Secure Boot on HABv4 Supported Devices, Rev. 0, 09/2012
- NXP CST: i.MX High Assurance Boot Reference Code Signing Tool
- U-Boot: doc/imx/habv4/guides/mx8m_secure_boot.txt
Acronyms:
- CSF: Command Sequence File
- CST: NXP Code-Signing Tool version >= 3.3.1
- FIT: Flattened Image Tree. In this context, it is used as a container (for BL3 stages according to Trusted Firmware-A terminology)
- HAB: High Assurance Boot
- SPL: Second Program Loader, also known as BL2 according to Trusted Firmware-A terminology
- SRK: Super Root Key
imx-boot structure¶
The built image is named imx-boot
and is structured as follows (padding is
not shown):
-------- +-----------------------------+ --------
Signed ^ | u-boot-spl | ^
Data v | DDR FW | |
--------- +-----------------------------+ | SPL (~BL2)
| CSF (commands, SRK table, | | Block
| signatures, certificates) | v
-------- +-----------------------------+ --------
Signed ^ | FIT header | ^
Data v | | |
--------- +-----------------------------+ |
| CSF (commands, SRK table, | |
| signatures, certificates) | | FIT (~BL3)
-------- +-----------------------------+ | Block
^ | u-boot.bin | |
Signed | | u-boot.dtb | |
Data | | bl31.bin (ATF) | |
v | OP-TEE (Optional) | v
-------- +-----------------------------+ --------
The CSF contains all the commands that the ROM executes during the secure boot. These commands instruct HABv4 on which memory areas of the image to authenticate, which keys to install and use, what data to write to a register, and so on. In addition, the necessary certificates and signatures involved in the verification of the image, as well as the SRK table, are attached to the CSF binary signature.
Two CSF binaries are required:
- CSF-SPL used by the boot ROM to authenticate and load the SPL image + DDR firmware
- CSF-FIT used by SPL (through HAB APIs) to authenticate and load the FIT components
First, i.MX Boot ROM reads the eFuses to determine the security configuration of the SoC and the type of the boot device. The ROM then loads the SPL image and verifies its signature embedded in the CSF. If it succeeds, SPL is executed. A FIT image is used to package the next components which are:
- U-boot and its control device tree blob
- ARM trusted firmware
- OP-TEE binary
If that second stage verification succeeds, control is passed to U-Boot which then loads the Linux kernel and initiates the boot process.
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 RSA 4096 with SHA-256 for hashing.
-
SPL CSF Authentication:
-
Assets contained in the SPL CSF:
- SRK_1_2_3_4: table of the 4 public keys SRK1, 2, 3, 4 (DER format)
- CSFK: certificate (X.509 DER format)
- IMGK: certificate (X.509 DER format)
-
Authentication:
- The ROM loads the SPL block into on-chip RAM.
- The ROM Code authenticates the SRK_1_2_3_4 table using OCOTP_SRK_HASH (SHA-256) stored in the OTP fuses.
- The ROM Code authenticates CSFK using SRK1 (RSA-4096, SHA-256)
- The ROM Code authenticates the SPL CSF using CSFK (RSA-4096, SHA-256)
-
-
SPL Image Authentication:
-
Assets contained:
- u-boot-spl
- DDR FW
-
Authentication:
- The ROM Code authenticates IMGK using SRK1 (RSA-4096, SHA-256)
- The ROM Code authenticates the SPL image using IMGK (RSA-4096, SHA-256)
-
-
The ROM Code starts u-boot-spl.
-
FIT CSF Authentication:
-
Assets contained in the FIT CSF:
- SRK_1_2_3_4: table of the 4 public keys SRK1, 2, 3, 4 (DER format)
- CSFK: certificate (X.509 DER format)
- IMGK: certificate (X.509 DER format)
-
Authentication:
- u-boot-spl loads the FIT block into external RAM. The FIT header has references to U-boot bin and dtb, ATF, and OP-TEE.
- u-boot-spl authenticates the SRK_1_2_3_4 table using OCOTP_SRK_HASH (SHA-256) stored in the OTP fuses.
- u-boot-spl authenticates CSFK using SRK1 (RSA-4096, SHA-256)
- u-boot-spl authenticates the FIT CSF using CSFK (RSA-4096, SHA-256)
-
-
FIT Image Authentication:
-
Assets contained:
- u-boot.bin
- u-boot.dtb
- bl31.bin (ATF)
- OP-TEE
-
Authentication:
- The SPL authenticates IMGK using SRK1 (RSA-4096, SHA-256)
- The SPL authenticates the FIT image using IMGK (RSA-4096, SHA-256)
-
-
u-boot-spl passes control ATF, OP-TEE, 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-imx8plus-mbep5)
- Default Welma partition layout
- Default Welma 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 = "hab4"
- 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 tableCSF_KEY
: Path to CSFK. Must be named%_crt.pem
and have its related private key in../keys/%.key.pem
. (default: one of the development keys).IMG_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
imx-boot-offsets-sd
file generated and deployed. It indicates which blocks of imx-boot shall be authenticated. - Have imx-boot signed with the development keys and embed all necessary
certificates (execute
imx-sign
). - Have
WELMA_KEY_SWK1_PUB
injected (executeinject-pubkey-uboot-dtb
).
- Have the
-
u-boot:
- Activate HAB (
CONFIG_IMX_HAB
) - 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 HAB (
-
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
- Extract
u-boot-dtb
from imx-boot (tool upcoming) - Inject SWK1.crt into
u-boot-dtb
: - Replace
u-boot-dtb
in imx-boot (tool upcoming)
- Extract
-
Sign fitImage:
- Create the BOOT partition (vfat) populated with the signed fitImage, using
mkdosfs
&mcopy
- Create the BOOT partition (vfat) populated with the signed fitImage, using
-
Sign .verity images:
Fusing your Products¶
-
Prepare the hash of the SRK table to be fused: Sign imx-boot
-
Disable JTAG
Burning the eFuses¶
fuse-bootcmd.scr
can be used in then u-boot command line interpreter to burn
the eFuses.
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 hab_status
command.
Example:
u-boot=> setenv ipaddr 169.254.142.1 && setenv serverip 169.254.142.224
u-boot=> tftp fuse-bootcmd.scr
Using ethernet@30bf0000 device
TFTP from server 169.254.142.224; our IP address is 169.254.142.1
Filename 'fuse-bootcmd.scr'.
Load address: 0x40480000
Loading: #
67.4 KiB/s
done
Bytes transferred = 692 (2b4 hex)
u-boot=> source $loadaddr
## Executing script at 40480000
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
u-boot=>
Check the values written in the fuses with fuse sense
in U-Boot:
u-boot=> fuse sense 6 0 4
Sensing bank 6:
Word 0x00000000: dadd030d 8b5d3ea7 4ec5a321 836ff123
u-boot=> fuse sense 7 0 4
Sensing bank 7:
Word 0x00000000: 6578c108 e7483aab 51fe0260 25f904da
When a device is closed, hab_status
reflects the following:
u-boot=> hab_status
Secure boot enabled
HAB Configuration: 0xcc, HAB State: 0x99
No HAB Events Found!
Offline signing of imx-boot¶
In order to sign imx-boot
with other keys, after a Yocto
build (and out of the Yocto build environment), two scripts can to be used:
imx-srk-table-gen
: will create the SRK table for the new public keysimx-sign
: will sign the binary file with the new private keys and insert the SRK table
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 hab4
$ imx-sign --sb-version hab4 \
--csfk /path/to/csfk_crt.pem \
--imgk /path/to/imgk_crt.pem \
--srk-table /path/to/srk_table \
--template /path/to/csf_template \
--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 High Assurance Boot (HAB) events that might indicate a security breach or a failure in the secure boot process.
To check for HAB events, we stop the U-Boot execution and launch the
hab_status
command. This command displays the HAB events that occurred during
the boot process. A successful test case will show no HAB 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 HAB events:
u-boot=> hab_status
Secure boot disabled
HAB Configuration: 0xf0, HAB State: 0x66
No HAB Events Found!
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
hab_status
command will show a HAB event with a status of HAB_FAILURE,
signifying a failure, and a reason of HAB_INV_CERTIFICATE, indicating an invalid
certificate. This suggests that the key used to sign U-Boot does not match the
one fused into the device, or that U-Boot was not signed at all.
Both give the following hab_status
output:
u-boot=> hab_status
Secure boot disabled
HAB Configuration: 0xf0, HAB State: 0x66
--------- HAB Event 1 -----------------
event data:
0xdb 0x00 0x14 0x45 0x33 0x21 0xc0 0x00
0xbe 0x00 0x0c 0x00 0x03 0x17 0x02 0x00
0x00 0x00 0x00 0x7c
STS = HAB_FAILURE (0x33)
RSN = HAB_INV_CERTIFICATE (0x21)
CTX = HAB_CTX_COMMAND (0xC0)
ENG = HAB_ENG_ANY (0x00)
--------- HAB Event 2 -----------------
event data:
0xdb 0x00 0x14 0x45 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x40 0x1f 0xdd 0xc0
0x00 0x00 0x00 0x20
STS = HAB_FAILURE (0x33)
RSN = HAB_INV_ASSERTION (0x0C)
CTX = HAB_CTX_ASSERT (0xA0)
ENG = HAB_ENG_ANY (0x00)
--------- HAB Event 3 -----------------
event data:
0xdb 0x00 0x14 0x45 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x00 0x91 0xff 0xc0
0x00 0x00 0x00 0x20
STS = HAB_FAILURE (0x33)
RSN = HAB_INV_ASSERTION (0x0C)
CTX = HAB_CTX_ASSERT (0xA0)
ENG = HAB_ENG_ANY (0x00)
--------- HAB Event 4 -----------------
event data:
0xdb 0x00 0x14 0x45 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x00 0x91 0xff 0xe0
0x00 0x00 0x00 0x0c
STS = HAB_FAILURE (0x33)
RSN = HAB_INV_ASSERTION (0x0C)
CTX = HAB_CTX_ASSERT (0xA0)
ENG = HAB_ENG_ANY (0x00)
--------- HAB Event 5 -----------------
event data:
0xdb 0x00 0x14 0x45 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x00 0x92 0x00 0x00
0x00 0x00 0x00 0x04
STS = HAB_FAILURE (0x33)
RSN = HAB_INV_ASSERTION (0x0C)
CTX = HAB_CTX_ASSERT (0xA0)
ENG = HAB_ENG_ANY (0x00)
--------- HAB Event 6 -----------------
event data:
0xdb 0x00 0x14 0x45 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x40 0x1f 0xcd 0xc0
0x00 0x00 0x00 0x04
STS = HAB_FAILURE (0x33)
RSN = HAB_INV_ASSERTION (0x0C)
CTX = HAB_CTX_ASSERT (0xA0)
ENG = HAB_ENG_ANY (0x00)
--------- HAB Event 7 -----------------
event data:
0xdb 0x00 0x14 0x45 0x33 0x21 0xc0 0x00
0xbe 0x00 0x0c 0x00 0x03 0x17 0x00 0x00
0x00 0x00 0x00 0x5c
STS = HAB_FAILURE (0x33)
RSN = HAB_INV_CERTIFICATE (0x21)
CTX = HAB_CTX_COMMAND (0xC0)
ENG = HAB_ENG_ANY (0x00)
The first HAB event indicates a failure (STS = HAB_FAILURE). The reason for the failure is an invalid certificate (RSN = HAB_INV_CERTIFICATE). This event occurred in the context of a command (CTX = HAB_CTX_COMMAND). The engine field (ENG = HAB_ENG_ANY) suggests that the event can be associated with any engine.
This is also true when the image is corrupted.
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:
Trying to boot from BOOTROM
image offset 0x8000, pagesize 0x200, ivt offset 0x0
Authenticate image from DDR location 0x401fcdc0...
spl: ERROR: image authentication unsuccessful
resetting ...
To repair your device, you will need to re-install a properly signed
imx-boot (using a SD card or the uuu
tool).