4、安全启动日志基础:什么是安全启动日志、日志的存储位置(Event Log)、如何查看安全启动日志

安全启动日志,说白了就是 UEFI 固件在启动过程中记录的一份「体检报告」。它把每个被加载的组件——固件驱动、Option ROM、BootLoader、内核——的签名验证结果,一条一条写下来。

我刚开始接触安全启动时,觉得这东西就是个黑盒。系统起不来,报个 Secure Boot Violation,然后就没了。后来才发现,日志里藏着大量细节。你只要会看,就能定位到是哪个环节出了问题。

4.1 什么是安全启动日志

安全启动日志的正式名称是 UEFI Secure Boot Event Log。它由固件在启动过程中动态生成,记录了两个关键信息:

  • 被验证的对象:比如某个 .efi 文件、某个 Option ROM、某个 MBR/VBR 引导扇区。
  • 验证结果:签名是否匹配、证书链是否完整、是否被吊销。

每条日志条目都包含一个 PCR(Platform Configuration Register)索引。PCR 是 TPM 芯片内部的寄存器,用来做完整性度量。安全启动日志本质上就是 PCR 扩展操作的「流水账」——你扩展了什么值、扩展了几次、最终 PCR 值是多少,全记在里面。

核心概念:安全启动日志 ≠ 系统日志(如 /var/log/messages)。它是 UEFI 固件层面的二进制数据,操作系统启动后才能被读取和解析。

4.2 日志的存储位置

日志存在哪?这得分两个阶段看。

4.2.1 运行时:ACPI 表

系统启动后,固件会把安全启动日志映射到内存中,并通过 ACPI 表暴露给操作系统。具体来说,是 UEFI 安全启动表(UEFI Secure Boot Table),其签名是 UEFI(ASCII 字符串)。

你可以用 acpidump 或 tpm2_eventlog 工具来读取它。我个人习惯用 tpm2_eventlog,因为它直接解析成人类可读的格式。

4.2.2 持久化:TPM NVRAM

日志本身不持久化存储。但 PCR 值是持久化的(只要 TPM 芯片不掉电)。所以如果你需要事后分析,必须在系统启动后立即捕获日志。一旦重启,之前的日志就丢了。

嗯,这里要注意:有些固件会把日志写到 UEFI 变量 中,比如 SecureBootEventLog。但这不是标准行为,不同厂商实现差异很大。我在项目中遇到过某品牌服务器,日志只保留最近三次启动的记录,超过就覆盖。当时排查一个间歇性启动失败的问题,差点被这个坑死。

存储位置 访问方式 持久性 备注
ACPI 表(运行时内存) tpm2_eventlog、acpidump 仅当前启动 标准方式,推荐使用
TPM NVRAM tpm2_nvread 持久化(受 TPM 限制) 部分固件支持
UEFI 变量 efibootmgr、sysfs 取决于固件实现 非标准,厂商差异大

4.3 如何查看安全启动日志

查看日志,我一般分三步走。第一步确认系统支持,第二步读取原始数据,第三步解析成可读格式。

4.3.1 确认 TPM 和安全启动状态

先检查 TPM 是否可用:

# 检查 TPM 设备是否存在
ls /dev/tpm* /dev/tpmrm*

# 检查安全启动状态
mokutil --sb-state

如果 TPM 设备不存在,或者安全启动处于关闭状态,那日志大概率是空的。我曾经帮一个同事排查问题,他折腾了半天说日志读不出来,结果发现安全启动根本没开……

4.3.2 使用 tpm2_eventlog 读取日志

这是最直接的方法。tpm2_eventlog 是 tpm2-tools 套件的一部分,它会自动从 ACPI 表中读取安全启动日志并解析:

# 读取并解析安全启动日志
sudo tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements

输出示例(简化):

Event Log:
  PCR: 0
  Event Type: EV_EFI_VARIABLE_DRIVER_CONFIG
  Digest: 9f1c...a3b2
  Event Data:
    Variable Name: SecureBoot
    Variable Data: 01

  PCR: 4
  Event Type: EV_EFI_BOOT_SERVICES_APPLICATION
  Digest: 4d5e...7f8a
  Event Data:
    Image Path: \EFI\Microsoft\Boot\bootmgfw.efi
    Image Hash: a1b2...c3d4
    Signature Status: Success

你看,每条日志都告诉你:哪个 PCR 被扩展了、扩展了什么内容、验证结果如何。如果 Signature Status 显示 Failed,那就是签名验证没通过。

4.3.3 手动解析二进制日志

如果你需要更底层的分析,可以直接读取二进制日志文件:

# 读取原始二进制日志
sudo cat /sys/kernel/security/tpm0/binary_bios_measurements > sb_log.bin

# 使用 hexdump 查看
hexdump -C sb_log.bin | head -50

二进制格式遵循 TCG EFI Protocol Specification。每个事件条目包含:

  • PCR Index(4 字节):目标 PCR 编号。
  • Event Type(4 字节):事件类型,如 EV_EFI_BOOT_SERVICES_APPLICATION。
  • Digest(20/32/64 字节):SHA-1/SHA-256/SHA-384 哈希值。
  • Event Data(变长):具体内容,如被加载文件的路径和签名信息。

小技巧:如果你在排查「为什么某个驱动加载失败」,重点关注 PCR 7 的事件。PCR 7 专门记录安全启动策略相关的度量,包括 SecureBoot 变量、PK/KEK/db 数据库的变化。

4.4 安全启动日志结构图

下面这张图展示了安全启动日志从生成到读取的完整流程:

安全启动日志结构图 安全启动日志生成与读取流程 UEFI 固件启动 加载并验证每个组件 生成 Event Log PCR 扩展 + 记录事件 存储到 ACPI 表 运行时内存映射 操作系统启动 读取日志:tpm2_eventlog / sysfs / hexdump 分析日志 定位签名验证失败的组件 注意 日志仅当前启动有效 重启后丢失

4.5 常见问题与避坑指南

坑一:日志为空

如果你执行 tpm2_eventlog 后什么输出都没有,先检查安全启动是否开启。我曾经遇到过一台机器,安全启动在固件设置里是 Enabled,但实际状态是 Setup Mode。这种情况下固件不会生成完整的日志。

坑二:PCR 值对不上

如果你在比对 PCR 值,记得日志里的 Digest 是扩展前的值,不是扩展后的。PCR 扩展公式是:PCR_new = SHA256(PCR_old || Digest)。我刚开始做 TPM 远程证明时,在这个细节上卡了两天。

坑三:日志被截断

有些固件对日志大小有限制。如果启动过程中加载了大量 Option ROM 或驱动,日志可能被截断。你可以用 tpm2_eventlog --verbose 查看日志条目总数,如果远少于预期,那可能就是被截断了。

4.6 小结

安全启动日志是排查启动失败的第一手资料。你只要记住三点:

  • 日志存在 ACPI 表里,用 tpm2_eventlog 读。
  • 每条日志都对应一个 PCR 扩展操作,记录了被验证的对象和结果。
  • 日志不持久化,重启就丢,所以发现问题后要第一时间捕获。