#!/bin/sh # # 1) mounts a device (e.g. a USB drive) # 2) returns (by the command cat) a key found on the device # # this script runs in connection with /conf/conf.d/cryptroot in the initramfs # # e.g. cryptroot # target=root,source=/dev/sda3,key=/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/filename.key,keyscript=/keyscripts/keyscript # # what's actually passed to this script is the key= part # e.g. # /dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/filename.key # # note: This parameter is awkward since it isn't a real path. The script # will split that string on the last '/' using the right substring # as the filename, and the left substring as the device name. In # this method, the key 'filename.key' must be found in the root # directory of the specified device. # # since output is considered the "key", the script has to be careful about what # it outputs (hence all the >/dev/null 2>&1 nonsense) # # from crypttab man: # "keyscript= # The executable at the inidicated path is executed with the key file from the third field of the crypttab as its only argument and # the output is used as the key. This also works with encrypted root filesystems via initramfs if the executable is self-contained # (i.e. not a shell script which relies on external programs)." # fatal_error() { echo "Boot Error: $1" > /dev/console exit 1 } # check for presence of parameters if [ -z $1 ]; then fatal_error "No script parameters" fi parameters="$1" keydevice="${parameters%/*}" keyfile="${parameters##*/}" # e.g. # keydevice=/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # keyfile=keyfile.key # wait for udev to be ready, see https://launchpad.net/bugs/85640 if [ -x /sbin/udevsettle ]; then /sbin/udevsettle --timeout=30 fi # wait max 8 seconds for the keydevice to appear if [ ! -b "${keydevice}" ] || ! /lib/udev/vol_id "${keydevice}" >/dev/null 2>&1; then slumber=8 slumber=$(( ${slumber} * 10 )) while [ ! -b "${keydevice}" ] || ! /lib/udev/vol_id "${keydevice}" >/dev/null 2>&1; do /bin/sleep 0.1 slumber=$(( ${slumber} - 1 )) [ ${slumber} -gt 0 ] || break done fi # device must exist at this point if [ ! -b "${keydevice}" ]; then fatal_error "Device not found" fi # make sure it's a luks device cryptsetup isLuks $keydevice if [ $? -ne 0 ]; then fatal_error "$keydevice is not LUKS formatted" fi # open the device, with 3 retries on the password count=0 openstat=0 while [ $count -lt 3 ]; do count=$(( $count + 1 )) if [ ! -e /dev/mapper/bootkey ]; then echo -n "Enter Passphrase ==> " > /dev/console cryptsetup luksOpen $keydevice bootkey > /dev/null 2>&1 openstat=$? else break fi done # check for failure if [ $openstat -ne 0 ]; then fatal_error "Failed to open device" fi # create mount point and mount the opened device if [ ! -d /mnt/bootkey ]; then mkdir -p -m 0700 /mnt/bootkey > /dev/null 2>&1 fi mount -r -t ext2 /dev/mapper/bootkey /mnt/bootkey > /dev/null 2>&1 # check status if [ $? -ne 0 ]; then fatal_error "Failed to mount device" elif [ -r "/mnt/bootkey/${keyfile}" -a -s "/mnt/bootkey/${keyfile}" ]; then # SUCCESS: echo the keyfile contents echo "Success! Welcome." > /dev/console cat /mnt/bootkey/${keyfile} else fatal_error "Could not find ${keyfile} on ${keydevice}" fi # unmount and close the USB Keys umount /mnt/bootkey > /dev/null 2>&1 rmdir /mnt/bootkey > /dev/null 2>&1 cryptsetup luksClose bootkey > /dev/null 2>&1