Matthew Johnson

Page Body


Passwordless Encrypted Root in Debian

If, like me, you wanted both an encrypted root filesystem and some form of bootsplash you may have discovered that this is tricky. You need to enter the decryption passphrase on the terminal which means exiting the bootsplash.

I decided it must be possible to use a USB token with the key on it rather than a passphrase to decrypt the drive and while this seems supported upstream, it is not supported out of the box on Debian. This is a short howto explaining my solution.

Pre-requisites

You will need a USB hard disk and a computer using Debian with an encrypted root filesystem. I am assuming that you are using a stock kernel with an initramfs image and have a luks encrypted LVM containing the root filesystem. You will have to change some of the details below to match your specific system.

In the examples below /dev/hda5 is the encrypted partition and /dev/sda2 is the partition on the USB disk holding the key.

Setting up the key

First we need to generate a random key and put it on the disk. To save having to mount things in the initramfs, I chose to use a partition at the end of the USB flash disk. This means repartitioning and reformatting your USB disk. I recommend allocating the last cylinder in fdisk to primary partition 2.

Once you have the second, small partition (you are only going to use 1k, so as small a partition as possible) you can put a key on it. This is as simple as dd if=/dev/urandom of=/dev/sda2 bs=1M.

Adding the key to the luks partition

Next, you need to add your new key as able to decrypt the partition. Luks allows several keys to be able to unlock the partition. The real key is decrypted under each of the user keys or passphrases and stored in a key `slot' in the partition. To add your key type:

touch /tmp/keyfile
chmod 600 /tmp/keyfile 
dd if=/dev/sda2 bs=1k count=1 of=/tmp/keyfile
cryptsetup luksAddKey /dev/hda5 /tmp/keyfile
wipe /tmp/keyfile

Note the careful handling of the temporary key file (luksKeyAdd won't read from stdin, whereas luksOpen will), I recommend storing it on a ramdisk and you should certainly use wipe rather than rm if you don't.

Once you have added your USB key you could remove the passphrase from the key list with luksDelKey, but if for any reason you lose the USB hdd you will be unable to decrypt the partition; I recommend leaving both keys available.

Booting automatically

In order to boot using the USB key we need to provide a couple of helper scripts in order for the initramfs to work. We also need to set some parameters on the kernel command line.

In Debian these scripts can be added to the initramfs by putting them in /etc/initramfs-tools/. The first script is a helper script used when building the initramfs. This writes a second script into the initramfs itself which takes the partition as a parameter and prints the key on stdout. This should be written to /etc/initramfs-tools/hooks/cryptkey (executable) and contain:

#!/bin/sh --

PREREQ=""
prereqs()
{
   echo "$PREREQ"
}

case $1 in
prereqs)
   prereqs
   exit 0
   ;;
esac

. /usr/share/initramfs-tools/hook-functions

cat > ${DESTDIR}/bin/loadkey <<END
#!/bin/sh --
/bin/dd if=\$1 bs=1k count=1
END
chmod +x ${DESTDIR}/bin/loadkey

The second script runs immediately before the cryptsetup script in the initramfs and ensures that the USB disk is available. This will cause the boot sequence to block until the USB disk is inserted and the device nodes created by udev. It can be provided directly in /etc/initramfs-tools/scripts/local-top/00ensureusb (executable) and should contain:

#!/bin/sh --

PREREQ=""
prereqs()
{
   echo "$PREREQ"
}

case $1 in
   prereqs)
      prereqs
      exit 0
   ;;
esac

if ! grep cryptopts /proc/cmdline >/dev/null; then return; fi

. /scripts/functions

log_begin_msg "Waiting for USB to become available..."

modprobe usbcore
modprobe uhci_hcd
modprobe ehci_hcd
modprobe usb_storage

while [ ! -b /dev/sda2 ]; do
   sleep 1
done
log_end_msg
exit 0

The cryptsetup script itself reads configuration from the kernel command line. Here you can give it a script which will read the key and the source for the key to read. Edit your grub or lilo config and append the following to the kernel command line: cryptopts=keyscript=/bin/loadkey,key=/dev/sda2,source=/dev/hda5,target=hda5_crypt,lvm=hecate-root You will obviously have to change the name of your lvm root partition (volumegroup-logicalvolume). I recommend having two entries in the boot menu, one with the cryptopts and one without to allow easy decryption using the passphrase instead.

Conclusion

That should be everything. Boot your computer and inset the usb hdd. When the boot process passes decryption you can remove it again. You may have to replug it if you boot with it inserted to start with.