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 内核度量
内核度量分两个层面:
- Pre-OS 层面:引导程序在加载内核时,先度量内核映像和 initramfs,再把度量值扩展到 PCR。
- 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 知识体系总览
下面这张图把度量时机、度量对象、度量算法的关系串起来了。我建议你保存下来,后面配置策略时经常要回头对照。
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 的基准值比对——结果当然永远不匹配。
嗯,这一章的内容就到这儿。度量时机、度量对象、度量算法,这三个维度你搞清楚了,后面配置策略就是水到渠成的事。