1. 可信启动概述
各位同学,今天咱们来聊聊可信启动。说实话,这个主题在嵌入式安全里算是"地基"一样的存在。我做了十几年固件,见过太多因为启动链被攻破而全盘皆输的项目。嗯,咱们就从最基础的问题开始:到底什么是可信启动?
1.1 什么是可信启动
可信启动,说白了就是让设备从通电那一刻起,每一步都"验明正身"。你想想看,一个嵌入式设备上电后,CPU 先跑的是 BootROM,然后加载 Bootloader,再加载操作系统内核,最后拉起应用程序。这一串流程里,只要有一个环节被篡改,整台设备就不可信了。
我习惯把可信启动比作"接力赛"——每一棒选手都要确认上一棒的身份,才能接过接力棒继续跑。具体来说:
- BootROM 验证 Bootloader 的签名
- Bootloader 验证 OS Kernel 的哈希值
- Kernel 验证关键驱动的完整性
- 每一级都只信任上一级验证过的代码
核心定义:可信启动是一种从硬件根信任开始,逐级验证固件完整性和来源真实性的安全机制。它确保设备只运行经过授权的、未被篡改的代码。
我在一个 IoT 网关项目里遇到过这样的情况:客户说设备偶尔会"变砖",查了三个月才发现是 Bootloader 被某个野鸡固件覆盖了。从那以后,我所有项目的第一件事就是先把可信启动链路搭好。
1.2 为什么需要可信启动
你可能会问:不加可信启动,设备不也能跑吗?能跑,但风险太大了。我列几个真实场景给你看:
| 威胁场景 | 没有可信启动的后果 | 有可信启动的保护 |
|---|---|---|
| 固件被逆向篡改 | 攻击者植入后门,设备沦为肉鸡 | 签名校验失败,拒绝启动 |
| OTA 升级被劫持 | 恶意固件被刷入,全盘沦陷 | 来源验证不通过,升级回滚 |
| 物理攻击(SPI Flash 替换) | 攻击者直接换芯片,绕过软件保护 | BootROM 校验失败,设备锁死 |
| 供应链攻击 | 生产环节被植入恶意代码 | 出厂签名链断裂,无法量产 |
说白了,可信启动解决的是"我怎么知道我跑的是我写的代码"这个问题。我曾经帮一个做智能门锁的团队做安全审计,他们的设备没有可信启动,攻击者只需要用编程器把 Flash 里的固件读出来,改几行代码再写回去,门锁就变成"万能钥匙"了。嗯,这种漏洞在合规审查里属于"致命级"。
避坑指南:千万不要以为"我的设备不上网就不需要可信启动"。物理攻击、JTAG 调试接口暴露、甚至维修站都能成为攻击入口。我见过最离谱的案例——攻击者通过替换设备的 SD 卡启动分区,直接拿到了整个系统的 root 权限。
1.3 可信启动的信任链模型
信任链模型是可信启动的骨架。我画了一张图,帮你把整个链条看清楚:
这个模型里,最底层的 硬件根信任(Root of Trust, RoT) 是整个链条的基石。它通常固化在芯片的 OTP(一次性可编程)存储器里,包含公钥哈希或证书。BootROM 在出厂时就被掩膜在芯片里,攻击者改不了它。
我习惯把 RoT 比作"保险箱的锁芯"——你可以在外面加多少层防护,但锁芯本身必须是物理上不可篡改的。我在一个车规级项目里用过 Infineon 的 TPM 芯片做 RoT,那玩意儿确实稳,但调试起来也够呛。嗯,后面章节咱们会手把手教你配。
1.4 信任链的三种常见形态
实际项目中,信任链的实现方式不止一种。我根据经验给你总结了三类:
| 类型 | 特点 | 适用场景 | 安全等级 |
|---|---|---|---|
| 静态信任链 | 启动时一次性验证,之后不再检查 | 资源受限的 MCU、简单 IoT 设备 | 中等 |
| 动态信任链 | 运行时持续验证,支持远程证明 | Linux 嵌入式设备、网关、服务器 | 高 |
| 混合信任链 | 启动时静态验证 + 关键操作时动态验证 | 汽车 ECU、医疗设备、工业控制器 | 最高 |
你可能会问:那我该选哪种?我的建议是——看你的威胁模型。如果设备丢了最多损失几十块钱的硬件成本,静态信任链就够了。但如果设备控制着生产线、汽车刹车或者病人的输液泵,那必须上动态甚至混合信任链。
个人经验:我在一个智能电表项目里选了静态信任链,结果客户要求过 DLMS/COSEM 安全认证,硬生生补了动态远程证明模块。从那以后,我建议大家在架构设计阶段就把信任链等级定好,不然后面改起来比重新写还痛苦。
1.5 信任链的度量与报告
信任链不只是"验签名"这么简单。它还需要做两件事:度量(Measurement)和报告(Reporting)。
- 度量:在每一级启动前,计算下一级代码的哈希值,并与预期值比对。我习惯用 SHA-256,安全性和性能平衡得不错。
- 报告:将度量结果存储在平台配置寄存器(PCR)中,供远程验证方查询。TPM 芯片就是干这个的。
举个例子,一个典型的 TPM 度量流程是这样的:
// 伪代码:TPM 度量流程
BootROM:
hash = SHA256(bootloader.bin)
TPM_PCR_Extend(PCR[0], hash)
if (hash != golden_hash) halt
Bootloader:
hash = SHA256(kernel.bin)
TPM_PCR_Extend(PCR[1], hash)
if (hash != golden_hash) fallback_to_recovery
Kernel:
hash = SHA256(initramfs.img)
TPM_PCR_Extend(PCR[2], hash)
// 继续加载...
注意看,每次度量后都会调用 TPM_PCR_Extend。这个操作会把新哈希和 PCR 里的旧值做拼接再哈希,形成一条不可逆的度量链。攻击者就算篡改了某个阶段的代码,PCR 里的值也会对不上,远程验证方一眼就能看出来。
我曾经踩过的坑:第一次做 TPM 集成时,我忘了在 BootROM 里初始化 PCR 寄存器。结果每次启动 PCR 值都不一样,远程证明永远失败。查了三天才发现是 PCR 没复位。嗯,这种低级错误犯一次就够了。
1.6 小结
这一章咱们把可信启动的"骨架"搭起来了。你记住三件事就行:
- 可信启动是从硬件根信任开始的逐级验证过程
- 没有可信启动,设备在物理攻击和供应链攻击面前就是裸奔
- 信任链模型的核心是"每一级只信任上一级验证过的代码"
后面的章节,我会带你从 BootROM 的签名验证开始,一步步把整个信任链在真实硬件上跑通。准备好了吗?咱们开始动手。