4. RA 启动流程与信任根建立

RA 系列 MCU 的启动过程并不是“复位后直接跳到 main 函数”这么简单。为了保证固件在每一级都经过验证,RA 在硬件层面把启动过程划分为若干阶段,每一阶段只信任上一阶段验证过的代码,从而形成一条从不可变硬件锚点出发、逐级向用户应用延伸的信任链。理解这条链路,是后续实现安全启动、固件升级和防回滚的基础。

一、为什么需要分阶段启动

如果让 ROM 中的固化代码直接验证整个用户应用,会带来两个问题:一是 ROM 空间有限,无法容纳复杂的签名验证逻辑;二是用户应用可能很大,验证过程会显著拖慢启动速度。因此 RA 采用“小步验证”的思路:先用最小的、不可修改的硬件信任根验证一小段引导代码,再由这段引导代码验证下一段,逐级放大可信范围。这样每一级的验证逻辑都可以做得足够简单、足够可靠。

RA 的启动链路通常划分为 BL0、BL1、BL2 三个阶段,最终进入用户应用。这里的“BL”是 Boot Loader 的缩写,但 BL0 并不一定是传统意义上的引导程序,它更多是硬件行为与固化代码的组合。

二、BL0:硬件信任根与不可变锚点

BL0 是整条信任链的起点,也是唯一不需要被验证的环节,因为它的可信性由芯片制造过程保证。BL0 主要包含以下内容:

  • 复位向量与初始启动代码:上电复位后,Cortex-M 内核从固定地址取出栈顶指针和复位向量,开始执行固化在 ROM 中的启动代码。
  • 硬件信任根:RA 的 Secure Crypto Engine(SCE)或 Trusted Secure IP(TSIP)内部保存了不可读出的密钥和唯一设备标识,构成硬件信任根。
  • 启动模式判断:BL0 会读取启动模式引脚或选项字节,判断当前是从主 Flash 启动、从 SCI/USB 下载启动,还是进入调试模式。
  • BL1 验证:在安全启动使能的情况下,BL0 使用硬件信任根中的公钥或对称密钥,对 BL1 镜像进行完整性校验和签名验证。

BL0 的关键特征是“不可修改”。它位于 ROM 中,用户无法擦写,因此可以作为整个系统的信任锚点。如果 BL0 验证 BL1 失败,芯片会停止启动或进入错误处理流程,不会把控制权交给未经验证的代码。

三、BL1:第一级可更新引导

BL1 通常位于主 Flash 的起始区域,是第一个可以被用户更新、但仍然受到严格保护的阶段。它的职责包括:

  • 初始化最基本的时钟、Flash 控制器和必要外设;
  • 验证 BL2 镜像的完整性和签名;
  • 在验证通过后,把控制权交给 BL2;
  • 在部分方案中,BL1 还负责检查 BL2 的版本号,防止回滚到旧版本。

BL1 的代码量通常较小,因为它运行在启动早期,很多外设尚未初始化。它的验证对象是 BL2,验证所用的公钥或密钥通常由 BL0 传递或从受保护区域读取。BL1 本身一旦被 BL0 验证通过,就进入可信状态,可以执行相对复杂的验证逻辑。

四、BL2:功能更完整的引导阶段

BL2 是启动链路中功能最丰富的阶段,通常承担以下任务:

  • 初始化更完整的外设,例如外部 Flash、SDRAM、通信接口;
  • 验证用户应用镜像的签名和完整性;
  • 支持固件升级流程,例如从通信接口接收新固件并写入备用区;
  • 执行版本检查和防回滚判断;
  • 在验证通过后跳转到用户应用。

BL2 的代码量可以较大,因为它已经运行在相对完整的系统环境中。BL2 验证用户应用时,通常使用非对称签名(如 ECDSA)或对称 CMAC,具体取决于方案配置。验证通过后,BL2 会设置好向量表偏移,跳转到用户应用的复位入口。

五、信任根锚点与信任链传递

整条链路的信任传递关系可以用下面的图来理解。图中从硬件信任根出发,逐级向右传递信任,每一级只验证下一级,最终把可信状态延伸到用户应用。

RA 启动链路与信任传递 BL0 ROM 固化代码 硬件信任根 (SCE/TSIP) 复位向量 / 启动模式 不可修改 · 信任锚点 BL1 主 Flash 起始区 基础时钟 / Flash 初始化 验证 BL2 签名 可更新 · 受保护 BL2 外设完整初始化 验证用户应用签名 固件升级 / 防回滚 功能最丰富 用户应用 main() 业务逻辑 通信 / 控制 最终执行目标 验证 验证 验证 信任链方向: 硬件信任根 → BL1 可信 → BL2 可信 → 用户应用可信 验证失败处理: BL0 验证 BL1 失败 → 停止启动 / 进入错误状态,不交出控制权 BL1 验证 BL2 失败 → 回退到安全镜像或停止启动 BL2 验证应用失败 → 拒绝跳转,保持引导模式 版本回滚检测失败 → 拒绝降级,保护已知安全版本

从图中可以看到,信任并不是一次性覆盖全部代码,而是沿着 BL0 → BL1 → BL2 → 用户应用的方向逐级传递。每一级只负责验证下一级,验证通过后,下一级才被纳入可信范围。这种设计使得即使某一级被替换,只要签名验证机制没有被攻破,攻击者也无法让未签名的代码获得执行权。

六、实际启动过程中的关键观察点

在实际调试和部署中,可以通过以下现象判断启动链路是否按预期工作:

  • 启动时间:BL0 验证 BL1、BL1 验证 BL2、BL2 验证应用,每一级都会增加启动耗时。如果启用 ECDSA 验证,单次验证通常在几十毫秒量级,具体取决于时钟频率和密钥长度。
  • 错误引脚或状态寄存器:验证失败时,RA 可能通过特定引脚输出错误信号,或在状态寄存器中留下失败标志,可用于定位是哪一级验证失败。
  • 版本号检查:BL2 在跳转前会检查应用版本号,如果低于安全版本阈值,会拒绝跳转。这一机制用于防止攻击者刷入旧版本固件以利用已知漏洞。
  • 向量表偏移:BL2 跳转到用户应用前,需要正确设置 VTOR(向量表偏移寄存器),否则中断会跳转到错误位置。这是实际集成中常见的配置错误。
BL0 是硬件信任根,不可修改;BL1 和 BL2 是可更新的引导阶段,但必须经过上一级验证。用户应用是最终执行目标,只有通过 BL2 验证后才能获得控制权。整条链路的信任传递是单向的,不能反向信任。

七、信任根锚点的工程意义

信任根锚点的存在,使得整个系统的安全性不依赖于“用户应用是否被篡改”,而是依赖于“硬件信任根是否安全”。只要 BL0 和硬件信任根没有被攻破,即使攻击者能够读写主 Flash,也无法让未签名的固件运行。这就是安全启动的核心价值。

在实际项目中,BL0 通常由芯片厂商固化,用户无法修改;BL1 和 BL2 由用户根据方案需求实现或由厂商提供参考实现。用户需要重点关注的是:BL1 和 BL2 的签名密钥如何管理、版本号如何递增、验证失败后的恢复策略如何设计。这些内容将在后续章节中结合具体工具和代码进一步展开。

理解 BL0/BL1/BL2 的划分和信任传递关系,是后续配置安全启动、实现固件升级和设计防回滚策略的前提。只有清楚每一级的职责和验证对象,才能在出现启动失败时快速定位问题,也才能在设计升级流程时保证新固件能够被正确验证和接受。