Skip to content

Instantly share code, notes, and snippets.

@duyfken
Created October 4, 2024 09:37
Show Gist options
  • Save duyfken/493bcb7177da6963cef38bf316e23efa to your computer and use it in GitHub Desktop.
Save duyfken/493bcb7177da6963cef38bf316e23efa to your computer and use it in GitHub Desktop.

Registering a FIDO2 key to unlock a LUKS2 drive & lock system on unplug

This guide is based off some articles from Fedora Magazine by Alexander Wellbrock. What you see here brings together information from multiple articles to give this one specific use-case succinctly and contiguously in one guide.

Note

While this guide is specific to Fedora and it's EL derivatives, it can easily be adjusted to other distributions by substituting commands and packages as necessary (i.e. On Debian derivatives, swap DNF for apt)

Install dependencies:

[…]$ sudo dnf install fido2-tools dracut

Plug in the FIDO2 U2F key and check that it's correctly detected:

[…]$ fido2-token -L
/dev/hidraw1: vendor=0x1050, product=0x0407 (Yubico YubiKey OTP+FIDO+CCID)

(Optional) Set a PIN for the new FIDO2 key, for added security if somebody gets physical access to it:

[…]$ fido2-token -C /dev/hidraw1
Enter current PIN for /dev/hidraw1: 
Enter new PIN for /dev/hidraw1:

Use lsblk to find your encrypted drive

[…]$ lsblk
NAME                  MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda                     8:0    1     0B  0 disk
sdb                     8:16   1     0B  0 disk
zram0                 252:0    0     8G  0 disk  [SWAP]
nvme0n1               259:0    0 476.9G  0 disk
├─nvme0n1p1           259:1    0   600M  0 part  /boot/efi
├─nvme0n1p2           259:2    0     1G  0 part  /boot
└─nvme0n1p3           259:3    0 475.4G  0 part
  └─luks-fdb98c38-... 253:0    0 475.3G  0 crypt /home
                                                 /

Find the partition number(s) hosting the luks-* partition of type crypt. In this case that'd be /dev/nvme0n1p3. Use this path as target for the following sections.

Add the fido2 dracut module to your dracut configuration.

[…]$ echo "add_dracutmodules+=\" fido2 \"" | sudo tee /etc/dracut.conf.d/fido2.conf
add_dracutmodules+=" fido2 "

Now enroll the FIDO key with your LUKS partition as an alternative decryption factor. See systemd-cryptenroll(1) for options to control features like touch or pin prompt. By default presence and pin (if you chose to set one) are requested for enrollment and use. Depending on your FIDO2 device, you may also need to press an activation button/fingerprint scanner. Repeat this command for any subsequent FIDO2 key (always have a backup key) after you have unplugged the previous key and plugged in the next one.

[…]$ sudo systemd-cryptenroll --fido2-device auto /dev/nvmen1p3

Now update /etc/crypttab and append fido2-device=auto to the appropriate line's options. A line in /etc/crypttab consists of four fields with the last one being a comma separated list. I've chosen to remove discard due to it's security implications1 but this can be overcome somewhat by first doing a random wipe of the entire storage device with a PRNG2 Stream from nwipe, DBAN or simply dd if=/dev/random of=<device>.

[…]$ sudo nano /etc/crypttab
luks-#### UUID=#### none fido2-device=auto

Finally, rebuild your initramfs using dracut. The following command will rebuild your currently-booted initramfs slot.

[…]$ sudo dracut -f

Now you can choose to leave the LUKS2 password active if you had the foresight to have a sufficently secure (long and complex, think 32+ alphanumeric characters) password. Otherwise proceed to remove the password entirely and solely use your FIDO2 keys.

[…]$ sudo systemd-cryptenroll --wipe-slot password

Personally, I also like the idea of locking the GNOME system if you have to leave on short notice and take your FIDO2 key/s with you.

Create an udev rule to catch the device detach event with a shell script. The model ID in this example might differ so please check your lsusb output to confirm it. Save the following udev rule into /etc/udev/rules.d/20-u2f.rules:

[…]$ sudo nano /etc/udev/rules.d/20-u2f.rules
ACTION=="remove", ENV{ID_BUS}=="usb", ENV{ID_MODEL_ID}=="0407", ENV{ID_VENDOR_ID}=="1050", RUN+="/usr/local/bin/lockscreen.sh"

Add the following script to the /usr/local/bin/lockscreen.sh file:

[…]$ sudo nano /usr/local/bin/lockscreen.sh
#!/bin/sh
 for bus in /run/user/*/bus; do
   uid=$(basename $(dirname $bus))
   if [ $uid -ge 1000 ]; then
     user=$(id -un $uid)
     export DBUS_SESSION_BUS_ADDRESS=unix:path=$bus
     if su -c 'dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply  /org/freedesktop/DBus org.freedesktop.DBus.ListNames' $user | grep org.gnome.ScreenSaver; then
       su -c 'dbus-send --session --type=method_call --dest=org.gnome.ScreenSaver /org/gnome/ScreenSaver org.gnome.ScreenSaver.Lock' $user
     fi
    fi
 done

Add execution permission to this script and reload udev:

[…]$ sudo chmod +x /usr/local/bin/lockscreen.sh
[…]$ sudo udevadm control -R

Reboot with your FIDO2 key plugged in and you should be in business.

Footnotes

  1. A discard request, aka "TRIM", puts part of a solid-state drive into an "unused, ready to write" state. An attacker can use this to figure out which parts of the drive are empty, something they couldn't figure out if those sections contained encrypted empty space. See here

  2. Pseudo Random Number Generators, such as the Mersenne Twister, ISAAC, XORoshiro-256 or Lagged Fibonacci.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment