度量启动:从BIOS到可信链的建立
度量启动(Measured Boot)这个概念,我第一次认真研究是在一个金融客户的项目里。当时他们要求服务器启动时必须能证明「我没有被篡改过」。安全启动(Secure Boot)只能保证启动代码签名有效,但签名有效不代表代码没被改过——嗯,这里有个微妙的区别。
说白了,度量启动干的事就是:把启动过程中每个组件的哈希值记下来,存到日志里,再扩展到TPM的PCR寄存器。这样远程验证方就能拿到一份「启动过程的完整体检报告」。
核心思想:度量启动不阻止恶意代码运行,但它确保任何篡改都会被记录在案。你改得了代码,改不了PCR里的哈希值。
BIOS/UEFI启动度量流程
我习惯把度量启动分成三个阶段来看:
- 前BIOS阶段:CPU微码、启动ROM的度量
- BIOS/UEFI阶段:固件、驱动、Option ROM的度量
- OS Loader阶段:引导加载程序、内核的度量
每个阶段都会调用TPM的TPM2_PCR_Extend命令,把当前组件的哈希值「扩展」到PCR里。扩展操作不是简单的覆盖,而是:
PCR新值 = SHA256(PCR旧值 || 新组件的哈希值)
这个设计很巧妙。你没法回滚PCR值,也没法伪造一个合法的扩展链。我在调试一个国产服务器时遇到过一个问题——BIOS度量顺序和规范不一致,导致远程验证总是失败。查了两天才发现是固件厂商把某个Option ROM的度量顺序搞反了。
度量日志(Event Log)
PCR只存了最终的哈希链,但没存「谁度量了谁」的详细信息。度量日志就是补这个缺的。
日志格式遵循TCG规范,每个事件记录包含:
| 字段 | 说明 | 长度 |
|---|---|---|
| PCRIndex | 扩展到了哪个PCR寄存器 | 4字节 |
| EventType | 事件类型(如EV_EFI_BOOT_SERVICES_APPLICATION) | 4字节 |
| Digest | 该组件的哈希值 | 20/32/48字节 |
| EventData | 组件名称、版本、签名信息等 | 可变 |
你想想看,远程验证时,验证方会做两件事:
- 重放日志中的每个事件,计算PCR值是否匹配
- 检查每个组件的哈希值是否在白名单中
如果日志被篡改,重放计算出的PCR值就和TPM报告的PCR值对不上。这就是度量启动的防篡改机制。
实战技巧:在Linux下可以用tpm2_eventlog命令查看度量日志。我建议你抓一份真实日志看看,比读十遍规范都管用。
与安全启动(Secure Boot)的区别
很多初学者会把这两个概念搞混。我做个对比表,你一看就明白:
| 维度 | 安全启动(Secure Boot) | 度量启动(Measured Boot) |
|---|---|---|
| 目标 | 阻止未签名代码运行 | 记录所有运行过的代码 |
| 机制 | 签名验证,拒绝未授权代码 | 哈希扩展,记录到PCR |
| 阻断能力 | 能阻断启动 | 不阻断,只记录 |
| 依赖硬件 | UEFI固件 | TPM芯片 |
| 远程验证 | 无法直接远程验证 | 通过PCR引用进行远程验证 |
| 篡改后果 | 启动失败 | PCR值与日志不匹配 |
我曾经在一个项目里看到有人只配了安全启动,没开度量启动。结果设备被攻破后,攻击者直接替换了合法的签名证书——安全启动照样通过,但系统已经被完全控制了。如果开了度量启动,PCR值的变化会立刻暴露问题。
重要提醒:安全启动和度量启动是互补关系,不是替代关系。最佳实践是两者都开。安全启动负责「防」,度量启动负责「记」。
度量启动的完整流程
下面这张图展示了从BIOS到OS Loader的完整度量链:
PCR寄存器的分配规则
TCG规范定义了PCR的用途。我挑几个关键的说说:
- PCR[0]:BIOS/UEFI固件代码
- PCR[1]:BIOS/UEFI配置数据
- PCR[2]:Option ROM代码
- PCR[3]:Option ROM配置数据
- PCR[4]:MBR/引导加载程序
- PCR[5]:GPT分区表
- PCR[6]:状态转换和唤醒事件
- PCR[7]:安全启动策略
我记得有一次排查问题,发现PCR[7]的值和预期不符。查了半天,原来是安全启动的DBX(吊销签名数据库)更新了,但度量日志里没体现。这提醒了我:度量日志和PCR必须一一对应,缺一个都不行。
调试技巧:用tpm2_pcrread可以实时查看PCR值。我习惯在设备启动前后各抓一次,对比变化。如果某个PCR值没变,说明对应的组件可能没被度量——这是个危险信号。
远程验证中的度量启动
在远程证明场景里,度量启动的价值就体现出来了。验证方拿到设备发来的度量日志和PCR引用后,会做三步检查:
- PCR值验证:重放日志,计算预期PCR值,比对TPM报告的PCR引用
- 组件白名单:检查每个组件的哈希值是否在已知的可信列表中
- 启动链完整性:确认度量顺序符合规范,没有跳过的步骤
这三步只要有一项不通过,设备就被判定为不可信。我在做金融项目时,客户要求每15分钟做一次远程验证。一开始觉得频率太高,后来发现确实有必要——攻击者可能在两次验证之间篡改系统。
避坑指南:我曾经遇到一个案例,设备度量日志完整,PCR值也匹配,但远程验证就是失败。最后发现是TPM固件版本太老,PCR引用算法和验证方不兼容。所以,TPM固件版本和验证方的算法套件必须对齐。
度量启动不是银弹,但它提供了启动过程的可信证据。配合安全启动和远程验证,就能构建一条从硬件到应用的完整可信链。嗯,这就是为什么我在所有涉及可信计算的方案里,都会把度量启动作为必选项。