3221 字
16 分钟
Arch Linux 启用 Secure Boot
NOTE

文章还有点缺陷,需要补充,会持续更新 | 最后更新时间:2025-3-12

前言#

上个学期不愿意每次背着几十斤重的游戏本和砖头一样大的电源去图书馆,于是在某二手平台买了Surface Pro 4并安装了Arch Linux。为了使用Surface的硬件功能,将内核更换为linux-surface内核。触摸屏、蓝牙模块等硬件正常工作,非常完美。现在又想折腾为Arch启用安全引导,本着Arch用户一切从简的原则,需要参考Arch Wiki手动配置(笑)。

如果是别的发行版就不用像arch这么折腾,比如Fedora、Debian、Ubuntu 还有 openSUSE等,安装系统及内核之后直接安装 linux-surface 提供的 linux-surface-secureboot-mok 软件包即可。它会将公钥直接导入引导加载程序,从而在不禁用安全启动的情况下引导内核启动系统。但是Arch和基于Arch的其他发行版与它们相比显得与众不同,Arch Linux的安装文件中包含了未签署的EFI二进制文件使得无法启用安全引导,需要手动签名引导程序和内核。好了废话就说到这里,正题开始~

WARNING

提示:本文只是整理知识和记录操作,设置安全启动之前建议备份有关的EFI文件以及UEFI配置,错误地配置证书可能会导致电脑无法正常开机,甚至无法进入UEFI。如果你想启用安全启动请参考Arch Wiki 以及 linux-surface wiki

我用的是GRUB引导,如果是别的引导程序实现方式可能会有所不同。

安全启动 (Secure Boot)#

Secure Boot是 UEFI(统一可扩展固件接口)的一项功能。Secure Boot在加载EFI二进制文件之前会校验签名和校验和 验证二进制文件是否受信任,并阻止加载未受信任的EFI二进制文件。确保只有经过验证的程序被加载,可以阻止类似于Rootkit之类的恶意攻击,以提高安全性。

现在绝大多数x86整机电脑在出厂时预装OEM和微软提供的公钥,默认开启安全启动。意味着系统固件只信任由OEM和微软签名的二进制文件,不会运行未签名的二进制文件。但微软并没有把这一条路彻底封死,除了微软官方的CA证书(公钥)提供验证外,用户还可以将第三方CA证书导入固件系统。甚至可以清除固件上预装的证书换成用户自己签名的证书进行安全认证。

现在大多数GNU/Linux发行版支持安全启动,除了个例发行版。说的就是你Arch Linux

根据维基百科援引的信息,微软自2014年开始禁止用户在搭载Windows的ARM设备上修改或禁用Secure Boot。无法安装其他操作系统。(我没有ARM架构的电脑,不知道微软现在有没有解除限制)

Secure Boot 密钥验证#

Secure Boot验证会使用设备存储的证书(公钥)验证EFI二进制文件,EFI二进制文件则需要对应的私钥签名才能通过验证。

Secure Boot验证需要用到多种密钥和数据库,包括平台密钥(PK)、密钥交换密钥(KEK)、签名数据库(db)以及禁用签名数据库(dbx)。

Secure Boot 验证所需要的密钥以UEFI安全变量的形式存储在NVRAM(非易失性存储器)中,其中包括

  • 平台密钥(Plantform Key) PK密钥由OEM提供,作为平台根节点证书,用于签名验证/吊销KEK密钥,每台机器只有一份PK密钥。
  • 密钥交换密钥(Key Exchange Key) KEK密钥用于更新签名数据库和禁用签名数据库,可以保护数据库免受未经允许的修改。一台机器可以存储多个KEK密钥或者是有效签名二进制文件。由微软、硬件厂商、Linux基金会或开源社区还有企业管理部门提供。

密钥间的信任链:

PK(根证书)

├── KEK1(微软)
│   ├── db更新权限
│   └── dbx更新权限

├── KEK2(硬件厂商)
│   ├── 添加设备专用驱动证书到db
│   └── 吊销固件漏洞哈希到dbx

└── KEK3(企业CA)
    └── 部署内部开发的UEFI应用证书

UEFI Specification Release 2.11 第 32.4 章节中规定了验证EFI文件所需的公钥必须存储在NVRAM中,NVRAM具有防篡改和防删除的特性

数据库则包括

  • 签名数据库 (The Signature Database)(db) 签名数据库中存储了已验证证书以及对应的Hash,在安全模式下引导系统内核前将EFI文件的私钥与数据库中已存储的公钥进行比对,如果EFI文件没有私钥则验证Hash,如果被验证的EFI文件满足下列条件之一:
    1. 文件未签名,但是其Hash与数据库中存储的Hash一致
    2. 文件已签名,签名本身在存储库中
    3. 文件已签名,用于签名的密钥存储在数据库中(且签名有效)

则认为该EFI文件签名有效是可信任的

  • 禁用签名数据库(The Forbidden Signatures Database) 禁用签名数据库中存储了被禁止验证的证书以及对应的Hash,如果被验证的EFI文件满足下列条件之一:
    1. 文件未签名,但是其Hash与数据库中存储的Hash一致
    2. 文件已签名,签名与数据库中存储的签名匹配
    3. 文件已签名,用于签名的密钥与数据库中的密钥匹配

则认为该EFI文件是不可信的,禁止执行该 EFI 二进制文件

NOTE:安全模式会直接禁止执行未签名的 EFI 二进制文件,向 dbx 中添加未签名二进制文件的 Hash 是为了防止曾经被允许执行的未签名的二进制文件重新获得授权

UEFI Secure Boot Modes#

UEFI Secure Boot Modes 分为 设置模式、用户模式、审计模式和部署模式。

设置模式:当未设置 PK 证书或清除 PK 证书会进入设置模式。在该模式下用户可以自由更改 PK、KEK、db、dbx。一旦设置 PK,UEFI 在下一次启动时自动从设置模式切换为用户模式。

用户模式:设置PK证书后,UEFI会进入用户模式。在该模式下,修改PK、KEK、db、dbx则需要更高一级别的密钥签署更新(比如sign-EFI-sig-list)。用户模式是UEFI的默认模式。

审计模式:审计模式实际上就是调试模式,用于验证安全启动配置,并记录有关检查结果以及调试信息,本质上还是用户模式。

部署模式:部署模式则是最安全的模式,用户模式和审计模式支持未经认证切换至部署模式,但要从部署模式切换至其他模式则需要使用特定于平台的安全方法或者清除PK。

启用Secure Boot的方式#

根据Arch Wiki的介绍,启用 Secure Boot 可以通过以下方法:

  1. 使用自己设置的密钥和证书 在设备上安装由自己生成 PK,KEK 证书,并用生成的 db 密钥对 EFI 二进制文件签名。
WARNING

警告:千万千万要备份原先的EFI变量,以免设置出错及时恢复 使用自己的密钥和证书可能会瘫痪设备上的硬件,甚至无达进入UEFI/BIOS恢复,只能通过重刷UEFI/BIOS救回!因为某些硬件的固件使用微软的密钥进行签署。

有大佬折腾过这样的方法实现安全引导,这是她的博客,感兴趣的话可以看看。 2. 使用微软预签名的签名引导加载程序 这是实现安全引导最简单的方式,也是现在各 GNU/Linux 发行版启用安全引导的主要实现方式。主要使用的签名引导加载程序有 PreLoader 和 Shim。它们都有微软提供的签名和内置的第三方 CA 证书,它们的作用是不改变设备CA的情况下让用户安装自己的证书加载由用户签名的EFI二进制文件。

微软为 Linux 平台签名所使用的证书为 Microsoft Corporation UEFI CA 2011

Shim使用机器所有者密钥 MOK(Machine Owner Key)和机器所有者密钥列表 MOKlist 对用户导入的EFI二进制文件进行签名验证。MOKList的功能与db库相同,会比较EFI二进制文件私钥签名和Hash。只有EFI二进制文件拥有 MOKlist 中所对应公钥的私钥签名或Hash存在 MOKlist 中,引导程序才会加载这个EFI二进制文件,否则同样会禁止加载该文件。

我使用的方案则是第二种,即通过签名引导加载程序导入创建的MOK证书启用安全引导。

启用安全引导#

安装#

参考Arch Wiki,需要安装 shim-signed、sbsigntools 包。前者是 shim ,后者用于签名和管理 MOK 证书。其中 shim-signed 在 AUR 仓库中,使用 AUR 助手安装。

安装 Shim#

将 Shim 和 MokManager 复制到ESP引导分区中

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

接着创建新的引导项引导 BOOTx64.EFI

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

GRUB模块嵌入grubx64.efi#

GRUB不允许在Secure Boot开启时加载文件系统上的任何模块,所以需要把所有用到的模块嵌入grubx64.efi中。如果GRUB从shim中启动,还需要SBAT文件包含在EFI二进制文件中

定义 GRUB_MODULES 环境变量并将GRUB所需的模块添加进去,Arch Wiki提供了模块列表,一般只需要基础模块,其他模块按需添加。

GRUB安装后会提供一个sbat.csv文件,在/usr/share/grub/sbat.csv

然后重新安装GRUB,执行以下命令

grub-install --target=x86_64-efi --efi-directory=esp --modules=${GRUB_MODULES} --sbat /usr/share/grub/sbat.csv

生成MOK证书#

建议将MOK证书和私钥存放至同一个文件夹中,然后切至该文件夹

mkdir -p /path/to/file/
cd /path/to/file/

在该文件夹下生成MOK证书和私钥

openssl req -newkey rsa:4096 -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

现在文件夹里应该有以下文件

  • MOK.key:PEM格式的私有密钥,用于签署EFI二进制文件
  • MOK.crt:PEM格式的证书,用于sbsign
  • MOK.cer:DER格式的证书,用于MokManager

之后签署你的引导加载程序(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

每当内核和引导加载程序更新必须重新签署,可以构建pacman钩子执行自动化签署,这是一个示例,详见Arch Wiki

[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = linux
Target = linux-lts
Target = linux-hardened
Target = linux-zen

[Action]
Description = Signing kernel with Machine Owner Key for Secure Boot
When = PostTransaction
Exec = /usr/bin/find /boot/ -maxdepth 1 -name 'vmlinuz-*' -exec /usr/bin/sh -c 'if ! /usr/bin/sbverify --list {} 2>/dev/null | /usr/bin/grep -q "signature certificates"; then /usr/bin/sbsign --key MOK.key --cert MOK.crt --output {} {}; fi' ;
Depends = sbsigntools
Depends = findutils
Depends = grep

最后复制MOK.cer到一个FAT格式的文件系统(比如esp分区)

启用 Secure Boot#

重新启动并启用安全启动,MokManager会被唤起(如下图),选择 Enroll key from disk 选项,找到 MOK.cer 并添加进 Moklist,输入你创建密钥时设置的密码,Continue Boot后不出意外可以正常启动系统了。

实拍,不是网图

linux-surface MOK#

在linux-surface的wiki中,官方提供了预签名的MOK密钥。在设置Shim之后直接导入该密钥应该可以正常使用。但我并不是很了解,建议直接阅读wiki原文

结语#

写这篇文章时查阅了不少资料和大佬们有关 Secure Boot 的文章,设置 Secure Boot 一步一步照着 Arch Wiki 操作并没有多难,但是想要了解其背后的机制却废了不少精力。在查找资料的过程中自己学到了很多,在此感谢各位前辈付出的努力!如果没有你们的实践经验和文章总结恐怕我这个泛泛之辈无法轻易地获取关于 Secure Boot 知识,也更难写出一篇文章总结了。文章肯定有不足之处,欢迎前辈们批评指错,本人虚心接受指教。

参考资料#

Unified Extensible Firmware interface (UEFI) Specification Release 2.11 (2024)

UEFI SECURE BOOT IN MODERN COMPUTER SECURITY SOLUTIONS (2019)

Secure boot - Microsoft Learn

SecureBoot - Debian Wiki

UEFI/安全启动 - Arch Linux 中文维基

实施 Secure Boot - Cascade

Managing EFI Boot Loaders for Linux: Dealing with Secure Boot - Rod Smith

The Meaning of all the UEFI Keys - James Bottomley

Arch Linux 启用 Secure Boot
https://yuuko.qzz.io/posts/为-arch-linux-开启-secure-boot/
作者
Yuuko
发布于
2025-03-12
许可协议
CC BY-NC-SA 4.0

🚧评论系统正在测试,所以出现蜜汁bug是正常的啦 (。・∀・)ノ゙ 如果评论加载异常试试F5大法~