cryptsetup - manage plain dm-crypt and LUKS encrypted volumes

Debian: Unlock LUKS root device on LVM by an USB key

Scenario

  • You want to unlock a system remotely during boot process.
  • Your root partition is a LVM volume.
  • Your LVM setup is fully encrypted with LUKS.
  • You’re running Debian on the remote system.

How To

cryptsetup - manage plain dm-crypt and LUKS encrypted volumes

If your Linux is running on a disk with LUKS encryption and you’re annoyed to enter a passphrase by keyboard to unlock your LUKS root device on every boot, this guide might be right for you.
It shows how to unlock your root devices using a keyfile from an USB drive.

NOTE: The keyfile on your USB drive is stored UNENCRYPTED. If you lose your USB key you MUST delete the corresponding slot from the LUKS device and add a new one.

The guide is tested against Debian 9.6 (Stretch) which uses cryptsetup 1.7.3.
In my setup the root device is a logical volume located on a LVM volume group.

First, install your system with Debian and run the basic configuration.
During the installation process you add a passphrase as key to your LUKS device. This passphrase is required to add further keys to the device. I recommend to keep a passphrase as fallback option if you lose your new USB key. But an existing short passphrase should be replaced by a longer passphrase later (cryptsetup luksChangeKey <your_luks_device>).

To create an USB key to unlock LUKS, attach an USB device to your system an run the commands below:

  1. Get the name of your USB device just attached and set path to LUKS device and the mapper name used
    dmesg | grep usb
    USB_DEVICE=/dev/sdb
    
    cat /etc/crypttab
    LUKS_DEVICE=/dev/sda3
    LUKS_MAPPER_NAME=sda3_crypt
  2. Format your USB device and create a filesystem on it
    # WARNING: Existing data on your USB device will be erased!!!
    fdisk ${USB_DEVICE} <<EOF
    o
    n
    p
    1
     
    +64M
    w
    EOF
    
    mkfs.ext4 ${USB_DEVICE}1
    mkdir /root/usbkey-${LUKS_MAPPER_NAME}
    mount ${USB_DEVICE}1 /root/usbkey-${LUKS_MAPPER_NAME}
  3. Generate a keyfile from random data
    dd if=/dev/urandom of=/root/usbkey-${LUKS_MAPPER_NAME}/${LUKS_MAPPER_NAME} bs=1M count=4
  4. Add the new keyfile to your device
    cryptsetup luksAddKey ${LUKS_DEVICE} /root/usbkey-${LUKS_MAPPER_NAME}/${LUKS_MAPPER_NAME}
    # -> enter your existing passphrase here
    cryptsetup luksDump ${LUKS_DEVICE}
    umount /root/usbkey-${LUKS_MAPPER_NAME}
  5. Change unlock options for your LUKS device
    blkid | grep ${USB_DEVICE}1
    sed -i "s@^\(${LUKS_MAPPER_NAME} .*\) none luks@\1 /dev/disk/by-uuid/$(blkid | grep ${USB_DEVICE}1 | cut -d'"' -f2):/${LUKS_MAPPER_NAME} luks,keyscript=/lib/cryptsetup/scripts/passdev@" /etc/crypttab
    cat /etc/crypttab
  6. Your /etc/crypttab may look like this now:
    sda3_crypt UUID=f9aefe4-13f0-1256-9309-8daeee9c127a /dev/disk/by-uuid/99821e18-abcd-de00-2156-e410836baba1:/sda3_crypt luks,keyscript=/lib/cryptsetup/scripts/passdev
    
  7. Don’t forget to update all init disks with new crypttab entry and reboot your system:
    update-initramfs -k all -u
    reboot
    

The script passdev defined by keyscript pauses the boot and waits for a device with the given UUID (first part of 3rd field from /etc/crypttab).
When the device appears, it’s temporarilly mounted and the path defined in the second part of 3rd field from /etc/crypttab is used as the keyfile to unlock the LUKS device.

Notes

After LUKS is unlocked you should remove to USB key, cause the USB key device could may be accessed during normal system runtime by processes running with higher permissions as expected.

References