Introduction
Recently I've installed Debian 4.0 (Etch) with disk encryption to protect my data. However the password entry at boot is quite tiresome after couple of days.
Fortunately, there's a better way!
I took some inspiration in System encryption on Debian Etch article and decided to do it the "initramfs-tools way". Because I don't like the idea of installing yet another mkinitrd front-end AND the article on DA seems a bit dated. :-)
Prerequisites
You'll need your Etch installation with encrypted partition that's being setup at boot time via initramfs-tools. This is easy -- it's what you end up with when you select "encrypted filesystem" option during installation.
You'll also need to have at least moderate understanding of how to operate shell and you absolutely HAVE TO backup your data, because if something goes wrong, you might very well end up with system you can't get into anymore. Which is not cool situation without backup.
(OK, I know you'll skip backing up your data because you're lazy and/or you think you know better. Well, I had to remind you about the backup to protect myself from hate-mail. Don't come to me crying you nuked your system.)
Part One - adding password file to LUKS
First you have to determine which partition is encrypted -- you can do that by inspecting contents of /etc/crypttab:
# cat /etc/crypttab sda5_crypt /dev/sda5 none luks
So, we have sda5 encrypted. Good to know.
Now, we need to generate key file which we'll name root.key (for instance):
# head -c 2880 /dev/urandom | uuencode -m - | head -n 65 | tail -n 64 > root.key
If the command sequence fails for any reason, you don't have sharutils installed. Fix that via:
# apt-get install sharutils
and retry the previous password file generation one-liner.
You should end up with something like this:
# wc -l root.key 64 root.key # head -n 3 root.key 9iDTzZlOy6P44YnoW7etVwVK7Xjj6SCvRNUkpTUPy1KjvQ3IsF8Q4hQ+Yda6 5XkXGJC8ylvAqc1ZvLMLEhIb2L73O90WCZhoj3GUkvTeohHDWLguBl23k1AX wfVtPDZre3gpPuHhZNb3vOFzwjihfR2yMxykp6uuXjFlWLK4JNc4TLgRSWIq
Now we need to add the key file to that partition key pool:
# cryptsetup luksAddKey /dev/sda5 root.key
You will be asked for password, which is the boot-up password you've been using so far.
Cool. Now we have the password file registered as a valid key, so we just copy it over to USB stick and go about changing initramfs-tools setup.
Part Two - setting up (known) safe boot option
We should make backup of existing initrd before attempting to tinker with the boot setup. Here's how:
Go to "/boot" and copy existing initrd image with -safe extension, to have known good copy.
In my case it looks like this:
# cd /boot/ # ls -1 init* initrd.img-2.6.18-5-amd64 initrd.img-2.6.18-5-amd64.bak # cp initrd.img-2.6.18-5-amd64 initrd.img-2.6.18-5-amd64-safe
Now we need to add the safe option to Grub (or your favorite boot manager).
Open /boot/grub/menu.lst, locate the kernel you're booting into, copy that block under the "END DEBIAN AUTOMAGIC KERNELS LIST" line.
Change "initrd" definition by adding "-safe" at the end and change "title" to indicate it's your safe option.
In my case the end of /boot/grub/menu.lst now looks like this:
# tail -n 7 /boot/grub/menu.lst ### END DEBIAN AUTOMAGIC KERNELS LIST title Debian GNU/Linux, kernel 2.6.18-5-amd64 (safe version) root (hd0,0) kernel /vmlinuz-2.6.18-5-amd64 root=/dev/mapper/vg-root ro initrd /initrd.img-2.6.18-5-amd64-safe savedefault
and I've created that from boot option that looked like this:
title Debian GNU/Linux, kernel 2.6.18-5-amd64 root (hd0,0) kernel /vmlinuz-2.6.18-5-amd64 root=/dev/mapper/vg-root ro initrd /initrd.img-2.6.18-5-amd64 savedefault
Part Three - making our boot process run passwordless
So, now we need to make few adjustments to make it all work.
First we need to add couple of modules to be loaded to the ramdisk:
# echo -e "vfat\nfat\nnls_cp437\nnls_iso8859_1" >> /etc/initramfs-tools/modules
because I assume you have your USB keychain with FAT filesystem and therefore you need vfat, fat, nls_cp437, and nls_iso8859_1 modules to mount it.
Next we need to change /etc/crypttab to accept our custom "keyscript" with proper key file. Mine looks like this, after the modification:
# cat /etc/crypttab sda5_crypt /dev/sda5 root.key luks,keyscript=/usr/local/sbin/crypto-usb-key.sh
So I've changed the "key" option from "none" to "root.key" (which is the name of our pwfile) and added "keyscript" option which says to the init scripts to run that script in order to get password.
So far so good.
Now we need the keyscript ... add this:
#!/bin/sh
# Part of passwordless cryptofs setup in Debian Etch.
# See: http://wejn.org/how-to-make-passwordless-cryptsetup.html
# Author: Wejn <wejn at box dot cz>
if [ "x$1" = "x" -o "x$1" = "xnone" ]; then
KEYF=root.key
else
KEYF=$1
fi
MD=/tmp-usb-mount
echo "Trying to get the key from USB keychain ..." >&2
mkdir -p $MD
modprobe usb-storage >/dev/null 2>&1
modprobe vfat >/dev/null 2>&1
sleep 7
OPENED=0
for SFS in /sys/block/sd*; do
DEV=`basename $SFS`
F=$SFS/${DEV}1/dev
if [ 0`cat $SFS/removable` -eq 1 -a -f $F ]; then
echo "> Trying device: $DEV ..." >&2
mount /dev/${DEV}1 $MD -t vfat -o ro 2>/dev/null
if [ -f $MD/$KEYF ]; then
cat $MD/$KEYF
umount $MD 2>/dev/null
OPENED=1
break
fi
umount $MD 2>/dev/null
fi
done
if [ $OPENED -eq 0 ]; then
echo "FAILED to find suitable USB keychain ..." >&2
echo -n "Try to enter your password: " >&2
read -s -r A
echo -n "$A"
else
echo "Success loading keyfile from the keychain!" >&2
fi
as /usr/local/sbin/crypto-usb-key.sh and chmod it a+x ...
You can download the file here if you're not comfortable copy&pasting it.
Finishing line! All you need to do now is to update your initrd:
# update-initramfs -u all update-initramfs: Generating /boot/initrd.img-2.6.18-5-amd64
and you're ready to reboot! :-)
Conclusion
It ain't that hard to get to passwordless cryptofs setup in Etch, as you can see.
This document describes the whole process in reasonable detail, even though it doesn't explain all the details WHY it's done that way.
Anyway, if you have comments / improvements, feel free to contact me at: wejn at box dot cz.
Please use reasonable Subject line so I don't mistake your email for spam.
Oh, and I won't mind you digg-ing this how-to if you happen to like it.
Update: Password file generation concern
I've received email from Paul Walker asking me about the method used for password generation. He was concerned that using base64 on the /dev/urandom input (see part one) we might end up limiting the password strength by one third (in case the cryptsetup was limiting size of the password material).
Well, it took me a while to figure out how the password handling works with LUKS, but here's the result of my research:
The password handling in LUKS is done with a help of hashing function and the input stream (file) is read in its entirety, see "NOTES ON PASSWORD PROCESSING FOR LUKS" section in cryptsetup manual.
The actual protocol used is PBKDF2, which is some "password-based key derivation function", see Wikipedia's PBKDF2 page for details.
As a conclusion, it's perfectly safe to use any file you like, even the uuencoded one based on the recipe I have copied from the Debian Administration article referenced above.
But Paul is right, the uuencode is superfluous and simple:
head -c 256 /dev/urandom > root.key
will do just as well. You might even increase the number of characters taken from /dev/urandom and/or switch to /dev/random, if you're really paranoid.
The only difference might be if you're planning on printing the contents of your root.key to put it in a high-security vault for backup purposes. In that case having the file uuencoded helps a bit.
But that's not a likely scenario... :-)
Anyway, thanks Paul for bringing it up!
Update: Using crypto-usb-key.sh with multiple devices
I've received email from Kix (Rodolfo Garcia) regarding problems with using my keyscript with multiple devices. The thing is that my keyscript attempts to load the kernel modules and waits for 7 seconds prior looking for the keyfile(s).
For encrypted root that is desired feature. Not so when you have more partitions you want to auto-setup. Because in this case the "sleep 7" gets annoying.
Anyway, Kix came up with modified version of the crypto-usb-key.sh script:
#!/bin/sh
# Part of passwordless cryptofs setup in Debian Etch.
# See: http://wejn.org/how-to-make-passwordless-cryptsetup.html
# Author: Wejn <wejn at box dot cz>
#
# Updated by Rodolfo Garcia (kix) <kix at kix dot com>
# For multiple partitions
# http://www.kix.es/
# USB Disk partition type (ext2 or vfat)
PARTTYPE=ext2
# Key file in the USB disk
KEYFILE=.key
# # # # # CODE # # # # #
MD=/tmp-usb-mount
if [ "x$1" = "x" -o "x$1" = "xnone" ]; then
KEYF=$KEYFILE
else
KEYF=$1
fi
USBLOAD=0
FSLOAD=0
cat /proc/modules | busybox grep usb_storage >/dev/null 2>&1
USBLOAD=$?
cat /proc/modules | busybox grep $PARTTYPE >/dev/null 2>&1
FSLOAD=$?
if [ $USBLOAD -gt 0 ] || [ $FSLOAD -gt 0 ]; then
modprobe usb_storage >/dev/null 2>&1
modprobe $PARTTYPE >/dev/null 2>&1
sleep 7
fi
OPENED=0
ls -d /sys/block/sd* >/dev/null 2>&1
SDS=$?
if [ $SDS -eq 0 ]; then
echo "Trying to get the key from USB keychain ..." >&2
mkdir -p $MD
for SFS in /sys/block/sd*; do
DEV=`busybox basename $SFS`
F=$SFS/${DEV}1/dev
if [ 0`cat $SFS/removable` -eq 1 -a -f $F ]; then
echo "> Trying device: $DEV ..." >&2
mount /dev/${DEV}1 $MD -t ext2 -o ro 2>/dev/null
if [ -f $MD/$KEYF ]; then
cat $MD/$KEYF
umount $MD 2>/dev/null
OPENED=1
break
fi
umount $MD 2>/dev/null
fi
done
fi
if [ $OPENED -eq 0 ]; then
echo "FAILED to find suitable USB keychain ..." >&2
echo -n "Try to enter your password: " >&2
read -s -r A </dev/console
echo -n "$A"
else
echo "Success loading keyfile from the keychain!" >&2
fi
which can be downloaded here.
In addition to fixing the module loading and delay it also allows you to configure partition type (for example ext2) and name of the default key file.
Nice work.
You might also note that instead of this script you might store keys for additional partitions on your (encrypted) root filesystem (in /etc, for instance) and use simple one-line keyscript like this one below:
#!/bin/bash ## /etc/swap.cryptokey should be owned by root:root with perms: 0600 exec cat /etc/swap.cryptokey
The choice is yours, either way will work just fine.
Update: Ubuntu-specific instructions
Zenon sent me link to his ubuntu hard drive encryption with external key article.
You might find it interesting.
Update: Loading keyfile from SD card
Cromwel managed (after a bit of tinkering) to get the keyscript working with his internal Ricoh SD card reader and SD-HC card.
Here's the modified keyscript to load keyfile from SD cards.