在Manjaro Linux上启用SecureBoot

什么是安全引导(SecureBoot)?

Secure Boot 是一项用于提高计算机启动安全性的技术。它的主要作用是在计算机启动过程中验证引导加载程序和操作系统内核的安全性和完整性。

Secure Boot 的工作原理是:

  1. 在 UEFI 固件中内置一个可信的公钥,用于验证引导加载程序和操作系统内核的数字签名。这些组件在发布前都要使用该公钥对应的私钥进行签名。

  2. 当计算机启动时,固件会检查引导加载程序的签名。如果签名有效,则加载引导加载程序并执行。如果签名无效,则停止启动过程。

  3. 引导加载程序再检查操作系统内核的签名。如果签名有效,则加载内核并启动操作系统。

  4. 整个启动过程中,任何一个组件的签名验证失败,都会停止启动,从而防止潜在的恶意软件入侵。

启用 Secure Boot 可以防止 rootkit 和 bootkit 等病毒的感染。它是 UEFI 固件的一个重要安全功能,现代个人计算机和服务器广泛采用。但也存在可能限制操作系统选择、增加软件兼容性问题等缺点。

启用SecureBoot过程

Manjaro Linux 系统启用 Secure Boot 的过程包括:

  • 系统引导程序需要获得 Microsoft 的签名密钥才能让操作系统内核通过 Secure Boot 验证,但这是不可能的,因为微软不会这么做。因此替代方案是自行生成MOK密钥(Machine Owner Key)并替换 UEFI 固件的默认密钥;
  • 按照GRUB的官方文档重新生成并安装GRUB,这一步坑比较多;
  • 使用MOK密钥对引导程序进行签名。

MOK密钥生成和导入

在开始之前,先重启系统进入BIOS设置界面,设置SecureBoot进入Setup Mode(不同的机器可能操作不一样)。

设置完成后重启进入系统,安装以下软件:

  • sbctl:Secure Boot key manager,这个工具使得密钥的生成和写入变得非常简单,它还拥有引导程序签名、pacman hook等功能。
1
yay -S sbctl

查看SecureBoot状态:

1
sudo sbctl status

应该看到 sbctl 工具未安装并且SecureBoot已禁用。

生成MOK密钥:

1
sudo sbctl create-keys

这将在默认位置生成MOK密钥。

将MOK密钥连带Microsoft密钥一起导入UEFI固件中:

1
sudo sbctl enroll-keys -m

注意:如果不附带“-m”选项,将会导致Mincrosoft密钥丢失,使Windows无法启动,而且某些固件会使用 Microsoft 密钥进行签名和验证,不验证设备可能会使它们变砖。

再次检查SecureBoot状态,此时sbctl会显示已安装。

1
sudo sbctl status

重新构建GRUB

要使GRUB能在SecureBoot模式下启动,GRUB必须集成运行过程中所需的所有模块,可以参考ubuntu的grub生成脚本来选择所需要的模块。然后,将这些模块记录成环境变量使用。

新建\etc\grub_modules文件:

1
sudo touch /etc/grub_modules

打开文件,加入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
CD_MODULES="
all_video
boot
btrfs
cat
chain
configfile
echo
efifwsetup
efinet
ext2
fat
font
gettext
gfxmenu
gfxterm
gfxterm_background
gzio
halt
help
hfsplus
iso9660
jpeg
keystatus
loadenv
loopback
linux
ls
lsefi
lsefimmap
lsefisystab
lssal
memdisk
minicmd
normal
ntfs
part_apple
part_msdos
part_gpt
password_pbkdf2
png
probe
reboot
regexp
search
search_fs_uuid
search_fs_file
search_label
sleep
smbios
squash4
test
true
video
xfs
zfs
zfscrypt
zfsinfo
cpuid
play
tpm
"
GRUB_MODULES="$CD_MODULES
cryptodisk
gcry_arcfour
gcry_blowfish
gcry_camellia
gcry_cast5
gcry_crc
gcry_des
gcry_dsa
gcry_idea
gcry_md4
gcry_md5
gcry_rfc2268
gcry_rijndael
gcry_rmd160
gcry_rsa
gcry_seed
gcry_serpent
gcry_sha1
gcry_sha256
gcry_sha512
gcry_tiger
gcry_twofish
gcry_whirlpool
luks
lvm
mdraid09
mdraid1x
raid5rec
raid6rec
"

或者,通过已有的grub.cfg文件寻找所需的模块:

1
sudo cat /boot/grub/grub.cfg | awk '/insmod/ { print $2 }' | sort | uniq

保存文件并source:

1
source /etc/grub_modules

重新构建安装GRUB到ESP分区:

1
sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --modules="${GRUB_MODULES}" --sbat /usr/share/grub/sbat.csv --disable-shim-lock

target选项指明系统架构,efi-directory指明ESP分区挂载的位置,sbat是SecureBoot过程中GRUB需要的小节,disable-shim-lock选项解决了shim_lock protocol not found错误。

重新生成grub.cfg:

1
sudo grub-mkconfig -o /boot/grub/grub.cfg

对引导程序进行签名

1
sudo sbctl sign -s /boot/efi/EFI/Manjaro/grubx64.efi

重新检查efi文件签名情况:

1
sudo sbctl verify

除windows相关的引导文件外,其他efi都应该进行签名,例如黑苹果引导OpenCore文件的签名:

1
2
3
4
5
6
7
8
sudo -i
sbctl sign -s /boot/efi/EFI/OC/OpenCore.efi #假设esp挂载点为/boot/efi/
for file in /boot/efi/EFI/OC/Drivers/*; do
sbctl sign -s $file;
done
for file in /boot/efi/EFI/OC/Tools/*; do
sbctl sign -s $file;
done

测试

签名完成后,进入BIOS将SecureBoot设为启用状态。

重启进入系统,检查SecureBoot状态:

1
sudo sbctl status

正常应该如下所示:

1
2
3
4
5
Installed:      ✓ sbctl is installed
Owner GUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Setup Mode: ✓ Disabled
Secure Boot: ✓ Enabled
Vendor Keys: microsoft

然后,测试其他系统是否能够启动成功。

至此,SecureBoot启用完成。