Banner image of Using a YubiKey as a second factor for LUKS

The Linux Unified Key Setup (LUKS) is a platform-independent specification for hard disk encryption. In this tutorial, we use the challenge-response feature of a YubiKey to add two-factor authentication (2FA) to an existing LUKS-protected device.

Always stay in the loop!
Subscribe to our RSS/Atom feeds.

The goal of this tutorial

We add two-factor authentication to an existing LUKS-protected device. 2FA can improve its security if you set strong passwords and enter them in trustworthy environments. After the setup, an attacker needs to either insert your YubiKey and enter a password or enter a backup password.

Technically, you enter a password that is sent as a challenge to the YubiKey. The YubiKey sends a response that unlocks your LUKS-protected device.

Please note that LUKS doesn’t offer ultimate protection against every kind of attacker. An attacker could learn about the password for the YubiKey or your backup password to decrypt your hard disk. It is even possible to back up the LUKS header and the key slot areas. If an attacker gets the LUKS header and any LUKS password, the attacker can decrypt your hard disk – even if you change all of your LUKS passwords. This isn’t a limitation of the YubiKey, but a limitation of LUKS. Therefore, protect your passwords, your YubiKey, and your Linux device accordingly.

Requirements

For this tutorial, you need:

  • root access to a local Linux device that already uses LUKS-based full-disk encryption with a passphrase. Setting up LUKS is typically achieved during the initial setup of your operating system.
  • one free LUKS key slot.
  • the package “yubikey-luks 0.5.1.” This package is included in the standard repositories of Debian 10, Ubuntu (16.04 to 19.10), and Kali Linux 2019.4. For Arch, there is another tool called “yubikey-full-disk-encryption” (see our external links below) that uses a very similar setup.
  • a YubiKey with an unused second slot (or a similar security token that supports challenge-response authentication).

Step 1: Prepare everything

Step 1a: Identify your encrypted partition

For the following tutorial, identify the name of the encrypted partition. You can enter sudo fdisk -l to list all partitions. On some systems, names look like “/dev/sda3”; newer systems that use NVM Express have names similar to “/dev/nvme0n1p3.” For instance, the output of sudo fdisk -l shows “Disk /dev/mapper/nvme0n1p3_crypt.” Then, the partition name is likely “/dev/nvme0n1p3.”

Step 1b: Identify a free LUKS key slot

LUKS offers 8 key slots, allowing you to set up 8 different passwords (or keys in files).

Enter sudo cryptsetup luksDump /dev/[partition] (change the partition name according to step 1a). The output lists all 8 key slots. Key slots are either in use (ENABLED) or free (DISABLED). Note down one of the free key slot numbers for your YubiKey.

Step 1c: Generate a new, strong challenge password

Additionally, you need a new password for the YubiKey. This password is technically a challenge sent to the YubiKey. The YubiKey answers with a response that is used to decrypt your hard disk. In the following, we name it the challenge password. Use a strong password.

Besides, there is still your previous password. Your old LUKS password is used for emergency access (e.g., after losing your YubiKey). Of course, this should also be a strong password, so an attacker can’t use brute force to guess it. We name your old password backup password in the following steps.

Step 2: Install the necessary packages

Enter sudo apt update && sudo apt install yubikey-luks to refresh your local package list, and to install yubikey-luks and yubikey-personalization.

Step 3: Configure your YubiKey

After installing the necessary packages, you need to configure your YubiKey.

Warning
Make sure that you don't use the second slot of your YubiKey at the moment (e.g., for KeePass). The following command overwrites the second slot of your YubiKey.

Enter ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible. The single options of this command are:

  • -2: Use the second slot of the YubiKey. Alternatively, you can enter -1 to use the first slot that is typically preconfigured for Yubico OTP.
  • -ochal-resp: Set the ticket flag CHAL_RESP.
  • -ochal-hmac: Set the configuration flag CHAL_HMAC.
  • -ohmac-lt64: Set the configuration flag HMAC_LT64.
  • -oserial-api-visible: Set the extended flag SERIAL_API_VISIBLE.

After entering this command, you see the “Configuration data to be written to key configuration 2” on screen.

Check the output and press y to write the configuration to slot 2 of your YubiKey.

Step 4: Customize the configuration file of yubikey-luks

Enter sudo nano /etc/ykluks.cfg to see the configuration of yubikey-luks.

In the file, you can set three different values:

  • WELCOME_TEXT=: This is the text visible on the screen when you have to insert your YubiKey and provide your challenge password (or backup password). It is only useful for humans.
  • CONCATENATE=: This option changes the key written to the LUKS key slot.
    • 0 (default): If you set it to 0, only the response of the YubiKey is written to the LUKS key slot. For instance, “0123456789ABCDEF.”
    • 1: If you set it to 1, your challenge password + the YubiKey response are written to the LUKS key slot. For instance, “challengepassword0123456789ABCDEF.”
  • HASH=: This option changes whether your cleartext password or its hash value is used as a challenge for the YubiKey.
    • 0 (default): The challenge is your challenge password in cleartext.
    • 1: The challenge is the hash value (SHA-256) of your challenge password.

Change values if needed, and save the file.

Step 5: Write your configuration to a free LUKS key slot, and set your passwords

In step 1b, you identified a free LUKS key slot. To write your configuration to the LUKS key slot, enter sudo yubikey-luks-enroll -d /dev/[partition] -s [free-key-slot]. The single options of this command are:

  • -d /dev/[partition]: Use the specified partition.
  • -s [free-key-slot]: Use the specified LUKS key slot on the specified partition.

For instance, LUKS key slot 6 is free and our LUKS partition is /dev/nvme0n1p3, then the full command is sudo yubikey-luks-enroll -d /dev/nvme0n1p3 -s 6.

After entering the command, the tool needs two passwords:

  1. Enter your challenge password twice. The challenge password is the challenge sent to your YubiKey each time.
  2. Finally, enter an existing LUKS password once. Typically, this is your previously-used LUKS passphrase (the backup password).

If you want to reconfigure a key slot that is already in use, append the option -c: sudo yubikey-luks-enroll -d /dev/nvme0n1p3 -s 6 -c. This command clears the LUKS key slot before setting up the new YubiKey configuration. It asks, “Enter any remaining LUKS passphrase.” Just enter your previously-used LUKS passphrase (the backup password).

Step 6: Modify your /etc/crypttab file to use the YubiKey

We need to modify the crypttab file. Enter sudo nano /etc/crypttab, and add keyscript=/usr/share/yubikey-luks/ykluks-keyscript as described below.

Look for a line similar to:

1
cryptroot /dev/[partition] … luks,…

Change it to:

1
cryptroot /dev/[partition] … luks,keyscript=/usr/share/yubikey-luks/ykluks-keyscript…

Afterward, save the file and close your editor. Then, enter update-initramfs -u. The output is similar to “update-initramfs: Generating /boot/initrd.img-5.3.0-kali3-amd64.” You can ignore any warnings. They are also shown during regular kernel updates.

Step 7: Reboot your device and test your passwords

Finally, reboot your system. Your screen should look similar to the following screenshot:

An image showing the prompt to connect your YubiKey and enter your passphrase.
If you configured everything correctly, your system asks for your YubiKey and the passphrase to get the response that logs you in. (🔍 Zoom in)

You should be able to either:

  • enter any passphrase that already existed before you configured your YubiKey (e.g., your backup password), or
  • enter your challenge password to get a response from the connected YubiKey.

Try all possibilities to ensure that everything works as expected.

Optional step 1: Enable and start the module yubikey-luks-suspend

Additionally, you can enable and start “yubikey-luks-suspend.” It automatically locks your LUKS partitions and wipes keys from memory on suspend. If you want this, enter sudo systemctl enable yubikey-luks-suspend and sudo systemctl start yubikey-luks-suspend.

Optional step 2: Set or modify other LUKS keys

Optionally, you can add, modify, or remove other LUKS keys.

Add a LUKS key

Enter sudo cryptsetup luksAddKey /dev/[partition] -s [free-key-slot]. The tool needs a current LUKS key, and sets another LUKS key.

Modify a LUKS key

Enter sudo cryptsetup luksChangeKey /dev/[partition] -s [key-slot-in-use]. You will be asked for the old and a new passphrase.

Remove a LUKS key

There are three different ways to achieve this:

  • sudo cryptsetup luksRemoveKey /dev/[partition]: This command asks for a passphrase to be removed. If you set the same passphrase multiple times, it only removes the first appearance. Repeating the same command removes the next appearance.
  • sudo cryptsetup luksKillSlot /dev/[partition] [key-slot-in-use]: This command removes the specified key slot.
Warning
There is also the command 'luksErase.' This command immediately wipes all key slots. You won't be able to decrypt your partition afterward. Decrypting is only possible if you have a previous backup of your LUKS header. Therefore, 'luksErase' is only useful in unusual situations. 😉

For more commands, enter man cryptsetup on your device.

Follow us on Mastodon:
@infosechandbook

Summary

By implementing this tutorial, LUKS encrypted partitions are protected using two-factor authentication (you own the YubiKey and know the challenge password). Keep in mind that your other LUKS keys must also be strong to protect your system, and understand the above-mentioned limitations of LUKS.

We successfully tested this tutorial on Kali Linux 2019.4.

Read also