3. 安全启动链与信任根:RoT 概念、硬件信任锚、安全启动流程

各位同学,今天我们聊一个非常核心的话题——信任根。说白了,就是整个系统安全的起点。你想想看,如果起点都不安全,后面做再多防护也是白搭。

我在做嵌入式安全的头几年,踩过最大的坑就是「以为软件能解决一切」。后来被现实教育了——没有硬件级别的信任锚,安全启动就是空中楼阁。嗯,这节课我们就把它彻底讲透。

3.1 信任根(RoT)到底是什么?

信任根,英文叫 Root of Trust,简称 RoT。它不是一个具体的芯片,而是一个概念——系统中必须有一个绝对可信、不可篡改的起点。

我个人习惯把 RoT 比作「安全世界的奇点」。所有后续的信任判断,都从这个点开始一级一级传递下去。如果这个点被攻破了,整个信任链就断了。

信任根的核心属性:

  • 不可篡改性——物理上无法被改写
  • 不可绕过性——系统启动必须经过它
  • 行为可预测——执行逻辑固化在硬件中

我曾经在一个 IoT 项目里见过团队用 Flash 存储启动校验公钥,结果被攻击者直接物理替换了 Flash 芯片。这就是没有硬件信任锚的后果——公钥本身就不安全,校验还有什么意义?

3.2 硬件信任锚:为什么必须用硬件?

你可能会问:我把校验逻辑写在 Bootloader 里,用软件做校验不行吗?

答案是:不行。原因很简单——软件可以被改写。攻击者只要拿到固件更新权限,就能把你的校验逻辑直接替换掉。

硬件信任锚,通常是一块只读存储器(ROM)或者一次性可编程(OTP)存储。芯片出厂时就把根公钥或者根哈希烧进去,之后谁也别想改。

信任锚类型 存储介质 可改写性 典型用途
BootROM Mask ROM 不可改写 存放第一级启动代码
OTP eFuse 电熔丝阵列 一次性编程 存储根公钥哈希
硬件安全模块 专用安全芯片 物理防篡改 密钥存储与签名运算

我的经验:选型时优先看芯片是否提供 OTP 区域。如果连 OTP 都没有,这个芯片基本不适合做安全启动。别问我怎么知道的——吃过亏。

3.3 安全启动流程:从 BootROM 到 Bootloader

安全启动的流程,说白了就是「一级验一级,环环相扣」。我们以典型的 ARM Cortex-M 系列为例,走一遍完整流程。

3.3.1 第一级:BootROM

芯片上电后,CPU 从复位向量开始执行。复位向量指向的地址,就是 BootROM 的入口。BootROM 是芯片出厂时用掩膜工艺写死的,物理上无法修改。

BootROM 做的事情很简单:

  1. 初始化最基本的硬件(时钟、SRAM)
  2. 从 OTP 中读取根公钥哈希
  3. 从外部 Flash 读取第一级 Bootloader
  4. 用根公钥验证 Bootloader 的签名
  5. 验证通过,跳转到 Bootloader;失败,进入错误处理

注意:BootROM 本身不包含任何用户可配置的逻辑。它的代码量通常只有 4KB-16KB,越精简越安全。我见过有人试图在 BootROM 里加功能,结果引入了一个缓冲区溢出漏洞——教训深刻。

3.3.2 第二级:Bootloader

Bootloader 是用户可更新的,但它必须被 BootROM 签名验证后才能执行。Bootloader 的职责是:

  • 初始化更复杂的硬件(DDR、存储控制器)
  • 验证操作系统内核或应用程序固件的签名
  • 提供固件更新功能(通常带回滚保护逻辑)

这里有个关键点:Bootloader 的签名密钥不能和根密钥是同一个。通常的做法是:

  • 根密钥(存储在 OTP)只用来验证 Bootloader
  • Bootloader 内部存储另一个密钥,用来验证应用固件

这样做的好处是:即使应用密钥泄露,也不会影响根密钥的安全。我在项目中把这个叫做「密钥隔离原则」。

3.4 安全启动链的完整视图

下面这张图展示了从硬件信任锚到应用固件的完整信任链。我建议你仔细看看每个环节的校验关系。

安全启动信任链 硬件信任锚 (OTP) BootROM (不可改写) Bootloader (签名验证) 应用固件 (运行时) 信任传递规则 1. 每一级只信任上一级 2. 签名验证不可跳过 3. 失败必须停止启动 回滚保护关键点 • BootROM 版本号检查 • Bootloader 版本号检查 • 应用固件版本号检查 信任链完整性 = 系统安全的基础 任何一个环节被破坏,整个信任链失效 回滚保护必须在每一级都实施

3.5 回滚保护在启动链中的位置

你可能会问:回滚保护和安全启动链有什么关系?关系大了。

安全启动保证「只运行可信的固件」,回滚保护保证「只运行最新的固件」。两者缺一不可。

具体来说,回滚保护在启动链中的实现位置:

  • BootROM 层:检查 Bootloader 的版本号是否 >= 当前记录的版本
  • Bootloader 层:检查应用固件的版本号,同时更新版本号记录
  • 应用固件层:运行时检查自身版本号,防止被降级攻击

关键设计原则:

  • 版本号必须存储在不可回滚的介质中(如 OTP 或安全存储区)
  • 版本号比较逻辑必须在签名验证通过之后执行
  • 版本号更新必须在固件成功运行之后才提交

3.6 常见攻击手法与防御

我整理了几个在项目中真实遇到过的攻击场景,供你参考:

攻击手法 攻击目标 防御措施
物理替换 Flash 绕过 BootROM 校验 使用 OTP 存储根公钥,Flash 内容必须签名
电压毛刺攻击 跳过签名验证步骤 BootROM 中加入时序检测和冗余校验
版本号回滚 降级到有漏洞的固件 版本号存储在 OTP,只增不减
中间人攻击 篡改固件更新包 固件包必须包含完整签名链

避坑指南:我曾经在一个项目里发现,团队把版本号存在了外部 EEPROM 里。攻击者直接拆掉 EEPROM,换上存有旧版本号的芯片,回滚保护就形同虚设了。记住:版本号存储介质的安全等级,必须和信任锚一致。

3.7 小结

这节课我们聊了信任根、硬件信任锚、安全启动流程,以及它们和回滚保护的关系。核心就三句话:

  • 信任根必须是硬件级别的,不可篡改
  • 安全启动是一级验一级的信任链
  • 回滚保护必须嵌入到启动链的每一级

嗯,内容不少。建议你课后找一块带安全启动的开发板,实际走一遍启动流程,看看 BootROM 和 Bootloader 是怎么配合的。纸上得来终觉浅,动手才是硬道理。