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. This 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 in the future. It is even possible to backup the LUKS header and the key slot areas. If an attacker is able to do so and learns about any password, the attacker can decrypt your hard disk in the future – even if you change all of your passwords for it. 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. This 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; on newer system that use NVM Express, names are 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 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 will overwrite it.

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 will be the text visible on 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 will be written to the LUKS key slot. For instance, “0123456789ABCDEF”.
    • 1: If you set it to 1, your challenge password + the YubiKey response will be written to the LUKS key slot. For instance, “challengepassword0123456789ABCDEF”.
  • HASH=: This option changes whether your cleartext password or its hash value will be used as a challenge for the YubiKey.
    • 0 (default): The challenge is your challenge password in cleartext.
    • 1: The challenge is the hash value of your challenge password (SHA-256 is used).

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, you will be asked for two different passwords:

  1. Enter your challenge password twice. This 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 prior to setting up the new YubiKey configuration. It will ask for “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…

Afterwards, 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 normal 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, you will be asked 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]. You will be asked for a passphrase. This will be the 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 will only remove the first appearance. Repeating the same command, will remove 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 afterwards. Decrypting is only possible if you have a previous backup of your LUKS header. Therefore, 'luksErase' is only useful in special situations. 😉

For more commands, enter man cryptsetup on your device.

Follow us on Mastodon:
@infosechandbook

Summary

Using this setup, 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 in order to protect your system, and understand the above mentioned limitations of LUKS.

We successfully tested this tutorial on Kali Linux 2019.4.

Read also