TPM 技术详解:TPM 2.0架构、PCR寄存器与度量扩展、EK与AK密钥体系、Quote与Sign操作
各位同学,今天我们聊一个硬核话题——TPM。说实话,TPM 这东西在零信任远程证明里,就像人的身份证加诚信记录。没有它,你根本没法证明“我是我,我没被篡改”。
我在做第一个远程证明项目时,踩过不少坑。当时对 TPM 的理解停留在“就是个安全芯片”的层面。结果一上手,发现 PCR 怎么扩展、EK 和 AK 怎么配、Quote 怎么验,全是细节。今天我把这些经验掰开揉碎了讲给你听。
TPM 2.0 架构:不只是个芯片
TPM 2.0 相比 1.2,最大的变化是架构更灵活了。1.2 时代,算法被锁死在 SHA-1 和 RSA,你没法选。2.0 则支持多种算法族,你甚至可以自定义。
它的核心组件包括:
- I/O 接口:LPC、SPI、I2C,跟主板通信用
- 密码协处理器:硬件加速 RSA、ECC、哈希
- 密钥生成器:真随机数发生器,物理噪声源
- 非易失性存储器:存 EK 证书、NV 索引
- 易失性存储器:PCR 值、会话上下文
- 执行引擎:跑固件代码,处理 TPM 命令
我个人习惯把 TPM 2.0 架构理解成三层:
- 命令层:你发 TPM2_Quote、TPM2_PCR_Extend 这些命令
- 资源管理层:管理密钥句柄、会话、对象
- 硬件执行层:真正做密码运算、存储保护
下面这张图帮你理清整体脉络:
PCR 寄存器与度量扩展
PCR(Platform Configuration Register)是 TPM 里最核心的寄存器。说白了,它就是一组“只增不减”的哈希值记录器。
每个 PCR 有 20 字节(SHA-1)或 32 字节(SHA-256)。系统启动时,BIOS、Bootloader、OS 内核依次度量自己,然后把度量值“扩展”进 PCR。
扩展操作的数学公式很简单:
PCR_new = SHA256( PCR_old || 度量值 )
注意,这里不是覆盖,是拼接后哈希。所以 PCR 的最终值,依赖所有历史度量值的顺序和内容。你改任何一个环节,最终值都不一样。
常见的 PCR 分配如下:
| PCR 索引 | 度量内容 | 典型用途 |
|---|---|---|
| 0 | BIOS/固件代码 | 验证固件完整性 |
| 1 | 主板配置 | 检测硬件变更 |
| 2 | Option ROM 代码 | 扩展卡完整性 |
| 3 | Option ROM 配置 | 扩展卡配置验证 |
| 4 | MBR/VBR 代码 | 引导扇区完整性 |
| 5 | MBR/VBR 配置 | 引导配置验证 |
| 6 | 状态转换/唤醒 | 休眠恢复验证 |
| 7 | 安全策略 | Secure Boot 策略 |
| 8-15 | OS 组件 | 内核、驱动、initrd |
| 16-23 | 调试/动态度量 | IMA、容器度量 |
EK 与 AK 密钥体系
TPM 的密钥体系,我习惯用“身份证 vs 临时通行证”来类比。
- EK(Endorsement Key):出厂时烧录的 RSA 或 ECC 密钥对。私钥永远不出 TPM,公钥有证书。它就像你的身份证号——唯一且不可变。
- AK(Attestation Key):由 EK 派生出的签名密钥。用于远程证明时的签名操作。它就像你每次出入用的临时通行证。
为什么要有两套密钥?直接拿 EK 签名不行吗?
嗯,这里要注意隐私问题。EK 是唯一的,如果你每次都用 EK 签名,验证方就能追踪你的设备。AK 可以随时换,而且验证方只知道“这是一个合法 TPM 签的”,但不知道具体是哪个 TPM。
AK 的创建流程:
- 调用 TPM2_Create,指定密钥用途为 signing
- TPM 内部生成 AK 公私钥对
- 私钥加密存储在 TPM 内部,公钥可导出
- 用 EK 对 AK 公钥做证书签名(EK 证书链验证)
验证方拿到 AK 公钥后,怎么确认它是合法 TPM 生成的?
通过 EK 证书链。TPM 厂商会签发 EK 证书,验证方信任该 CA。AK 公钥由 EK 签名,所以信任链是:
根 CA → 厂商 CA → EK 证书 → AK 公钥
Quote 与 Sign 操作
这两个操作是远程证明的“临门一脚”。
Sign:TPM 用 AK 私钥对任意数据进行签名。这是基础操作,但远程证明很少直接用 Sign。
Quote:TPM 用 AK 私钥对一组 PCR 值和时间戳(或随机数)做签名。这是远程证明的核心操作。
Quote 的输入参数:
- AK 句柄(哪个密钥签)
- PCR 选择(要报哪些 PCR 的值)
- Nonce(验证方给的随机数,防重放)
- 额外数据(可选,比如平台信息)
Quote 的输出:
- TPM2B_ATTEST:包含 PCR 值、Nonce、时间戳的明文结构
- 签名:对上述结构的签名值
验证方收到 Quote 后,做三步验证:
- 用 AK 公钥验签名,确认是合法 TPM 签的
- 比对 Nonce,确认不是重放攻击
- 比对 PCR 值,确认平台状态符合预期
下面是一个典型的 Quote 调用示例(伪代码):
// 验证方生成随机数
nonce = random_bytes(32)
// 发送给证明方
send(nonce)
// 证明方调用 TPM Quote
pcr_select = [0, 1, 2, 3, 4, 5, 7]
quote = TPM2_Quote(
keyHandle = ak_handle,
pcrSelect = pcr_select,
qualifyingData = nonce
)
// 返回给验证方
send(quote.attested, quote.signature)
// 验证方验签
result = verify_signature(
publicKey = ak_pub,
data = quote.attested,
signature = quote.signature
)
// 验证 Nonce
assert(quote.attested.extraData == nonce)
// 验证 PCR 值
expected_pcrs = load_expected_values()
for pcr_index in pcr_select:
assert(quote.attested.pcrValues[pcr_index] == expected_pcrs[pcr_index])
总结一下
TPM 2.0 的远程证明能力,核心就四块:
- 架构:命令层→资源管理层→硬件执行层,分层清晰
- PCR:只增不减的度量寄存器,记录平台启动链的完整性
- EK/AK:EK 是身份锚点,AK 是签名代理,保护隐私
- Quote/Sign:Quote 是带 PCR 值的签名,远程证明的核心操作