跳到主要内容

使用 YubiKey 解密 LUKS 分区(续)

· 阅读需 5 分钟
Skyone
科技爱好者

在上一篇文章 使用 YubiKey 解密 LUKS 分区 之后我发现了两个问题:

  • 使用 Yubikey FIDO2 解密并不稳定,有时候还算要使用密码解密
  • 有时候强制使用 Yubikey 解密,不支持回退到密码解密

最近又查看了一下 ArchWiki1,最终解决了以上两个问题。写下这篇文章以作记录。

计划分盘

由于GRUB只识别基础的文件系统,解密根分区任务位于 initramfs 之中,因此内核镜像和 initramfs 不能被加密。具体步骤是:

  • UEFI 识别到 /dev/sda1 下的 /EFI/arch/grubx64.efi ,将控制权交给 grub
  • grub 根据 /dev/sda2 下的 /grub.cfg 显示引导选项,选择 arch 后使用 /dev/sda2 下的内核镜像和 initramfs 调用内核
  • initramfs 下的内核使用 initramfs 中的 /etc/crypttab 提示用户解密分区
  • initramfs 下的内核使用 /dev/mapper/system 中的 /etc/fstab 挂载分区,引导结束

本次分区假设如下2

/dev/sda1 1GB   -> /boot/efi FAT32
/dev/sda2 500MB -> /boot FAT32
/dev/sda3 other -> /dev/mapper/system btrfs
|- /
|- /@ -> /
|- /@home -> /home
|- /.snapshots

进行之前先确保已经能使用密码解密系统,具体参考使用 YubiKey 解密 LUKS 分区

配置 Yubikey

首先安装相关依赖3,然后将 Yubikey 插入电脑,检查是否出现 /dev/hidrawX 设备,完成后将 Yubikey FIDO2 插入密钥槽:

systemd-cryptenroll --fido2-device=auto /dev/sda3

可选参数:

参数说明
/dev/sda3设备路径
--fido2-device设备,可用 auto,或前面的 /dev/hidrawX
--fido2-with-client-pin默认是 yes,若为 no,从而开机时只需要触摸 YubiKey 而不需输入 PIN
--fido2-credential-algorithm算法,此处选择 eddsa

配置 crypttab

编辑 /etc/crypttab.initramfs ,systemd 会将这个文件打包到 initramfs 的 /etc/crypttab

# name  device                                     password  options
system UUID=2f9a8428-ac69-478a-88a2-4aa458565431 none fido2-device=auto,token-timeout=30

意思是:使用 FIDO2 设备将 /dev/sda3 解密到 /dev/mapper/system ,如果超过 30 秒未使用 FIDO2 设备则回退到密码解密。

配置 initramfs

BusyBox 模式下并不支持这些功能4,我们需要改用 systemd 模式。幸好这个过程并不复杂。

编辑 /etc/mkinitramfs.conf ,修改其中的 HOOKS (参考 dm-crypt/System configuration#mkinitramfs),要确保:

  • 如果包含 keymapconsolefont ,去掉,就地换成 sd-vconsole
  • 如果包含 udev ,就地换成 systemd
  • 如果包含 encrypt ,就地换成 sd-encrypt ,否则在 sd-vconsole 之后加上 sd-encrypt

重新生成 initramfs

mkinitramfs -p linux

修改内核参数

如果你之前配置过 luks 相关的内核参数,需要修改一下。

编辑 /etc/default/grub ,修改其中的 GRUB_CMDLINE_LINUX ,与 luks 相关的 cryptdevice 等参数全部删掉,因为这是用于 encrypt hook 的,而我们现在用的是 sd-encrypt hook,这个 hook 会自动识别 /etc/crypttab 中的配置(由 systemd 自动从 /etc/crypttab.initramfs 复制到 initramfs 中的 /etc/crypttab )。

只需要保留 root=/dev/mapper/system 即可。例如

GRUB_CMDLINE_LINUX="root=/dev/mapper/system rw loglevel=3 quiet"

这里的 /dev/mapper/system 不需要使用 UUID,因为这个是由我们 /etc/crypttab 中的 name 指定的,不会改变。

改完记得 grub-mkconfig -o /boot/grub/grub.cfg

Footnotes

  1. dm-crypt/System configuration - ArchWiki

  2. dm-crypt/Device encryption

  3. 安装 FIDO2 及 Yubikey 的相关依赖

  4. Linux Full Disk Encryption with Yubikey