4. 度量启动流程:BIOS/UEFI阶段度量、Option ROM度量、OS Loader度量、内核度量

启动度量这件事,说白了就是给系统的每个启动环节拍一张「身份证照片」。从你按下电源键到操作系统跑起来,中间经过的每一段代码都要被记录、被验证。我这些年调试过不少启动失败的板子,十有八九都是某个环节的度量链断了。

咱们这一章就顺着启动流程,把四个关键阶段的度量点挨个捋一遍。

4.1 BIOS/UEFI阶段度量:信任的起点

系统上电后,CPU首先执行的是固化在ROM里的复位向量代码。这段代码是硬件可信根(CRTM),它本身是物理不可篡改的。CRTM会去度量BIOS或UEFI固件的主体部分。

我个人习惯把BIOS/UEFI阶段的度量分成两步:

  1. CRTM度量BIOS/UEFI主固件:计算主固件代码的哈希值,与存储在TPM PCR[0]中的预期值比对。
  2. BIOS/UEFI度量自身模块:UEFI启动管理器会逐个度量DXE驱动、ACPI表、SMBIOS表等模块。

关键点:PCR[0]是信任链的锚点。如果CRTM本身被篡改,整个信任链就崩塌了。所以硬件设计上,CRTM必须位于只读存储器中,且物理上受保护。

我在项目中遇到过一种情况:某款国产主板的UEFI固件升级后,PCR[0]的预期值没同步更新,导致每次启动都报度量失败。嗯,这种问题排查起来特别头疼,因为硬件本身没坏,但信任链就是接不上。

4.2 Option ROM度量:容易被忽视的环节

Option ROM是什么?说白了就是插在PCIe槽上的设备自带的固件。显卡、网卡、RAID卡都有。这些固件在系统初始化阶段会被加载执行,但它们的安全性往往被忽视。

你想想看,如果一张网卡的Option ROM被植入了后门,攻击者就能在操作系统启动前拿到网络控制权。这可不是危言耸听,我在做安全审计时就发现过某品牌网卡的Option ROM存在未签名代码。

Option ROM的度量流程是这样的:

  • UEFI的PCI总线驱动枚举设备时,会定位Option ROM。
  • 驱动调用安全策略模块,计算Option ROM的哈希值。
  • 哈希值被扩展到PCR[2]中(部分平台使用PCR[4])。
  • 如果Option ROM有数字签名,还会验证签名的有效性。
度量对象 目标PCR 度量时机
BIOS/UEFI主固件 PCR[0] CRTM执行后立即度量
UEFI驱动/应用 PCR[1] DXE阶段逐个度量
Option ROM PCR[2] PCI枚举阶段
启动配置数据 PCR[3] BDS阶段

避坑指南:我曾经遇到过一块RAID卡,它的Option ROM在UEFI模式下工作正常,但切换到Legacy模式后度量就跳过了。后来发现是固件配置表里漏写了Legacy模式的度量入口。所以,测试时一定要覆盖所有启动模式。

4.3 OS Loader度量:信任链的接力棒

UEFI启动管理器在完成自身度量后,会去加载OS Loader(比如Windows的bootmgfw.efi或Linux的shim.efi)。这个环节是信任链从固件层向操作系统层传递的关键节点。

度量过程大致如下:

  1. UEFI启动管理器读取启动项配置,找到OS Loader的文件路径。
  2. 调用安全策略模块,计算OS Loader文件的哈希值。
  3. 哈希值扩展到PCR[4](部分平台使用PCR[5])。
  4. 如果启用了Secure Boot,还会验证OS Loader的数字签名。

这里有个细节:OS Loader本身也会度量它要加载的内核和驱动。比如Linux的shim会去度量GRUB2,GRUB2再去度量内核。这就是所谓的「嵌套度量」。

个人经验:我在调试Linux安全启动时,发现shim度量GRUB2时会把GRUB2的配置文件也纳入哈希计算。这意味着你改了grub.cfg里的任何参数,度量值都会变。很多运维同学不知道这个,升级内核后启动失败,其实就是配置文件变了导致度量不匹配。

4.4 内核度量:最后的防线

OS Loader把控制权交给内核后,内核会继续度量自身的核心模块。这一步通常由内核的IMA(Integrity Measurement Architecture)机制完成。

IMA会在内核启动早期初始化,然后开始度量:

  • 内核代码段和数据段
  • 内核模块(.ko文件)
  • 关键系统文件(如/etc/shadow、/etc/ssh/sshd_config)
  • 可执行文件和共享库

IMA的度量结果会扩展到TPM的PCR[10]中。为什么用PCR[10]?因为前面的PCR[0]-PCR[7]已经被固件和OS Loader占用了,PCR[8]-PCR[9]留给特定用途,PCR[10]正好给IMA用。

# 查看IMA度量日志(Linux)
cat /sys/kernel/security/ima/ascii_runtime_measurements

# 输出示例:
# 10 1234567890abcdef ima-ng sha256:abcdef1234567890 /usr/bin/ssh
# 10 1234567891abcdef ima-ng sha256:fedcba0987654321 /etc/ssh/sshd_config

核心要点:内核度量是信任链的最后一道防线。如果内核本身被篡改,后续所有度量都失去意义。所以内核度量必须在内核启动的最早期完成,越早越好。

我见过一个案例:某云厂商的服务器被入侵,攻击者替换了内核模块。因为IMA度量了所有模块的哈希值,运维团队通过比对PCR[10]的扩展记录,很快就定位到了被篡改的模块。如果没有IMA,这种隐蔽的篡改可能要过很久才能被发现。

4.5 完整的度量信任链

把上面四个阶段串起来,就是一条完整的度量信任链:

CRTM → BIOS/UEFI → Option ROM → OS Loader → 内核

每个环节度量下一个环节,并把度量值扩展到对应的PCR中。任何环节的篡改都会导致PCR值与预期不符,远程证明时就能发现异常。

下面这张图展示了完整的度量流程和PCR分配:

启动度量信任链与PCR分配 启动度量信任链与PCR分配 CRTM(硬件可信根) BIOS/UEFI 固件 Option ROM OS Loader 操作系统内核 度量 度量 度量 度量 PCR分配表 PCR[0] PCR[1] PCR[2] PCR[4] PCR[10] BIOS/UEFI主固件 UEFI驱动/应用 Option ROM OS Loader 内核模块

从这张图可以看得很清楚:每个启动环节的度量结果都沉淀到特定的PCR中。远程证明时,验证方只需要比对PCR的最终值,就能判断整个启动过程是否可信。

嗯,度量启动流程就讲到这里。记住一句话:信任链的强度取决于最薄弱的那个环节。Option ROM和内核度量往往是容易被忽略的薄弱点,我在实际项目中没少在这两个地方踩坑。