已经是 2022 年的尾巴了,这里默认主板是 UEFI 而不是 Legacy BIOS 了。

如今的笔记本和台式机主板一般都有 TPM,而且一般都是 TPM 2.0。使用 TPM2 自动解密, 意味着只要相关的 bios 设置、启动参数没有改变,系统在启动的时候就会自动解锁加密的文件系统, 不需要输入密码。

从 systemd 版本 251 开始,增加了额外输入 PIN 码再解锁的功能。 如果需要更安全的保护你的数据,请使用 --tpm2-with-pin=yes 选项启用 PIN 码。

但是 TPM2 自动解密并不意味着就没有意义了。使用 systemd 和 TPM2 自动解密依然可以保护你的数据。 比如以下应用场景:

  • 把设备送修的时候只需要清除加密分区储存 TPM 密钥的 slot, 就可以取消自动解密。取回设备之后可以用主密钥解锁系统和数据,重新配置自动解锁。 整个过程不需要格式化硬盘,可以节省很多时间。
  • 把硬盘拿去卖二手的时候清除掉分区头部储存的密钥,然后取出来就可以了,不用担心会被买家解密。
  • 系统安装在移动硬盘上,只有用特定主板启动才自动解锁。

此外,我还发现不使用 TPM2 的话,开机解密需要更长的时间,暂时还没有头绪。 所以,有一定安全要求的情况下,配置 TPM2 + PIN 是比较合适的。

LUKS 加密#

Fedora 等其他常见 Linux 发行版默认使用的是 grub2,而 Arch 应该是没有默认的启动引导程序。 不过 Arch 安装 ISO 自带的 archinstall 安装脚本默认使用 systemd-boot 作为引导程序。 对我来说,systemd-boot 配置 kernel command line 更方便一些,安装维护也更接单一些。 所以我使用 systemd-boot 作为启动引导程序很有一段时间了。

配置 TPM2 自动解锁需要系统已经安装在 LUKS 加密的分区上。 如果不是,可以先备份一下系统到其他分区或硬盘,等配置好 LUKS 加密再恢复备份。 一般直接 dd 整个分区就可以了。如果分区比较大,可以用 GParted 先 resize 一下分区。 如果有很多不需要备份的文件,比如 btrfs 的 snapshot、pacman 的 cache 之类的。 因为是系统分区,所以这些操作都需要从 Live CD 进行。 因为 Arch Linux 没有带 GUI 的 Live CD,我一般使用 EndeavourOS 的 LiveCD 进行这些操作。 因为 EndeavourOS 是基于 Arch 的发行版。而且基于 Vanilla Arch 的改动很小。 从而保证在 EndeavourOS 下大部分操作的结果和在 Vanilla Arch 下的操作结果一致。

这里不展开讨论如何对分区进行 LUKS 加密。

安装依赖#

1
# pacman -Syu tpm2-tools tpm2-abrmd tpm2-tss

配置 initramfs generator#

Arch Linux 默认使用 mkinitcpio。EndeavourOS 从 Cassini (2022-12-19)开始默认使用 Dracut。

Arch w/ mkinitcpio#

配置 mkinitcpio#

需要配置 systemd-boot 使用 systemd 的 kernel hook 进行解密。 编辑 /etc/mkinitcpio.conf 文件,修改 HOOKS变量,添加 systemdkeyboardsd-vconsolesd-encryptlvm2

1
HOOKS=(base systemd autodetect modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)

配置 crypttab#

编辑 /etc/crypttab.initramfs 文件。

1
2
# <name>    <device>            <password>    <options>
root        UUID=<UUID>    -             tpm2-device=auto

重新生成 initramfs#

1
# mkinitcpio -P

配置 systemd-boot#

systemd-boot 的引导入口可以直接在 /boot/loader/entries 里添加。 这里用我最常用的 zen-kernel 入口文件举例。 编辑 /boot/loader/entries/arch-zen.conf 文件。

1
2
# ...
options rd.luks.name=<UUID>=root root=/dev/mapper/root # ...

EndeavourOS w/ dracut#

只考虑 EndeavourOS。Vanilla Arch 没有一键生成 initramfs,kernel,boot entry 的脚本。

配置加密方式#

EndeavourOS 默认用的 luks1 加密,不能使用 TPM2。TPM2 需要使用 luks2。 系统安装完成之后需要转换一下加密方式。

1
# cryptsetup convert --type luks2 /dev/sdxY

配置 dracut#

编辑 /etc/dracut.conf.d/tpm2.conf

1
add_dracutmodules+=" tpm2-tss "

配置内核参数#

编辑 /etc/kernel/cmdline

1
nvme_load=YES rw rootflags=subvol=/@ rd.luks.uuid=<UUID> rd.luks.options=<UUID>=tpm2-device=auto root=/dev/mapper/luks-<UUID> rw

配置 crypttab#

注释掉 /etc/crypttab 里系统分区的配置。

1
2
3
# ...
# <name>               <device>                         <password> <options>
# luks-<UUID> UUID=<UUID>     /crypto_keyfile.bin luks

重新生成 initramfs#

1
# reinstall-kernels

Enroll LUKS 密钥到 TPM 里#

检查系统内是否有 TPM2 设备

1
$ systemd-cryptenroll --tpm2-device=list

如果只有一个 TPM2 设备,可以运行下面的脚本自动进行 Enroll。

1
# systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/sdX

如果有多个 TPM2 设备,需要指定使用的设备。

1
# systemd-cryptenroll --tpm2-device=/path/to/tpm2_device --tpm2-pcrs=0+7 /dev/sdX

重启系统#

完成配置之后重启系统就可以啦。

1
# reboot

如果需要取消自动解锁#

运行下面的代码可以删除所有添加的 TPM 密钥

1
# systemd-cryptenroll /dev/sdX --wipe-slot=tpm2

参考文献: