4. Layerscape启动流程与安全启动链

Layerscape系列处理器的启动过程是一条严格分层的信任传递链。从上电复位到Linux用户空间,每一级固件在将控制权交给下一级之前,都必须先验证下一级镜像的完整性与真实性。理解这条链的每一环——PBL、SPL、U-Boot、ATF、OP-TEE、Linux内核——以及它们如何借助OTP fuses和SEC引擎完成签名验证,是配置安全启动的前提。

启动阶段的分层结构

Layerscape上电后,最先运行的是芯片内部ROM中的PBL(Pre-Boot Loader)。PBL代码固化在芯片内,不可修改,它读取启动介质(QSPI、SD、eMMC或NAND)上的RCW(Reset Configuration Word)和SPL(Secondary Program Loader)镜像。PBL根据RCW中的启动模式、时钟和DDR参数完成最基础的硬件初始化,然后将SPL加载到片上SRAM并跳转执行。

SPL运行在SRAM中,空间有限,它的职责是初始化DDR控制器,把完整的U-Boot镜像从启动介质搬运到DDR,然后跳转到U-Boot。U-Boot阶段完成更丰富的外设初始化,并负责加载ATF(ARM Trusted Firmware)、OP-TEE和Linux内核。ATF运行在EL3,提供PSCI电源管理和安全监控调用;OP-TEE运行在EL1的安全世界,为可信应用提供隔离执行环境;Linux内核运行在EL1的非安全世界。整个启动链的信任根来自芯片内部的OTP fuses和SEC(Security Engine)硬件模块。

Layerscape 安全启动链与信任传递 信任根 → PBL → SPL → U-Boot → ATF / OP-TEE → Linux Kernel OTP Fuses SRK Hash (256bit) SB_EN / ITS / BOOT_SEQ 不可逆 · 一次性烧写 SEC 引擎 RSA-2048/3072 验签 SHA-256 哈希加速 Job Ring 硬件队列 PBL(芯片内 ROM) 读取 RCW → 初始化时钟/DDR → 加载 SPL 验证 SPL 签名 SPL(片上 SRAM) 初始化 DDR → 搬运 U-Boot 到 DDR 验证 U-Boot 签名 U-Boot(DDR) 外设初始化 → 加载 ATF / OP-TEE / Kernel 验证 ATF 签名 ATF(EL3 安全监控) PSCI 电源管理 · 安全世界切换 验证 OP-TEE 签名 OP-TEE(EL1 安全世界) 可信应用隔离 · 安全存储 验证 Kernel 签名 Linux Kernel(EL1 非安全世界) SRK Hash 比对 硬件验签 图例 信任传递方向 SEC 硬件验签路径

Chain of Trust 与信任根

Chain of Trust的核心思想是:每一级代码在运行前,必须由上一级已可信的代码验证其签名。信任的起点是芯片内不可修改的PBL ROM代码和OTP fuses中烧写的SRK(Super Root Key)哈希值。SRK哈希是整条信任链的锚点,一旦烧写便不可更改。

具体验证流程如下:PBL从启动介质读取SPL镜像及其签名(CSF头),将SRK哈希与OTP fuses中的值比对,确认公钥可信后,用SRK公钥验证SPL镜像的RSA签名。验证通过后,PBL将SPL加载到SRAM执行。SPL、U-Boot、ATF、OP-TEE、Linux内核依次重复这一过程。每一级镜像的CSF(Command Sequence File)中包含签名、公钥和证书链信息,SEC引擎负责加速RSA和SHA运算。

OTP Fuses与SEC密钥存储

OTP fuses是芯片内的一次性可编程存储区,关键字段包括:SRK Hash(256位,存储SRK公钥的SHA-256哈希)、SB_EN(安全启动使能位)、ITS(Image Trust Source,指定启动介质)、BOOT_SEQ(启动顺序)。烧写OTP fuses是不可逆操作,必须在量产前确认所有密钥和配置正确。

SEC引擎提供硬件级密钥存储和加密加速。在安全启动中,SEC的Job Ring接收验签任务,从内存读取镜像和签名数据,执行RSA-2048或RSA-3072验签和SHA-256哈希计算,返回验证结果。SEC还支持密钥封装(Key Blob),将敏感密钥加密后存储,只有SEC内部才能解密使用。

镜像签名与安全启动配置实践

以下以LS1046A为例,展示从生成密钥到烧写OTP的完整流程。假设使用RSA-2048和SHA-256算法。

第一步:生成SRK密钥对和自签名证书。

# 生成SRK私钥
openssl genrsa -out srk.pri 2048

# 生成SRK公钥
openssl rsa -in srk.pri -pubout -out srk.pub

# 生成自签名证书(用于CST工具)
openssl req -new -x509 -key srk.pri -out srk.crt -days 3650 \
  -subj "/CN=SRK-LS1046A/O=NXP/C=CN"

# 计算SRK哈希(烧写到OTP fuses的值)
openssl dgst -sha256 -binary srk.pub | openssl enc -base64

第二步:使用NXP CST工具签名镜像。

# 创建输入文件描述
cat <<EOF > input_spl.txt
0x10000000 0x00000000 \
  /path/to/spl.bin
EOF

# 生成CSF头
cst -i input_spl.txt -o csf_spl.bin \
  -k srk.pri -c srk.crt -a sha256 -e rsa2048

# 将CSF头附加到SPL镜像
cat csf_spl.bin spl.bin > spl_signed.bin

第三步:烧写OTP fuses。

# 在U-Boot中烧写SRK哈希
=> fuse prog 0 0 0x12345678
=> fuse prog 0 1 0x9abcdef0
=> fuse prog 0 2 0x11223344
=> fuse prog 0 3 0x55667788

# 使能安全启动
=> fuse prog 1 0 0x00000002

# 验证烧写结果
=> fuse read 0 0 4
=> fuse read 1 0 1
烧写OTP fuses前务必确认SRK哈希值正确。一旦烧写SB_EN位,芯片将强制验证所有启动镜像的签名,未签名或签名错误的镜像将导致启动失败,且无法回退。

验证安全启动是否生效

烧写完成后,重新上电。观察串口输出:PBL阶段会打印“SEC: Validating image...”或类似信息。如果签名验证通过,SPL、U-Boot依次启动,最终进入Linux。如果验证失败,PBL会停止启动并输出错误码,常见错误包括“SRK hash mismatch”和“Signature verification failed”。

在U-Boot中可以通过以下命令确认安全启动状态:

=> fuse read 1 0 1
Reading bank 1: 00000002
=> bdinfo
...
secure_boot = 1
...

在Linux中,可以通过检查/proc/device-tree或使用NXP提供的sec_tool读取SEC状态寄存器,确认安全启动已使能且镜像验证通过。

调试阶段建议先使用未烧写OTP的芯片验证签名流程,确认所有镜像签名正确后再烧写OTP。可以使用NXP提供的“Fuse Programming”脚本在开发板上模拟安全启动环境。

关键参数与常见问题

参数/字段 说明 典型值
SRK Hash SRK公钥的SHA-256哈希,烧写在OTP bank 0 256位(8个32位字)
SB_EN 安全启动使能位,位于OTP bank 1 0x00000002
ITS 镜像信任源,指定从哪个介质加载镜像 0x00000000(QSPI)
RSA密钥长度 签名算法强度 2048或3072位
哈希算法 镜像摘要算法 SHA-256

常见问题包括:SRK哈希烧写错误导致启动失败(需更换芯片);CSF头未正确附加导致签名验证失败;SEC Job Ring队列满导致验签超时。排查时优先检查OTP烧写值和镜像签名文件是否匹配,再确认SEC驱动是否正常初始化。

安全启动链的每一级都依赖上一级的正确验证。PBL验证SPL,SPL验证U-Boot,U-Boot验证ATF和OP-TEE,ATF验证Linux内核。任何一级验证失败,启动链即中断。理解这条链的结构和验证机制,是配置和维护Layerscape网络安全设备的基础。