Prerequisites

  1. Make sure you have LUKS2
  2. A FIDO2 compatible security key like the Yubikey 5
  3. Install libfido2 and dracut or mkinitcpio

Adding A Security Key

  1. Check your security key is present

    sudo systemd-cryptenroll --fido2-device=list

  2. If the security key is detected, you should see the device info similar to the following:

    PATH         MANUFACTURER PRODUCT              
    /dev/hidraw4 Yubico       YubiKey OTP+FIDO+CCID
    
  3. Actually adding the security key to LUKS

    sudo systemd-cryptenroll /dev/name --fido2-device=auto --fido2-with-client-pin=yes

    It’s going to ask for your PIN, after you entered the correct PIN, it’s going to ask you to tap the security key twice.

  4. Checking the security key is added

    • Check with luksDump

      sudo cryptsetup luksDump /dev/sdXn

      You should an addtional keyslot used, as well as “systemd-fido2” listed under “Token”

    • Use systemd-cryptsetup to test if the security key works

      sudo /usr/lib/systemd/systemd-cryptsetup attach mytest /dev/sdXn - fido2-device=auto

Adding LUKS Parameters to Kernel Flags or crypttab

Personally, I only use kernel flags for LUKS options for simplicity sake, one less config file to manage compared to using crypttab.

  • To use kernel flags, add rd.luks.options=fido2-device=auto. Here is my exmaple with btrfs and LUKS on systemd-boot:

    options  rd.luks.name=<UUID>=cryptroot root=/dev/mapper/mytest rootflags=subvol=@ rd.luks.options=fido2-device=auto,token-timeout=0s
    
  • To use crypttab, add the following to the /etc/crypttab mytest /dev/sdXn - fido2-device=auto

Configuring initramfs Generator

mkinitcpio

  1. Edit /etc/mkinitcpio/, and add systemd keyboard sd-vconsole and sd-encrypt in the HOOKS section in the following order
HOOKS=(base systemd autodetect modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)
  1. Rebuild initramfs images for all kernels sudo mkinitcpio -P

  2. Check files are added

    lsinitcpio /boot/initramfs-linux-zen.img | grep fido2

    You should see the same output below

    usr/lib/cryptsetup/libcryptsetup-token-systemd-fido2.so
    usr/lib/libfido2.so
    usr/lib/libfido2.so.1
    usr/lib/libfido2.so.1.13.0
    

dracut

dracut does grep on /etc/crypttab, and adds FIDO2 support only when fido2 is found in the file. If you use crypttab with dracut, just add add the kernel flags mentioned above. If you don’t want to use /etc/crypttab like me, you need to explicitly add the fido2 module to dracut.

  1. Add the fido2 module to your dracut config file

     add_dracutmodules+=" systemd btrfs fido2 "
    
  2. Regenerate initramfs image with dracut

  3. Check files are successfully added to initramfs lsinitcpio /boot/path-to-your-dracut-initramfs | grep fido2 You should see the same output below

    usr/lib/cryptsetup/libcryptsetup-token-systemd-fido2.so
    usr/lib/libfido2.so.1
    usr/lib/libfido2.so.1.13.0
    

https://0pointer.net/blog/unlocking-luks2-volumes-with-tpm2-fido2-pkcs11-security-hardware-on-systemd-248.html

https://man.archlinux.org/man/crypttab.5.en

https://man.archlinux.org/man/systemd-cryptenroll.1.en

https://man.archlinux.org/man/dracut.conf.5.en

https://github.com/dracutdevs/dracut/blob/master/modules.d/90crypt/module-setup.sh