TPM 基础与配置:TPM 2.0 架构、EK/AK 与 PCR

聊远程证明,TPM 是绕不开的硬件根基。很多朋友刚开始接触时,容易被 TPM 内部那一堆术语搞晕——EK、AK、PCR、NV Index…… 说实话,我早年第一次看 TPM 2.0 规范时也头大。但后来我发现,只要抓住三个核心概念,整个远程证明的信任链条就清晰了:TPM 2.0 架构、EK/AK 密钥体系、PCR 机制。这一章,我们就把这三点彻底讲透。

TPM 2.0 架构:从“黑盒”到“分层”

TPM 1.2 像个黑盒子,功能固定,你改不了。TPM 2.0 不一样,它引入了分层架构,说白了就是“内核 + 库 + 应用”的思路。我个人觉得,理解这个分层是后续所有配置的基础。

TPM 2.0 内部主要分三层:

  • TPM 设备驱动:最底层,负责和硬件通信。这部分你基本不用碰,操作系统帮你搞定了。
  • TPM 资源管理器 (TBS):中间层,管理 TPM 的有限资源。TPM 硬件资源很金贵,比如同时只能处理一个会话,TBS 就是那个调度员。
  • TPM 命令与响应:最上层,你通过工具(比如 tpm2-tools)发送命令给 TPM,TPM 返回结果。

嗯,这里要注意:TPM 2.0 的架构里,密钥、会话、对象都是“实体”,它们有生命周期。你创建了一个密钥,如果不显式保存或加载,TPM 重启后就没了。我在项目中遇到过好几次,同事抱怨“我的密钥怎么丢了”,其实就是没理解 TPM 的易失性存储机制。

核心要点:TPM 2.0 是“命令驱动”的。你通过发送命令来创建密钥、扩展 PCR、生成签名。所有操作都是显式的,没有“自动保存”这回事。

下面这张图,是我自己总结的 TPM 2.0 内部逻辑分层,你看一眼就能明白数据是怎么流动的:

TPM 2.0 内部逻辑分层与数据流 应用层(tpm2-tools, TSS, 远程证明客户端) 发送 TPM 命令(创建密钥、PCR 扩展、签名、引用) TPM 资源管理器(TBS) 管理会话、密钥槽、NV 索引;调度 TPM 硬件访问 TPM 设备驱动 与 TPM 硬件通信(LPC/SPI 总线) TPM 2.0 硬件(安全芯片) 内部包含:PCR 寄存器、EK 种子、RSA/ECC 引擎、随机数发生器 你主要打交道的层 命令从这里下发

EK(背书密钥)与 AK(证明密钥)

这两个密钥是远程证明的“身份证”和“工作证”。很多初学者容易混淆,我当年也犯过这个错。你想想看,EK 是 TPM 出厂时烧录的,全世界唯一,相当于 TPM 的“出生证明”。而 AK 是你自己生成的,用于日常的远程证明操作。

EK(背书密钥)

EK 是 TPM 的根信任。它是一对非对称密钥(RSA-2048 或 ECC),私钥永远不出 TPM 芯片。EK 的公钥会附带一个由 TPM 厂商签发的证书,叫 EK 证书。这个证书是远程证明中“验证对方 TPM 是否真实”的关键。

我的经验:在实际部署中,EK 证书的获取往往是第一个坑。有些厂商的 TPM 没有预置 EK 证书,或者证书格式不标准。我曾经在一个项目中,因为 EK 证书的 OID 字段解析失败,导致整个远程证明链路卡了两天。解决方案是:先通过 tpm2_getekcertificate 确认证书是否存在,如果不存在,需要从厂商官网手动下载并注入。

AK(证明密钥)

AK 是你自己创建的,用于签名 PCR 值或其他证明数据。AK 的私钥同样受 TPM 保护,但 AK 本身需要被 EK “背书”。这个过程叫 AK 认证(MakeCredential / ActivateCredential)。

AK 的生成流程,我建议你记住这四步:

  1. 创建 AK:使用 tpm2_createak 命令,指定算法(RSA 或 ECC)。
  2. 获取 AK 公钥:TPM 返回 AK 公钥和它的名字(Name)。
  3. 生成 AK 证书:这一步通常由远程证明服务端完成——服务端用 EK 公钥加密一个“激活凭据”,TPM 用 EK 私钥解密,验证 AK 确实是在这个 TPM 里生成的。
  4. 保存 AK 句柄:AK 创建后是易失性的,你需要把它保存到 TPM 的持久化存储(NV Index)中,否则 TPM 重启后 AK 就丢了。

避坑指南:我曾经遇到过一个问题:AK 创建后,重启机器,AK 句柄失效了。原因是我没有把 AK 保存到 NV Index。记住,tpm2_evictcontrol 是必须的步骤。另外,AK 的名字(Name)是后续验证的关键,一定要妥善保存。

EK 和 AK 的关系,我用一个表格来对比,这样更清晰:

特性 EK(背书密钥) AK(证明密钥)
生成方式 TPM 厂商预置(出厂时) 用户创建(运行时)
私钥位置 永远在 TPM 内部 永远在 TPM 内部
用途 身份证明、解密激活凭据 签名 PCR 值、远程证明
证书 EK 证书(厂商签发) AK 证书(服务端签发)
生命周期 永久(不可删除) 可创建、可删除、可持久化
数量 通常 1 个 可创建多个

PCR(平台配置寄存器)

PCR 是 TPM 里最巧妙的设计之一。它本质上是一组只能扩展、不能重置(除重启外)的哈希寄存器。你想想看,如果 PCR 可以随意写入任意值,那远程证明就没意义了。正是这种“单向扩展”的特性,让 PCR 能记录系统的启动链。

PCR 的扩展操作很简单:PCR[n] = SHA256(PCR[n] || new_data)。也就是把当前 PCR 值和新的测量值拼接,再做一次哈希。这样,最终的 PCR 值就包含了所有历史测量信息的“指纹”。

TPM 2.0 规范定义了 24 个 PCR(0-23),每个 PCR 有特定的用途:

PCR 索引 用途 测量内容
0-1 BIOS/固件 BIOS 代码、ACPI 表
2-3 Option ROM 扩展卡固件
4 MBR/引导加载器 GRUB 第一阶段
5 引导加载器配置 GRUB 配置文件
6 状态转换/休眠 休眠恢复映像
7 安全策略 Secure Boot 策略
8-9 操作系统内核 内核、initramfs
10-15 操作系统组件 系统服务、模块
16-23 用户定义/调试 应用层测量

在实际的远程证明中,我们通常只关心 PCR 0-7(固件和引导链)和 PCR 8-11(内核和关键服务)。你想想看,如果攻击者篡改了 GRUB 配置文件,PCR 5 的值就会和预期值不同,远程证明服务端就能立刻发现。

关键理解:PCR 不是用来“存储数据”的,而是用来“记录测量历史”的。远程证明的核心逻辑就是:客户端报告 PCR 值,服务端比对“预期 PCR 值”。如果一致,说明系统没有被篡改。

嗯,这里还要提一个我踩过的坑:PCR 的“重置”时机。TPM 重启后,所有 PCR 会重置为初始值(全 0 或全 1,取决于规范)。但有些平台在 S3 休眠恢复后,PCR 不会重置。我曾经在一个项目中,因为没考虑到 S3 恢复场景,导致 PCR 值“看起来”没变,但实际系统已经换了状态。解决方案是:在远程证明前,先检查 TPM 的启动计数器(TPM2_GetCapability),确认系统是冷启动还是热启动。

最后,我用一张图来总结 PCR 的扩展过程和它在远程证明中的位置:

PCR 扩展过程与远程证明引用 测量事件 1 BIOS 代码 测量事件 2 GRUB 配置 测量事件 3 内核映像 PCR 扩展引擎 PCR[n] = SHA256(旧值 || 新数据) 初始值: 0x00...00 ↓ 扩展后: 0xA3...F1 ↓ 最终: 0x7B...9C 远程证明引用 TPM2_Quote(PCR 选择) AK 签名 PCR 值 发送给验证服务端 服务端比对预期 PCR 值 一致则信任,不一致则告警

好了,TPM 的这三个核心概念——架构、EK/AK、PCR——是远程证明的基石。你理解了它们,后续的 Quote、验证、策略配置就顺理成章了。我个人建议,你可以在自己的实验环境里,用 tpm2_pcrread 和 tpm2_createak 实际动手操作一遍,感受一下 TPM 的“单向扩展”和“密钥绑定”到底是怎么回事。纸上得来终觉浅,绝知此事要躬行。