4、信任根(RoT):硬件信任根与软件信任根、不可变引导ROM、一次性可编程存储器(OTP/eFuse)

聊到安全启动,有个概念绕不开——信任根(Root of Trust,RoT)。

说白了,信任根就是整个安全体系的“第一块基石”。你想想看,如果连最底层的代码都不确定是不是可信的,那上层再怎么加密、签名、校验,都是白搭。就像盖楼,地基要是歪了,上面装修得再漂亮也没用。

我个人习惯把信任根分成两类:硬件信任根和软件信任根。这两者不是二选一的关系,而是层层递进、互相配合的。今天咱们就把它们掰开揉碎了讲清楚。

4.1 硬件信任根 vs 软件信任根

先看一个简单的对比表格,帮你快速建立认知:

维度 硬件信任根 软件信任根
物理载体 芯片内部固化电路、熔丝、ROM 存储在Flash中的Bootloader代码
不可篡改性 出厂后物理上无法修改 可通过安全更新机制修改(需签名)
启动顺序 最先执行,上电即运行 由硬件信任根加载并验证
典型实现 Boot ROM、eFuse、PUF 签名验证的Stage 1 Bootloader
安全强度 极高(物理不可更改) 较高(依赖签名算法强度)

硬件信任根,是芯片出厂时就焊死在硅片上的逻辑。它不依赖任何外部存储,上电瞬间就开始工作。我做过一个项目,芯片的Boot ROM里有一段代码,专门负责读取eFuse中的公钥哈希,然后用这个哈希去验证下一级镜像的签名。这段ROM代码,就是整个系统的硬件信任根。

软件信任根呢,则是建立在硬件信任根之上的第一段可更新代码。它通常存储在Flash中,由硬件信任根加载并验证其完整性。一旦验证通过,软件信任根就接过控制权,继续加载后续的镜像。

核心原则:信任链必须从一个不可变的、可信的起点开始。这个起点就是硬件信任根。软件信任根是信任链上的第一个“可更新”环节,但它的可信度必须由硬件信任根来保证。

4.2 不可变引导ROM(Boot ROM)

Boot ROM,就是硬件信任根最典型的实现。它是芯片内部一块只读存储器,出厂时由芯片厂商写入固定的启动代码。这块ROM,你没法擦除,也没法改写。

嗯,这里要注意:Boot ROM不是万能的。它虽然不可变,但功能通常非常精简。我见过一些设计,Boot ROM只做三件事:

  1. 初始化硬件:配置时钟、内存控制器等最基本的外设。
  2. 读取eFuse:获取芯片的唯一身份信息、公钥哈希、安全配置位。
  3. 验证并跳转:从预定义的存储位置(比如Flash的0x0地址)加载下一级镜像,验证签名,通过后跳转执行。

为什么Boot ROM不能做得太复杂?因为ROM的面积很贵,而且一旦流片出来,里面的逻辑就永远固定了。如果Boot ROM有bug,那这颗芯片就永远带着这个bug——除非你重新流片。所以,Boot ROM里的代码都是经过反复验证、极度精简的。

避坑指南:我曾经在一个项目里,Boot ROM的代码里写死了Flash控制器的时序参数。结果后来换了一颗不同品牌的Flash,时序对不上,导致启动失败。最后只能通过修改PCB上的电阻分压来“欺骗”芯片。所以,Boot ROM里尽量不要写死跟外部器件强相关的参数,留一些可配置的接口会安全得多。

4.3 一次性可编程存储器(OTP/eFuse)

OTP(One-Time Programmable)存储器,顾名思义,只能写一次。eFuse是OTP的一种主流实现方式,通过熔断芯片内部的金属丝或硅丝来存储信息。熔断前代表“0”,熔断后代表“1”。

eFuse在安全启动中扮演着至关重要的角色。它存储的是芯片的“身份”和“密钥”。

我列一下eFuse里通常会存些什么:

  • 公钥哈希(Public Key Hash):用于验证签名公钥的完整性。Boot ROM里会硬编码一个根公钥哈希,用来校验eFuse里存储的公钥是否被篡改。
  • 芯片唯一ID(Unique ID):每颗芯片一个,用于设备身份认证、证书绑定。
  • 安全配置位(Security Configuration Bits):比如是否启用调试接口、是否允许JTAG访问、是否强制签名验证等。
  • 密钥加密密钥(KEK):用于解密存储在Flash中的固件密钥。
  • 生命周期状态(Lifecycle State):比如芯片处于“开发模式”、“生产模式”、“RMA模式”等。

为什么用eFuse而不用Flash?因为Flash可以被擦除、重写,攻击者可以通过电压注入、激光切割等方式篡改Flash内容。但eFuse一旦熔断,物理结构就永久改变了,几乎无法恢复。这就提供了硬件级别的不可逆性。

警告:eFuse的编程是一次性的,而且通常需要高电压(比如1.8V或3.3V)和特定的时序。编程过程中如果掉电或电压不稳,可能导致eFuse处于“半熔断”状态,既不是0也不是1,芯片直接变砖。我见过一个团队,在生产线上因为电源纹波过大,一次性烧坏了3000多颗芯片的eFuse,损失惨重。所以,eFuse编程的电源设计和时序控制,一定要做足冗余。

4.4 信任根的整体架构

为了让你更直观地理解,我画了一张图,展示信任根在安全启动中的位置和作用:

信任根架构图 信任根(RoT)架构与信任链传递 硬件信任根(不可变) Boot ROM 不可变引导代码 eFuse / OTP 公钥哈希 / 安全配置 读取 软件信任根(可更新,但需签名验证) Stage 1 Bootloader 验证并加载下一级 公钥(Flash) 由eFuse哈希保护 验证通过后跳转 提供公钥 后续信任链 Stage 2 Bootloader OS Kernel 应用程序 物理不可变 出厂即固定 信任链起点

从这张图你可以看到,信任链的传递是单向的、逐级验证的。硬件信任根(Boot ROM + eFuse)验证软件信任根(Stage 1 Bootloader),软件信任根再验证下一级镜像。每一级都只信任上一级,上一级只做一件事:验证下一级的签名是否正确。

这种设计的好处是,即使攻击者攻破了某一级(比如Stage 1 Bootloader),他也无法向上回溯去篡改硬件信任根。他最多只能破坏这一级之后的信任链,但无法伪造一个假的硬件信任根。

关键点:信任根不是一块硬件,也不是一段代码,而是一个信任锚点。这个锚点必须是物理上不可篡改的,并且能够验证整个系统其余部分的可信度。没有这个锚点,安全启动就是空中楼阁。

4.5 实际项目中的选择

在实际项目中,选择什么样的信任根方案,取决于你的产品需求和安全等级。

我简单总结一下常见的几种做法:

  • 低成本MCU:通常只有Boot ROM,没有eFuse。公钥直接硬编码在Boot ROM里。优点是成本低,缺点是公钥无法更新,一旦泄露整个产品线都得召回。
  • 中端SoC:Boot ROM + eFuse。公钥哈希存在eFuse里,公钥本身存在Flash里。这样可以在产线上为每颗芯片烧录不同的公钥,灵活性高。
  • 高端安全芯片:Boot ROM + eFuse + PUF(物理不可克隆函数)。PUF利用芯片制造过程中的工艺偏差生成唯一密钥,连芯片厂商都无法预测。这种方案安全性最高,但成本也最高。

我个人更倾向于中端方案,也就是Boot ROM + eFuse的组合。它在安全性和成本之间取得了很好的平衡。我在一个物联网网关项目里就是这么做的,量产了50万台,没出过安全问题。

小技巧:如果你的芯片支持eFuse,建议在产线上把调试接口(JTAG/SWD)的熔丝也一并熔断。这样攻击者就无法通过调试接口直接读取内存或寄存器,安全性会提升一个档次。当然,前提是你得确保固件已经足够稳定,不需要再调试了。

好了,信任根这部分就讲到这里。记住一句话:没有信任根,就没有安全启动。下一层级的可信,都建立在这一层级的不可变之上。这是整个安全体系的基石,也是你设计安全启动方案时首先要考虑清楚的问题。