2、信任根(RoT)建立:硬件信任锚点、Boot ROM、一次性可编程存储器(OTP)的作用

安全启动,说白了就是「信任的传递」。但有个问题——最初的信任从哪来?

你不能让软件自己证明自己可信,对吧?那等于让贼来查贼。所以,这个信任的起点必须是一个物理上不可篡改、逻辑上不可绕过的硬件实体。这就是我们常说的信任根(Root of Trust, RoT)。

我个人习惯把 RoT 拆成三个角色来看:硬件信任锚点、Boot ROM、OTP。它们三个配合,才构成了 ATF 安全启动的第一道防线。

2.1 硬件信任锚点:物理上的「第一把锁」

硬件信任锚点,你可以把它理解成芯片出厂时焊死在硅片上的一个物理身份。它通常由芯片厂商在流片阶段就固化,用户无法修改。

在 ARM 平台里,这个锚点一般就是芯片的唯一标识符(UID)或者根密钥的哈希值。我记得在某个项目中,客户要求我们支持多级密钥派生,但根密钥的哈希必须锁死在芯片内部。当时我们用的就是硬件信任锚点来绑定这个哈希——一旦写入,连芯片厂商自己都改不了。

核心原则:硬件信任锚点必须是不可变且不可绕过的。任何软件层面的校验,最终都要回溯到这个物理锚点。

2.2 Boot ROM:芯片上电后执行的「第一行代码」

Boot ROM 是芯片上电后 CPU 执行的第一段代码。它固化在芯片内部的只读存储器里,不可写、不可擦除。

它的任务很简单:验证下一级镜像(通常是 BL1)的签名。但这里有个关键点——Boot ROM 自己怎么被信任?

答案是:它不需要被信任。因为它是只读的,攻击者改不了它。你想想看,如果攻击者能改 Boot ROM,那说明他已经物理接触了芯片内部,这种攻击场景已经超出了安全启动的防御范围。

我在调试一块开发板时遇到过一个问题:Boot ROM 总是报签名校验失败。查了半天,发现是 OTP 里存储的根密钥哈希和 Boot ROM 里硬编码的哈希不一致。嗯,这里要注意——Boot ROM 和 OTP 必须配对使用,否则信任链就断了。

2.3 OTP:一次性可编程存储器

OTP 是芯片上的一块特殊存储区域。它出厂时全是 0,你可以把 0 写成 1,但不能把 1 改回 0。所以它叫「一次性可编程」。

OTP 在安全启动里主要存什么?我列个表给你看:

存储内容 作用 写入时机
根密钥哈希 用于验证 Boot ROM 签名的公钥哈希 芯片出厂前
芯片 UID 唯一标识,用于密钥派生 芯片出厂前
安全配置位 控制调试接口、JTAG 是否开放 产品量产阶段
回滚防护计数器 防止固件降级到有漏洞的旧版本 每次固件更新时
避坑指南:我曾经在一个量产项目里,因为 OTP 写入顺序搞反了,导致一批芯片的根密钥哈希写错了位置。结果所有芯片都无法启动,只能报废。所以,OTP 写入前一定要做三遍检查——写一次,读一次,再写一次。

2.4 三者如何配合?

我把它们的协作流程画了一张图,你看完就明白了:

信任根建立流程 信任根(RoT)建立流程 硬件信任锚点 芯片 UID / 根密钥哈希 OTP 存储根密钥哈希 / 配置位 Boot ROM 读取 OTP → 验证 BL1 签名 BL1(下一级镜像) 签名校验通过后执行 信任链:硬件锚点 → OTP → Boot ROM → BL1 → ... 逐级传递

流程其实不复杂:

  1. 硬件信任锚点提供不可变的物理身份。
  2. OTP 存储根密钥哈希和安全配置,写入后不可更改。
  3. Boot ROM 上电后读取 OTP,用里面的根密钥哈希验证 BL1 的签名。
  4. 验证通过后,信任传递给 BL1,BL1 再验证 BL2,以此类推。
我的经验:在实际项目中,我建议你在 OTP 里额外存一个安全版本号。这样即使攻击者拿到了旧版本的固件,也无法降级攻击。因为 Boot ROM 会检查版本号是否大于等于 OTP 里记录的值。

2.5 常见问题与避坑

  • OTP 写错了怎么办?——没办法,只能换芯片。所以量产前一定要做充分的测试。
  • Boot ROM 有漏洞怎么办?——Boot ROM 无法更新,所以芯片选型时一定要选经过充分验证的型号。
  • 硬件信任锚点被克隆?——理论上不可能,因为 UID 是芯片制造时随机生成的,全球唯一。

好了,信任根这块就讲这么多。记住一句话:安全启动的强度,取决于信任根的安全强度。如果 RoT 被攻破,后面所有的安全措施都是白搭。