4. 度量值采集原理:度量时机、度量对象与度量算法

好,咱们进入第四章节。前面几章我们把可信启动的宏观流程讲清楚了,这一章要扎进去,看看度量值到底是怎么采出来的。

说白了,度量采集就是回答三个问题:什么时候量?量什么东西?用什么算法量? 这三个问题搞不清楚,后面策略配置全是空中楼阁。我在项目里见过不少团队,策略写得花里胡哨,结果度量时机没选对,开机直接蓝屏——嗯,这种坑我踩过,所以今天咱们重点把这三个维度掰开揉碎。

4.1 度量时机:Pre-OS 与 OS 阶段

度量时机,就是问「什么时候动手」。可信开机里,度量不是一次性完成的,它分两个大阶段:Pre-OS(操作系统前) 和 OS(操作系统内)。

核心观点:Pre-OS 度量决定「能不能启动」,OS 度量决定「启动后安不安全」。两者缺一不可。

4.1.1 Pre-OS 阶段

这个阶段从按下电源键开始,到操作系统内核加载之前结束。度量主体是 BIOS/UEFI 固件 和 Boot Loader。

  • 时机特征:没有操作系统,没有文件系统,度量代码跑在固件环境里。
  • 度量方式:TPM 的 PCR(平台配置寄存器)扩展操作。每次度量结果不是覆盖,而是 新值 = SHA(旧值 || 度量值)。
  • 我个人的习惯:Pre-OS 阶段一定要把 PCR 0-7 全部覆盖到。PCR 0 量固件代码,PCR 1 量固件配置,PCR 2 量 Option ROM,PCR 4 量 MBR/GPT……这些 PCR 的用途是 TCG 规范定死的,别自己乱改。

避坑指南:我曾经遇到一个案例,某厂商为了「优化启动速度」,把 PCR 2(Option ROM)的度量跳过了。结果显卡固件被替换成恶意版本,系统照样启动,但后台开始挖矿。所以——不要跳过任何规范要求的 PCR,除非你清楚知道自己在做什么。

4.1.2 OS 阶段

操作系统启动后,度量主体从固件切换到 内核度量模块(比如 Linux 的 IMA,Integrity Measurement Architecture)。

  • 时机特征:有完整的操作系统环境,可以访问文件系统、网络、进程。
  • 度量方式:IMA 会在文件被打开、执行、映射到内存时触发度量。度量结果同样扩展到 TPM 的 PCR(通常是 PCR 10 和 PCR 11)。
  • 度量粒度:可以细到每个可执行文件、每个内核模块、甚至每个脚本。

你想想看,Pre-OS 阶段度量的是「启动链的完整性」,OS 阶段度量的是「运行时环境的完整性」。两个阶段合起来,才构成一条完整的信任链。

4.2 度量对象:固件、引导程序与内核

度量对象就是「量什么东西」。我按启动顺序把三个核心对象列出来:

度量对象 所处阶段 度量内容 典型 PCR
固件(Firmware) Pre-OS BIOS/UEFI 代码、ACPI 表、SMBIOS 数据 PCR 0, PCR 1
引导程序(Boot Loader) Pre-OS MBR/GPT、Boot Loader 二进制、配置文件 PCR 4, PCR 5
内核(Kernel) Pre-OS → OS 过渡 内核映像、内核模块、initramfs PCR 4, PCR 8

4.2.1 固件度量

固件是信任链的根。如果固件被篡改,后面所有度量都是白费。我记得有一次做安全审计,发现某设备 UEFI 固件里被植入了持久化后门——它躲过了所有 OS 层的检测,因为度量链在 PCR 0 就断了。

固件度量的关键点:

  • 度量发生在 SEC(安全初始化)阶段之后,PEI(预EFI初始化)阶段开始之前。
  • 度量结果写入 PCR 0(固件代码)和 PCR 1(固件配置)。
  • 如果固件支持 UEFI Secure Boot,还会额外度量签名数据库(PCR 7)。

4.2.2 引导程序度量

引导程序是固件和内核之间的桥梁。常见的引导程序有 GRUB 2(Linux)、Windows Boot Manager、shim(用于 Secure Boot 链)。

度量内容:

  • 引导程序本身的二进制文件
  • 引导配置文件(比如 GRUB 的 grub.cfg)
  • 引导程序加载的内核和 initramfs

注意:我曾经见过一个案例,攻击者没有改 GRUB 二进制,而是改了 grub.cfg,在启动参数里加了一个 init=/bin/sh,直接绕过 root 密码。所以——配置文件也必须纳入度量,不能只量二进制。

4.2.3 内核度量

内核度量分两个层面:

  1. Pre-OS 层面:引导程序在加载内核时,先度量内核映像和 initramfs,再把度量值扩展到 PCR。
  2. OS 层面:内核启动后,IMA 模块继续度量后续加载的内核模块、驱动、以及用户空间的可执行文件。

这里有个容易忽略的点:initramfs 必须度量。initramfs 里包含早期用户空间的脚本和工具,如果被篡改,可以在内核完全启动前植入恶意代码。

4.3 度量算法:SHA-1 与 SHA-256

度量算法就是「用什么算法算哈希」。目前主流的选择是 SHA-1 和 SHA-256。我直接说结论:能用 SHA-256 就别用 SHA-1。

特性 SHA-1 SHA-256
摘要长度 160 位(20 字节) 256 位(32 字节)
安全性 已发现碰撞攻击(2017 年 SHAttered) 目前无实际碰撞攻击
PCR 兼容性 所有 TPM 版本都支持 TPM 2.0 原生支持,TPM 1.2 需扩展
性能 较快(约 2-3 倍于 SHA-256) 较慢,但现代 CPU 有硬件加速

4.3.1 为什么 SHA-1 还没被淘汰?

你可能会问:SHA-1 都已经被证明有碰撞攻击了,为什么还在用?

原因有两个:

  • TPM 1.2 的硬件限制:TPM 1.2 的 PCR 只有 20 字节,正好对应 SHA-1 的摘要长度。如果要升级到 SHA-256,必须换 TPM 2.0 硬件。
  • 兼容性包袱:很多旧设备、嵌入式系统还在用 TPM 1.2,不可能全部淘汰。

但说实话,新项目必须上 SHA-256。我在 2020 年做过一个项目,客户坚持用 SHA-1,结果第二年安全审计就被打了个高危漏洞——虽然实际利用难度很高,但合规上过不去。

4.3.2 TPM 2.0 的算法灵活性

TPM 2.0 比 TPM 1.2 灵活得多。它支持 多算法银行(Bank),可以同时使用 SHA-1 和 SHA-256。比如:

# 查看 TPM 2.0 支持的算法银行
tpm2_pcrlist -L

# 输出示例:
# sha1: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23
# sha256: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23

这意味着同一个 PCR 索引可以同时保存 SHA-1 和 SHA-256 的度量值。策略配置时,你可以选择用哪个算法做比对。

我的建议:如果硬件支持 TPM 2.0,优先使用 SHA-256,同时保留 SHA-1 银行做兼容。这样既保证了安全性,又不会让旧策略失效。

4.4 知识体系总览

下面这张图把度量时机、度量对象、度量算法的关系串起来了。我建议你保存下来,后面配置策略时经常要回头对照。

度量值采集原理知识体系 度量值采集原理知识体系 度量时机 度量对象 度量算法 Pre-OS 阶段 OS 阶段 固件 引导程序 内核 SHA-1 SHA-256 核心要点说明 1. 度量时机:Pre-OS 阶段由固件主导,度量启动链;OS 阶段由 IMA 主导,度量运行时环境。 2. 度量对象:固件(PCR 0-1)、引导程序(PCR 4-5)、内核(PCR 4/8/10-11),层层递进。 3. 度量算法:SHA-1 用于兼容旧 TPM 1.2,SHA-256 用于新 TPM 2.0,建议双银行并行。 4. 信任链传递:固件量引导程序 → 引导程序量内核 → 内核量应用,环环相扣。 5. 常见误区:只量二进制不量配置、跳过 Option ROM、混用 SHA-1 和 SHA-256 的 PCR 值。 度量采集是策略配置的基础,基础不牢,地动山摇

4.5 实战中的常见问题

最后,我把自己这些年遇到的几个典型问题列出来,你对照着检查自己的方案:

问题1:PCR 值对不上,但明明没改过代码

原因:可能是固件版本更新导致的。UEFI 固件每次更新,PCR 0 的值都会变。策略配置时,必须把新固件的度量值重新采集一遍。

问题2:OS 阶段度量导致启动变慢

原因:IMA 默认度量所有可执行文件,包括 /tmp 下的临时文件。我建议配置 IMA 策略,排除临时目录和只读文件系统。

问题3:SHA-1 和 SHA-256 的 PCR 值不能混用

同一个 PCR 索引,SHA-1 银行和 SHA-256 银行是独立的。比对策略时,必须指定用哪个算法。我曾经见过有人把 SHA-1 的 PCR 值拿去和 SHA-256 的基准值比对——结果当然永远不匹配。

嗯,这一章的内容就到这儿。度量时机、度量对象、度量算法,这三个维度你搞清楚了,后面配置策略就是水到渠成的事。