信任根与信任链:硬件信任根(TPM、TEE)、信任链建立过程、静态与动态信任根
聊远程证明,绕不开一个核心问题:凭什么相信你?
设备说“我是安全的”,你得有办法验证。这个验证的起点,就是信任根。我做了这么多年物联网安全,见过太多设备因为信任根没扎牢,整个安全体系形同虚设。说白了,信任根就是整个安全大厦的地基,地基不稳,上面盖多高都没用。
2.1 什么是信任根?
信任根(Root of Trust,RoT),是一个必须被无条件信任的组件。它本身不能被验证,因为它是验证链条的起点。你想想看,如果信任根还需要别的组件来验证它,那就不叫“根”了。
在实际项目中,信任根通常是一个硬件安全模块。为什么必须是硬件?因为纯软件方案容易被篡改。我见过一个客户,早期用软件模拟TPM,结果被攻击者直接patch了内存里的度量值,整个信任链瞬间崩塌。从那以后,我对纯软件信任根一直持保留态度。
信任根的核心属性:
- 不可伪造性:攻击者无法冒充信任根的行为
- 防篡改性:信任根自身的代码和数据不能被修改
- 隔离性:信任根运行在独立的安全环境中,主CPU无法直接访问其内部状态
2.2 硬件信任根:TPM vs TEE
目前主流的硬件信任根方案有两种:TPM 和 TEE。很多人搞不清它们的区别,我简单说说。
2.2.1 TPM(可信平台模块)
TPM 是一个独立的安全芯片,有自己独立的CPU、存储和密码运算单元。它跟主CPU是分离的,通过LPC或SPI总线通信。
TPM 的核心能力包括:
- 平台配置寄存器(PCR):用于存储度量值的哈希,一旦写入就不能被篡改(只能扩展)
- 背书密钥(EK):每个TPM芯片出厂时烧录的唯一身份密钥
- 存储根密钥(SRK):保护用户数据的根密钥
- 单调计数器:防止回滚攻击
我记得有一次做车联网项目,需要保证每个T-Box的固件不被篡改。我们就是用TPM的PCR来存储每个启动阶段的度量值,然后远程证明时直接读取PCR值。攻击者就算改了Flash里的固件,PCR里的哈希对不上,立马现原形。
2.2.2 TEE(可信执行环境)
TEE 跟 TPM 思路不同。它不是在主芯片外面加一个独立芯片,而是在主CPU内部划出一个安全区域。这个区域有独立的地址空间、独立的中断处理,甚至独立的IO路径。
常见的TEE实现:
- ARM TrustZone:把CPU分为安全世界和普通世界
- Intel SGX:在内存中创建飞地(Enclave)
- RISC-V 物理内存保护(PMP):通过硬件规则隔离内存区域
TEE 的好处是性能好,因为它跟主CPU共享计算资源,不需要额外的芯片。但坏处是,如果主CPU本身有硬件漏洞,TEE也保不住。嗯,这里要注意,TEE的安全假设是“CPU硬件是可信的”,这个假设在某些场景下不一定成立。
| 对比维度 | TPM | TEE |
|---|---|---|
| 物理形态 | 独立芯片 | CPU内部安全区域 |
| 性能 | 较低(独立芯片,通信有延迟) | 较高(共享CPU资源) |
| 安全隔离 | 物理隔离,抗物理攻击强 | 逻辑隔离,抗物理攻击弱 |
| 成本 | 较高(额外芯片和PCB面积) | 较低(集成在SoC内) |
| 典型应用 | PC、服务器、工业设备 | 手机、IoT设备、边缘计算 |
2.3 信任链建立过程
有了信任根,接下来就是怎么把信任从根传递到整个系统。这个过程叫信任链(Chain of Trust)。
信任链的核心思想很简单:每一级在启动下一级之前,先度量下一级的代码,然后把度量值存到信任根里,最后才把控制权交给下一级。
2.3.1 典型的信任链流程
- 阶段1:信任根(Boot ROM)
- 上电后CPU首先执行固化在ROM里的代码
- 这段代码是硬件写死的,不可修改
- 它度量Bootloader的代码,计算哈希,写入TPM的PCR[0]
- 阶段2:Bootloader
- Boot ROM验证通过后,跳转到Bootloader
- Bootloader度量OS内核,写入PCR[1]
- 阶段3:OS内核
- 内核度量关键系统服务,写入PCR[2]
- 阶段4:应用层
- 系统服务度量应用程序,写入PCR[3]
我曾经在一个IoT网关项目里,发现Bootloader没有度量内核的签名,而是直接度量了整个内核镜像文件。结果攻击者往内核镜像里塞了一段恶意代码,虽然哈希变了,但攻击者同时修改了Bootloader的度量逻辑,让它跳过校验。这就是典型的信任链断裂——度量者本身没有被度量。
避坑指南:信任链的每一级都必须度量下一级的完整代码和关键配置,不能只度量部分内容。我曾经见过一个方案,Bootloader只度量了内核的头部,结果攻击者修改了内核的尾部代码,绕过了度量。记住:度量范围必须是“执行前能访问到的所有可执行内容”。
2.4 静态信任根 vs 动态信任根
信任根根据其生命周期,可以分为静态信任根和动态信任根。这个区分很重要,直接决定了你的远程证明方案能覆盖多广。
2.4.1 静态信任根(SRoT)
静态信任根在设备上电时建立,之后在整个运行期间保持不变。它通常固化在Boot ROM里,从设备启动开始就参与信任链的构建。
特点:
- 信任根在设备生命周期内不变
- 只能度量启动时的系统状态
- 无法应对运行时的动态攻击(如代码注入、内存篡改)
说白了,静态信任根只能保证“启动时是干净的”,但启动之后系统被黑了,它管不了。
2.4.2 动态信任根(DRoT)
动态信任根可以在设备运行过程中随时建立新的信任锚点。它不依赖启动时的信任链,而是通过硬件指令在任意时刻创建一个可信环境。
典型的实现:
- Intel TXT(Trusted Execution Technology):通过GETSEC指令在运行时启动一个可信度量
- ARM TrustZone 动态建立安全世界:通过SMC指令切换到安全世界,重新度量关键代码
- TPM 2.0 的“授权策略”:允许在运行时动态扩展PCR
动态信任根的好处是,你可以按需建立信任。比如,当系统检测到可疑行为时,可以动态启动一个安全环境,重新度量关键内存区域,然后跟远程证明服务器通信。
| 对比维度 | 静态信任根(SRoT) | 动态信任根(DRoT) |
|---|---|---|
| 建立时机 | 设备上电时 | 运行过程中任意时刻 |
| 信任锚点 | Boot ROM(不可变) | 硬件指令或安全监控器 |
| 覆盖范围 | 启动过程 | 启动过程 + 运行时 |
| 抗运行时攻击 | 弱 | 强 |
| 实现复杂度 | 低 | 高 |
| 典型场景 | 简单IoT设备、传感器 | 边缘服务器、自动驾驶域控制器 |
我的建议:如果你的设备资源受限(比如MCU只有几百KB Flash),用静态信任根就够了。但如果是高性能设备(比如带Linux的网关),我强烈建议引入动态信任根。原因很简单——静态信任根只能证明“启动时是好的”,但攻击者完全可以在系统运行后注入恶意代码。动态信任根让你能在运行时重新建立信任,这才是远程证明真正需要的。
2.5 信任根与信任链的关系图
下面这张图展示了信任根如何通过信任链,把信任从硬件层传递到应用层。注意看,每一级都在度量下一级,度量值最终汇总到信任根里。
2.6 实际项目中的选择建议
讲了这么多,到底怎么选?我根据自己的项目经验,给几个实用建议:
- 低端MCU设备(Cortex-M0/M3,Flash < 1MB):用静态信任根 + 片上Boot ROM。TPM太贵,TEE不支持,老老实实做启动度量就够了。
- 中端Linux设备(Cortex-A系列,带MMU):用TEE(TrustZone)作为信任根。性能好,成本可控,支持动态信任根。
- 高端服务器/边缘节点(x86/ARMv8):TPM + TEE 双保险。TPM做静态信任根,TEE做动态信任根,互相补充。
- 车规级设备:必须用独立HSM(硬件安全模块),同时支持静态和动态信任根。车规要求ISO 21434,对信任链有严格规定。
特别提醒:不要为了省成本砍掉信任根。我见过一个智能门锁项目,为了省几毛钱没用安全芯片,结果被攻击者通过SPI接口直接dump了Flash,拿到了所有用户的指纹模板。事后复盘,如果当时加一颗TPM,成本增加不到2块钱,但整个安全等级能提升一个数量级。信任根不是成本,是保险。