第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 做这几件事:
- 加载根证书——从 OTP 中读出根证书公钥。这是硬件信任锚。
- 验证中间证书——用根证书公钥验中间证书的签名。通过后,提取中间证书的公钥。
- 验证固件证书——用中间证书公钥验固件证书的签名。通过后,提取固件哈希。
- 验证固件镜像——计算固件实际哈希,与固件证书中的哈希比对。
每一步都环环相扣。只要有一环断裂,启动就失败。
我的经验:曾经有个客户,中间证书过期了,但设备没有校验证书有效期。结果一台用了三年的设备,突然刷不上新固件。查了两天,才发现是证书时间戳的问题。所以,证书有效期校验一定要做,哪怕你的设备不联网。
4.4 证书链的 SVG 结构图
下面这张图展示了证书链的层级关系和验证流向。我习惯把它画在每一份安全设计文档的首页。
4.5 根证书的保护策略
根证书是整个信任链的命门。一旦泄露,整个产品线的安全就崩塌了。我见过最惨的一次,是某厂商把根证书私钥放在一个 SVN 仓库里——嗯,你没听错,版本控制仓库。结果离职员工带走了整个仓库。
保护根证书,我建议做到以下几点:
- 硬件隔离:私钥存储在 HSM(硬件安全模块)中,永远不离开安全边界。
- 多人授权:签名操作需要至少两人同时授权。单人无法操作。
- 物理保护:HSM 放在机房,门禁、摄像头、日志审计一个不能少。
- 备份策略:私钥分片备份,每片由不同人保管。恢复时需要 M of N 机制。
警告:千万不要把根证书私钥放在开发人员的笔记本上。我曾经审计过一个项目,根证书私钥竟然以「root_key.pem」的名字放在桌面。这不是开玩笑。
4.6 中间证书的轮换机制
中间证书的好处是:你可以定期轮换,而不影响根证书。比如每年换一次中间证书,即使某张中间证书泄露,攻击者也只能伪造当年签发的固件。
轮换流程大致如下:
- 用根证书签发新的中间证书。
- 新固件包中包含新的中间证书。
- BootROM 验证新中间证书的签名(用根证书公钥)。
- 通过后,用新中间证书的公钥验固件签名。
这里有个细节:旧固件怎么办?如果设备还在用旧中间证书签发的固件,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 不是写几行代码就完事的,它需要从硬件、软件、流程三个维度一起设计。下次你设计启动校验时,不妨先画一张证书链图,再动手写代码。