统一可扩展固件接口/安全启动

来自 ArchWiki

安全启动UEFI 标准中的一项安全特性,旨在为 预启动过程 增加一层保护:通过维护一份经过加密签名的二进制文件列表,授权或禁止在启动时运行,它有助于提高机器核心启动组件(启动管理器、内核、initramfs)未被篡改的可信度。

因此,它可以被看作是 安全 计算环境努力的延续或补充,减少了其他软件安全解决方案(如 系统加密)不易 覆盖 的攻击面,同时它完全独立,不依赖于它们。安全启动作为当前安全实践的一个组成部分而独立存在,有其自身的一系列优点和缺点

注意: 有关 Linux 中安全启动的更深入概述,请参阅 Rodsbooks 的安全启动 文章和 其他在线资源。本文重点介绍如何在 Arch Linux 中设置安全启动。

检查安全启动状态

在启动操作系统之前

此时,需要查看固件设置。如果机器已启动并在运行,在大多数情况下需要重启。

您可以通过在启动过程中按下特殊按键来访问固件配置。使用的按键取决于固件。通常是 EscF2Del 或可能是其他 Fn 键。有时,正确的按键会在启动过程开始时短暂显示。主板手册通常会记录它。您可能需要在机器开机后立即按下按键,并持续按住,甚至在屏幕实际显示任何内容之前。

进入固件设置后,请小心不要在没有事先意图的情况下更改任何设置。通常在每个设置屏幕的底部都有导航说明和设置的简短帮助。设置本身可能由多个页面组成。您需要导航到正确的位置。感兴趣的设置可能只是简单地标示为安全启动,可以设置为开启或关闭。

在启动操作系统之后

在使用 systemd 的系统上检查安全启动状态的简单方法是使用 systemd-boot

注意: 此命令的工作不需要您使用 systemd-boot 作为启动管理器,它更类似于其他的 *ctl systemd 工具(localectl、timedatectl...),并且不会触及您的配置。
$ bootctl
System:
      Firmware: UEFI 2.80 (American Megatrends 5.26)
 Firmware Arch: x64
   Secure Boot: enabled (user)
  TPM2 Support: yes
  Measured UKI: yes
  Boot into FW: supported
...

在这里我们看到安全启动已启用并强制执行(在用户模式下);其他值包括“设置模式”的 disabled (setup),安全启动被禁用的 disabled (disabled),以及固件不具备安全启动特性的 disabled (unsupported)

另一种检查机器是否在安全启动下启动的方法是使用此命令

$ od --address-radix=n --format=u1 /sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c

如果安全启动已启用,此命令将返回 1 作为五个整数列表中的最后一个,例如

6  0  0  0  1

但请注意,如果使用了能力不足的启动加载器,即使安全启动在固件中已启用,内核也可能不知道安全启动(即使它在固件中已启用)。这可以通过在系统启动后不久检查内核消息来验证

# dmesg | grep -i secure
[    0.013442] Secure boot disabled
[    0.013442] Secure boot could not be determined

否则,内核消息将显示 Secure boot enabled(安全启动已启用)。

启动安装介质

官方安装镜像不支持安全启动 (FS#53864)。安全启动支持最初在 archlinux-2013.07.01-dual.iso 中添加,后来在 archlinux-2016.06.01-dual.iso 中移除。当时 prebootloader 被替换为 efitools,即使后者使用未签名的 EFI 二进制文件。从那时起,官方安装介质中一直没有安全启动支持。

为了在安全启动系统中启动安装介质,您需要禁用安全启动或修改镜像以添加已签名的启动加载器。

Archboot 镜像提供了一种在安装介质上使用安全启动的方法。

禁用安全启动

安全启动功能可以通过 UEFI 固件界面禁用。如何访问固件配置在 #在启动操作系统之前 中描述。

如果使用热键不起作用并且您可以启动 Windows,您可以按照以下方式强制重启进入固件配置(对于 Windows 10):设置 > 更新和安全 > 恢复 > 高级启动(立即重启) > 疑难解答 > 高级选项 > UEFI 固件设置 > 重启

请注意,某些主板(例如 Packard Bell 笔记本电脑和近期小米笔记本电脑就是这种情况)仅在您设置了管理员密码后才允许禁用安全启动(之后可以移除该密码)。另请参阅 Rod Smith 的禁用安全启动

重新打包安装镜像

参见 #ISO 重新打包

编辑安装介质

如果您正在使用 USB 闪存安装介质,则可以手动编辑介质上的 EFI 系统分区 以添加对安全启动的支持。

插入 USB 驱动器,然后挂载分区

# mount /dev/disk/by-label/ARCHISO_EFI /mnt

然后按照 #使用已签名的启动加载器 中的说明安装任何已签名的启动加载器。例如,安装 #PreLoader

# mv /mnt/EFI/BOOT/BOOTx64.EFI /mnt/EFI/BOOT/loader.efi
# cp /usr/share/preloader-signed/PreLoader.efi /mnt/EFI/BOOT/BOOTx64.EFI
# cp /usr/share/preloader-signed/HashTool.efi /mnt/EFI/BOOT/HashTool.efi

实施安全启动

安全启动的理想设置需要满足某些条件

  1. UEFI 被认为基本可信(尽管有一些众所周知的批评和漏洞[1]),并且必须用强密码保护
  2. 默认制造商/第三方密钥未使用,因为它们已被证明会大幅削弱安全启动的安全模型[2]
  3. UEFI 直接加载用户签名的兼容 EFI 启动存根统一内核镜像(无启动管理器),包括微码(如果适用)和 initramfs,以便在整个启动过程中维持由安全启动建立的信任链,并减少攻击面
  4. 使用全盘驱动器加密,以便参与内核镜像创建和签名过程的工具和文件无法被拥有物理访问机器权限的人访问和篡改。
  5. 使用 TPM 可以获得一些进一步的改进。

#使用您自己的密钥 中描述了一个简单且完全自力更生的设置,而 #使用已签名的启动加载器 则使用了由第三方签名的中间工具。

使用 GRUB 启动加载器需要在启用安全启动之前执行额外的步骤,详情请参见 GRUB#安全启动支持

使用您自己的密钥

警告: 将平台密钥替换为您自己的密钥可能会导致某些机器(包括笔记本电脑)的硬件变砖,从而无法进入固件设置来纠正情况。这是由于以下事实:某些设备(例如 GPU)固件 (OpROMs),在启动期间执行,使用 Microsoft 第三方 UEFI CA 证书或供应商证书签名。许多 Lenovo Thinkpad X、P 和 T 系列笔记本电脑就是这种情况,它们使用 Lenovo CA 证书来签名 UEFI 应用程序和固件。

安全启动实现使用这些密钥

平台密钥 (PK)
顶级密钥。
密钥交换密钥 (KEK)
用于签名签名数据库和禁止签名数据库更新的密钥。
签名数据库 (db)
包含允许的 EFI 二进制文件的密钥和/或哈希值。
禁止签名数据库 (dbx)
包含被拒绝列入列表的 EFI 二进制文件的密钥和/或哈希值。

有关更详细的解释,请参见 所有 UEFI 密钥的含义

要使用安全启动,您至少需要 PKKEKdb 密钥。虽然您可以添加多个 KEK、db 和 dbx 证书,但只允许一个平台密钥。

一旦安全启动处于“用户模式”,密钥只能通过使用更高级别的密钥(使用 sign-efi-sig-list)签名更新来更新。平台密钥可以自行签名。

备份当前变量

在创建新密钥和修改 EFI 变量之前,建议备份当前变量,以便在发生错误时可以恢复它们。

安装 efitools 软件包,然后运行以下命令以备份所有四个主要的“安全启动”变量

$ for var in PK KEK db dbx ; do efi-readvar -v $var -o old_${var}.esl ; done

如果您在新电脑或主板上执行此命令,您提取的变量很可能将是 Microsoft 提供的变量。

将固件置于“设置模式”

当平台密钥被移除时,安全启动处于设置模式。要将固件置于设置模式,进入固件设置实用程序,并找到删除或清除证书的选项。如何进入设置实用程序在 #在启动操作系统之前 中描述。

使用 systemd 的辅助过程

从 v257 版本开始,您可以使用 systemdsystemd-boot 轻松设置安全启动。安装 systemd-ukifysbsigntools

首先使用例如以下命令生成您的签名密钥:

# ukify genkey \
--secureboot-private-key /etc/kernel/secure-boot-private-key.pem \
--secureboot-certificate /etc/kernel/secure-boot-certificate.pem
提示: 或者,在 /etc/kernel/uki.conf 中设置您期望的配置(或使用来自 /usr/lib/kernel/uki.conf 的模板),并使用 ukify 的 --config 选项。这对于自动重用密钥以在稍后使用 kernel-install 签名 UKI 非常有用。

接下来,配置 ESP 以进行自动注册

# bootctl install --secure-boot-auto-enroll yes \
--certificate /etc/kernel/secure-boot-certificate.pem \
--private-key /etc/kernel/secure-boot-private-key.pem

这将在 /boot/loader/keys/auto/ 中创建三个文件 PK.authKEK.authdb.auth。请注意,此命令还会将 systemd-boot 启动加载器安装(或更新)到 ESP

最后,在 /boot/loader.conf 中设置 secure-boot-enroll=force。参见 loader.conf(5)

使用 sbctl 的辅助过程

sbctl 是一种用户友好的设置安全启动和签名文件的方式。

注意: sbctl 并非适用于所有硬件。其工作效果如何取决于制造商。

要使用它,安装 sbctl。另请参阅 上游 READMEsbctl(8)

创建和注册密钥

开始之前,请转到您的固件设置并将安全启动模式设置为设置模式。这对于每个设备都不同:参见 sbctl(8) § 用法

重新登录后,检查安全启动状态

$ sbctl status

您应该看到 sbctl 未安装,并且安全启动已禁用。

然后创建您的自定义安全启动密钥

# sbctl create-keys

将您的密钥与 Microsoft 的密钥一起注册到 UEFI

# sbctl enroll-keys -m
警告: 当启用安全启动时,某些固件会使用 Microsoft 的密钥进行签名和验证。不验证设备可能会导致它们变砖。要在不注册 Microsoft 的密钥的情况下注册您的密钥,请运行:sbctl enroll-keys。仅在您知道自己在做什么时才执行此操作。

再次检查安全启动状态

$ sbctl status

现在应该已安装 sbctl,但是只有在启动文件已使用您刚刚创建的密钥签名后,安全启动才会工作。

签名

检查哪些文件需要签名才能使安全启动工作

# sbctl verify

现在签名所有未签名的文件。通常需要签名内核启动加载器。例如

# sbctl sign -s /boot/vmlinuz-linux
# sbctl sign -s /boot/EFI/BOOT/BOOTX64.EFI

需要签名的文件将取决于您系统的布局、内核和启动加载器。

提示: 特别是如果您正在与 Windows 进行双启动,则可能有很多文件需要签名。使用 sbctl 签名所有需要文件的过程可以使用 sed 完成
# sbctl verify | sed 's/✗ /sbctl sign -s /e'

此示例假设输出的文件路径相对于 /boot。或者,您可以使用

# sbctl verify | sed -E 's|^.* (/.+) is not signed$|sbctl sign -s "\1"|e'

这与文件路径无关,并且不需要 '✗' 字符。

现在您完成了!重启您的系统并在固件设置中重新打开安全启动。如果启动加载器和操作系统加载,则安全启动应该正在工作。使用以下命令检查:

$ sbctl status
使用 pacman hook 自动签名

sbctl 附带一个 pacman hook,每当 Linux 内核systemd启动加载器更新时,它都会自动签名所有新文件。

提示: 如果您使用 Systemd-bootsystemd-boot-update.service,则启动加载器仅在重启后更新,因此 sbctl pacman hook 将不会签名新文件。作为一种变通方法,直接在 /usr/lib/ 中签名启动加载器可能很有用,因为如果存在,bootctl installupdate 将自动识别并将 .efi.signed 文件复制到 ESP,而不是普通的 .efi 文件。参见 bootctl(1)
# sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi

手动过程

安装 efitools

以下几乎所有部分都要求您安装 efitools 软件包。

创建密钥

要生成密钥,请执行以下步骤。

您将需要多种格式的私钥和证书

.key
用于 EFI 二进制文件和 EFI 签名列表签名的 PEM 格式私钥
.crt
用于 sbsign(1)sbvarsign(1)sign-efi-sig-list(1) 的 PEM 格式证书。
.cer
用于固件的 DER 格式证书。
.esl
用于 sbvarsign(1)efi-updatevar(1)KeyTool 和固件的 EFI 签名列表中的证书。
.auth
用于 efi-updatevar(1)sbkeysyncKeyTool 和固件的带有身份验证标头(即签名证书更新文件)的 EFI 签名列表中的证书。

创建一个 GUID 以进行所有者识别

$ uuidgen --random > GUID.txt

平台密钥

$ openssl req -newkey rsa:4096 -nodes -keyout PK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Platform Key/" -out PK.crt
$ openssl x509 -outform DER -in PK.crt -out PK.cer
$ cert-to-efi-sig-list -g "$(< GUID.txt)" PK.crt PK.esl
$ sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt PK PK.esl PK.auth

签名一个空文件,以允许在“用户模式”下移除平台密钥

$ sign-efi-sig-list -g "$(< GUID.txt)" -c PK.crt -k PK.key PK /dev/null noPK.auth

密钥交换密钥

$ openssl req -newkey rsa:4096 -nodes -keyout KEK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Key Exchange Key/" -out KEK.crt
$ openssl x509 -outform DER -in KEK.crt -out KEK.cer
$ cert-to-efi-sig-list -g "$(< GUID.txt)" KEK.crt KEK.esl
$ sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt KEK KEK.esl KEK.auth

签名数据库密钥

$ openssl req -newkey rsa:4096 -nodes -keyout db.key -new -x509 -sha256 -days 3650 -subj "/CN=my Signature Database key/" -out db.crt
$ openssl x509 -outform DER -in db.crt -out db.cer
$ cert-to-efi-sig-list -g "$(< GUID.txt)" db.crt db.esl
$ sign-efi-sig-list -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db db.esl db.auth
辅助脚本

参考页面作者提供了辅助/便捷脚本[3](需要 python)。一个经过轻微编辑的版本也打包为 sbkeysAUR

为了使用它,只需在安全位置创建一个文件夹(例如,如果计划稍后使用 sbupdate-gitAUR 自动化统一内核镜像创建和签名,则为 /etc/efi-keys/),然后运行它

# mkdir /etc/efi-keys
# cd !$
# curl -L -O https://www.rodsbooks.com/efi-bootloaders/mkkeys.sh
# chmod +x mkkeys.sh
# ./mkkeys.sh
Enter a Common Name to embed in the keys, e.g. "Secure Boot"

这将生成不同格式的所需文件。

在固件中注册密钥

使用以下方法之一注册 dbKEKPK 证书。

提示: 由于 dbx(禁止签名数据库)为空,因此在以下说明中可以安全地将其忽略。
警告: 注册平台密钥会将安全启动设置为“用户模式”,离开“设置模式”,因此应在序列中最后注册。
使用 sbkeysync

安装 sbsigntools。创建一个具有以下目录结构的 /etc/secureboot/keys 目录 -

/etc/secureboot/keys
├── db
├── dbx
├── KEK
└── PK

例如使用:

# mkdir -p /etc/secureboot/keys/{db,dbx,KEK,PK}

然后将之前生成的每个 .auth 文件复制到它们各自的位置(例如,将 PK.auth 复制到 /etc/secureboot/keys/PK,依此类推)。

如果您想验证 sbkeysync 将对系统 UEFI 密钥库所做的更改,请使用:

# sbkeysync --keystore /etc/secureboot/keys --pk --dry-run --verbose

最后,使用 sbkeysync 注册您的密钥。

# sbkeysync --keystore /etc/secureboot/keys --verbose
# sbkeysync --keystore /etc/secureboot/keys --verbose --pk
提示
  • 如果 sbkeysync 返回写入错误,请先运行 chattr -i /sys/firmware/efi/efivars/{PK,KEK,db}*,然后再使用 sbkeysync 发出命令以临时更改文件属性,从而允许在 efivars 目录中写入 EFI 密钥。参见 chattr(1)
  • 如果您收到 PK.auth 的权限被拒绝错误,您可以使用命令 efi-updatevar -f /etc/secureboot/keys/PK/PK.auth PK 注册它。
  • 如果这失败,可能是由于固件锁定了 BIOS 设置。在 Dell 和 Lenovo 系统上,您可能需要重置 BIOS 密码:Sysfs 固件身份验证文档

在 Lenovo 系统上

# cat > /sys/class/firmware-attributes/thinklmi/authentication/Admin/current_password 
my-super-secret-password
^D

在 Dell 系统上

# cat > /sys/class/firmware-attributes/dell-wmi-sysman/authentication/Admin/current_password 
my-super-secret-password
^D
然后重试。

在下次启动时,UEFI 应该恢复为用户模式并强制执行安全启动策略。

使用固件设置实用程序

将所有 *.cer*.esl*.auth 文件(除了 noPK.auth 文件!)复制到 FAT 格式的文件系统(您可以使用 EFI 系统分区)。

警告: 不要noPK.auth 文件复制到您 PC 的 EFI 系统分区 (ESP)!如果您这样做,并且有人例如偷了您的 PC,此人可以再次删除 UEFI 安全启动固件中的个人平台密钥,再次在您的 PC 上打开“设置模式”,并用他们自己的平台密钥替换您的安全启动密钥(PK、KEK、db、dbx),从而破坏 UEFI 安全启动的整个目的。只有您应该能够替换平台密钥,因此只有您应该有权访问 noPK.auth 文件。因此,请将 noPK.auth 文件保存在只有您有权访问的秘密、安全的地方。noPK.auth 文件的安全位置是:

根据 UEFI 规范,您 PC 的 EFI 系统分区 不得加密,并且可以在另一台 PC 上挂载和读取(如果您的 PC 被盗并且硬盘驱动器被取出并连接到另一台 PC)。将 noPK.auth 文件复制到您 PC 的 ESP 并在之后删除它也是不可取的,因为 FAT32 EFI 系统分区 上已删除的文件可以使用 PhotoRec 等工具恢复

启动固件设置实用程序并注册 dbKEKPK 证书。固件具有各种不同的界面,例如,请参见 使用固件设置实用程序替换密钥 以了解如何注册密钥。

如果使用的工具支持,则首选使用 .auth.esl 而不是 .cer

使用 KeyTool

KeyTool.efiefitools 软件包中,将其复制到 ESP。要在注册密钥后使用它,请使用 sbsign 签名它。

# sbsign --key db.key --cert db.crt --output esp/KeyTool-signed.efi /usr/share/efitools/efi/KeyTool.efi

使用固件设置实用程序、启动加载器或 UEFI Shell 启动 KeyTool-signed.efi 并注册密钥。

请参阅 使用 KeyTool 替换密钥 以了解 KeyTool 菜单选项的说明。

使用 systemd-boot

从 systemd 版本 252 开始,systemd-boot 可以用于注册密钥。要注册密钥,请将 db.authKEK.authPK.auth 复制到 ESP 上的特殊文件夹

# cp db.auth KEK.auth PK.auth esp/loader/keys/NAME/

其中 NAME 可以是您分配的任何唯一名称,例如 MYKEYS

在复制密钥并启用安全启动设置模式后,启动菜单中将出现一个新条目,内容为 Enroll Secure Boot keys: MYKEYS。激活此条目将注册安全启动密钥。

签名 EFI 二进制文件

安全启动处于活动状态(即“用户模式”)时,只有签名的 EFI 二进制文件(例如应用程序、驱动统一内核镜像)可以启动。

使用 sbsigntools

安装 sbsigntools 以使用 sbsign(1) 签名 EFI 二进制文件。

提示
  • 要检查二进制文件是否已签名并列出其签名,请使用 sbverify --list /path/to/binary
  • rEFInd 启动管理器的 refind-install 脚本可以签名 rEFInd EFI 二进制文件,并将它们与 db 证书一起复制到 ESP。有关说明,请参阅 rEFInd#使用您自己的密钥
注意: 如果在没有 --output 的情况下运行 sbsign,则生成的文件将为 filename.signed。有关更多信息,请参阅 sbsign(1)

要签名您的内核和启动管理器,请使用 sbsign,例如:

# sbsign --key db.key --cert db.crt --output /boot/vmlinuz-linux /boot/vmlinuz-linux
# sbsign --key db.key --cert db.crt --output esp/EFI/BOOT/BOOTx64.EFI esp/EFI/BOOT/BOOTx64.EFI
警告: 仅签名内核不会保护 initramfs 免受篡改。请参阅 统一内核镜像,了解如何生成可以手动使用 sbsign 签名的组合镜像。
使用 mkinitcpio 后期挂钩签名内核

您还可以使用 mkinitcpio 后期挂钩,以便在生成 initramfs 时签名内核。

创建 以下文件并使其成为可执行文件

/etc/initcpio/post/kernel-sbsign
#!/usr/bin/env bash

kernel="$1"
[[ -n "$kernel" ]] || exit 0

# use already installed kernel if it exists
[[ ! -f "$KERNELDESTINATION" ]] || kernel="$KERNELDESTINATION"

keypairs=(/path/to/db.key /path/to/db.crt)

for (( i=0; i<${#keypairs[@]}; i+=2 )); do
    key="${keypairs[$i]}" cert="${keypairs[(( i + 1 ))]}"
    if ! sbverify --cert "$cert" "$kernel" &>/dev/null; then
        sbsign --key "$key" --cert "$cert" --output "$kernel" "$kernel"
    fi
done

/path/to/db.key/path/to/db.crt 替换为您要用于签名内核的密钥对的路径。

如果您使用的是 systemd-boot,则有一个 专用 pacman 挂钩 以半自动方式执行此任务。

使用 mkinitcpio 后期挂钩签名统一内核镜像

请参阅 统一内核镜像#为安全启动签名 UKI

使用 sbupdate 完全自动化统一内核生成和签名

本文或本章节已过时。

原因: sbupdate 上游存储库[死链接 2024-07-30 ⓘ] 已于 2023 年 8 月存档。此外,它是在 mkinitcpio 和其他 initramfs 生成器获得生成 统一内核镜像 的能力之前很久创建的,这为以前繁琐的过程提供了极大的便利。如今,请考虑改用 #使用 sbctl 的辅助过程。(在 Talk:Unified Extensible Firmware Interface/Secure Boot 中讨论)

sbupdate 是一个专门用于自动化 Arch Linux 上统一内核镜像生成和签名的工具。它通过 pacman 挂钩 处理内核的安装、删除和更新。

安装 sbupdate-gitAUR 并按照项目主页上给出的说明进行配置。[4]

提示: 如果使用 systemd-boot,请设置 OUT_DIR="EFI/Linux" 以使您的签名内核镜像直接被识别,而无需配置。请参阅 systemd-boot(7) § FILESsystemd-boot#添加加载器

配置完成后,只需以 root 身份运行 sbupdate 即可首次生成镜像。

注意: sbupdate 输出通常包含错误,例如 warning: data remaining[26413568 vs 26423180]: gaps between PE/COFF sections?。这些是无害的,可以安全地忽略。[5]

更新密钥

一旦安全启动处于“用户模式”,对 KEK、db 和 dbx 的任何更改都需要使用更高级别的密钥进行签名。

例如,如果您想用新密钥替换您的 db 密钥

  1. 创建新密钥,
  2. 将其转换为 EFI 签名列表,
  3. 签名 EFI 签名列表,
  4. 注册签名证书更新文件。
$ cert-to-efi-sig-list -g "$(< GUID.txt)" new_db.crt new_db.esl
$ sign-efi-sig-list -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db new_db.esl new_db.auth

如果不是替换您的 db 密钥,而是想在签名数据库中添加另一个密钥,则需要使用选项 -a(请参阅 sign-efi-sig-list(1)

$ sign-efi-sig-list -a -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db new_db.esl new_db.auth

new_db.auth 创建后,注册它

与其他操作系统双启动

Microsoft Windows

本文或本章节需要扩充。

原因: 是否可以通过使用自定义密钥签名 Windows 启动加载器来启动 Windows?(在 Talk:Unified Extensible Firmware Interface/Secure Boot#使用自定义启动加载器签名启动 Windows 中讨论)

通常不可能在启用安全启动模式的情况下,通过使用自定义的个人密钥签名 Windows 启动加载器 (EFI/Microsoft/Boot/bootmgfw.efi) 来启动 Windows,除非在 UEFI 安全启动变量中注册“Microsoft Windows Production PCA 2011”密钥

  • 如果 bootmgfw.efi 包含来自“Microsoft Windows Production PCA 2011”您自己的安全启动 db 密钥的两个签名(即两个签名),则 UEFI 固件实现(如INSYDE Corp. 4096.01 (UEFI Version 2.31, Version F.70, Release Date: 07/18/2016, BIOS Revision 15.112, Firmware Revision: 29.66))将不会启动 bootmgfw.efi,并且会抛出安全违规错误(Selected boot image did not authenticate. Press ENTER to continue.):像这样的 UEFI 固件实现可能只能读取第一个签名,而不能读取第二个签名。只有第二个签名的证书注册在 UEFI 安全启动变量中,因此安全启动验证失败。
  • 如果从 bootmgfw.efi 文件中剥离/删除“Microsoft Windows Production PCA 2011”签名,并且仅将您自己的安全启动 db 密钥的签名添加到文件中,则 UEFI 将启动该文件,但 Windows 将启动恢复/修复环境:Windows 抱怨 Windows 安装已损坏(因为 bootmgfw.efi 文件上缺少“Microsoft Windows Production PCA 2011”签名)。

因此,要与 Windows 双启动

使用 Microsoft 的 GUID (77fa9abd-0359-4d32-bd60-28f4e78f784b) 从 Microsoft 的 DER 格式 db 证书创建 EFI 签名列表,并将它们合并到一个文件中以简化操作

$ sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_Win_db_2011.esl MicWinProPCA2011_2011-10-19.crt
$ sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_Win_db_2023.esl 'windows uefi ca 2023.crt'
$ sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_UEFI_db_2011.esl MicCorUEFCA2011_2011-06-27.crt
$ sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_UEFI_db_2023.esl 'microsoft uefi ca 2023.crt'
$ cat MS_Win_db_2011.esl MS_Win_db_2023.esl MS_UEFI_db_2011.esl MS_UEFI_db_2023.esl > MS_db.esl

可选(为了严格符合 Microsoft UEFI 安全启动要求):使用 Microsoft 的 GUID (77fa9abd-0359-4d32-bd60-28f4e78f784b) 从 Microsoft 的 DER 格式 KEK 证书创建 EFI 签名列表

$ sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_Win_KEK_2011.esl MicCorKEKCA2011_2011-06-24.crt
$ sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_Win_KEK_2023.esl 'microsoft corporation kek 2k ca 2023.crt'
$ cat MS_Win_KEK_2011.esl MS_Win_KEK_2023.esl > MS_Win_KEK.esl

使用您的 KEK 签名 db 变量更新。使用带有选项 -asign-efi-sig-list添加而不是替换 db 证书

$ sign-efi-sig-list -a -g 77fa9abd-0359-4d32-bd60-28f4e78f784b -k KEK.key -c KEK.crt db MS_db.esl add_MS_db.auth

可选(为了严格符合 Microsoft UEFI 安全启动要求):使用您的 PK 签名 KEK 变量更新。使用带有选项 -asign-efi-sig-list添加而不是替换 KEK 证书

$ sign-efi-sig-list -a -g 77fa9abd-0359-4d32-bd60-28f4e78f784b -k PK.key -c PK.crt KEK MS_Win_KEK.esl add_MS_Win_KEK.auth

按照 #在固件中注册密钥 注册 add_MS_db.auth,为了严格符合 Microsoft UEFI 安全启动要求,将 add_MS_Win_KEK.auth 注册到 UEFI 安全启动数据库变量中。

使用已签名的启动加载器

使用已签名的启动加载器意味着使用 Microsoft 密钥签名的启动加载器。有两个已知的已签名启动加载器:PreLoader 和 shim。它们的目的是链式加载其他 EFI 二进制文件(通常是启动加载器)。由于 Microsoft 永远不会签名一个自动启动任何未签名二进制文件的启动加载器,因此 PreLoader 和 shim 使用一个名为 Machine Owner Key 列表的允许列表,缩写为 MokList。如果二进制文件(Preloader 和 shim)的 SHA256 哈希值或二进制文件签名的密钥(shim)在 MokList 中,它们就会执行它,否则它们会启动一个密钥管理实用程序,该实用程序允许注册哈希值或密钥。

警告: Microsoft 所谓的“安全核心 PC”在出厂时未注册 Microsoft 第三方 UEFI CA 证书(Microsoft Corporation UEFI CA 2011 或 Microsoft UEFI CA 2023)。[6]。唯一注册的 DB 证书是 Microsoft Windows Production PCA 2011 证书,该证书专门用于签名 Windows 启动加载器。

需要在固件设置中启用 Microsoft 第三方 UEFI CA 证书的注册,以启动使用此证书签名的 EFI 二进制文件和 OpROM。

PreLoader

运行时,PreLoader 尝试启动 loader.efi。如果 loader.efi 的哈希值不在 MokList 中,PreLoader 将启动 HashTool.efi。在 HashTool 中,您必须注册要启动的 EFI 二进制文件的哈希值,这意味着您的启动加载器 (loader.efi) 和内核。

注意: 每次更新任何二进制文件(例如启动加载器或内核)时,您都需要注册其新哈希值。
提示: rEFInd 启动管理器的 refind-install 脚本可以将 rEFInd 和 PreLoader EFI 二进制文件复制到 ESP。有关说明,请参阅 rEFInd#使用 PreLoader
设置 PreLoader
注意: efitools 包中的 PreLoader.efiHashTool.efi 未签名,因此它们的实用性受到限制。您可以从 preloader-signedAUR手动下载 获取已签名的 PreLoader.efiHashTool.efi

安装 preloader-signedAUR 并将 PreLoader.efiHashTool.efi 复制到启动加载器目录;对于 systemd-boot,请使用

# cp /usr/share/preloader-signed/{PreLoader,HashTool}.efi esp/EFI/systemd

现在复制启动加载器二进制文件并将其重命名为 loader.efi;对于 systemd-boot,请使用

# cp esp/EFI/systemd/systemd-bootx64.efi esp/EFI/systemd/loader.efi

最后,创建一个新的 NVRAM 条目以启动 PreLoader.efi

# efibootmgr --unicode --disk /dev/sdX --part Y --create --label "PreLoader" --loader /EFI/systemd/PreLoader.efi

X 替换为驱动器盘符,将 Y 替换为EFI 系统分区的分区号。

此条目应添加到列表中作为第一个启动项;使用 efibootmgr 命令检查并在必要时调整启动顺序。

回退

如果启动自定义 NVRAM 条目时出现问题,请将 HashTool.efiloader.efi 复制到 UEFI 系统自动启动的默认加载器位置

# cp /usr/share/preloader-signed/HashTool.efi esp/EFI/BOOT/
# cp esp/EFI/systemd/systemd-bootx64.efi esp/EFI/BOOT/loader.efi

复制 PreLoader.efi 并重命名它

# cp /usr/share/preloader-signed/PreLoader.efi esp/EFI/BOOT/BOOTx64.EFI

对于特别顽固的 UEFI 实现,请将 PreLoader.efi 复制到 Windows 系统使用的默认加载器位置

# mkdir -p esp/EFI/Microsoft/Boot
# cp /usr/share/preloader-signed/PreLoader.efi esp/EFI/Microsoft/Boot/bootmgfw.efi
注意: 如果与 Windows 双启动,请先备份原始的 bootmgfw.efi,因为替换它可能会导致 Windows 更新出现问题。

与之前一样,将 HashTool.efiloader.efi 复制到 esp/EFI/Microsoft/Boot/

当系统在启用安全启动的情况下启动时,按照上述步骤注册 loader.efi/vmlinuz-linux(或正在使用的任何内核镜像)。

如何在启动时使用?

将显示一条消息,提示 Failed to Start loader... I will now execute HashTool. 要使用 HashTool 注册 loader.efivmlinuz.efi 的哈希值,请按照以下步骤操作。这些步骤假定为重新制作的 archiso 安装介质的标题。您将获得的具体标题取决于您的启动加载器设置。

  • 选择确定
  • 在 HashTool 主菜单中,选择注册哈希,选择 \loader.efi 并使用确认。再次选择注册哈希archiso 以进入 archiso 目录,然后选择 vmlinuz.efi 并使用确认。然后选择退出返回到启动设备选择菜单。
  • 在启动设备选择菜单中,选择Arch Linux archiso x86_64 UEFI CD
删除已注册的哈希值

MOK 数据库中注册的每个哈希值条目都会占用 NVRAM 的一小部分空间。您可能需要删除无用的哈希值以释放空间并防止过时的程序启动。

安装 efitools 并复制 KeyTool.efi

# cp /usr/share/efitools/efi/KeyTool.efi esp/EFI/systemd/KeyTool.efi

设法启动到 Preloader,您将看到 KeyTool 条目。然后,您可以编辑 MOK 数据库中的哈希值。

删除 PreLoader
注意: 由于您要删除内容,因此最好备份它。

卸载 preloader-signedAUR 并简单地删除复制的文件并恢复配置;对于 systemd-boot,请使用

# rm esp/EFI/systemd/{PreLoader,HashTool}.efi
# rm esp/EFI/systemd/loader.efi
# efibootmgr --unicode --bootnum N --delete-bootnum
# bootctl update

其中 N 是为启动 PreLoader.efi 创建的 NVRAM 启动条目。使用 efibootmgr 命令检查并在必要时调整启动顺序。

注意: 上述命令涵盖了最简单的情况;如果您创建、复制、重命名或编辑了更多文件,则可能也必须处理它们。如果 PreLoader 是您的操作启动条目,那么您显然还需要 #禁用安全启动

shim

本文或本章节需要扩充。

原因: 需要测试。(在 Talk:Unified Extensible Firmware Interface/Secure Boot#shim 中讨论)

运行时,shim 尝试启动 grubx64.efi。如果 MokList 不包含 grubx64.efi 的哈希值或其签名的密钥,shim 将启动 MokManager (mmx64.efi)。在 MokManager 中,您必须注册要启动的 EFI 二进制文件的哈希值(您的启动加载器 (grubx64.efi) 和内核)或注册它们签名的密钥。

注意
  • 如果您使用 #使用哈希值的 shim,则每次更新任何二进制文件(例如启动加载器或内核)时,您都需要注册其新哈希值。
  • 自 15.3 版本起,shim 将不会启动没有有效 .sbat 区段的 EFI 二进制文件。运行 objdump -j .sbat -s /path/to/binary.efi 以验证 EFI 二进制文件是否具有它。有关详细信息,请参阅 SBAT 文档
  • 如果您实际上对安全启动带来的安全性不感兴趣,而只是为了满足 Windows 11 提出的要求而启用它,您可能需要考虑使用 mokutil --disable-validation 禁用 shim 中的验证过程。在这种情况下,您将不需要签名 grub(可能仍然需要 sbat)或内核镜像,同时能够使用 grub 中的 chainloader 启动 Windows。
设置 shim
提示: rEFInd 启动管理器的 refind-install 脚本可以签名 rEFInd EFI 二进制文件,并将它们与 shim 和 MOK 证书一起复制到 ESP。有关说明,请参阅 rEFInd#使用 shim

安装 shim-signedAUR

将您当前的启动加载器重命名为 grubx64.efi,因为默认情况下,Shim 将尝试加载并运行名为 grubx64.efi 的文件。虽然可以通过将文件路径作为命令行参数传递给 shim 来覆盖此默认设置,但由于某些固件在具有命令行参数的 UEFI 启动条目中存在问题,因此依赖默认设置更可靠。

# mv esp/EFI/BOOT/BOOTx64.EFI esp/EFI/BOOT/grubx64.efi

shimMokManager 复制到 ESP 上的启动加载器目录;使用您的启动加载器的先前文件名作为 shimx64.efi 的文件名

注意: 确保您复制 fbx64.efi(它在同一目录下),除非您实际有一个有效的 bootx64.csv 可以使用。否则,shim 将不会执行 grubx64.efi,而是似乎无法工作并仅重置机器。
# cp /usr/share/shim-signed/shimx64.efi esp/EFI/BOOT/BOOTx64.EFI
# cp /usr/share/shim-signed/mmx64.efi esp/EFI/BOOT/

最后,创建一个新的 NVRAM 条目以启动 BOOTx64.EFI

# efibootmgr --unicode --disk /dev/sdX --part Y --create --label "Shim" --loader /EFI/BOOT/BOOTx64.EFI

shim 可以通过 Machine Owner Key 或存储在 MokList 中的哈希值来验证二进制文件。

Machine Owner Key (MOK)
用户生成并用于签名 EFI 二进制文件的密钥。
哈希值
EFI 二进制文件的 SHA256 哈希值。

使用哈希值更简单,但每次更新启动加载器或内核时,您都需要在 MokManager 中添加它们的哈希值。使用 MOK,您只需添加一次密钥,但每次更新启动加载器和内核时,都必须对其进行签名。

使用哈希值的 shim

如果 shim 在 MokList 中找不到 grubx64.efi 的 SHA256 哈希值,它将启动 MokManager (mmx64.efi)。

MokManager 中,选择从磁盘注册哈希,找到 grubx64.efi 并将其添加到 MokList。重复步骤并添加您的内核 vmlinuz-linux。完成后,选择继续启动,您的启动加载器将启动,并且它将能够启动内核。

使用密钥的 shim

安装 sbsigntools

您将需要

.key
PEM 格式的私钥,用于 EFI 二进制文件签名。
.crt
用于 sbsign 的 PEM 格式证书。
.cer
用于 MokManager 的 DER 格式证书。

创建 Machine Owner Key

$ openssl req -newkey rsa:2048 -nodes -keyout MOK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Machine Owner Key/" -out MOK.crt
$ openssl x509 -outform DER -in MOK.crt -out MOK.cer
注意: 似乎 shim 不支持将 4096 RSA 密钥添加到 MokList(在加载和验证 grubx64.efi 二进制文件时可能会冻结),因此请确保现在使用 2048 密钥。请参阅 Debian:SecureBoot#生成新密钥

签名您的启动加载器(名为 grubx64.efi)和内核

# sbsign --key MOK.key --cert MOK.crt --output /boot/vmlinuz-linux /boot/vmlinuz-linux
# sbsign --key MOK.key --cert MOK.crt --output esp/EFI/BOOT/grubx64.efi esp/EFI/BOOT/grubx64.efi

每次更新它们时,您都需要执行此操作。您可以使用 mkinitcpio 后期挂钩 自动化内核签名。创建 以下文件并使其成为可执行文件

/etc/initcpio/post/kernel-sbsign
#!/usr/bin/env bash

kernel="$1"
[[ -n "$kernel" ]] || exit 0

# use already installed kernel if it exists
[[ ! -f "$KERNELDESTINATION" ]] || kernel="$KERNELDESTINATION"

keypairs=(/path/to/MOK.key /path/to/MOK.crt)

for (( i=0; i<${#keypairs[@]}; i+=2 )); do
    key="${keypairs[$i]}" cert="${keypairs[(( i + 1 ))]}"
    if ! sbverify --cert "$cert" "$kernel" &>/dev/null; then
        sbsign --key "$key" --cert "$cert" --output "$kernel" "$kernel"
    fi
done

MOK.cer 复制到 FAT 格式化的文件系统(您可以使用EFI 系统分区)。

重新启动并启用安全启动。如果 shim 在 MokList 中找不到 grubx64.efi 签名的证书,它将启动 MokManager (mmx64.efi)。

MokManager 中,选择从磁盘注册密钥,找到 MOK.cer 并将其添加到 MokList。完成后,选择继续启动,您的启动加载器将启动,并且它将能够启动任何使用您的 Machine Owner Key 签名的二进制文件。

使用密钥和 GRUB 的 shim

有关说明,请参阅 GRUB#Shim-lock

删除已注册的哈希值/密钥

MOK 数据库中注册的每个哈希值/密钥条目都会占用 NVRAM 的一小部分空间。您可能需要删除无用的哈希值/密钥以释放空间并防止过时的程序启动。

MOK 数据库可以使用 mokutil 进行管理

列出已注册的密钥和哈希值

# mokutil --list-enrolled

从数据库中删除哈希值。此处输入的密码将在 MOK 管理器中要求确认删除。

# mokutil --delete-hash <hash to remove from above command>
Input password:

从数据库中删除密钥

# mokutil --delete MOK.cer

列出下次重启时要删除的哈希值/密钥

# mokutil --list-delete

下次重启时,将启动 MOK 管理器,其中包含注册/删除哈希值/密钥的选项。更多详细信息,请参阅 mokutil(1)

删除 shim

卸载 shim-signedAUR,删除复制的 shimMokManager 文件,并将您的启动加载器重命名回来。

保护安全启动

防止任何具有物理访问权限的人员禁用安全启动的唯一方法是使用密码保护固件设置。大多数 UEFI 固件都提供此功能,通常在固件设置的“安全”部分下列出。

考虑启用 内核锁定模式。请参阅 [7]

提示和技巧

ISO 重打包

可以使用 libisoburnmtools 解包和重打包官方安装镜像。这样,您可以创建支持安全启动的镜像,无论使用自定义密钥还是已签名的启动加载器。

本文或本章节需要扩充。

原因: 添加重新打包 ISO 以包含 shim 的说明。(在 Talk:Unified Extensible Firmware Interface/Secure Boot 中讨论)

使用自定义密钥签名官方 ISO

只需提取启动加载器(BOOTx64.EFIBOOTIA32.EFI)、内核、UEFI shell,对其进行签名,然后使用签名的文件重新打包 ISO,即可将对使用自定义密钥的安全启动的支持添加到官方 ISO。

首先提取相关文件和 El Torito 启动镜像

$ osirrox -indev archlinux-YYYY.MM.DD-x86_64.iso \
	-extract_boot_images ./ \
	-cpx /arch/boot/x86_64/vmlinuz-linux \
	/EFI/BOOT/BOOTx64.EFI \
	/EFI/BOOT/BOOTIA32.EFI \
	/shellx64.efi \
	/shellia32.efi ./

xorrisofs(1) 选项 -rational-rockmkarchiso 使用)使 ISO 9660 上的文件变为只读,这在提取后仍然存在。使文件可写,以便可以修改它们

$ chmod +w BOOTx64.EFI BOOTIA32.EFI shellx64.efi shellia32.efi vmlinuz-linux

签名文件。例如,要使用 sbsigntools 执行此操作

$ sbsign --key db.key --cert db.crt --output BOOTx64.EFI BOOTx64.EFI
$ sbsign --key db.key --cert db.crt --output BOOTIA32.EFI BOOTIA32.EFI
$ sbsign --key db.key --cert db.crt --output shellx64.efi shellx64.efi
$ sbsign --key db.key --cert db.crt --output shellia32.efi shellia32.efi
$ sbsign --key db.key --cert db.crt --output vmlinuz-linux vmlinuz-linux

将签名的 EFI 二进制文件复制到 eltorito_img2_uefi.img。它将用作 EFI 系统分区,并将列为 El Torito UEFI 启动镜像。eltorito_img2_uefi.img 的大小是固定的,但 mkarchiso 添加了 8 MiB 的可用空间(用于舍入/对齐,以考虑保留扇区等),因此签名导致的大小增加不应成为问题。

$ mcopy -D oO -i eltorito_img2_uefi.img vmlinuz-linux ::/arch/boot/x86_64/vmlinuz-linux
$ mcopy -D oO -i eltorito_img2_uefi.img BOOTx64.EFI BOOTIA32.EFI ::/EFI/BOOT/
$ mcopy -D oO -i eltorito_img2_uefi.img shellx64.efi shellia32.efi ::/

使用修改后的 El Torito UEFI 启动镜像重新打包 ISO,并将签名的 EFI 二进制文件添加到 ISO 9660

$ xorriso -indev archlinux-YYYY.MM.DD-x86_64.iso \
	-outdev archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso \
	-map vmlinuz-linux /arch/boot/x86_64/vmlinuz-linux \
	-map_l ./ /EFI/BOOT/ BOOTx64.EFI BOOTIA32.EFI -- \
	-map_l ./ / shellx64.efi shellia32.efi -- \
	-boot_image any replay \
	-append_partition 2 0xef eltorito_img2_uefi.img

启动生成的 archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso

使用 PreLoader 替换启动加载器

将安全启动支持添加到官方 ISO 的另一种方法是提取启动加载器并将其替换为 #PreLoader

首先,提取启动加载器和 El Torito 启动镜像

$ osirrox -indev archlinux-YYYY.MM.DD-x86_64.iso \
	-extract_boot_images ./ \
	-extract /EFI/BOOT/BOOTx64.EFI loader.efi

BOOTx64.efi 文件替换为 PreLoader

$ cp /usr/share/preloader-signed/PreLoader.efi BOOTx64.EFI
$ cp /usr/share/preloader-signed/HashTool.efi HashTool.efi

将新文件添加到启动镜像

$ mcopy -D oO -i eltorito_img2_uefi.img BOOTx64.EFI loader.efi HashTool.efi ::/EFI/BOOT/

最后,使用修改后的启动镜像和新的启动加载器文件重新打包 ISO

$ xorriso -indev archlinux-YYYY.MM.DD-x86_64.iso \
	-outdev archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso \
	-map_l ./ /EFI/BOOT/ BOOTx64.EFI loader.efi HashTool.efi -- \
	-boot_image any replay \
	-append_partition 2 0xef eltorito_img2_uefi.img

使用 Machine Owner Key 为 shim 签名官方 ISO

只需提取启动加载器、内核和 UEFI shell,对其进行签名,然后使用签名的文件和 shim 重新打包 ISO,即可将对使用带有 Machine Owner Key (MOK) 的 shim 的安全启动的支持添加到官方 ISO。

首先提取相关文件和 El Torito 启动镜像。启动加载器文件名需要为 grubx64.efi,以便 shim 可以找到它。

$ osirrox -indev archlinux-YYYY.MM.DD-x86_64.iso \
	-extract_boot_images ./ \
	-extract /EFI/BOOT/BOOTx64.EFI grubx64.efi \
	-extract /shellx64.efi shellx64.efi \
	-extract /arch/boot/x86_64/vmlinuz-linux vmlinuz-linux

xorrisofs(1) 选项 -rational-rockmkarchiso 使用)使 ISO 9660 上的文件变为只读,这在提取后仍然存在。使文件可写,以便可以修改它们

$ chmod +w grubx64.efi shellx64.efi vmlinuz-linux

使用您的 MOK 签名文件

$ sbsign --key MOK.key --cert MOK.crt --output grubx64.efi grubx64.efi
$ sbsign --key MOK.key --cert MOK.crt --output shellx64.efi shellx64.efi
$ sbsign --key MOK.key --cert MOK.crt --output vmlinuz-linux vmlinuz-linux

获取预签名的 shim EFI 二进制文件,例如,通过安装 shim-signedAUR。将 shim 和 MokManager 放在当前目录中,并将 shim EFI 二进制文件的文件名更改为 BOOTx64.EFI

$ cp /usr/share/shim-signed/shimx64.efi BOOTx64.EFI
$ cp /usr/share/shim-signed/mmx64.efi ./

将 shim、MokManager、签名的 EFI 二进制文件和 DER 格式的 MOK 复制到 eltorito_img2_uefi.img。它将用作 EFI 系统分区,并将列为 El Torito UEFI 启动镜像。eltorito_img2_uefi.img 的大小是固定的,但 mkarchiso 添加了 8 MiB 的可用空间(用于舍入/对齐,以考虑保留扇区等),因此添加的文件导致的大小增加不应成为问题。

$ mcopy -D oO -i eltorito_img2_uefi.img vmlinuz-linux ::/arch/boot/x86_64/vmlinuz-linux
$ mcopy -D oO -i eltorito_img2_uefi.img MOK.cer shellx64.efi ::/
$ mcopy -D oO -i eltorito_img2_uefi.img BOOTx64.EFI grubx64.efi mmx64.efi ::/EFI/BOOT/

使用修改后的 El Torito UEFI 启动镜像重新打包 ISO,并将 shim、MokManager、签名的 EFI 二进制文件和 DER 格式的 MOK 添加到 ISO 9660

$ xorriso -indev archlinux-YYYY.MM.DD-x86_64.iso \
	-outdev archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso \
	-map vmlinuz-linux /arch/boot/x86_64/vmlinuz-linux \
	-map_l ./ / shellx64.efi MOK.cer -- \
	-map_l ./ /EFI/BOOT/ BOOTx64.EFI grubx64.efi mmx64.efi -- \
	-boot_image any replay \
	-append_partition 2 0xef eltorito_img2_uefi.img

启动生成的 archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso。当 MokManager 启动时,选择从磁盘注册密钥 > ARCHISO_EFI > MOK.cer。注册密钥后,重新启动,在下次启动时,live 环境将成功启动。

注册 Option ROM 摘要

Option ROM (OpROM),即在启动期间执行的设备固件,必须为安全启动签名,否则设备将不会初始化。通常,OpROM 使用 Microsoft 第三方 UEFI CA 证书签名,这可能会阻止仅使用您自己的密钥实施安全启动。为了解决这个问题,可以改为注册 OpROM 的 SHA256 摘要。

警告: 通过删除 Microsoft 第三方 UEFI CA 证书来阻止基本设备初始化可能会导致某些机器(包括笔记本电脑)变砖,从而无法进入固件设置来纠正这种情况。

在具有 TPM 的系统上,可以从 TPM 事件日志 获取 Option ROM SHA256 摘要。

安装 tpm2-toolsdigest-to-efi-sig-listAUR

使用 tpm2_eventlog(1) 读取 /sys/kernel/security/tpm0/binary_bios_measurements 并查找 BOOT_SERVICES_DRIVER 的摘要。[8]

例如

# tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements
...
- EventNum: 9
  PCRIndex: 2
  EventType: EV_EFI_BOOT_SERVICES_DRIVER
  DigestCount: 1
  Digests:
  - AlgorithmId: sha256
    Digest: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
...
- EventNum: 10
  PCRIndex: 2
  EventType: EV_EFI_BOOT_SERVICES_DRIVER
  DigestCount: 1
  Digests:
  - AlgorithmId: sha256
    Digest: "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"
...

这将打印一个易于解析的摘要列表

# tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements | grep -o 'Digest: "[a-f0-9]\{64\}"' | sed 's/Digest: "//;s/"$//'

使用 digest-to-efi-sig-listAUR 为您找到的每个 OpROM 摘要创建一个 EFI 签名列表

$ digest-to-efi-sig-list 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef OpROM1.esl
$ digest-to-efi-sig-list fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210 OpROM2.esl

如果您有多个 OpROM,请将它们的 EFI 签名列表合并为一个,以便可以将其签名为单个文件

$ cat OpROM1.esl OpROM2.esl > OpROM.esl

如果您有很多摘要,可以使用像 这样的 bash 脚本

签名 EFI 签名列表以附加到签名数据库

$ sign-efi-sig-list -a -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db OpROM.esl OpROM.auth

注册它.

最后也是最危险的一步是从签名数据库中删除 Microsoft 第三方 UEFI CA 证书,并查看系统是否仍然启动并且所有设备是否仍然工作。

另请参阅