2、安全启动链:硬件信任根 (RoT)、BootROM 到 BL1/BL2 的加载流程、ATF BL31 作为EL3运行时固件的角色
安全启动链,说白了就是系统上电后的第一道防线。我做了这么多年嵌入式安全,见过太多因为启动链没锁死而被攻破的设备。你想想看,如果连系统是怎么跑起来的都不可信,那上层应用做得再安全也是白搭。
这一章我们聚焦三个核心问题:信任从哪里开始?、信任怎么传递?、EL3运行时固件到底在干什么?。嗯,咱们一个一个来拆。
2.1 硬件信任根 (RoT) —— 信任的起点
信任根,就是整个安全体系的锚点。它必须是一个不可篡改的实体。在ARM架构里,这个锚点通常是芯片内部的BootROM。
为什么是BootROM?因为它固化在芯片硅片上,出厂后物理上就无法修改。我见过有些团队试图用外部Flash存启动代码,结果被物理攻击直接替换掉——那真是血的教训。
硬件信任根的核心要求:
- 不可变性:代码固化在ROM中,无法通过软件或常规物理手段修改
- 不可绕过性:CPU复位后第一条指令必须从BootROM开始执行
- 最小可信计算基 (TCB):信任根代码量要尽可能小,便于形式化验证
我个人习惯把信任根比作「保险箱的锁芯」。锁芯本身必须是钢制的、不可拆卸的,否则整个保险箱就是个笑话。BootROM就是那个锁芯。
2.2 BootROM 到 BL1/BL2 的加载流程
上电后,CPU从BootROM开始执行。BootROM的代码量通常只有几十KB,它只做一件事:验证并加载下一级镜像。这个「逐级验证、逐级加载」的过程,就是安全启动链的核心。
我画了一张流程图,帮你理清这个链条:
流程其实不复杂:
- BootROM 从预定义的存储位置(比如eMMC的特定分区)读取BL1镜像,验证其签名是否与芯片内嵌的公钥匹配。匹配则加载到SRAM并跳转执行。
- BL1 初始化部分硬件(比如DRAM控制器),然后从存储中读取BL2镜像,同样做签名验证。
- BL2 是Trusted Firmware的早期阶段,它负责加载BL31、BL32(TEE OS)和BL33(Normal World OS)。
避坑指南: 我曾经在一个项目里遇到BL1加载BL2时签名验证失败的问题。查了两天才发现,是BootROM里固化的公钥哈希和BL2签名用的私钥不匹配——因为芯片批次不同,公钥被换掉了。所以,一定要在芯片选型阶段确认信任根的公钥管理策略。
2.3 ATF BL31 作为 EL3 运行时固件的角色
BL31是ATF里我最喜欢的一块。它运行在EL3,是安全世界和普通世界的「交通警察」。说白了,所有跨世界的调用都得经过它。
BL31的核心职责可以归纳为:
| 功能模块 | 说明 | 我遇到的坑 |
|---|---|---|
| SMC 异常处理 | 处理来自EL1/EL2的SMC指令,路由到对应的安全服务 | 参数传递错误导致系统挂死,后来加了参数校验才解决 |
| PSCI 电源管理 | CPU热插拔、挂起、复位等电源状态控制 | 某款SoC的PSCI实现不规范,BL31和内核驱动对不上 |
| 中断路由 | 将安全中断路由到EL3或S-EL1,普通中断路由到Non-secure EL1 | 中断优先级配置错了,安全中断被普通中断淹没了 |
| 运行时服务注册 | 提供标准接口让TEE OS和普通OS注册自己的服务 | 服务ID冲突,两个模块注册了同一个SMC功能ID |
你可能会问:为什么BL31要待在EL3?因为EL3是ARMv8架构里最高特权级。只有EL3才能配置SCR_EL3(安全配置寄存器)、访问TrustZone地址空间控制器。没有EL3,安全世界和普通世界的隔离就是一句空话。
注意: BL31一旦跑起来,就不能轻易退出。它是个常驻固件,直到系统掉电。所以BL31的代码质量要求极高——内存泄漏、死锁、未初始化变量,任何一个bug都会导致整个系统崩溃。我见过一个案例,BL31里有个全局变量没初始化,导致第二次SMC调用时直接跳到了空指针。嗯,从那以后我写BL31代码必加静态检查。
2.4 信任链的完整性保障
整个安全启动链,从BootROM到BL31,每一步都在做同一件事:验证签名。但光有签名还不够,还得防止回滚攻击。
回滚攻击是什么?攻击者拿一个旧版本的、有漏洞的固件刷回去,绕过新版本的安全补丁。我当年在一个IoT项目里就遇到过——设备OTA升级了,但攻击者把BL2降级到了有漏洞的版本,然后利用那个漏洞提权。
防止回滚的常见做法:
- 版本计数器:在OTP(一次性可编程)区域存储当前固件版本号,BootROM在加载BL1时比较版本,只允许升级不允许降级。
- anti-rollback fuse:硬件熔丝,烧断后无法恢复,用于锁定关键安全配置。
一句话总结: 安全启动链的本质是「信任传递」——从不可篡改的BootROM开始,逐级验证、逐级加载,每一级都只信任上一级。BL31作为EL3运行时固件,是这条链上的最后一个「把关人」,它负责在系统运行期间维护安全世界和普通世界的隔离。