强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

GRUB2 引导管理器完全教程 / 第 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 章:网络引导