2、硬件信任根:eFuse与OTP原理、RoT在MCU中的实现、密钥存储与生命周期管理

好,咱们进入正题。

安全启动这件事,说白了就是「我怎么证明我是我」。在MCU的世界里,这个信任的起点,就是硬件信任根——RoT。没有它,后面所有的签名校验、固件加密都是空中楼阁。

我当年第一次接触车载MCU安全方案时,觉得软件做校验就够了。后来被一个老前辈点醒:你校验的代码本身,谁来校验?嗯,这就是RoT要解决的问题。

2.1 eFuse与OTP:一次编程,终身锁定

先聊聊物理基础。eFuse和OTP,都是「写一次就不能改」的存储单元。但它们的原理和用法,其实差别不小。

2.1.1 OTP(One-Time Programmable)

OTP是最朴素的方案。芯片出厂时,所有bit都是0。你通过施加高电压,把某些bit熔断成1。一旦熔断,物理上就回不去了。

我在项目中遇到过一种情况:某供应商的OTP区域,因为测试时电压纹波过大,导致相邻bit被误烧写。从那以后,我要求所有OTP烧写操作必须做「读回校验」——写进去什么,读出来必须一致。

关键特性:
  • 每个bit只能从0→1(或1→0,取决于工艺)
  • 不可逆,物理锁定
  • 容量通常较小(几KB到几十KB)
  • 适合存储根密钥、芯片唯一ID、安全配置

2.1.2 eFuse(电子熔丝)

eFuse是OTP的一种变体,但更灵活。它用电流熔断金属丝或多晶硅,实现「熔断」效果。有些eFuse支持「部分烧写」——比如一个32bit的eFuse字,你可以分多次烧写不同的bit。

你想想看,这有什么用?

举个例子:芯片的生命周期管理。你可以先烧写「开发模式」的bit,等产品量产时再烧写「生产模式」的bit。最后,如果需要禁用某些调试接口,再烧写「安全锁定」的bit。一次编程,但可以分阶段使用。

我的经验: 设计eFuse布局时,一定要预留冗余bit。我曾经因为没留冗余,导致一批芯片的密钥存储区有一个bit熔断失败,整批报废。现在我的习惯是:每个关键配置至少留2-3个冗余bit,用「多数表决」机制来容错。

2.2 RoT在MCU中的实现:信任链的起点

RoT(Root of Trust)不是一个硬件模块,而是一个概念。它指的是:芯片内部一个不可篡改的、可信的起点。这个起点,通常是ROM里的一段固化代码,加上OTP/eFuse里存储的根密钥。

为什么必须是ROM?因为ROM是只读的,芯片出厂后谁也改不了。你想想看,如果启动代码放在Flash里,攻击者把Flash内容改了,那信任链就断了。

2.2.1 典型的RoT启动流程

  1. 上电复位:CPU从ROM的固定地址开始执行
  2. ROM Bootloader:读取eFuse/OTP中的配置,判断启动模式
  3. 验证第一阶段Bootloader:用OTP中的根公钥,校验Flash中第一级Bootloader的签名
  4. 链式验证:第一级Bootloader再校验第二级,直到应用固件

这个链条上,每一级都校验下一级的完整性和真实性。只要根是安全的,整个链条就是安全的。

注意: 我见过一个翻车案例。某团队把根公钥放在OTP里,但ROM代码里留了一个「调试后门」——如果某个GPIO引脚在复位时拉高,就跳过签名校验。这个后门在开发时很有用,但量产时忘了熔断对应的eFuse。结果呢?攻击者只需要一根杜邦线,就能绕过整个安全启动。

2.3 密钥存储与生命周期管理

密钥是RoT的灵魂。密钥丢了,安全启动就是个摆设。

2.3.1 密钥存储策略

密钥类型 存储位置 生命周期 我的建议
根公钥 OTP/eFuse 芯片全生命周期 必须硬件锁定,不可更新
根私钥 HSM/安全芯片 产品生命周期 永远不出HSM,只签名不导出
会话密钥 SRAM/寄存器 单次会话 每次上电重新生成
固件加密密钥 OTP或派生 固件版本生命周期 建议用根密钥派生,不直接存储

这里有个关键点:根公钥可以公开,但根私钥必须绝对保密。我习惯的做法是:根私钥在HSM里生成,永远不离开HSM。芯片生产时,只把根公钥烧进OTP。

2.3.2 密钥生命周期管理

密钥不是一成不变的。从生成到销毁,每个阶段都要有明确的管理策略。

  • 生成阶段:在安全环境中生成,使用真随机数发生器(TRNG)。我建议用HSM内部的TRNG,不要用软件伪随机。
  • 分发阶段:公钥可以明文分发,私钥必须加密传输。我在项目中用「密钥封装」机制——用芯片的公钥加密私钥,只有对应的芯片能解开。
  • 使用阶段:限制密钥的使用次数和用途。比如,签名密钥只能用于签名,不能用于加密。
  • 更新阶段:有些场景需要更新密钥。但根密钥一旦烧进OTP,就改不了了。怎么办?我的方案是:用「密钥派生」——根密钥不变,但用不同的派生因子生成新的子密钥。
  • 销毁阶段:芯片报废时,必须确保密钥无法恢复。OTP的物理熔断特性,天然支持这一点。但如果是存储在Flash里的密钥,需要做「安全擦除」——多次覆写随机数据。
避坑指南: 我曾经遇到一个项目,客户要求「密钥可更新」。他们想用eFuse存储一个「密钥更新令牌」,每次更新时用令牌派生新密钥。听起来很合理,对吧?但问题在于:令牌本身也是存储在eFuse里的,一旦攻击者拿到了令牌,就能无限更新密钥。最后我们改用「物理不可克隆函数(PUF)」来生成唯一密钥,才解决了这个问题。

2.4 实战中的几个关键决策点

说了这么多理论,咱们落地到实际项目中。我总结几个你一定会遇到的决策点:

  1. OTP容量够不够? 别只看当前需求。我建议预留30%的冗余空间,用于未来功能扩展。
  2. 要不要用PUF? PUF的好处是密钥不存储,每次上电重新生成。但PUF的稳定性受温度、电压影响。我建议配合「辅助数据」使用,否则低温下可能恢复失败。
  3. 调试接口怎么处理? JTAG/SWD在开发阶段必须开放,但量产时必须永久关闭。用eFuse控制,一旦熔断,连你自己都打不开。
  4. 密钥备份方案? 根密钥丢了,芯片就废了。我建议在安全环境中保留一份加密备份,但备份的密钥必须用「密钥分割」技术——分成多份,由不同的人保管。
一个小技巧: 在芯片设计阶段,就规划好「安全生命周期状态机」。比如:开发态→生产态→RMA态→报废态。每个状态对应不同的eFuse配置和调试权限。这样量产时就不会手忙脚乱。

好了,关于硬件信任根的内容,咱们就聊到这儿。下一章我会讲「安全启动的完整实现」,包括签名算法选择、镜像格式设计、以及如何应对回滚攻击。到时候见。