第 9 章:Secure Boot
第 9 章:Secure Boot
9.1 Secure Boot 概述
Secure Boot(安全启动)是 UEFI 规范定义的一项安全特性,确保系统只执行经过签名验证的引导软件,防止引导阶段的恶意软件(如 rootkit)。
9.1.1 工作原理
┌──────────────────────────────────────────────────┐
│ 信任链 │
│ │
│ 平台密钥 (PK) │
│ └── 密钥交换密钥 (KEK) │
│ └── 签名数据库 (db / dbx) │
│ ├── db: 允许的签名 │
│ └── dbx: 禁止的签名(吊销列表) │
│ │
│ UEFI 固件加载 EFI 程序时: │
│ 1. 检查程序是否由 db 中的密钥签名 │
│ 2. 检查签名是否在 dbx 吊销列表中 │
│ 3. 验证通过则执行,否则拒绝 │
└──────────────────────────────────────────────────┘
9.1.2 密钥层次
| 密钥 | 缩写 | 说明 |
|---|---|---|
| Platform Key | PK | 最高权限密钥,控制 Secure Boot 策略 |
| Key Exchange Key | KEK | 用于更新 db 和 dbx |
| Signature Database (Allow) | db | 存储允许的签名/证书 |
| Signature Database (Deny) | dbx | 存储禁止的签名/哈希 |
9.1.3 Secure Boot 模式
| 模式 | 说明 |
|---|---|
| Enabled | 严格验证所有 EFI 程序 |
| Disabled | 不验证(等同于无 Secure Boot) |
| Setup Mode | 清除 PK,允许用户自定义密钥 |
9.2 Linux 中的 Secure Boot 方案
9.2.1 shim 方案
大多数 Linux 发行版使用 shim(第一阶段引导加载程序)来实现 Secure Boot:
UEFI 固件(验证 Microsoft 签名)
→ shimx64.efi(Microsoft 签名 + 发行版第二签名)
→ grubx64.efi(发行版签名)
→ vmlinuz(发行版签名)
→ 内核模块(可选签名)
为什么需要 shim?
- UEFI 固件内置 Microsoft 的签名密钥
- Linux 发行版无法直接让硬件厂商预装自己的密钥
- shim 由 Microsoft 签名,同时内置了各发行版的密钥
- shim 充当"桥梁",将信任从 Microsoft 传递到 Linux 发行版
9.2.2 相关文件
| 文件 | 说明 |
|---|---|
shimx64.efi | 第一阶段引导器(Microsoft 签名) |
grubx64.efi | GRUB(发行版签名) |
mmx64.efi | MokManager(密钥管理工具) |
vmlinuz | 内核(可选签名) |
9.2.3 检查 Secure Boot 状态
# 方法一:mokutil
$ mokutil --sb-state
# SecureBoot enabled
# 或
# SecureBoot disabled
# 方法二:内核日志
$ dmesg | grep -i "secure boot"
# [ 0.000000] Secure boot enabled
# 方法三:efivar
$ cat /sys/firmware/efi/SecureBoot
# 1 表示启用,0 表示禁用
# 方法四:bootctl
$ bootctl status | grep "Secure Boot"
9.3 安装支持 Secure Boot 的 GRUB
9.3.1 Debian/Ubuntu
# 安装 shim 和签名的 GRUB
$ sudo apt install shim-signed grub-efi-amd64-signed
# 安装 GRUB 到 EFI 分区
$ sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian
# 验证 shim 已安装
$ ls /boot/efi/EFI/debian/
# grubx64.efi shimx64.efi mmx64.efi
# 检查 EFI 启动项
$ sudo efibootmgr -v
# Boot0001* debian HD(1,GPT,...)/File(\EFI\debian\shimx64.efi)
9.3.2 RHEL/Fedora
# 安装 shim 和 GRUB
$ sudo dnf install shim-x64 grub2-efi-x64
# RHEL 自动处理签名
$ sudo grub2-install --target=x86_64-efi --efi-directory=/boot/efi
9.3.3 Arch Linux
# 安装 shim
$ sudo pacman -S shim-signed
# 安装 GRUB
$ sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi \
--bootloader-id=GRUB --modules="tpm" --disable-shim-lock
# 注意:Arch 使用不同的 shim 集成方式
# 详细参考 ArchWiki: Unified Extensible Firmware Interface/Secure Boot
9.4 MOK(Machine Owner Key)
9.4.1 什么是 MOK
MOK(Machine Owner Key,机器所有者密钥)是 shim 提供的一种机制,允许机器所有者注册自定义密钥,用于签名自定义内核或第三方驱动模块。
9.4.2 MOK 工作流程
用户注册 MOK
→ 重启进入 MokManager
→ 确认注册(需要输入 MOK 密码)
→ MOK 写入 shim 的非易失存储
→ 之后 shim 信任由 MOK 签名的程序
9.4.3 生成 MOK 密钥对
# 1. 生成自签名证书和私钥
$ openssl req -new -x509 -newkey rsa:2048 \
-keyout MOK.key -outform DER -out MOK.der \
-nodes -days 36500 -subj "/CN=My Machine Owner Key/"
# 参数说明:
# -newkey rsa:2048: 生成 2048 位 RSA 密钥
# -keyout MOK.key: 私钥输出文件
# -out MOK.der: 证书输出文件(DER 格式)
# -nodes: 不加密私钥
# -days 36500: 有效期 100 年
# -subj: 证书主题
# 2. 设置私钥权限
$ chmod 600 MOK.key
9.4.4 注册 MOK
# 使用 mokutil 注册
$ sudo mokutil --import MOK.der
# 输入一个临时密码(用于 MokManager 确认)
# 重启系统
$ sudo reboot
# 在 MokManager 界面中:
# 1. 选择 "Enroll MOK"
# 2. 选择 "Continue"
# 3. 输入注册时设置的密码
# 4. 确认注册
# 5. 重启
9.4.5 验证 MOK 注册
# 查看已注册的 MOK
$ mokutil --list-enrolled
# [key 1]
# SHA1 Fingerprint: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
# Subject: /CN=My Machine Owner Key
# 查看待注册的 MOK
$ mokutil --list-new
# 检查 MOK 状态
$ mokutil --test-key MOK.der
# MOK.der is already enrolled
9.4.6 删除 MOK
# 标记 MOK 为待删除
$ sudo mokutil --delete MOK.der
# 重启后在 MokManager 中确认删除
$ sudo reboot
9.5 签名自定义内核
9.5.1 使用 MOK 签名内核
# 签名内核文件
$ sudo sbsign --key MOK.key --cert MOK.der \
--output /boot/vmlinuz-6.8.0-custom /boot/vmlinuz-6.8.0-custom
# 签名 EFI 程序
$ sudo sbsign --key MOK.key --cert MOK.der \
--output /boot/efi/EFI/custom/myapp.efi /path/to/myapp.efi
# 验证签名
$ sudo sbverify --cert MOK.der /boot/vmlinuz-6.8.0-custom
# Signature verification OK
9.5.2 签名 GRUB 模块
# 签名 shim(不推荐,通常使用发行版预签名的 shim)
# 签名 GRUB
$ sudo sbsign --key MOK.key --cert MOK.der \
--output /boot/efi/EFI/debian/grubx64.efi.signed \
/boot/efi/EFI/debian/grubx64.efi
# 注意:如果使用 shim,GRUB 需要由发行版签名
# 自签名的 GRUB 需要通过 MOK 注册
9.5.3 签名内核模块
# 为内核模块签名(如 DKMS 模块、NVIDIA 驱动)
# 使用内核自带的签名工具
$ sudo /usr/lib/linux-kbuild-6.1/scripts/sign-file \
sha256 MOK.key MOK.der /lib/modules/6.1.0/extra/mydriver.ko
# 或使用 kmodsign
$ sudo kmodsign sha256 MOK.key MOK.der /lib/modules/6.1.0/extra/mydriver.ko
9.5.4 自动签名脚本
创建一个 DKMS 签名钩子,自动为新编译的模块签名:
#!/bin/bash
# /etc/dkms/sign_helper.sh
# DKMS 签名助手
KEY="/path/to/MOK.key"
CERT="/path/to/MOK.der"
SIGN_FILE="/usr/lib/linux-kbuild-${1%.*}/scripts/sign-file"
$SIGN_FILE sha256 "$KEY" "$CERT" "$2"
在 /etc/dkms/framework.conf 中配置:
sign_tool="/etc/dkms/sign_helper.sh"
9.6 验证链详解
9.6.1 完整验证链
UEFI 固件
│ 验证: shimx64.efi 由 Microsoft KEK 签名 ✓
▼
shimx64.efi
│ 验证: grubx64.efi 由发行版密钥签名 ✓
▼
grubx64.efi
│ 验证: vmlinuz 由发行版密钥签名 ✓
▼
vmlinuz(Linux 内核)
│ 验证: insmod 加载的模块签名 ✓(可选)
▼
用户空间
9.6.2 验证 EFI 程序签名
# 验证 shim 签名(应该由 Microsoft 签名)
$ sbverify --list /boot/efi/EFI/debian/shimx64.efi
# signature 1
# image signature issuers:
# - /CN=Microsoft Windows UEFI Driver Publisher
# image signature certificates:
# - /CN=Microsoft Windows UEFI Driver Publisher
# 验证 GRUB 签名(应该由发行版签名)
$ sbverify --cert /usr/share/secureboot/updates/dbx/dbxupdate_x64.bin \
/boot/efi/EFI/debian/grubx64.efi
9.6.3 查看内核签名信息
# 查看内核签名
$ pesign -S -i /boot/vmlinuz-6.1.0-amd64
# 先安装 pesign: sudo apt install pesign
# 检查内核模块签名
$ modinfo -F signer <module_name>
# 或
$ hexdump -C /lib/modules/6.1.0/kernel/drivers/xxx.ko | tail
9.7 Secure Boot 故障排除
问题 1:安装第三方驱动后无法引导
# 症状:shim 提示 "Verification failed"
# 原因:未签名的内核模块
# 解决方案 1:临时禁用 Secure Boot
# 进入 BIOS 设置,禁用 Secure Boot
# 解决方案 2:签名模块(推荐)
# 参考 9.5.3 节
# 解决方案 3:在 shim 中禁用验证
# 重启时选择 "Change Secure Boot state"(如果可用)
问题 2:更新 GRUB 后 Secure Boot 失败
# 原因:新安装的 GRUB 未正确签名
# 解决:使用发行版签名的 GRUB 包
$ sudo apt install --reinstall grub-efi-amd64-signed shim-signed
$ sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi
问题 3:自编译内核无法引导
# 原因:自编译内核未签名
# 解决:签名内核(参考 9.5.1 节)
# 或使用 PreLoader(较旧方案)
$ sudo apt install preloader-signed
问题 4:shim 认证失败后无法恢复
# 在 MokManager 中:
# 选择 "Reset MOK" 或 "Enroll key from disk"
# 手动导航到密钥文件并注册
问题 5:dbx 更新导致旧 shim 无法启动
# 症状:更新 dbx 后 shim 被拒绝
# 原因:新 dbx 吊销了旧版本 shim 的签名
# 解决:更新 shim 到最新版本
$ sudo apt install shim-signed
# 或在 BIOS 中清除 dbx(不推荐,会降低安全性)
9.8 Secure Boot 与不同发行版
| 发行版 | shim 包名 | GRUB 签名包 | 默认启用 |
|---|---|---|---|
| Ubuntu | shim-signed | grub-efi-amd64-signed | ✅ |
| Debian | shim-signed | grub-efi-amd64-signed | ✅ |
| Fedora | shim-x64 | grub2-efi-x64 | ✅ |
| RHEL | shim-x64 | grub2-efi-x64 | ✅ |
| openSUSE | shim | grub2 | ✅ |
| Arch Linux | shim-signed | 需手动签名 | 视安装配置 |
9.9 企业级 Secure Boot 部署
9.9.1 自定义密钥部署
在企业环境中,可以使用自定义 PK/KEK/db 密钥完全控制信任链:
# 1. 生成企业密钥
$ openssl req -new -x509 -newkey rsa:4096 -nodes \
-keyout PK.key -out PK.der -days 3650 \
-subj "/CN=Enterprise Platform Key/"
$ openssl req -new -x509 -newkey rsa:4096 -nodes \
-keyout KEK.key -out KEK.der -days 3650 \
-subj "/CN=Enterprise KEK/"
$ openssl req -new -x509 -newkey rsa:4096 -nodes \
-keyout db.key -out db.der -days 3650 \
-subj "/CN=Enterprise Signature Database/"
# 2. 使用 efi-updatevar 或 KeyTool.efi 注册密钥
# (需要进入 Setup Mode)
9.9.2 批量签名工具
#!/bin/bash
# sign-efi-batch.sh - 批量签名 EFI 文件
KEY="MOK.key"
CERT="MOK.der"
EFI_DIR="/boot/efi/EFI"
find "$EFI_DIR" -name "*.efi" -exec sh -c '
for file; do
echo "Signing: $file"
sbsign --key "'"$KEY"'" --cert "'"$CERT"'" \
--output "$file" "$file"
done
' _ {} +
9.10 扩展阅读
上一章:第 8 章:恢复模式 | 下一章:第 10 章:网络引导