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 编号都记住。

度量过程完整流程图(BIOS → OS) CRTM(硬件固化) BIOS 固件 Option ROM BootLoader(GRUB) OS Kernel IMA 度量 TPM PCR 寄存器 Event Log(度量日志) 度量 BIOS 代码段 度量 Option ROM 度量 BootLoader 度量 Kernel + initramfs 加载 IMA 策略 扩展 PCR(Extend) 记录 Event Log 验证 说明:实线箭头表示控制权转移,虚线箭头表示度量数据流向。每个阶段度量后, 都会同时执行 PCR Extend 和 Event Log 记录,两者缺一不可。

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,四个阶段接力
  • 度量日志——记录谁度量了谁,用于事后审计