NXP i.MX8MP 作为面向中高端嵌入式场景的 SoC,其 QSPI(FlexSPI NOR)安全启动基于 HABv4(High Assurance Boot v4)机制,通过数字签名验证确保只有授权镜像才能启动,防止固件篡改与非授权执行。该方案核心依赖 CST(Code Signing Tool)生成密钥与签名镜像,结合芯片 Fuse 烧录建立信任根,实现从 Boot ROM 到应用层的全链路安全验证。本文详解 i.MX8MP QSPI 安全启动的原理、镜像编译、签名流程与验证方法,适用于需要固件安全防护的嵌入式产品开发。
资料获取:在i.MX8MP上QSPI的安全启动
1. 核心原理与关键组件
1.1 安全启动核心逻辑
i.MX8MP 的安全启动通过 “信任链逐级验证” 实现,核心流程如下:
- 信任根建立:芯片出厂后,将 SRK(Super Root Key)哈希烧录至 Fuse,Boot ROM 仅信任该哈希对应的公钥证书;
- 镜像签名验证:启动镜像(SPL、U-Boot、ATF 等)经 CST 工具签名,包含 SRK 表、公钥证书与数字签名;
- 启动验证流程:
- 芯片复位后,Boot ROM 读取 QSPI Flash 中的镜像,提取 SRK 表哈希并与 Fuse 中的哈希比对;
- 比对通过后,用 SRK 公钥解密镜像签名,计算镜像哈希并与解密后的签名哈希比对;
- 所有验证步骤通过后,依次启动 SPL、ATF、U-Boot 等组件,任一环节失败则进入 SDP(Serial Download Protocol)模式。
1.2 关键组件解析
| 组件 | 作用 | 核心特性 |
|---|---|---|
| HABv4 | 嵌入式在 Boot ROM 中的安全验证引擎 | 支持 RSA/SHA 加密算法,提供镜像签名验证 API |
| CST | 签名工具(基于 OpenSSL) | 生成 SRK 表、密钥对、数字签名,输出签名镜像 |
| SRK | 超级根密钥 | 4 个密钥组成 SRK 表,哈希烧录至 Fuse 作为信任根 |
| CSF | 命令序列文件 | 定义验证规则、SRK 配置、签名块位置 |
| QSPI Flash | 启动介质(FlexSPI NOR) | 存储签名后的完整启动镜像,偏移 0x1000 开始 |
1.3 加密算法基础(RSA)
安全启动采用 RSA 非对称加密算法,核心流程:
- 生成密钥对:选取大质数 p、q,计算模 n=p*q,公钥 e(与 φ(n) 互质)、私钥 d(e 的模逆元);
- 签名过程:对镜像计算 SHA-256 哈希,用私钥 d 加密哈希值,生成数字签名;
- 验证过程:用公钥 e 解密密文,得到哈希值,与镜像实际哈希比对,一致则验证通过。
2. 环境准备与工具清单
2.1 软硬件环境
- 硬件:i.MX8MP-EVK 开发板、QSPI Flash(32MB 及以上)、USB 调试线、JTAG 调试器(可选);
- 软件:Ubuntu 20.04 主机、交叉编译工具链(aarch64-linux-gnu-)、NXP SDK 相关源码;
- 核心工具:
- imx-mkimage:镜像打包工具(生成 FIT 格式镜像);
- uboot-imx:i.MX8MP 适配版 U-Boot 源码;
- imx-atf:ARM 可信固件(ATF,BL31 组件);
- imx-optee-os:OPTEE OS(可选,用于安全执行环境);
- CST 工具:NXP Code Signing Tool(版本 3.4.0 及以上);
- uuu 工具:镜像烧录与 SDP 模式交互工具。
2.2 源码与工具下载链接
- imx-mkimage:
https://github.com/nxp-imx/imx-mkimage.git; - uboot-imx:
https://github.com/nxp-imx/uboot-imx.git; - imx-atf:
https://github.com/nxp-imx/imx-atf.git; - imx-optee-os:
https://github.com/nxp-imx/imx-optee-os.git; - CST 工具:NXP 官网搜索 “IMX_CST_TOOL_NEW” 下载;
- DDR 固件:
https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.23.bin。
3. 分步实现流程
步骤 1:编译启动组件(U-Boot、ATF、OPTEE)
(1)编译使能 HAB 的 U-Boot
- 解压并进入 U-Boot 源码目录:
tar -xf uboot-imx.tar.gz cd uboot-imx - 启用 HAB 配置,编译 U-Boot:
# 加载默认配置 make imx8mp_evk_defconfig # 启用HAB功能(或直接编辑.config文件添加CONFIG_IMX_HAB=y) make menuconfig # 编译 make -j$(nproc) - 编译产物:生成
u-boot.bin、spl/u-boot-spl.bin(第一阶段引导程序)。
(2)编译 ATF(BL31)
- 进入 ATF 源码目录,编译适配 i.MX8MP 的 BL31:
cd imx-atf export LDFLAGS= make PLAT=imx8mp SPD=opteed bl31 -j$(nproc) - 编译产物:
build/imx8mp/release/bl31.bin(ARM 可信固件)。
(3)编译 OPTEE OS(可选)
- 安装交叉编译工具链,编译 OPTEE:
sudo apt install gcc-aarch64-linux-gnu cd imx-optee-os export CROSS_COMPILE=aarch64-linux-gnu- make PLATFORM=imx-mx8mpevk -j$(nproc) - 编译产物:
out/arm-plat-imx/core/tee-raw.bin(安全执行环境镜像)。
步骤 2:打包 FIT 格式启动镜像(imx-mkimage)
(1)准备依赖文件
- 进入 imx-mkimage 目录,创建 iMX8M 文件夹并复制组件:
cd imx-mkimage mkdir -p iMX8M # 复制U-Boot相关文件 cp ../uboot-imx/u-boot.bin iMX8M/ cp ../uboot-imx/spl/u-boot-spl.bin iMX8M/ cp ../uboot-imx/arch/arm/dts/imx8mp-evk.dtb iMX8M/ cp ../uboot-imx/tools/mkimage iMX8M/mkimage_uboot # 复制ATF与OPTEE cp ../imx-atf/build/imx8mp/release/bl31.bin iMX8M/ cp ../imx-optee-os/out/arm-plat-imx/core/tee-raw.bin iMX8M/tee.bin # 复制DDR固件(从firmware-imx-8.23.bin解压) cp ../firmware-imx-8.23/lpddr4_* iMX8M/
(2)生成 FIT 镜像(flash.bin)
- 执行打包命令,生成 QSPI 启动镜像:
make SOC=iMX8MP flash_evk_flexspi - 关键输出:镜像偏移信息(需记录用于后续签名),示例:
Loader IMAGE: header_image_off=0x1000, csf_off=0x3b000 Second Loader IMAGE: sld_header_off=0x60000, sld_csf_off=0x61020 fit-fdt csf_off=0x63020
步骤 3:生成密钥与 CSF 配置文件(CST 工具)
(1)生成 PKI 密钥与 SRK 表
- 解压 CST 工具,进入 keys 目录生成密钥对:
cd cst-3.4.0/keys ./hab4_pki_tree.sh - 按提示配置参数(密钥类型 RSA、长度 2048、有效期等),生成文件:
- SRK 表:
SRK_1_2_3_4_table.bin; - 公钥证书:
CSF1_1_sha256_2048_65537_v3_usr_crt.pem、IMG1_1_sha256_2048_65537_v3_usr_crt.pem; - 私钥文件:
CSF1_1_sha256_2048_65537_v3_usr_key.pem、IMG1_1_sha256_2048_65537_v3_usr_key.pem。
- SRK 表:
(2)编写 CSF 配置文件
CSF 文件定义 HAB 验证规则,需针对 3 个镜像块分别编写(spl_csf.txt、fit_csf.txt、fit_fdt_csf.txt):
1. spl_csf.txt(SPL 镜像签名配置)
[Header]
Version = 4.3
Certificate Format = X509
Hash Algorithm = sha256
Engine = CAAM
Engine Configuration = 0
Signature Format = CMS
[Install SRK]
File = "../crts/SRK_1_2_3_4_table.bin"
Source index = 0
[Install CSFK]
File = "../crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem"
[Authenticate CSF]
[Unlock]
Engine = CAAM
Features = MID
[Install Key]
Verification index = 0
Target index = 2
File = "../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem"
[Authenticate Data]
Verification index = 2
Blocks = 0x91ffc0 0x1000 0x3a000 "flash.bin"
2. fit_csf.txt(FIT 镜像签名配置)
[Header]
Version = 4.3
Hash Algorithm = sha256
Engine = CAAM
Engine Configuration = 0
Certificate Format = X509
Signature Format = CMS
[Install SRK]
File = "../crts/SRK_1_2_3_4_table.bin"
Source index = 0
[Install CSFK]
File = "../crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem"
[Authenticate CSF]
[Install Key]
Verification index = 0
Target index = 2
File = "../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem"
[Authenticate Data]
Verification index = 2
Blocks = 0x401fadc0 0x060000 0x01020 "flash.bin",
0x40200000 0x065000 0x1148b0 "flash.bin",
0x403148b0 0x1798b0 0x14910 "flash.bin",
0x970000 0x18e1c0 0xc150 "flash.bin",
0x56000000 0x19A310 0x91390 "flash.bin"
3. fit_fdt_csf.txt(FDT 镜像签名配置)
[Header]
Version = 4.3
Hash Algorithm = sha256
Engine = CAAM
Engine Configuration = 0
Certificate Format = X509
Signature Format = CMS
[Install SRK]
File = "../crts/SRK_1_2_3_4_table.bin"
Source index = 0
[Install CSFK]
File = "../crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem"
[Authenticate CSF]
[Install Key]
Verification index = 0
Target index = 2
File = "../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem"
[Authenticate Data]
Verification index = 2
Blocks = 0x401fadc0 0x60000 0x3020 "flash.bin"
步骤 4:签名镜像(CST 工具)
- 执行 CST 命令生成签名块,并写入 flash.bin:
# 签名SPL镜像 cst-3.4.0/linux64/bin/cst -i spl_csf.txt -o csf_spl.bin dd if=csf_spl.bin of=signed_flash.bin seek=$((0x3b000)) bs=1 conv=notrunc # 签名FIT镜像 cst-3.4.0/linux64/bin/cst -i fit_csf.txt -o csf_fit.bin dd if=csf_fit.bin of=signed_flash.bin seek=$((0x61020)) bs=1 conv=notrunc # 签名FDT镜像 cst-3.4.0/linux64/bin/cst -i fit_fdt_csf.txt -o csf_fdt.bin dd if=csf_fdt.bin of=signed_flash.bin seek=$((0x63020)) bs=1 conv=notrunc - 产物:
signed_flash.bin(完整签名后的 QSPI 启动镜像)。
步骤 5:烧录镜像与验证安全启动
(1)烧录签名镜像到 QSPI Flash
- 将开发板设置为 SDP 模式,连接 USB 线,用 uuu 工具烧录:
uuu.exe -b qspi signed_flash.bin - 烧录完成后,切换开发板为 QSPI 启动模式。
(2)验证安全启动状态
- 上电启动开发板,通过串口进入 U-Boot 命令行;
- 执行
hab_status命令验证:u-boot=> hab_status Secure boot disabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found!
- 关键判断:“No HAB Events Found!” 表示镜像签名验证通过;若有错误事件,需检查 CSF 配置或签名流程。
(3)烧录 Fuse 启用永久安全启动(可选)
若需启用永久安全启动(防止镜像篡改),烧录 SEC_CONFIG [1] Fuse:
u-boot=> fuse prog 1 3 0x20000000
- 注意:Fuse 烧录后不可恢复,烧录前需确保镜像验证无错误。
4. 关键避坑事项
- 密钥与 CSF 配置一致性:CSF 文件中的 SRK 表路径、密钥索引需与 CST 生成的 PKI 文件一致,否则验证失败;
- 镜像偏移准确性:签名时的
seek偏移需严格匹配 imx-mkimage 输出的csf_off值,偏移错误会导致 HAB 无法找到签名块; - 工具版本兼容性:CST 工具需使用 3.4.0 及以上版本,否则不支持 i.MX8MP 的 HABv4 特性;
- 交叉编译环境配置:确保 aarch64-linux-gnu - 工具链正确安装,且环境变量生效,避免编译产物格式错误;
- Fuse 烧录谨慎操作:永久安全启动启用后,无法修改镜像,需在测试验证无误后再烧录 Fuse。
5. 常见问题排查
5.1 烧录后无法启动,进入 SDP 模式
- 排查方向:
- 启动模式设置错误(未切换为 QSPI 启动);
- 镜像打包时 DDR 固件缺失或错误;
- HAB 验证失败(CSF 配置错误或密钥不匹配);
- 解决方法:重新确认启动模式,检查 DDR 固件是否正确复制,通过
hab_status查看错误事件。
5.2 hab_status显示验证错误
- 排查方向:
- 签名时使用的 SRK 表与 Fuse 中的哈希不一致;
- CSF 文件中的
Blocks参数(地址、长度)错误; - 镜像被篡改(签名后修改了 flash.bin);
- 解决方法:重新生成 SRK 表并烧录 Fuse,核对 CSF 中的
Blocks参数与 imx-mkimage 输出一致,确保签名后镜像未被修改。
5.3 CST 工具签名失败,提示 “证书格式错误”
- 排查方向:CSF 文件中
Certificate Format配置错误,或证书文件路径错误; - 解决方法:确保
Certificate Format = X509,且File参数指向正确的.pem 证书文件。
i.MX8MP QSPI 安全启动的核心是 “信任链构建 + 数字签名验证”,通过 HABv4 引擎、CST 工具与 RSA 算法实现固件安全防护。关键步骤包括启动组件编译、FIT 镜像打包、PKI 密钥生成、CSF 配置与镜像签名,最终通过 QSPI 烧录与验证完成安全启动部署。
该方案适用于工业控制、车载电子、消费电子等对固件安全要求较高的场景,有效防止非授权镜像执行与固件篡改。开发过程中需重点关注配置一致性与偏移准确性,确保信任链各环节验证通过。
阅读全文
109