Secure Boot、Measured Boot 与 IMA

第 8.1 讲了 TPM 和 PCR——本篇讲怎么把它用起来。Secure Boot(验签防篡改)+ Measured Boot(度量记录)+ IMA(运行时完整性)= Linux 完整可信启动链。

三个机制对比

graph TB
  M1[Secure Boot]
  M1 --> R1[启动时验签
签名错就拒绝执行] M2[Measured Boot] M2 --> R2[启动时记录
哈希进 TPM PCR] M3[IMA] M3 --> R3[运行时验证
读文件时检查]
机制 时机 动作 失败后果
Secure Boot 启动 验签 拒绝启动
Measured Boot 启动 度量记录 不阻止启动,但 PCR 不同
IMA 运行 验签 / 度量 拒绝执行 / 报警

UEFI Secure Boot

graph LR
  PK[Platform Key
主板厂家] KEK[Key Exchange Key
OS 厂家] DB[DB
允许的签名 / 哈希] DBX[DBX
禁用的签名 / 哈希] PK --> KEK --> DB KEK --> DBX

UEFI Secure Boot 的密钥层次:

1
2
3
4
5
6
7
8
9
10
PK(Platform Key):     主板厂家,根
KEK(Key Exchange Key): OS 厂家用,可签 DB / DBX
DB(Allowed DB): 允许执行的签名 / 哈希列表
DBX(Forbidden DB): 禁用的签名(吊销列表)

启动时验签流程:
1. UEFI 加载 Bootloader
2. 检查 Bootloader 签名是否在 DB 中
3. 是 → 加载执行
4. 否 → 拒绝,停止启动

Microsoft 主导的 DB

1
2
3
4
5
6
7
8
默认 DB 包含:     
Microsoft Windows Production CA
Microsoft UEFI CA(用于第三方 OS)

Linux Bootloader(shim)签名:
shim 由 Microsoft UEFI CA 签
shim 内嵌 Linux 厂家公钥
shim 加载 GRUB → GRUB 验签 kernel → kernel 验 module

shim 是 Linux 在 Secure Boot 下的”信任桥梁”——所有发行版(RHEL / Ubuntu / SUSE)都用它。

自管 Secure Boot

1
2
3
4
5
6
7
8
9
10
11
12
13
# 装 shim 后看 Secure Boot 状态
mokutil --sb-state

# 看 MOK 列表(用户级密钥)
mokutil --list-enrolled

# 加自定义证书到 MOK
mokutil --import my_cert.crt
# 重启时设密码确认

# 完全清空 / 替换 PK / KEK / DB(高级用法)
sbkeysync --pk # 设 PK
sbkeysync --keystore /etc/secureboot/keys

shim → GRUB → kernel 的验签

1
2
3
4
5
6
7
8
9
10
11
12
13
shim 启动后:     
1. 检查 grubx64.efi 签名(用 shim 内嵌的发行版公钥)
2. 通过 → 加载 GRUB

GRUB 启动后:
1. 检查 vmlinuz 签名
2. 通过 → 加载 kernel

kernel 启动后:
1. 检查 .ko 模块签名(kernel 模块也要验签)
2. 通过 → 允许加载

任何一步不通过 → 拒绝执行 → 启动失败

Secure Boot 的几个重要实践

1
2
3
4
5
6
7
8
9
10
# 启用 / 禁用 Secure Boot:BIOS 中
# 看当前状态
bootctl status

# 看 EFI 变量
mokutil --sb-state
efivar -l

# 自己签 kernel 模块
sbsign --key MOK.priv --cert MOK.crt --output module.ko.signed module.ko

Measured Boot

Secure Boot 是”二选一”——通过或不通过。Measured Boot 是”完整记录”——把每一步都哈希进 TPM。

graph TB
  CRTM[CRTM] -->|度量并 Extend| PCR0[PCR 0]
  BIOS[BIOS] -->|度量 Bootloader| PCR4[PCR 4]
  GRUB[GRUB] -->|度量 kernel/initrd| PCR8[PCR 8]
  GRUB -->|度量 cmdline| PCR9[PCR 9]
  KER[Kernel] -->|度量初始化| PCR10[PCR 10]
  IMA[IMA] -->|度量文件| PCR10b[PCR 10]

启动度量事件日志

UEFI 实现把每次”度量”事件记到日志,开机后 OS 可以看:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 看 measured boot 事件日志
sudo tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements

# 输出例:
# Event: EV_S_CRTM_VERSION
# PCR: 0
# Digest: sha256: ...
# Data: "BIOS Vendor v3.5"
#
# Event: EV_EFI_VARIABLE_DRIVER_CONFIG
# PCR: 7
# Digest: sha256: ...
# Data: Secure Boot State=1

事件日志 + 当前 PCR 值 = “可重放”——验证方可以独立验证启动链。

用 PCR 7 还是 PCR 0-4?

1
2
3
4
5
6
7
PCR 0-4:     度量具体的 BIOS / Bootloader / kernel 哈希
→ 任何 BIOS / kernel 升级都改值
→ 灵活性差

PCR 7: 仅度量 Secure Boot 状态(PK / KEK / DB / DBX 等)
→ 升级 kernel 时 PCR 7 不变
→ 推荐用 PCR 7 + Secure Boot 组合

LUKS + Measured Boot 实战

1
2
3
4
5
6
7
8
9
10
11
12
13
# 把 LUKS 密钥密封到 PCR 7(推荐)
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 /dev/sda3

# 重启后自动解密:
# - Secure Boot 状态没变 → PCR 7 不变 → 解封成功
# - Secure Boot 被禁 → PCR 7 变了 → 解封失败 → 提示输 fallback 密码

# 配合 dracut / mkinitcpio:
# /etc/crypttab:
# root UUID=... none tpm2-device=auto

# 紧急情况:备用恢复 key
cryptsetup luksAddKey /dev/sda3 recovery_key.txt

IMA:Linux 文件完整性

IMA(Integrity Measurement Architecture)是 Linux 内核的运行时完整性子系统:

graph TB
  EXEC[执行 / mmap / open]
  EXEC --> IMA[IMA Hook]
  IMA --> CHECK{检查策略}
  CHECK --> M[度量:写入 measurement list + Extend PCR 10]
  CHECK --> A[Appraisal:验证签名 / 哈希]
  CHECK --> AUDIT[审计:仅记录]
  
  A --> R{验证通过?}
  R -- 是 --> RUN[允许执行]
  R -- 否 --> DENY[拒绝]

IMA 的三种模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
1. 度量(Measurement):     
- 把文件哈希写入 /sys/kernel/security/ima/ascii_runtime_measurements
- 同时 Extend PCR 10
- 不阻止执行
- 用于审计和远程证明

2. 评估(Appraisal):
- 验证文件的扩展属性签名
- 不通过 → 拒绝执行
- 严格但需要预先签名

3. 审计(Audit):
- 仅写日志

IMA 启用

1
2
3
4
5
6
7
8
9
10
11
12
# 启动参数(GRUB)
GRUB_CMDLINE_LINUX="ima_policy=tcb ima_template=ima-ng ima_hash=sha256"

# 重启后看 measurements
cat /sys/kernel/security/ima/ascii_runtime_measurements | head

# 例:
# 10 4d29... ima-ng sha256:abc... /usr/bin/ls
# 10 8def... ima-ng sha256:def... /usr/lib/libc.so.6

# 看当前 PCR 10
tpm2_pcrread sha256:10

IMA 度量后每个文件首次访问时都会哈希入 PCR 10——这就让”系统启动以来所有访问的文件”都被记录。

IMA 策略

1
2
3
4
5
6
7
# /etc/ima/ima-policy 例:
dont_measure fsmagic=0x9fa0 # 不度量 procfs
dont_measure fsmagic=0x62656572 # 不度量 sysfs
measure func=BPRM_CHECK # 度量 execve
measure func=FILE_MMAP mask=MAY_EXEC # 度量可执行 mmap
measure func=MODULE_CHECK # 度量内核模块
appraise func=POLICY_CHECK # 验签策略文件

EVM:扩展属性签名

1
2
3
4
5
6
7
EVM(Extended Verification Module):     
- 验证文件的扩展属性 xattr(IMA 哈希、SELinux 标签等)
- 防止单独篡改 xattr

启用:
GRUB_CMDLINE_LINUX="... evm=fix" # 第一次自动签
之后 evm=enforce

完整可信启动链的搭建

graph TB
  S1[BIOS Secure Boot]
  S1 --> S2[Bootloader 验签 kernel]
  S2 --> S3[Kernel 验签 module]
  S3 --> S4[IMA 度量 + Appraisal]
  S4 --> S5[远程证明可达]
  
  S6[Measured Boot 同步进行]
  S6 -.- S1 & S2 & S3 & S4

实际部署:

1
2
3
4
5
6
7
8
1. BIOS:     启用 Secure Boot + Measured Boot
2. Bootloader: shim + GRUB 签名
3. Kernel: 发行版签的 kernel + 自签 module
4. initrd: 生成时签
5. IMA: 启动 ima_policy=appraise_tcb
6. EVM: 启用 evm
7. LUKS: 密封到 PCR 7
8. 应用: 按需 IMA 度量

实战案例:金融业可信服务器

1
2
3
4
5
6
7
8
9
10
11
12
某银行核心交易系统:     
- 物理 TPM 2.0 + Secure Boot
- kernel + initrd 内部签
- LUKS 全盘加密 + TPM 密封 PCR 7
- IMA Appraisal 模式
- 远程证明每天定时到中心化平台
- 启动状态异常 → 自动告警 + 隔离

效果:
- 任何 BIOS / Bootloader / Kernel 篡改 → 启动失败
- 任何关键二进制篡改 → 拒绝执行
- 物理拆机偷盘 → 数据无法解密(PCR 不对)

远程证明实战

1
2
3
4
5
6
7
8
9
10
11
12
# 服务端:建立 attestation 服务(开源 keylime)
# 客户端:装 keylime agent
apt install keylime-agent

# Agent 注册到 verifier:
keylime_register --addr <verifier> --uuid <uuid>

# Verifier 周期发起 Quote 检查
# Agent 调 TPM_Quote 返回
# Verifier 比对 PCR 是否匹配预期

# 不匹配 → 隔离机器

主流远程证明方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
keylime(NCC 出品,CNCF 项目):     
- 开源
- Bootstrap + Periodic attest
- 集成 IMA 度量列表

Microsoft Attestation Service:
- Windows Defender Device Health
- Azure Attestation Service

Intel Trust Authority:
- Intel 官方
- 服务化远程证明

国产:
- 公安部一所 / 中电科 等可信认证体系
- 工信部"可信云"标准
- 各家 OEM 自家方案

几个老坑

坑 1:Secure Boot + 第三方驱动

1
2
3
4
5
6
7
8
9
NVIDIA / Mellanox 等内核模块:     
- shim 信任的是发行版公钥
- 第三方模块需要单独签
- 用 mokutil 加用户证书

正确流程:
1. 生成 MOK 密钥对
2. mokutil --import 加证书
3. 装第三方驱动时用 dkms 自动签

坑 2:Kernel 升级 PCR 0/4 改变

1
2
3
4
5
6
LUKS 密封 PCR 0/4 → kernel 升级 → PCR 不一样 → 启动后无法解密

防御:
- 升级前 systemd-cryptenroll 重新封装
- 或一直只用 PCR 7(推荐)
- 留一把 fallback 密码

坑 3:IMA 性能开销

1
2
3
4
5
6
7
8
9
IMA 默认全度量:     
- 每次 execve / mmap 都要哈希
- 4 KB 文件哈希 ~10 μs
- 大量小文件应用受影响 5-15%

调优:
- 用 dont_measure 排除不必要路径
- 用 ima-buf 替代 ima-ng(buffer 模式)
- SHA-1 比 SHA-256 快但安全性弱

坑 4:BIOS 升级清密钥

1
2
3
4
5
6
7
BIOS 升级有时候清空 PK / KEK / DB
→ Secure Boot 关闭
→ mokutil 之前导入的全没

防御:
- 升级前导出 PK / KEK / DB 备份
- 升级后用 sbkeysync 恢复

坑 5:vTPM 状态

1
2
3
4
5
KVM vTPM 默认 swtpm 持久化:     
/var/lib/swtpm/<uuid>

迁移 VM: vTPM 状态要同步迁移
否则: 新宿主机的 vTPM 是新的 → PCR 全空 → LUKS 解不开

坑 6:IMA Appraisal 启用前没签好

1
2
3
4
5
6
7
appraisal=enforce 时:     未签的文件不能执行
→ 突然启用 → 大量应用启动失败

正确:
1. 先 ima_appraise=fix 一次(自动签)
2. 验证一切正常
3. 再 ima_appraise=enforce

坑 7:远程证明引用值管理

1
2
3
4
5
6
万级集群每机 PCR 值不同(kernel / 配置略差异):     
- 集中维护"已知好"哈希列表
- 每次升级都要更新基线
- 大集群运维成本高

→ 这是为什么互联网厂启用率低

TPM 与 BIOS 的协议

1
2
3
4
5
6
7
8
TCG PC Client Profile:     
- 度量哪些事件(PCR mapping)
- 事件日志格式
- 厂家必须遵循

每家 BIOS 实现略有差别:
- 同款服务器换 BIOS 厂 PCR 不一样
- 跨厂家集群 PCR 基线管理头疼

一些查询命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Secure Boot 状态
mokutil --sb-state

# 已注册 MOK
mokutil --list-enrolled

# UEFI 变量
efivar -l
efibootmgr -v

# Measured Boot 事件
tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements
tpm2_pcrread sha256:0,1,2,3,4,5,6,7,8,9,10

# IMA 度量列表
cat /sys/kernel/security/ima/ascii_runtime_measurements | wc -l

# 看 IMA 策略
cat /sys/kernel/security/ima/policy

# 内核 lockdown 模式(与 Secure Boot 关联)
cat /sys/kernel/security/lockdown

一些数字直觉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
启动时间影响:     
Secure Boot: +50-200 ms
Measured Boot: +500-1000 ms
IMA 度量: +1-5 秒(按文件数)
TPM 解 LUKS: +200-500 ms

运行时性能:
IMA Measurement: 5% 性能损失
IMA Appraisal: 10-15% 性能损失
EVM 启用: 额外 5-10%

存储:
Measurement 列表: 小集群每天几十 MB
Event log: 每机几 MB

不同发行版默认情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
RHEL 9:     
- Secure Boot 默认启用
- shim 已签
- IMA 配置可选
- TPM 工具齐全

Ubuntu 24.04:
- Secure Boot 默认启用
- LUKS + TPM 通过 systemd-cryptenroll
- IMA 不默认

openEuler 22.03 LTS:
- 信创目录默认启用 Secure Boot + Measured Boot
- IMA 政企版默认启用
- 与 TCM 集成

麒麟 V10:
- 等保 3+ 默认 Secure Boot + IMA
- 国密签名(SM2/SM3)
- 与 TCM / TPCM 适配

小结

  • Secure Boot = 启动验签,不通过就拒绝
  • Measured Boot = 启动度量记录到 TPM PCR
  • IMA = 运行时文件完整性验证
  • 三者配合形成完整可信启动链
  • 远程证明把启动状态送到验证方
  • LUKS + TPM PCR 7 是最常用的全盘加密方案
  • 互联网厂启用率低,政企 / 金融 / 关基启用率高

下一篇讲 TEE——SGX、TDX、SEV、TrustZone 等”可信执行环境”。