After scouring the web and reading tonnes on un-connected posts, I managed, with a lot of trial and error, to work-up a method of unlocking a LUKS partition with a USB Key on boot. I outline the method below and welcome any suggestions on how to improve it. The method is tested on Fedora 12 and 13 on a Dell PowerEdge T105 server with 2x 2TB discs in RAID 1 and a cheap laptop with a single 250GB S-ATA hard drive. USB sticks used are a Lacie iamaKey and a Crucial Gizmo Jr.
Here is my method to date:
Part 1 - Create key file.
1.1 Fill a USB memory stick with random data:
dd if=/dev/urandom of=/dev/sdb bs=1
This assumes your memory stick is /dev/sdb.
Tip: A laptop with lots of devices will have a greater entropy pool than a server.
CAUTION: The 'dd' command will happily wipe your hard drive if you set the wrong /dev/sd?.
1.2 Extract a "key" from the random data on the USB stick:
dd if=/dev/sdb of=luks-secret.key bs=1 count=4096
The above line will extract 4096 bytes of random data from the USB stick.
(Updated: 16th June 2010)
1.3 Add the key to your LUKS partition:
cryptsetup luksAddKey /dev/sda2 luks-secret.key --key-slot 1
The command above adds the newly generated key to slot 1 (assuming slot 0 contains your LUKS passphrase) of your LUKS partition.
It is assumed your encrypted partition is on /dev/sda2.
You will be prompted for your usual LUKS passphrase before the key is added.
You can check the key has been added to slot 1 with the following command:
cryptsetup luksDump /dev/sda2
1.4 Delete the key from your file system:
shred --remove --zero luks-secret.key
Part 2 - Create a udev rule.
Create a udev rule that will detect the USB stick and make it available as /dev/usbkey. The rule can be created "device specific" so inserting another USB stick will not create /dev/usbkey.
2.1 udev rule:
To create the rule, we need to gather some information on the USB stick. Do this with the following command:
udevadm info -a -p $(udevadm info -q path -n /dev/sdb)
I recommend looking for SUBSYSTEMS=="usb" and ATTR{manufacturer}, ATTR{product} and ATTR{serial}. With this information, you can create a rule as follows:
In /etc/udev.d/rules.d create a file called 10-usbkey.rules
(Updated: 16th June 2010)
An example rule is (this is all on one line):
SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{manufacturer}=="LaCie", ATTRS{product}=="LaCie iamaKey", ATTRS{serial}=="60f2f4441dc104", SYMLINK+="usbkey%n"
Reload udev rules with: udevadm control --reload-rules
The entry SYMLINK+="usbkey%n" ensures the key is available in /dev/usbkey, which is needed by the next part.
Part 3 - Create a shell script to unlock partition:
Create a file in /sbin called 'dd-luks-unlock' with the following contents:
#!/bin/sh
#
# Script to unlock LUKS volume with USB key
# Read in luks and UUID information
#
LUKS="`grep \"${HAL_PROP_VOLUME_UUID#*_uuid_}\" /etc/crypttab`"
DEVICE="`echo $LUKS | awk '{print $2}' | awk -F= '{print $2}'`"
MAPPER="`echo $LUKS | awk '{print $1}'`"
DEV="/dev/disk/by-uuid/$DEVICE"
# Open LUKS volume
#
dd if=/dev/usbkey bs=1 count=4096 | \
cryptsetup luksOpen $DEV $MAPPER --key-file=- --key-slot 1
# Clean up
#
unset DEV DEVICE MAPPER LUKS
# We are done!
#
exit 0
Notes:
--key-file=- means the key-file will be read from stdin (piped from the dd command)
--key-slot 1 opens the slot with our key (slot 0 is passphrase).
Ensure the file has root:root and 700 permissions.
(Updated: 16th June 2010)
Part 4 - modify dracut.
Fedora (12 onwards) uses a system called 'dracut' to create the 'initramfs' that 'plymouth' uses to boot the kernel. Dracut builds the 'initramfs' from modules which can be modified to carry your own customisations.
4.1 Add the dd-luks-unlock script and awk to plymouth:
Modify the 'install' script found in /usr/share/dracut/modules.d/50plymouth and add the following line to the end of the file:
inst /sbin/dd-luks-unlock
inst /bin/awk
inst /bin/gawk
Notes: Without awk, our dynamic read of /etc/crypttab does not work.
4.2 Modify the cryptroot-ask.sh script to check for a USB key:
Modify the 'cryptroot-ask.sh' script found in /usr/share/dracut/modules.d/50plymouth. Add the following after "#!/bin/sh".
if [ -e /dev/usbkey ]; then
ask=0
echo "USB Key detected - unlocking partition..."
/sbin/dd-luks-unlock
fi
If you have a laptop and the USB key is not detected in time, you may need to sleep the script (until a better solution is found):
echo "Sleeping for 10 seconds to wait for devices..."
sleep 10
if [ -e /dev/usbkey ]; then
ask=0
echo "USB Key detected - unlocking partition..."
/sbin/dd-luks-unlock
fi
This causes the script to sleep for 10 seconds to allow the USB key scripts time to unlock the partition. If you are still prompted for the passphrase, the USB subsystem is not detecting the key.
(Updated: 16th June 2010)
4.3 Add udev rule.
Modify the 'install' script found in /usr/share/dracut/modules.d/95udev-rules and add the following line (with the other inst_rules):
inst_rules 10-usbkey.rules
I have placed this before the other inst_rules in the file so I can see my modification. Future versions of dracut may automagically detect udev rules.
(Updated: 16th June 2010)
4.4 Create new initramfs
Use the following command to create a new initramfs:
/usr/libexec/plymouth/plymouth-update-initrd
4.5 Check the new files have been added to initramfs
lsinitrd /boot/initramfs-{kernel version} | grep dd-luks-unlock
and
lsinitrd /boot/initramfs-{kernel version} | grep 10-usbkey
(Updated: 16th June 2010)
and
lsinitrd /boot/initramfs-{kernel version} | grep cryptroot-ask.sh
and
lsinitrd /boot/initramfs-{kernel version} | grep awk
will show if the files have been correctly added to the initramfs.
{kernel-version} should be the running kernel version number.
Part 5 - Reboot
With the key in place, the LUKS volume should automatically unlock. Without the key, the system will still prompt for the passphrase.


Reply With Quote
