第4章 公钥基础设施(PKI):证书链、根证书、中间证书在启动校验中的角色

说到启动校验,很多人第一反应就是「验签」。但验签用的公钥从哪来?谁保证这把公钥没被换过?这就引出了 PKI——公钥基础设施。说白了,PKI 就是一套信任传递的体系。我做了这么多年嵌入式安全,见过太多「自己签自己」的方案,最后都栽在密钥管理上。

这一章,我们聊聊证书链、根证书、中间证书在启动校验里到底扮演什么角色。

4.1 为什么启动校验需要证书链?

先想一个问题:你的 BootROM 里烧了一个公钥,用来验签下一级镜像。这个公钥是固定的,对吧?那如果有一天你想换一把新密钥呢?

嗯,这就是痛点。硬件里烧死的公钥没法改。除非你召回设备,或者留一个「密钥更新」的漏洞——但后者恰恰是攻击者最喜欢钻的空子。

证书链解决了这个问题。它让 BootROM 只信任一个根证书,而根证书可以签发中间证书,中间证书再签发固件。这样,你只需要更新中间证书或固件证书,根证书纹丝不动。

核心思想:信任锚(Root of Trust)固定不变,但信任链可以延伸和更新。

4.2 证书链的三层结构

典型的启动校验证书链分三层:

  • 根证书(Root Certificate)——自签名,烧死在 BootROM 或 OTP 中。不可更改。
  • 中间证书(Intermediate Certificate)——由根证书签发,存储在 Flash 或固件包中。可轮换。
  • 固件证书(Firmware Certificate)——由中间证书签发,直接绑定固件镜像的哈希和签名。

我见过一个项目,他们直接把根证书的公钥放在 Flash 里,结果被攻击者替换了。嗯,那台设备从此就「百毒不侵」了——什么恶意固件都能跑。所以记住:根证书必须放在一次性写入的存储里。

层级 存储位置 可更新性 安全要求
根证书 BootROM / OTP / eFuse 不可更新 物理防篡改
中间证书 Flash / 固件包 可轮换 需根证书签名
固件证书 固件镜像头部 每次发布更新 需中间证书签名

4.3 启动校验中的证书验证流程

设备上电后,BootROM 做这几件事:

  1. 加载根证书——从 OTP 中读出根证书公钥。这是硬件信任锚。
  2. 验证中间证书——用根证书公钥验中间证书的签名。通过后,提取中间证书的公钥。
  3. 验证固件证书——用中间证书公钥验固件证书的签名。通过后,提取固件哈希。
  4. 验证固件镜像——计算固件实际哈希,与固件证书中的哈希比对。

每一步都环环相扣。只要有一环断裂,启动就失败。

我的经验:曾经有个客户,中间证书过期了,但设备没有校验证书有效期。结果一台用了三年的设备,突然刷不上新固件。查了两天,才发现是证书时间戳的问题。所以,证书有效期校验一定要做,哪怕你的设备不联网。

4.4 证书链的 SVG 结构图

下面这张图展示了证书链的层级关系和验证流向。我习惯把它画在每一份安全设计文档的首页。

启动校验证书链结构 根证书 BootROM / OTP 中间证书 Flash / 固件包 固件证书 固件镜像头部 固件镜像 签名验证 签名验证 哈希比对 信任锚 不可更改 物理保护 可轮换 需根证书签名 每次更新 绑定固件哈希

4.5 根证书的保护策略

根证书是整个信任链的命门。一旦泄露,整个产品线的安全就崩塌了。我见过最惨的一次,是某厂商把根证书私钥放在一个 SVN 仓库里——嗯,你没听错,版本控制仓库。结果离职员工带走了整个仓库。

保护根证书,我建议做到以下几点:

  • 硬件隔离:私钥存储在 HSM(硬件安全模块)中,永远不离开安全边界。
  • 多人授权:签名操作需要至少两人同时授权。单人无法操作。
  • 物理保护:HSM 放在机房,门禁、摄像头、日志审计一个不能少。
  • 备份策略:私钥分片备份,每片由不同人保管。恢复时需要 M of N 机制。

警告:千万不要把根证书私钥放在开发人员的笔记本上。我曾经审计过一个项目,根证书私钥竟然以「root_key.pem」的名字放在桌面。这不是开玩笑。

4.6 中间证书的轮换机制

中间证书的好处是:你可以定期轮换,而不影响根证书。比如每年换一次中间证书,即使某张中间证书泄露,攻击者也只能伪造当年签发的固件。

轮换流程大致如下:

  1. 用根证书签发新的中间证书。
  2. 新固件包中包含新的中间证书。
  3. BootROM 验证新中间证书的签名(用根证书公钥)。
  4. 通过后,用新中间证书的公钥验固件签名。

这里有个细节:旧固件怎么办?如果设备还在用旧中间证书签发的固件,BootROM 必须同时信任新旧两张中间证书。我通常的做法是,在 BootROM 中维护一个「已吊销证书列表」或「有效证书哈希列表」。这样,旧证书到期后,新固件自然就用新证书了。

场景 根证书 中间证书 固件证书
初始发布 烧入 OTP V1 签发 V1 签名
第一次轮换 不变 V2 签发 V2 签名
紧急更新 不变 V2 仍有效 V2 签名(新固件)
证书泄露 不变 吊销 V2,签发 V3 V3 签名

4.7 实际项目中的避坑指南

做了这么多年,踩过的坑不少。挑几个典型的说说:

  • 证书长度超限:有些 BootROM 只支持 2048 位 RSA 证书。你塞一个 4096 位的,直接启动失败。我建议在设计阶段就定好证书规格,写在硬件设计文档里。
  • 证书链深度:BootROM 的代码空间有限,递归验证证书链可能撑爆栈。我一般限制最多 3 层,再多就不安全了——验证时间也受不了。
  • 时间戳依赖:设备没有 RTC 或 RTC 不可信,校验证书有效期就是个笑话。我见过一个方案,直接跳过有效期校验——结果旧证书永远有效。折中做法是:用固件版本号代替时间戳,版本号必须递增。
  • 吊销列表更新:离线设备怎么更新吊销列表?我常用的办法是:把吊销列表哈希打包进固件,BootROM 验签时一并检查。这样每次固件更新,吊销列表也跟着更新。

我的习惯:每次设计证书链,我都会画一张「信任链图」,标注每个证书的存储位置、保护措施、轮换周期。这张图贴在项目白板上,团队每个人都能看到。发现问题,当场改。

4.8 小结

证书链不是银弹,但它把「信任」这个抽象概念变成了可工程化的结构。根证书是锚,中间证书是桥,固件证书是门。锚要稳,桥要牢,门要严。

嗯,这一章的内容就到这里。记住:PKI 不是写几行代码就完事的,它需要从硬件、软件、流程三个维度一起设计。下次你设计启动校验时,不妨先画一张证书链图,再动手写代码。