This tutorial may render your system unusable. You should know what you're doing. Proceed at your own risk. = Encrypted LUKS FS with Removable Drive as Key Howto = Using this tutorial you can set up a LUKS encrypted partition to unlock at boot using a key stored on a removable device. Alternatively if the device is not present, you will be asked for a passphrase. THE KEY WILL NOT BE STORED AS A FILE, BUT ITS BYTES WILL BE RAW-COPYED ON THE REMOVABLE DEVICE. '''This tutorial assumes that you already have an encrypted partition and a removable device to store the key on.''' Let's call /dev/sdXX the encrypted drive/partition and /dev/sdY the removable device. == Partitioning your removable device == Format your device as you want but make sure to create a not formatted partition where we're going to physically write the key. Make sure to create a partition and not to just leave the space unallocated. For example you may want to create 2 partitions: one fat32 for storing file as usually and one (not formatted) for the key. You may use parted (Command Line Interface) or gparted (graphical UI), to install them just type: {{{ $ sudo apt-get install parted }}} or {{{ $ sudo apt-get install gparted }}} Here's an example with parted: {{{ $ sudo parted /dev/sdY GNU Parted 1.8.9 Viene usato /dev/sdY Benvenuti in GNU Parted. Digitare "help" per l'elenco dei comandi. (parted) mklabel Avviso: L'etichetta del disco su /dev/sdY verrà eliminata e tutti i dati su questo disco saranno persi. Continuare? Sì/Yes/No? Y Tipo dell'etichetta del nuovo disco? [msdos]? msdos (parted) mkpartfs primary fat32 0 -8m (parted) print Modello: Generic USB Disk (scsi) Disco /dev/sdY: 1032MB Dimensione del settore (logica/fisica): 512B/512B Tabella delle partizioni: msdos Numero Inizio Fine Dimensione Tipo File system Flag 1 512B 1024MB 1024MB primary fat32 lba (parted) mkpart primary 1024m -1s (parted) print Modello: Generic USB Disk (scsi) Disco /dev/sdY: 1032MB Dimensione del settore (logica/fisica): 512B/512B Tabella delle partizioni: msdos Numero Inizio Fine Dimensione Tipo File system Flag 1 512B 1024MB 1024MB primary fat32 lba 2 1024MB 1032MB 7999kB primary (parted) quit Informazioni: Potrebbe essere necessario aggiornare /etc/fstab. }}} Let's call /dev/sdY2 the unformatted partition. == Creating the key == Now we need to create a new key and add it to to the encrypted drive. You can use the following command for a 256-byte password (if the command blocks, just move your mouse or press some keys to generate the needed entropy): {{{ $ dd if=/dev/random of=keyfile.key bs=1 count=256 }}} Now add that key to the LUKS device (the encrypted one, not the removable one): {{{ $ sudo cryptsetup luksAddKey /dev/sdXX keyfile.key }}} You'll need to provide a working key for that drive. == Writing the key to the removable device == Now we're going to write the generated key directly on the not formatted partition of the removabile device. The key will NOT be written as a file, but raw bytes will be copied. It will not be visible when mounted to a system. The not formatted partition ensures we have a mean to access the location where the key is stored and prevents other systems from messing with your device. Now just do: {{{ $ sudo dd if=keyfile.key of=/dev/sdY2 bs=1 count=256 }}} At this point you can safely remove the keyfile: {{{ $ shred -u keyfile.key }}} == Getting the id of the newly created partition == Run: {{{ $ ls -l /dev/disk/by-id/ | grep sdY2 }}} The output will be like this: {{{ lrwxrwxrwx 1 root root 10 2009-04-24 15:45 usb-Generic_USB_Disk_00000000000000-0:0-part2 -> ../../sdc2 }}} Here the important thing is: '''usb-Generic_USB_Disk_00000000000000-0:0-part2''' (you will get a different string) We will use this later, it will be referred as . == Creating the keyscript == Now we need to create a keyscript that gets the key from the removable drive at boot time and uses it to open your encrypted volume. Do: {{{ $ sudo nano /usr/local/sbin/usbkeyscript.sh }}} And paste the following text: {{{ #!/bin/sh #!/bin/sh # Return true if usplash is running, otherwise return false. [ -x /sbin/usplash_write ] && usplash_exists='1' usplash_running() { [ -z "$usplash_exists" ] && return 1 pidof "usplash" >/dev/null return $? } fixup_verbosity() { if [ "$(expr match "$(cat /proc/cmdline)" '.*quiet')" -gt "0" ]; then /sbin/usplash_write "VERBOSE off" 2>/dev/null else /sbin/usplash_write "VERBOSE on" 2>/dev/null fi } # Write output to the console. n: now newline s: status (no time) write_to_console() { read system_uptime no_var < /proc/uptime if [ "x$2" != "xs" ]; then printf '[%8s0000] %s' "$system_uptime" "$1" >&2 else printf '%s' "$1" >&2 fi if [ "x$2" != "xn" ]; then printf '\n' >&2 fi } # Write output to usplash write_to_usplash() { usplash_running if [ $? -eq 0 ]; then /sbin/usplash_write "VERBOSE on" /sbin/usplash_write "$1 $2" fixup_verbosity fi write_to_console "$2" "$3" return 0 } if [ "x$1" = "x" -o "x$1" = "xnone" ]; then write_to_usplash "TEXT" "Keyscript: not configured for external keydevice." >&2 /lib/cryptsetup/askpass "Enter passphrase: " exit 0 else KEYDEVICE=$(echo $1 | cut -d# -f 1) KEYSIZE=$(echo $1 | cut -d# -f 2) KEYPOS=$(echo $1 | cut -d# -f 3) fi SETTLETIMEOUT=5 #in secs FIRSTDEVICETIMEOUT=100 #in decisecs DEFAULTDEVICETIMEOUT=5 #in decisecs DEVICETIMEOUT="${FIRSTDEVICETIMEOUT}" if [ -f /tmp/usbkey-discover-done ]; then DEVICETIMEOUT="${DEFAULTDEVICETIMEOUT}" fi touch /tmp/usbkey-discover-done write_to_usplash "TEXT" "Keyscript: waiting for udev to settle" # Wait for udev to be ready, see https://launchpad.net/bugs/85640 if [ -x /sbin/udevsettle ]; then /sbin/udevsettle --timeout=${SETTLETIMEOUT} > /dev/null 2>&1 fi write_to_usplash "TEXT" "Keyscript: searching for device..." "n" # Wait for the KEYDEVICE to appear slumber=${DEVICETIMEOUT} while [ ! -b "${KEYDEVICE}" ]; do /bin/sleep 0.1 slumber=$(( ${slumber} - 1 )) if [ ${slumber} -lt 0 ]; then write_to_usplash "FAILURE" "not found." "s" /lib/cryptsetup/askpass "Enter passphrase: " exit 0 fi done write_to_usplash "SUCCESS" "found." "s" dd if=${KEYDEVICE} bs=1 count=${KEYSIZE} skip=${KEYPOS} 2> /dev/null exit 0 }}} Press CTRL+X and then Enter to save the file. Now change the permissions: {{{ $ sudo chmod 500 /usr/local/sbin/usbkeyscript.sh }}} == Editing crypttab == At this point we need to tell the system to run our keyscript at boot to get the key: {{{ $ sudo nano /etc/crypttab }}} You will find something like this: {{{ /dev/ none luks }}} Where '''''' is the name of the device created after succefully mounting the encrypted disk and '''''' is the physical encrypted device. You'll need to modify the line to: {{{ /dev/ /dev/disk/by-id/#256#0 luks,keyscript=/usr/local/sbin/usbkeyscript.sh }}} Where '''''' is the id of the partition on the removable device we found before, '''256''' is the key lenght and '''0''' is the offset from the starting of the partition where the key is stored. Mine looks like this (i've edited some names): {{{ sdXX_crypt /dev/disk/by-uuid/00000000-1111-2222-3333-444444444444 /dev/disk/by-id/usb-Generic_USB_Disk_00000000000000-0:0-part2#256#0 luks,keyscript=/usr/local/sbin/usbkeyscript.sh }}} Again, press CTRL+X and save the file. == Updating initramfs == If the encrypted device you're working on is the one that contains your root ( / ), you'll need to regenerate initramfs to copy the files we've created/modifyed to initramfs. First you may want to make a backup, run: {{{ $ sudo cp /boot/initrd.img-$(uname -r) /boot/initrd.img-$(uname -r).bak }}} Now run: {{{ $ sudo update-initramfs -u }}} == Rebooting the system == At this point all should be fine. You can try rebooting your system and hope that everytihng went well. If the system fails to boot you can always mount the partition that contains /boot files from the recovery shell, and then replace the new initrd image with the backup one. The system shoul be able to automatically mount you encrypted device if your removable drive is present, or ask your password otherwise. If all went well you can remove the backup image with: {{{ $ sudo rm /boot/initrd.img-$(uname -r).bak }}} == Forcing yourself to remove the keydevice == There is no extra security in encrypted disks if you leave the device plugged id. This script stops the boot process right before gdm is started, until the keydevice is removed. Run: {{{ $ sudo nano /etc/init.d/remove-usbkeydevice }}} And paste the following text (usplash functions are edited from a script I found at ubuntu forums, credit to the autor: StR34k): {{{ #!/bin/sh #!/bin/sh ### BEGIN INIT INFO # Provides: remove-usbkeydevice # Required-Start: # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: # Short-Description: Forces removal of the keydevice to continue boot. # Description: ### END INIT INFO KEYDEVICE=/dev/disk/by-id/ # Return true if usplash is running, otherwise return false. [ -x /sbin/usplash_write ] && usplash_exists='1' usplash_running() { [ -z "$usplash_exists" ] && return 1 pidof "usplash" >/dev/null return $? } fixup_verbosity() { if [ "$(expr match "$(cat /proc/cmdline)" '.*quiet')" -gt "0" ]; then /sbin/usplash_write "VERBOSE off" 2>/dev/null else /sbin/usplash_write "VERBOSE on" 2>/dev/null fi } # Write output to the console. n: now newline s: status (no time) write_to_console() { read system_uptime no_var < /proc/uptime if [ "x$2" != "xs" ]; then printf '[%8s0000] %s' "$system_uptime" "$1" >&2 else printf '%s' "$1" >&2 fi if [ "x$2" != "xn" ]; then printf '\n' >&2 fi } # Write output to usplash write_to_usplash() { usplash_running if [ $? -eq 0 ]; then /sbin/usplash_write "VERBOSE on" /sbin/usplash_write "$1 $2" fixup_verbosity fi write_to_console "$2" "$3" return 0 } case "$1" in start) if [ -b ${KEYDEVICE} ]; then write_to_usplash "TEXT" "Please remove your keydevice to continue." fi while [ -b ${KEYDEVICE} ]; do sleep 0.1; done exit 0; ;; *) echo "Usage: remove-usbkeydevice start" exit 1 ;; esac }}} Put your keydevice partition id in place of '''''' on the top of the script. Save and exit as usual. Now change the permissions: {{{ $ sudo chmod 755 /etc/init.d/remove-usbkeydevice }}} Tell the system to run it at startup: {{{ $ sudo update-rc.d remove-usbkeydevice start 28 2 3 4 5 . }}}