3、TPM与硬件信任根:TPM 2.0 架构、平台配置寄存器(PCR)、EK与AK密钥
聊远程证明,绕不开一个物理存在——TPM。说白了,它就是一颗专门干「脏活累活」的安全芯片。我早年做服务器可信启动时,第一次拆开机箱摸到那个焊在主板上的小模块,心里还在嘀咕:就这玩意儿能扛住攻击?后来被现实教育了——它确实能。
TPM 2.0 和 1.2 差别很大。1.2 是硬编码的 SHA-1 和 RSA,2.0 把算法全开放了,你爱用 ECC 还是 SM3 都行。我个人习惯在项目里优先选 ECC,性能好,密钥短,尤其在嵌入式设备上优势明显。
3.1 TPM 2.0 架构概览
TPM 2.0 内部可以拆成几个关键模块。我画了张图,帮你快速建立整体认知。
这张图里最核心的,是「密钥永远不离开 TPM」这条红线。我在项目里见过有人试图把私钥从 TPM 里导出来做备份——嗯,这条路走不通,TPM 硬件设计上就不允许。私钥操作全在芯片内部完成,外部只能拿到签名或解密结果。
3.2 平台配置寄存器(PCR)
PCR 是 TPM 里最巧妙的设计之一。它本质上是一组不可逆的哈希累加器。你想想看,要证明一台设备的启动过程没有被篡改,光靠一个「是/否」的布尔值是不够的——你需要记录整个信任链的度量值。
PCR 的工作方式很简单:
- 只能扩展(Extend):新值 = SHA256(旧值 || 新度量数据)
- 不能直接写:除了 TPM 复位,没有任何命令能重置单个 PCR
- 不同 PCR 用途不同:PCR[0]-PCR[7] 给 BIOS/UEFI 用,PCR[8]-PCR[15] 给操作系统用
PCR 扩展过程示例:
初始状态: PCR[0] = 0x0000...0000 (全零)
第1次扩展: PCR[0] = SHA256(0x0000...0000 || BIOS_度量值)
第2次扩展: PCR[0] = SHA256(PCR[0] || BootLoader_度量值)
第3次扩展: PCR[0] = SHA256(PCR[0] || OS_Kernel_度量值)
最终: PCR[0] 唯一确定了整个启动链的度量摘要
我曾经在调试一个可信启动问题时,发现 PCR 值对不上。查了两天,最后发现是 BIOS 版本升级后,某个 UEFI 驱动的度量顺序变了。你看,PCR 就是这么敏感——任何微小的变化都会导致最终值完全不同。
3.3 EK 与 AK 密钥
TPM 里有两类密钥,用途完全不同。我刚开始接触时也搞混过,这里帮你理清楚。
| 特性 | EK(Endorsement Key) | AK(Attestation Key) |
|---|---|---|
| 生成时机 | 出厂时预置,不可变 | 运行时动态生成 |
| 私钥位置 | TPM NVRAM,永不可导出 | TPM 内部,可被父密钥保护 |
| 主要用途 | 设备身份标识 + 远程证明基础 | 签名 PCR 值,生成证明报告 |
| 证书 | 由 TPM 厂商或平台厂商签发 | 由 EK 签名或 CA 签发 |
| 隐私风险 | 高(唯一标识设备) | 低(可频繁更换) |
我的经验: 实际项目中,EK 证书通常由 TPM 芯片厂商预置。但有些场景下(比如国内信创项目),EK 证书需要由平台厂商重新签发。我建议你在选型时提前确认 EK 证书的签发链条,否则远程证明的信任锚点会断掉。
3.4 远程证明中的密钥关系
远程证明的流程,说白了就是「用 AK 签名 PCR,用 EK 证明 AK 可信」。我画了张流程图,帮你理解这个信任链。
这个流程里有个关键点:EK 是设备的「身份证」,不能直接用来签名 PCR——否则每次证明都会暴露设备唯一标识,隐私全没了。AK 就是用来解决这个问题的:它由 EK 签名认证,但本身可以频繁更换。验证方只需要确认 AK 是由可信 EK 签发的,就能信任 AK 签名的 PCR 报告。
避坑指南: 我曾经在一个项目中,发现 AK 证书的签发链条没有正确验证 EK 证书的吊销状态。结果一台被标记为「已吊销」的设备,依然能通过远程证明。后来我们加上了 OCSP 或 CRL 检查,才堵住这个漏洞。记住:EK 证书的吊销检查不是可选项,是必选项。
3.5 实战中的 PCR 选择策略
不同场景下,你需要选择不同的 PCR 集合。我整理了一份常用对照表:
| 场景 | 推荐 PCR | 说明 |
|---|---|---|
| BIOS/UEFI 完整性 | PCR[0], PCR[1], PCR[2] | 度量 BIOS 代码、配置和 Option ROM |
| BootLoader 完整性 | PCR[4] | 度量 MBR/GPT 和 BootLoader |
| OS Kernel 完整性 | PCR[8], PCR[9] | 度量内核和内核模块 |
| 应用层完整性 | PCR[12], PCR[13] | IMA 度量,记录文件哈希 |
| 完整启动链 | PCR[0]-PCR[7] | 覆盖从复位向量到 OS 加载 |
我个人习惯在远程证明中至少选择 PCR[0]-PCR[7] 的完整集合。虽然数据量大一些,但能确保启动链的每个环节都被度量到。如果只选个别 PCR,攻击者可能通过篡改未被度量的环节绕过检测。