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 安全启动日志结构图
下面这张图展示了安全启动日志从生成到读取的完整流程:
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 扩展操作,记录了被验证的对象和结果。
- 日志不持久化,重启就丢,所以发现问题后要第一时间捕获。