3、度量过程详解:度量是什么、度量时机(BIOS→OS)、度量日志(Event Log)
好,咱们进入第三章。前两章我们把 PCR 和可信启动的骨架搭起来了,这一章要往里填肉——度量过程到底是怎么跑的。
说白了,度量就是“在某个关键时刻,把一段代码或数据的哈希值算出来,然后存进 PCR”。听起来简单吧?但这里面的门道可不少。我刚开始接触 TPM 时,觉得度量不就是算个 SHA256 嘛,有什么好讲的?后来被坑了几次才明白——度量时机、度量对象、度量日志,这三样东西但凡有一个对不上,整个信任链就断了。
3.1 度量到底是什么?
先给个准确定义:度量(Measurement),是指将某个实体的完整性信息(通常是哈希值)记录下来,并扩展(Extend)到 PCR 中的过程。
注意,这里的关键词是“扩展”,不是“覆盖”。PCR 的更新方式是这样的:
PCR_new = SHA256( PCR_old || 新度量值 )
为什么要用扩展而不是直接覆盖?我举个例子你就明白了。假设你要度量 BIOS → BootLoader → OS Kernel 这三个阶段。如果每个阶段都直接覆盖 PCR,那最终 PCR 里只存了 OS Kernel 的哈希,前面两个阶段的信息全丢了。但用扩展的方式,最终 PCR 值其实是:
PCR_final = SHA256( SHA256( SHA256(0 || BIOS) || BootLoader ) || Kernel )
你看,这个值隐含了整个链条的完整性信息。只要中间任何一个环节被篡改,最终值就不一样。这就是信任链的数学基础。
核心要点:度量不是“记录”,而是“累积”。每次扩展都像在链上再加一个锁,最终 PCR 值就是整条链的指纹。
3.2 度量时机:从 BIOS 到 OS 的完整链条
度量不是一次性完成的。它像接力赛一样,一棒接一棒。我习惯把整个度量过程分成四个阶段:
| 阶段 | 度量者 | 度量对象 | 目标 PCR |
|---|---|---|---|
| 阶段 1:CRTM | CPU 微码 / 硬件 | BIOS 固件(BIOS 代码段) | PCR-0 |
| 阶段 2:BIOS | BIOS 自身 | Option ROM、MBR、GPT 头 | PCR-1 ~ PCR-4 |
| 阶段 3:BootLoader | BootLoader(如 GRUB) | Kernel、initramfs、内核命令行 | PCR-4 ~ PCR-8 |
| 阶段 4:OS | OS 内核 / IMA | 可执行文件、动态库、内核模块 | PCR-10 ~ PCR-11 |
这里有个容易混淆的点:CRTM(Core Root of Trust for Measurement)是谁?它其实是 CPU 出厂时固化的一段微码,是度量链条的起点。CRTM 度量完 BIOS 后,把控制权交给 BIOS,然后 BIOS 度量 BootLoader,BootLoader 度量 OS……
嗯,这里要注意:CRTM 本身是不可度量的。你想想看,如果 CRTM 都能被改,那整个信任链就建立在沙滩上了。所以 CRTM 必须是硬件固化的、不可篡改的。
我的经验:在实际项目中,最容易出问题的是阶段 2 到阶段 3 的交接。BIOS 度量完 BootLoader 后,如果 BootLoader 没有正确继承 PCR 状态,信任链就断了。我曾经遇到过一个案例,BIOS 升级后 PCR-4 的值变了,结果 GRUB 拒绝启动——就是因为度量时机没对齐。
3.3 度量日志(Event Log):信任链的“黑匣子”
PCR 只存了最终的哈希值,但没存“谁度量了谁”的详细信息。这就引出了度量日志(Event Log)的概念。
你可以把 Event Log 想象成飞机的黑匣子。PCR 是黑匣子里的最终数据,Event Log 是完整的飞行记录——什么时间、谁、度量了哪个文件、结果是什么。
Event Log 的典型结构是这样的:
typedef struct {
UINT32 PCRIndex; // 目标 PCR 编号
UINT32 EventType; // 事件类型(如 EV_EFI_BOOT_SERVICES_APPLICATION)
UINT8 Digest[20]; // 度量值(SHA1 或 SHA256)
UINT32 EventSize; // 事件数据大小
UINT8 Event[]; // 事件数据(如文件路径、版本号)
} TCG_PCR_EVENT;
为什么需要 Event Log?我给你说个真实场景。
有一次,客户反馈说某台服务器的 PCR-4 值跟预期不符,系统无法通过远程证明。我拿到 PCR 值一看,确实不对。但光看 PCR 值,我根本不知道是哪个环节出了问题。后来我调出 Event Log,发现是 BIOS 在度量某个 Option ROM 时,那个 ROM 的版本号跟预期不一样——原来是运维人员升级了网卡固件,但没更新白名单。
你看,没有 Event Log,你只能看到“结果不对”;有了 Event Log,你就能定位到“哪里不对”。
3.4 度量过程的完整流程图
下面这张图把整个度量过程串起来了。我建议你多看几遍,把每个箭头、每个 PCR 编号都记住。
3.5 度量过程中的常见坑
做度量实现时,有几个地方特别容易踩坑。我列出来,你以后遇到了能少走弯路。
坑一:PCR 索引搞混
不同厂商的 BIOS 对 PCR 的分配可能不一样。比如 PCR-1 在 TCG 规范里是“平台固件配置”,但有些厂商把它用来存 SMBIOS 信息。我曾经因为没看厂商文档,直接按规范写代码,结果 PCR 值死活对不上。
坑二:Event Log 不完整
有些 BIOS 实现只记录部分度量事件,或者 Event Log 的格式不符合 TCG 规范。这会导致远程证明时,验证方无法解析日志。我建议你在开发阶段就加一个 Event Log 的校验工具,确保每条记录都完整。
坑三:度量顺序不一致
同一个 BIOS 版本,如果度量顺序不同(比如先度量 Option ROM A 再度量 Option ROM B,跟先 B 再 A),最终 PCR 值会不一样。所以度量顺序必须是确定性的,不能依赖硬件枚举顺序。
3.6 小结
这一章我们讲了度量的三个核心要素:
- 度量是什么——哈希 + 扩展,形成信任链
- 度量时机——从 CRTM 到 OS,四个阶段接力
- 度量日志——记录谁度量了谁,用于事后审计