FDE_Yubikey

Table of Contents

Booting an Encrypted Linux System with a YubiKey

Introduction

If your into security like I am I think you might like this. I love Full Disk Encryption (FDE) but the problem is I would always forget my passphrases or I would have to write my passphrase down. Which means, either my passphrase is compromised or all my data is lost.

After some research I found a secure solution: using a YubiKey for authentication. In this guide, I’ll walk you through how to configure a YubiKey to unlock a LUKS-encrypted Linux system, so you can boot your machine without needing to type a password.


What You’ll Need

1. A YubiKey

Any modern YubiKey that supports challenge-response mode will work. I used a YubiKey 5C NFC, but other models should be fine as well.

2. A Linux System with LUKS Encryption

I installed Ubuntu 20.04 with full-disk encryption using LUKS (Linux Unified Key Setup). You can set up encryption during installation by selecting the “Encrypt disk” option.

3. Two Required Packages

To set this up, you’ll need two software packages:

  • yubikey-personalization → Configures your YubiKey’s settings.
    • Install it from the default Ubuntu repositories:
      sudo apt install yubikey-personalization -y
      
  • yubikey-luks → Integrates YubiKey authentication with LUKS.
    • The repository version may be outdated, so install it from source as described in its README.

Step-by-Step Setup

1. Enable Challenge-Response Mode on Your YubiKey

A YubiKey has multiple slots for different security features. We’ll use slot 2 for challenge-response authentication, keeping slot 1 free for two-factor logins.

Run the following command to configure your YubiKey:

ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -ochal-btn-trig -oserial-api-visible

2. Identify a Free LUKS Slot

LUKS allows multiple authentication slots so you can have multiple ways to unlock your encrypted drive.

First, list your drives and find the encrypted partition:

lsblk

Your encrypted drive might be something like nvme0n1p3.

Then, check the available LUKS slots:

sudo cryptsetup luksDump /dev/nvme0n1p3

Look at the Keyslots section. If only slot 0 is in use, then slot 1 is available for the YubiKey.

Assign your YubiKey to an available LUKS slot:

sudo yubikey-luks-enroll -d /dev/nvme0n1p3 -s 1

This will prompt you to create a passphrase. The complexity doesn’t matter much, since it will only work when the YubiKey is present.

4. Modify crypttab and ykluks.cfg

  • Update crypttab

    • Now we need to configure the system to use the YubiKey at boot. Edit /etc/crypttab:
    sudo nano /etc/crypttab
    

    Find the line for your encrypted partition, which should look something like this:

    nvme0n1p3_crypt UUID=[your-uuid-here] none luks,discard
    

    Modify it to include the YubiKey script:

    nvme0n1p3_crypt UUID=[your-uuid-here] none luks,discard,keyscript=/usr/share/yubikey-luks/ykluks-keyscript
    
  • Update ykluks.cfg

    • Next, edit /etc/ykluks.cfg to store your passphrase securely:
    sudo vim /etc/ykluks.cfg
    

    Overwrite ykluks.cfg:

    YUBIKEY_LUKS_SLOT=2 #Set this in case the value is missing in /etc/ykluks.cfg
    
    . /etc/ykluks.cfg
    
    if [ -z "$WELCOME_TEXT" ]; then
        WELCOME_TEXT="Please insert yubikey and press enter or enter a valid    passphrase"
    fi
    
    message()
    {
        if [ -x /bin/plymouth ] && plymouth --ping; then
            plymouth message --text="$*"
        else
            echo "$@" >&2
        fi
        return 0
    }
    
    check_yubikey_present="$(ykinfo -q -"$YUBIKEY_LUKS_SLOT")"
    
    if [ -z "$YUBIKEY_CHALLENGE" ] || [ "$check_yubikey_present" != "1" ] ; then
    if [ -z "$cryptkeyscript" ]; then
        if [ -x /bin/plymouth ] && plymouth --ping; then
            cryptkeyscript="plymouth ask-for-password --prompt"
        else
            cryptkeyscript="/lib/cryptsetup/askpass"
        fi
    fi
    PW="$($cryptkeyscript "$WELCOME_TEXT")"
    else
    PW="$YUBIKEY_CHALLENGE"
    fi
    
    if [ "$check_yubikey_present" = "1" ]; then
        message "Accessing yubikey..."
        if [ "$HASH" = "1" ]; then
            PW=$(printf %s "$PW" | sha256sum | awk '{print $1}')
        fi
        R="$(printf %s "$PW" | ykchalresp -"$YUBIKEY_LUKS_SLOT" -i- 2>/dev/null || true)"
        if [ "$R" ]; then
            message "Retrieved the response from the Yubikey"
            if [ "$CONCATENATE" = "1" ]; then
                printf '%s' "$PW$R"
            else
                printf '%s' "$R"
            fi
        else
            message "Failed to retrieve the response from the Yubikey"
        fi
    else
            printf '%s' "$PW"
    fi
    
    exit 0
    

    Add the following line:

    YUBIKEY_CHALLENGE="[your-new-passphrase]"
    

5. Update Initramfs and Reboot

Finally, update the initramfs to apply the changes:

sudo update-initramfs -u

Now, reboot your machine, and it should prompt you to use the YubiKey instead of requiring a typed password!