User Tools

Site Tools


howtos:full_disk_encryption

Setup partitions

There are many ways of using LUKS for disk encryption. I'll use the combination of LUKS and LVM to have one chunk of data (the volume group) which all is encrypted. This way all filesystems I make, including swap, will be encrypted. As this is a laptop I will not venture down all the possibilities that LVM has to offer.

Now lets get started!

Boot up on a usb/cd with the alternate Ubuntu installer on it. This is important otherwise you will not get the options that we will use for this setup.

Go through the install wizard and choose what you want.

Boot

When getting to the partitioning select Manual.

Select the harddrive you want to format.

If you get this you just say Yes.

Select the new partitioning space.

Create a new partition.

Select a size around 100-200MB. This is going to become the boot so not space is needed.

Create it as a primary partition.

Choose beginning.

Select a filesystem, I chose ext4, and select the mount point /boot.

Encrypted partition

Now select the remaining part of the diskspace.

And yet again make a new partition.

Fill out the rest of the remain diskspace.

Make it primary.

Make it a encrypted volume.

Now configure the encrypted volume.

Confirm the writing to disk.

Just choose a password you can remember. Later on we will remove it and make it keybased.

LVM

The wizard will automatically make one big ext3 filesystem out of the encrypted volume. We don't want that so go select the partition and hit enter.

Now change it to a volume for LVM instead.

When coming back to the overview move to the top and select configure LVM.

Make a volume group.

Call it something. Not important.

Now we choose the encrypted volume for our container for the volume group.

Next create a logical volume for the swap space.

We only got one volume group so the choice is fairly simple :)

Call it swap, or something else you would like to call your swap.

Give it a proper size so at least it can contain all what's in your ram when you hibernate.

Go back and make an other logical volume for the root filesystem.

Give it the rest of the space that is left.

Finish of in this part of the wizard.

Now select the logical volume that should contain our root filesystem.

Configure the filesystem for ext4 and select the mount point “/”.

Now go for the logical volume that contains the swapspace.

Choose it to be a swapspace.

Finish of the partitioning.

Save the changes to disk.

We do not need to encrypt our home as the hole root is encrypted. So say no.

Now when ever we boot we will have to enter our password for the encrypted filesystem to startup.

Keyfile

Lets create our keyfile for authentication and access to the encrypted filesystem.

dd if=/dev/random of=/dev/shm/root.key bs=1 count=256

This will create a random key called root.key in the ramdisk. The ramdisk is used to make sure the key is completely gone after reboot.

Now add the keyfile as authenticator for the filesystem:

cryptsetup luksAddKey /dev/sda2 /dev/shm/root.key

Now move the root.key to a usb device of some sort and keep it safe!!

After you have tested that your keyfile is working, you can remove the password from the encrypted disk:

cryptsetup luksDelKey /dev/sda2 0

Keyscript 1

Put this file into “/usr/local/sbin/crypto-usb-key.sh” and run “chmod 500” on it. If you change anything in the script you will have to update the initramfs file with the new version of the file.

The script handles both ordinary partitions, like vfat and ext3, but also encrypted usb devices (see Encrypted USB Storage on how to make one. I would recommend to have the key file store on a encrypted usb device. That way you maximize the security if someone should copy the usb device and try to get access to the key and you harddisk.

#!/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/
#
# Updated by TJ <linux@tjworld.net> 7 July 2008
# For use with Ubuntu Hardy, usplash, automatic detection of USB devices,
# detection and examination of *all* partitions on the device (not just partition #1), 
# automatic detection of partition type, refactored, commented, debugging code.
#
# Updated by Hendrik van Antwerpen <hendrik at van-antwerpen dot net> 3 Sept 2008
# For encrypted key device support, also added stty support for not
# showing your password in console mode.

# define counter-intuitive shell logic values (based on /bin/true & /bin/false)
# NB. use FALSE only to *set* something to false, but don't test for
# equality, because a program might return any non-zero on error
TRUE=0
FALSE=1

# set DEBUG=$TRUE to display debug messages, DEBUG=$FALSE to be quiet
DEBUG=$FALSE

# is usplash available? default false
USPLASH=$FALSE
# test for outfifo from Ubuntu Hardy cryptroot script, the second test
# alone proves not completely reliable.
if [ -p /dev/.initramfs/usplash_outfifo -a -x /sbin/usplash_write ]; then
    # use innocuous command to determine if usplash is running
    # usplash_write will return exit-code 1 if usplash isn't running
    # need to set a flag to tell usplash_write to report no usplash
    FAIL_NO_USPLASH=1
    # enable verbose messages (required to display messages if kernel boot option "quiet" is enabled
    /sbin/usplash_write "VERBOSE on"
    if [ $? -eq $TRUE ]; then
        # usplash is running
        USPLASH=$TRUE
        /sbin/usplash_write "CLEAR"
    fi
fi

# is stty available? default false
STTY=$FALSE
STTYCMD=false
# check for stty executable
if [ -x /bin/stty ]; then
    STTY=$TRUE
    STTYCMD=/bin/stty
elif [ `(busybox stty >/dev/null 2>&1; echo $?)` -eq $TRUE ]; then
    STTY=$TRUE
    STTYCMD="busybox stty"
fi

# print message to usplash or stderr
# usage: msg <command> "message" [switch]
# command: TEXT | STATUS | SUCCESS | FAILURE | CLEAR (see 'man usplash_write' for all commands)
# switch : switch used for echo to stderr (ignored for usplash)
# when using usplash the command will cause "message" to be
# printed according to the usplash <command> definition.
# using the switch -n will allow echo to write multiple messages
# to the same line
msg ()
{
    if [ $# -gt 0 ]; then
        # handle multi-line messages
        echo $2 | while read LINE; do
            if [ $USPLASH -eq $TRUE ]; then
                # use usplash
                /sbin/usplash_write "$1 $LINE"
            else
                # use stderr for all messages
                echo $3 "$2" >&2
            fi
        done
    fi
}

dbg ()
{
    if [ $DEBUG -eq $TRUE ]; then
        msg "$@"
	sleep 1
    fi
}

# read password from console or with usplash
# usage: readpass "prompt"
readpass ()
{
    if [ $# -gt 0 ]; then
        if [ $USPLASH -eq $TRUE ]; then
            usplash_write "INPUTQUIET $1: "
            PASS="$(cat /dev/.initramfs/usplash_outfifo)"
        else
            [ $STTY -ne $TRUE ] && msg TEXT "WARNING stty not found, password will be visible"
            echo -n "$1" >&2
            $STTYCMD -echo
            read -r PASS </dev/console >/dev/null
            [ $STTY -eq $TRUE ] && echo >&2
            $STTYCMD echo
        fi
    fi
    echo -n "$PASS"
}

dbg STATUS "Executing crypto-usb-key.sh ..."

# flag tracking key-file availability
OPENED=$FALSE

# temporary mount path for USB key
MD=/tmp-usb-mount

if [ "x$1" = "x" -o "x$1" = "xnone" ]; then
    # default key-file on the USB disk
    KEYFILE=.key
else
    KEYFILE=$1
fi

# If the file already exists use it.
# This is useful where an encrypted volume contains keyfile(s) for later
# volumes and is now mounted and accessible
if [ -f $KEYFILE ]; then
    dbg TEXT "Found $KEYFILE"
    cat $KEYFILE
    OPENED=$TRUE
    DEV="existing mount"
    LABEL=""
else
    # Is the USB driver loaded?
    cat /proc/modules | busybox grep usb_storage >/dev/null 2>&1
    USBLOAD=0$?
    if [ $USBLOAD -gt 0 ]; then
        dbg TEXT "Loading driver 'usb_storage'"
        modprobe usb_storage >/dev/null 2>&1
    fi

    # give the system time to settle and open the USB devices
    sleep 7

    # Are there any SCSI block devices?
    ls -d /sys/block/sd* >/dev/null 2>&1
    SBD=$?

    if [ $SBD -eq $TRUE ]; then
        mkdir -p $MD
        dbg TEXT "Trying to get key-file '$KEYFILE' ..."
        for SFS in /sys/block/sd*/sd??; do
            dbg TEXT "Examining $SFS" -n
            # is it a USB device?
            ls -l ${SFS}/../device | busybox grep 'usb' >/dev/null 2>&1
            USB=0$?
            dbg TEXT ", USB=$USB" -n
            # Is the device removable?
            REMOVABLE=0`cat ${SFS}/../removable`
            dbg TEXT ", REMOVABLE=$REMOVABLE" -n
            if [ $USB -eq 1 -a $REMOVABLE -eq 1 -a -f $SFS/dev ]; then
                dbg TEXT ", *possible key device*" -n
                DEV=`busybox basename $SFS`
                # Check if key device itself is encrypted
                /sbin/cryptsetup isLuks /dev/${DEV} >/dev/null 2>&1
                ENCRYPTED=0$?
                # Open crypted partition and prepare for mount
                if [ $ENCRYPTED -eq $TRUE ]; then
                    dbg TEXT ", encrypted device" -n
                    # Use vol_id to determine label
                    LABEL="`/lib/udev/vol_id /dev/${DEV} | busybox sed -n 's/.*ID_FS_LABEL_SAFE=\(.*\)/\1/p'`"
                    dbg TEXT ", label $LABEL" -n
                    TRIES=3
                    DECRYPTED=$FALSE
                    while [ $TRIES -gt 0 -a $DECRYPTED -ne $TRUE ]; do
                        TRIES=$(($TRIES-1))
                        PASS="`readpass \"Enter LUKS password for key device ${DEV} (${LABEL}) (or empty to skip): \"`"
                        if [ -z "$PASS" ]; then
                            dbg TEXT ", device skipped" -n
                            break
                        fi
                        echo $PASS | /sbin/cryptsetup luksOpen /dev/${DEV} bootkey >/dev/null 2>&1
                        DECRYPTED=0$?
                    done
                    # If open failed, skip this device
                    if [ $DECRYPTED -ne $TRUE ]; then
                        dbg TEXT "decrypting device failed" -n
                        break
                    fi
                    # Decrypted device to use
                    DEV=mapper/bootkey
                fi
                dbg TEXT ", device $DEV" -n
                # Use vol_id to determine label
                LABEL="`/lib/udev/vol_id /dev/${DEV} | busybox sed -n 's/.*ID_FS_LABEL_SAFE=\(.*\)/\1/p'`"
                dbg TEXT ", label $LABEL" -n
                # Use vol_id to determine fstype
                FSTYPE="`/lib/udev/vol_id /dev/${DEV} | busybox sed -n 's/.*ID_FS_TYPE=\(.*\)/\1/p'`"
                dbg TEXT ", fstype $FSTYPE" -n
                # Is the file-system driver loaded?
                cat /proc/modules | busybox grep $FSTYPE >/dev/null 2>&1
                FSLOAD=0$?
                if [ $FSLOAD -gt 0 ]; then
                    dbg TEXT ", loading driver for $FSTYPE" -n
                    # load the correct file-system driver
                    modprobe $FSTYPE >/dev/null 2>&1
                fi
                dbg TEXT ", mounting /dev/$DEV on $MD" -n
                mount /dev/${DEV} $MD -t $FSTYPE -o ro >/dev/null 2>&1
                dbg TEXT ", (`mount | busybox grep $DEV`)" -n
                if [ -f $MD/$KEYFILE ]; then
                    dbg TEXT ", found $MD/$KEYFILE" -n
                    cat $MD/$KEYFILE
                    OPENED=$TRUE
                fi
                dbg TEXT ", umount $MD" -n
                umount $MD >/dev/null 2>&1
                # Close encrypted key device
                if [ $ENCRYPTED -eq $TRUE -a $DECRYPTED -eq $TRUE ]; then
                    dbg TEXT ", closing encrypted device" -n
                    /sbin/cryptsetup luksClose bootkey >/dev/null 2>&1
                fi
                dbg TEXT ", done\n\n" -n
                if [ $OPENED -eq $TRUE ]; then
                    break
                fi
            else
                dbg TEXT ", device `busybox basename $SFS` ignored" -n
            fi
            dbg CLEAR ""
        done
    fi
fi

# clear existing usplash text and status messages
[ $USPLASH -eq $TRUE ] && msg STATUS "                               " && msg CLEAR ""

if [ $OPENED -ne $TRUE ]; then
    msg TEXT "FAILED to find suitable USB key-file ..."
    readpass "Try to enter the LUKS password: "
else
    msg TEXT "Success loading key-file from $SFS ($LABEL)"
fi

# 
[ $USPLASH -eq $TRUE ] && /sbin/usplash_write "VERBOSE default"

Keyscript 1 with Karmic Koala

With the release of Karmic Koala udev was removed from the distribution. This has the unfortunate consequence that the script looses its ability to identify the filesystem type.

What I've done is to replace vol_id commands with blkid. And now it works again.

#!/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/
#
# Updated by TJ <linux@tjworld.net> 7 July 2008
# For use with Ubuntu Hardy, usplash, automatic detection of USB devices,
# detection and examination of *all* partitions on the device (not just partition #1), 
# automatic detection of partition type, refactored, commented, debugging code.
#
# Updated by Hendrik van Antwerpen <hendrik at van-antwerpen dot net> 3 Sept 2008
# For encrypted key device support, also added stty support for not
# showing your password in console mode.
#
# Updated by Thomas 06-11-2009
# Made the script work on Ubuntu Karmic Koala. This release doesn't have udev thus 
# filesystem type recognitioning doesn't work. Changed it to us blkid instead.

# define counter-intuitive shell logic values (based on /bin/true & /bin/false)
# NB. use FALSE only to *set* something to false, but don't test for
# equality, because a program might return any non-zero on error
TRUE=0
FALSE=1

# set DEBUG=$TRUE to display debug messages, DEBUG=$FALSE to be quiet
DEBUG=$FALSE

# is usplash available? default false
USPLASH=$FALSE
# test for outfifo from Ubuntu Hardy cryptroot script, the second test
# alone proves not completely reliable.
if [ -p /dev/.initramfs/usplash_outfifo -a -x /sbin/usplash_write ]; then
    # use innocuous command to determine if usplash is running
    # usplash_write will return exit-code 1 if usplash isn't running
    # need to set a flag to tell usplash_write to report no usplash
    FAIL_NO_USPLASH=1
    # enable verbose messages (required to display messages if kernel boot option "quiet" is enabled
    /sbin/usplash_write "VERBOSE on"
    if [ $? -eq $TRUE ]; then
        # usplash is running
        USPLASH=$TRUE
        /sbin/usplash_write "CLEAR"
    fi
fi

# is stty available? default false
STTY=$FALSE
STTYCMD=false
# check for stty executable
if [ -x /bin/stty ]; then
    STTY=$TRUE
    STTYCMD=/bin/stty
elif [ `(busybox stty >/dev/null 2>&1; echo $?)` -eq $TRUE ]; then
    STTY=$TRUE
    STTYCMD="busybox stty"
fi

# print message to usplash or stderr
# usage: msg <command> "message" [switch]
# command: TEXT | STATUS | SUCCESS | FAILURE | CLEAR (see 'man usplash_write' for all commands)
# switch : switch used for echo to stderr (ignored for usplash)
# when using usplash the command will cause "message" to be
# printed according to the usplash <command> definition.
# using the switch -n will allow echo to write multiple messages
# to the same line
msg ()
{
    if [ $# -gt 0 ]; then
        # handle multi-line messages
        echo $2 | while read LINE; do
            if [ $USPLASH -eq $TRUE ]; then
                # use usplash
                /sbin/usplash_write "$1 $LINE"
            else
                # use stderr for all messages
                echo $3 "$2" >&2
            fi
        done
    fi
}

dbg ()
{
    if [ $DEBUG -eq $TRUE ]; then
        msg "$@"
	sleep 0.2
    fi
}

# read password from console or with usplash
# usage: readpass "prompt"
readpass ()
{
    if [ $# -gt 0 ]; then
        if [ $USPLASH -eq $TRUE ]; then
            usplash_write "INPUTQUIET $1: "
            PASS="$(cat /dev/.initramfs/usplash_outfifo)"
        else
            [ $STTY -ne $TRUE ] && msg TEXT "WARNING stty not found, password will be visible"
            echo -n "$1" >&2
            $STTYCMD -echo
            read -r PASS </dev/console >/dev/null
            [ $STTY -eq $TRUE ] && echo >&2
            $STTYCMD echo
        fi
    fi
    echo -n "$PASS"
}

dbg STATUS "Executing crypto-usb-key.sh ..."

# flag tracking key-file availability
OPENED=$FALSE

# temporary mount path for USB key
MD=/tmp-usb-mount

if [ "x$1" = "x" -o "x$1" = "xnone" ]; then
    # default key-file on the USB disk
    KEYFILE=.key
else
    KEYFILE=$1
fi

# If the file already exists use it.
# This is useful where an encrypted volume contains keyfile(s) for later
# volumes and is now mounted and accessible
if [ -f $KEYFILE ]; then
    dbg TEXT "Found $KEYFILE"
    cat $KEYFILE
    OPENED=$TRUE
    DEV="existing mount"
    LABEL=""
else
    # Is the USB driver loaded?
    cat /proc/modules | busybox grep usb_storage >/dev/null 2>&1
    USBLOAD=0$?
    if [ $USBLOAD -gt 0 ]; then
        dbg TEXT "Loading driver 'usb_storage'"
        modprobe usb_storage >/dev/null 2>&1
    fi

    # give the system time to settle and open the USB devices
    sleep 7

    # Are there any SCSI block devices?
    ls -d /sys/block/sd* >/dev/null 2>&1
    SBD=$?

    if [ $SBD -eq $TRUE ]; then
        mkdir -p $MD
        dbg TEXT "Trying to get key-file '$KEYFILE' ..."
        for SFS in /sys/block/sd*/sd??; do
            dbg TEXT "Examining $SFS" -n
            # is it a USB device?
            ls -l ${SFS}/../device | busybox grep 'usb' >/dev/null 2>&1
            USB=0$?
            dbg TEXT ", USB=$USB" -n
            # Is the device removable?
            REMOVABLE=0`cat ${SFS}/../removable`
            dbg TEXT ", REMOVABLE=$REMOVABLE" -n
            if [ $USB -eq 1 -a $REMOVABLE -eq 1 -a -f $SFS/dev ]; then
                dbg TEXT ", *possible key device*" -n
                DEV=`busybox basename $SFS`
                # Check if key device itself is encrypted
                /sbin/cryptsetup isLuks /dev/${DEV} >/dev/null 2>&1
                ENCRYPTED=0$?
                # Open crypted partition and prepare for mount
                if [ $ENCRYPTED -eq $TRUE ]; then
                    dbg TEXT ", encrypted device" -n
                    # Use vol_id to determine label
                    #LABEL="`/lib/udev/vol_id /dev/${DEV} | busybox sed -n 's/.*ID_FS_LABEL_SAFE=\(.*\)/\1/p'`"
                    dbg TEXT ", label $LABEL" -n
                    TRIES=3
                    DECRYPTED=$FALSE
                    while [ $TRIES -gt 0 -a $DECRYPTED -ne $TRUE ]; do
                        TRIES=$(($TRIES-1))
                        PASS="`readpass \"Enter LUKS password for key device ${DEV} (${LABEL}) (or empty to skip): \"`"
                        if [ -z "$PASS" ]; then
                            dbg TEXT ", device skipped" -n
                            break
                        fi
                        echo $PASS | /sbin/cryptsetup luksOpen /dev/${DEV} bootkey >/dev/null 2>&1
                        DECRYPTED=0$?
                    done
                    # If open failed, skip this device
                    if [ $DECRYPTED -ne $TRUE ]; then
                        dbg TEXT "decrypting device failed" -n
                        break
                    fi
                    # Decrypted device to use
                    DEV=mapper/bootkey
                fi
                dbg TEXT ", device $DEV" -n
                # Use blkid to determine fstype
                FSTYPE=`blkid /dev/${DEV} | busybox sed -n 's/.*TYPE=\(.*\)/\1/p'| busybox sed 's/\"//g'`
		dbg TEXT ", fstype $FSTYPE" -n
                # Is the file-system driver loaded?
                cat /proc/modules | busybox grep $FSTYPE >/dev/null 2>&1
                FSLOAD=0$?
                if [ $FSLOAD -gt 0 ]; then
                    dbg TEXT ", loading driver for $FSTYPE" -n
                    # load the correct file-system driver
                    modprobe $FSTYPE >/dev/null 2>&1
                fi
                dbg TEXT ", mounting /dev/$DEV on $MD" -n
                mount /dev/${DEV} $MD -t $FSTYPE -o ro >/dev/null 2>&1
                dbg TEXT ", (`mount | busybox grep $DEV`)" -n
                if [ -f $MD/$KEYFILE ]; then
                    dbg TEXT ", found $MD/$KEYFILE" -n
                    cat $MD/$KEYFILE
                    OPENED=$TRUE
                fi
                dbg TEXT ", umount $MD" -n
                umount $MD >/dev/null 2>&1
                # Close encrypted key device
                if [ $ENCRYPTED -eq $TRUE -a $DECRYPTED -eq $TRUE ]; then
                    dbg TEXT ", closing encrypted device" -n
                    /sbin/cryptsetup luksClose bootkey >/dev/null 2>&1
                fi
                dbg TEXT ", done\n\n" -n
                if [ $OPENED -eq $TRUE ]; then
                    break
                fi
            else
                dbg TEXT ", device `busybox basename $SFS` ignored" -n
            fi
            dbg CLEAR ""
        done
    fi
fi

# clear existing usplash text and status messages
[ $USPLASH -eq $TRUE ] && msg STATUS "                               " && msg CLEAR ""

if [ $OPENED -ne $TRUE ]; then
    msg TEXT "FAILED to find suitable USB key-file ..."
    readpass "Try to enter the LUKS password: "
else
    msg TEXT "Success loading key-file from $SFS ($LABEL)"
fi

# 
[ $USPLASH -eq $TRUE ] && /sbin/usplash_write "VERBOSE default"

Making changes to crypttab

To make use of the passwordless encryption we must tell LUKS what to do and where to find what it needs.

Inside /etc/crypttab you will see something like this:

sda2_crypt /dev/disk/by-uuid/8f65184b-75ce-4852-9caf-7994037d47be none luks

This file tells us that LUKS will find its encrypted partition on a device with the uuid “8f65184b-75ce-4852-9caf-7994037d47be” and that it should map it to a virtual device called “sda2_crypt”. It also tells us that there is no key used for opening the device by the “none” statement. It will just ask for a password to open the disk.

As we are looking for at passwordless authentication change the file into this:

sda2_crypt /dev/disk/by-uuid/8f65184b-75ce-4852-9caf-7994037d47be root.key luks,keyscript=/usr/local/sbin/crypto-usb-key.sh

Now LUKS will look for the keyfile called root.key and it will use the script crypto-usb-key.sh to get it.

In this version we will configure a keyfile that is a regular file on a regular filesystem. Later on I will make a version where the key is store on the usb-device outside of the partitions.

The crypttab file is also a guideline for the update-initramfs command so it knows that it needs to pack a script into initrd to be able to boot.

An other way of storing the keyfile

Instead of holding the keyfile as a ordinary file on a filesystem you can also store it in raw format somewhere on the usb key. This way it will be hard to copy the keyfile of the device for misuse. If it is more secure than a keyfile on an encrypted usb filesystem I can not tell. But it may fit someones needs.

Keyscript 2

The keyscript for extracting the keyfile is now different, so to boot with a key stored in raw format this will do it.

Paste this script into the file “/usr/local/sbin/usbkeyscript.sh” and make it executable.

#!/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

Now take your usb device and make two partitions on it. The first should be an ordinary fat partition and the other should be an unformated one.

After formating the usb device you will need to know the unique ID of it for the configuration later on. This also means that you will only be able to use this particular one to unlock you harddisk. Run this command:

ls -l /dev/disk/by-id/ | grep sdY2
lrwxrwxrwx 1 root root 10 2009-07-10 17:44 usb-Corsair_Voyager_Mini_332677b71000b3-0:0-part2 -> ../../sdY2

The part saying “usb-Corsair_Voyager_Mini_332677b71000b3-0:0-part2” is the one we're going to use later on.

Say our usb device is called /dev/sdY2 do the following to put the keyfile onto it:

sudo dd if=keyfile.key of=/dev/sdY2 bs=1 count=256

Edit /etc/crypttab

Now edit your crypttab file and make it look like this:

sdXX_crypt /dev/disk/by-uuid/00000000-1111-2222-3333-444444444444 /dev/disk/by-id/usb-Corsair_Voyager_Mini_332677b71000b3-0:0-part2#256#0 luks,keyscript=/usr/local/sbin/usbkeyscript.sh 

What it says is that on the device called “usb-Corsair_Voyager_Mini_332677b71000b3-0:0-part2” there is a 256 bit key with the offset of 0 (right at the beginning).

Now update the initramfs:

sudo update-initramfs -u

Force-unplug-script

To make sure the usb device is not left in the machine, which would make all this security pretty useless, this script will stop the bootup process and force you to eject the device before it continues the boot process.

Put the script inside this file: “/etc/init.d/remove-usbkeydevice” and make it executable.

Please note that the variable “KEYDEVICE” should match the one we have the keyfile on. Otherwise this script will not work.

#!/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/usb-Corsair_Voyager_Mini_332677b71000b3-0:0-part2

# 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

Tell the system to run the script at startup:

sudo update-rc.d remove-usbkeydevice start 28 2 3 4 5 .

Regaining access to data on a unbootable system

If you end up with a computer that is as useful as a brick there is still hope. As all infomation about the encrypted disk lies within the disk it self you can still gain access to you data on a unbootable system.

This is not a security risk as data stays encrypted if you cannot provide the correct authentication, so don't worry.

You should take note that an encrypted disk is harder to recover if there is a physical problem with the harddisk or data has been corrupted in some way. This foxhole is only gonna work if the disk is in working condition to some degree.

Boot on a liveCD

To get onto the system you will need a liveCD/USB. I use the one created by Ubuntu.

LVM and cryptsetup may not be on the LiveCD by default. This is very simple to overcome, just get an Internet connection, open a console and run:

sudo apt-get install lvm2 cryptsetup

This should “install” the needed tools for the rest of this exercise.

Open encrypted device

Next we can open the encrypted device. I'll assume my encrypted partition is called /dev/sdd1:

sudo cryptsetup luksOpen /dev/sdd1 encdisk --key-file key.txt

This command opens /dev/sdd1 and gives it the logcial name encdisk. I'm also using a keyfile for authentication, you could also use a password if so is allowed by removing the statement “–key-file”.

We cannot read our files just yet as we're using LVM. If you're not you would be able to mount the filesystem now like this:

mount /dev/mapper/encdisk /media/encdisk

Activate LVM

With the device open we can now activate our volume group:

root@ubuntu:~# vgchange -ay
  2 logical volume(s) in volume group "volgrp" now active

If things go right you should now have access to the two logical volumes we made earlier. You can check it out by running:

root@ubuntu:~# ls /dev/mapper/ -l
total 0
crw-rw---- 1 root root  10, 61 2009-07-12 18:41 control
brw-rw---- 1 root disk 252,  0 2009-07-12 16:53 encdisk
brw-rw---- 1 root disk 252,  2 2009-07-12 16:53 volgrp-root
brw-rw---- 1 root disk 252,  1 2009-07-12 16:53 volgrp-swap

Here we see that we have the logical name (encdisk), that represent the interface to the encrypted disk, volgrp-swap that is the logical volume “swap” in the volume group “volgrp” and the logical volume “root” also in the volume group “volgrp” (volgrp-root).

Mount filesystems

Now with both the encrypted disk unlocked and the logical volumes activated we can start mounting the root filesystem and yet again see our beloved files ;)

root@ubuntu:/media# mkdir /media/lv-root
root@ubuntu:/media# mount /dev/mapper/volgrp-root /media/lv-root/
root@ubuntu:/media# cd /media/lv-root/
root@ubuntu:/media/lv-root# ls
bin    dev   initrd.img      lost+found  opt   sbin     sys  var
boot   etc   initrd.img.old  media       proc  selinux  tmp  vmlinuz
cdrom  home  lib             mnt         root  srv      usr  vmlinuz.old

Tadaa!!


Sources:

https://wiki.edubuntu.org/EncryptedFSRemovableKeyDeviceHowto

http://wejn.org/how-to-make-passwordless-cryptsetup.html

howtos/full_disk_encryption.txt · Last modified: 16/02/2023 07:21 by domingo