TPM 2.0 基础:架构、PCR、密钥与远程证明流程

TPM 2.0 是远程证明的硬件根基。说白了,它就是一颗专门干「密码学脏活」的安全芯片。我最早接触 TPM 是在做服务器固件完整性校验的项目,那时候还是 TPM 1.2,功能限制很多。到了 2.0 版本,架构彻底重写了,灵活性和扩展性都上了一个台阶。

这一节我们不讲枯燥的规范文档,而是从实战角度拆解 TPM 2.0 的核心部件:架构长什么样、PCR 寄存器怎么用、EK 和 AK 密钥对到底有什么区别、Quote 和 Attestation 的完整流程是怎样的。

TPM 2.0 架构概览

TPM 2.0 的架构可以分成三层:I/O 层、命令处理层和密码学引擎层。我个人习惯把它理解成一个「黑盒密码机」——你往里送命令和数据,它返回签名或摘要,中间过程你碰不到。

核心要点:TPM 2.0 不再像 1.2 那样只支持单一算法(SHA-1 + RSA),而是支持算法套件自由组合。你可以选 ECC、SM2、SM3、SM4,甚至自定义算法。这一点在国产化场景下特别重要。

我画了一张架构图,帮你快速建立整体认知:

TPM 2.0 核心架构 I/O 接口层 LPC / SPI / I²C 总线 · 命令缓冲区 · 响应队列 命令处理层 命令解析 · 会话管理 · 授权校验 · 策略引擎 TPM 命令 TCG 标准 · 增强授权 (EA) · 多会话支持 密码学引擎层 对称加密 (AES/SM4) · 非对称加密 (RSA/ECC/SM2) 哈希 (SHA-1/SHA-256/SM3) · HMAC · 随机数生成器 密钥生成 · 签名 · 验证 · 密封/解封 持久存储区 (NVRAM) EK 证书 · AK 持久句柄 · PCR 初始值 · 平台配置 命令/数据流 自顶向下

你看,整个架构是分层解耦的。上层应用不需要关心底层用的是什么密码算法,只要通过标准命令接口调用就行。我在实际项目中遇到过一个问题:某厂商的 TPM 芯片只支持 RSA 2048,不支持 ECC,结果远程证明的签名速度慢得离谱。后来换了支持 ECC 的芯片,性能提升了 10 倍以上。

PCR 寄存器:平台状态的「指纹」

PCR(Platform Configuration Register)是 TPM 里最核心的寄存器。它的作用很简单:记录平台启动过程中的度量值。每个 PCR 只能做 Extend 操作,不能直接写值。

Extend 的数学公式是:

PCR_new = SHA256(PCR_old || 度量值)

这意味着 PCR 的值是链式累积的。你没法回退,也没法伪造。我经常跟团队说:PCR 就是平台状态的「区块链」,只不过链很短,只有 24 个寄存器。

PCR 索引 用途 度量内容
0-7 固件/BIOS 度量 BIOS 代码、ACPI 表、SMBIOS 数据
8-15 操作系统度量 Bootloader、内核模块、驱动签名
16 调试/测试 调试工具、测试代码
17-23 动态信任度量 应用层度量、容器镜像、策略数据

实战技巧:远程证明时,通常只读取 PCR 0-7 和 PCR 8-15 的值就够了。PCR 16 在正式环境里要禁用,否则攻击者可以通过调试接口篡改度量值。我曾经在客户现场排查过一个问题:PCR 16 被意外 Extend 了调试工具的值,导致远程证明一直失败。排查了整整两天才发现是测试脚本没清理干净。

EK 与 AK 密钥:身份与匿名的平衡

TPM 2.0 里有两类核心密钥:EK(Endorsement Key)和AK(Attestation Key)。很多人搞混它们的区别,我直接给你一个对比表:

属性 EK AK
生成方式 芯片出厂时预置 运行时动态生成
私钥可导出 否(永久锁定在 TPM 内) 否(但可创建多个)
用途 身份证明 + 密钥协商 签名证明数据(Quote)
证书 EK 证书(由 TPM 厂商签发) AK 证书(由隐私 CA 签发)
隐私保护 弱(直接暴露芯片身份) 强(可匿名化)

为什么需要两套密钥?说白了,EK 是 TPM 的「身份证」,不能随便拿出来用。如果你每次远程证明都用 EK 签名,那攻击者就能追踪你的平台。AK 相当于「临时工牌」,每次证明可以换一张,但背后绑定的还是同一个 EK。

注意:AK 的生成必须经过 EK 的授权。具体流程是:TPM 用 EK 解密一个由隐私 CA 加密的证书请求,然后生成 AK 并绑定到 EK。没有这一步,AK 就是无根之木。我在项目中见过有人直接生成 AK 而不做 EK 绑定,结果验证方根本不认。

Quote 与 Attestation 流程

Quote 是 TPM 2.0 远程证明的核心操作。它的本质是:TPM 用 AK 对一组 PCR 值进行签名。验证方拿到签名后,比对 PCR 的期望值,就能判断平台是否可信。

完整的 Attestation 流程分四步:

  1. 挑战阶段:验证方生成一个随机数(Nonce),发送给被验证方。
  2. Quote 阶段:被验证方调用 TPM2_Quote 命令,传入 Nonce、PCR 选择列表和 AK 句柄。TPM 返回签名后的 PCR 值和 Nonce。
  3. 传输阶段:被验证方将 Quote 数据、PCR 值、AK 证书一起发送给验证方。
  4. 验证阶段:验证方校验 AK 证书链、签名有效性、PCR 值是否匹配期望值。

我画了一张流程图,把关键步骤和数据结构都标出来了:

远程证明 Quote & Attestation 流程 验证方 (Verifier) 生成 Nonce · 校验签名 · 比对 PCR 被验证方 (Prover) TPM2_Quote · 收集 PCR · 发送证明 步骤 1:验证方生成 Nonce,发送给被验证方 步骤 2:被验证方调用 TPM2_Quote(Nonce, PCR_List, AK_Handle) TPM 内部 AK 签名 → 输出 Quote 结构体 步骤 3:被验证方发送 Quote + PCR 值 + AK 证书 → 验证方 步骤 4:验证方校验 AK 证书链 → 验证签名 → 比对 PCR 期望值 通过 → 平台可信;失败 → 平台被篡改

Quote 返回的数据结构长这样:

TPM2_Quote 返回结构:
{
  TPM2B_ATTEST  quoted;      // 包含 PCR 值、Nonce、时间戳
  TPMT_SIGNATURE signature;  // AK 对 quoted 的签名
}

quoted 内部字段:
- magic: 0xFF544347 (固定魔数)
- type: TPM_ST_ATTEST_QUOTE
- qualifiedSigner: AK 名称
- extraData: Nonce(防重放)
- clock: TPM 内部时钟
- firmwareVersion: 固件版本
- attested.quote.pcrSelect: PCR 选择位图
- attested.quote.pcrDigest: PCR 值的摘要

避坑指南:我曾经在调试 Quote 时发现签名总是校验失败。排查了半天,原来是 Nonce 长度不对——TPM 2.0 要求 Nonce 必须是 20 字节(SHA-1 输出长度),而我传了 32 字节。TPM 内部会截断,导致两边 Nonce 不一致。记住:Nonce 长度必须严格遵循 TPM 规范,不要自己拍脑袋定长度。

小结

TPM 2.0 的远程证明,核心就是三件事:PCR 度量平台状态、AK 签名证明数据、验证方比对期望值。架构上分层解耦,密钥体系上 EK 和 AK 分工明确,流程上挑战-响应防重放。