Difference between revisions of "LUKS"

From YobiWiki
Jump to navigation Jump to search
m
Line 68: Line 68:
 
dpkg-reconfigure linux-image-2.6.25-2-686
 
dpkg-reconfigure linux-image-2.6.25-2-686
 
Reboot
 
Reboot
  +
===Avoiding to type many times the LUKS password===
==TODO==
 
 
One major drawback on my setup (you don't see it here) is that I've several partitions encrypted as such and it leads to some problems:
 
One major drawback on my setup (you don't see it here) is that I've several partitions encrypted as such and it leads to some problems:
 
* At boot time I've to enter the passphrase for each of the partitions
 
* At boot time I've to enter the passphrase for each of the partitions
Line 77: Line 77:
 
** quintuple-agent could be used for example, but it has to be integrated into the initrd
 
** quintuple-agent could be used for example, but it has to be integrated into the initrd
 
** maybe a simple environment variable would be enough
 
** maybe a simple environment variable would be enough
  +
** In both cases I've to take care that the passphrase cannot be retrieved later from a RAM dump.
 
  +
That's finally the last solution I implemented, composed of one part that will join the initramfs and capture the LUKS password to tmpfs and one part that will use it during rc stage:
  +
  +
[{{#file:cryptoroot_persist}} /etc/initramfs-tools/hooks/cryptoroot_persist] (make it executable)
  +
<source lang=bash>
  +
#!/bin/sh
  +
  +
# List the soft prerequisites here. This is a space separated list of
  +
# names, of scripts that are in the same directory as this one, that
  +
# must be run before this one can be.
  +
#
  +
PREREQ=""
  +
  +
prereqs()
  +
{
  +
echo "$PREREQ"
  +
}
  +
  +
case $1 in
  +
# get pre-requisites
  +
prereqs)
  +
prereqs
  +
exit 0
  +
;;
  +
esac
  +
  +
. /usr/share/initramfs-tools/hook-functions
  +
  +
# Fix bug #486916 that copies /lib/cryptsetup/askpass to /lib/cryptsetup
  +
if [ -x /lib/cryptsetup/askpass ] && [ -f "$DESTDIR/lib/cryptsetup" ]; then
  +
rm -f "$DESTDIR/lib/cryptsetup"
  +
copy_exec /lib/cryptsetup/askpass
  +
fi
  +
  +
# Patch cryptroot script to export LUKS passphrase
  +
cat << EOF | patch -p0
  +
--- $DESTDIR/scripts/local-top/cryptroot 2008-06-13 23:58:53.000000000 +0200
  +
+++ $DESTDIR/scripts/local-top/cryptroot 2008-06-13 23:45:27.000000000 +0200
  +
@@ -182,8 +182,10 @@
  +
# Prepare commands
  +
if /sbin/cryptsetup isLuks \$cryptsource > /dev/null 2>&1; then
  +
cryptcreate="/sbin/cryptsetup -T 1 luksOpen \$cryptsource \$crypttarget"
  +
+ cryptpersist=true
  +
else
  +
cryptcreate="/sbin/cryptsetup -T 1 -c \$cryptcipher -s \$cryptsize -h \$crypthash create \$crypttarget \$cryptsource"
  +
+ cryptpersist=false
  +
fi
  +
cryptremove="/sbin/cryptsetup remove \$crypttarget"
  +
NEWROOT="/dev/mapper/\$crypttarget"
  +
@@ -205,6 +207,11 @@
  +
usplash_write "INPUTQUIET Enter password for \$crypttarget: "
  +
PASS="\$(cat /dev/.initramfs/usplash_outfifo)"
  +
echo -n "\$PASS" | \$cryptcreate > /dev/null 2>&1
  +
+ \$cryptpersist && echo -n "PASS=\$PASS" > /dev/.initramfs/pass
  +
+ elif \$cryptpersist; then
  +
+ PASS=\$(/lib/cryptsetup/askpass "Enter passphrase:" < /dev/console 2> /dev/console)
  +
+ echo -n "\$PASS" | \$cryptcreate > /dev/console 2>&1
  +
+ echo -n "PASS=\$PASS" > /dev/.initramfs/pass
  +
else
  +
\$cryptcreate < /dev/console > /dev/console 2>&1
  +
fi
  +
EOF
  +
  +
if [ $? -ne 0 ];
  +
then
  +
echo "An error occured in $0: patching cryptroot script failed" >&2
  +
exit 1
  +
fi
  +
  +
exit 0
  +
</source>
  +
And a [{{#file:cryptdisks.functions.diff}} patch for /lib/cryptsetup/cryptdisks.functions]
  +
<source lang=diff>
  +
--- /lib/cryptsetup/cryptdisks.functions 2008-03-31 16:36:32.000000000 +0200
  +
+++ /lib/cryptsetup/cryptdisks.functions 2008-06-13 23:51:39.000000000 +0200
  +
@@ -299,6 +299,8 @@
  +
tried=$(( $tried + 1 ))
  +
done
  +
else
  +
+ [ "$PASS" != "" ] && \
  +
+ echo -n "$PASS" | cryptsetup $PARAMS luksOpen "$src" "$dst" || \
  +
cryptsetup $PARAMS luksOpen "$src" "$dst" <&1 || tried="$TRIES"
  +
fi
  +
  +
@@ -576,6 +578,10 @@
  +
modprobe -qb dm-crypt || true
  +
dmsetup mknodes > /dev/null 2>&1 || true
  +
log_action_begin_msg "Starting $INITSTATE crypto disks"
  +
+ if [ -f /dev/.initramfs/pass ]; then
  +
+ . /dev/.initramfs/pass
  +
+ rm /dev/.initramfs/pass
  +
+ fi
  +
mount_fs
  +
  +
egrep -v "^[[:space:]]*(#|$)" "$TABFILE" | while read dst src key opts; do
  +
</source>

Revision as of 01:13, 19 June 2008

Documentation

To encrypt the swap

apt-get install cryptsetup

Follow instructions of /usr/share/doc/cryptsetup/CryptoSwap.HowTo
The diff is that I had to destroy the content of the swap partition before /etc/init.d/cryptdisks otherwise cryptsetup refuses to work.

To encrypt disks

Creation

cryptsetup luksFormat /dev/hdaX
cryptsetup luksOpen /dev/hdaX hdaX
mkfs.ext3 /dev/mapper/hdaX
cryptsetup luksClose hdaX

Usage

cryptsetup luksOpen /dev/hdaX hdaX && mount -t ext3 /dev/mapper/hdaX /mnt/
umount /mnt && cryptsetup luksClose hdaX

To encrypt the root fs

Get packages

To use the XTS block chaining method we need a recent kernel (>=2.6.24 and 2.6.24 had apparently a bug related to XTS on some CPUs so I went for 2.6.25)

apt-get install initramfs-tools cryptsetup linux-image-2.6.25-2-686

If you didn't have a separate /boot partition, make one in clear as we cannot boot on an encrypted kernel & initrd!

Have /boot on a separate partition

If it's not yet done, it's time!
Moving /boot to a separate partition involves a crucial step:
Recreating the MBR stage1 so it founds the new location of stage2
cf http://www.troubleshooters.com/linux/grub/grubpartition.htm
Assuming your /boot partition is /dev/[hs]da1, here's how you do it:

grub
grub> root (hd0,0)
grub> setup (hd0)
grub> quit

/boot/grub/menu.lst needs the following changes:

# groot=(hd0,0)
# splashimage=(hd0,0)/grub/...

FYI and to understand my instructions, here's my intended layout:

# /dev/sda1 /boot
# /dev/sda2 will be the encrypted /
# /dev/sda5 encrypted swap
# /dev/sda6 /home

reboot to your temp / after you've altered the table of partitions

Creation of the encrypted volume

Backup the original partition

dd if=/dev/sda2 of=./sda2.img bs=1024k

Fill it with random data

dd if=/dev/urandom of=/dev/sda2

Create a LUKS volume

cryptsetup luksFormat -c aes-xts-plain -s 256 /dev/sda2
YES
my_boot_password

Edit /etc/crypttab and add a ref to our new partition

echo "croot /dev/sda2 none luks" >> /etc/crypttab

Start the encrypted root filesystem (don't worry if your swap is already started)

/etc/init.d/cryptdisks start
my_boot_password

Setup the filesystem

mkfs.ext3 /dev/mapper/croot

Mount the device

mount /dev/mapper/croot /mnt/disk

Copy your root filesystem into place, sth like this in the simplest case

cp -axv / /mnt/disk

Make sure the root device is listed in /etc/fstab

/dev/mapper/croot / ext3 defaults 0 1

/boot/grub/menu.lst needs to point to /dev/mapper/croot:

# kopt=root=/dev/mapper/croot ro vga=791

Regenerate the initramfs image

dpkg-reconfigure linux-image-2.6.25-2-686

Reboot

Avoiding to type many times the LUKS password

One major drawback on my setup (you don't see it here) is that I've several partitions encrypted as such and it leads to some problems:

  • At boot time I've to enter the passphrase for each of the partitions
  • I tried the "noauto" keyword in /etc/crypttab to avoid mounting some of the partitions but it didn't work, I've to find out why.
  • One solution is to use a keyfile stored in the root partition to decrypt the other partitions but I don't want to give access to all partitions to those I give access to my rootfs (e.g. my homedir to my employer)
  • Another solution is to use keyfiles stored on a USB stick, which means I've to wear such USB stick and not getting it stolen aside my laptop...
  • The last solution I see is to implement something like the gpg or ssh agents to remember briefly my passphrase during boot time and try it against all partitions.
    • quintuple-agent could be used for example, but it has to be integrated into the initrd
    • maybe a simple environment variable would be enough

That's finally the last solution I implemented, composed of one part that will join the initramfs and capture the LUKS password to tmpfs and one part that will use it during rc stage:

[{{#file:cryptoroot_persist}} /etc/initramfs-tools/hooks/cryptoroot_persist] (make it executable)

#!/bin/sh

# List the soft prerequisites here.  This is a space separated list of
# names, of scripts that are in the same directory as this one, that
# must be run before this one can be.
#
PREREQ=""

prereqs()
{
	echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
	prereqs
	exit 0
	;;
esac

. /usr/share/initramfs-tools/hook-functions

# Fix bug #486916 that copies /lib/cryptsetup/askpass to /lib/cryptsetup
if [ -x /lib/cryptsetup/askpass ] && [ -f "$DESTDIR/lib/cryptsetup" ]; then
    rm -f "$DESTDIR/lib/cryptsetup"
    copy_exec /lib/cryptsetup/askpass
fi

# Patch cryptroot script to export LUKS passphrase
cat << EOF | patch -p0
--- $DESTDIR/scripts/local-top/cryptroot	2008-06-13 23:58:53.000000000 +0200
+++ $DESTDIR/scripts/local-top/cryptroot	2008-06-13 23:45:27.000000000 +0200
@@ -182,8 +182,10 @@
 	# Prepare commands
 	if /sbin/cryptsetup isLuks \$cryptsource > /dev/null 2>&1; then
 		cryptcreate="/sbin/cryptsetup -T 1 luksOpen \$cryptsource \$crypttarget"
+		cryptpersist=true
 	else
 		cryptcreate="/sbin/cryptsetup -T 1 -c \$cryptcipher -s \$cryptsize -h \$crypthash create \$crypttarget \$cryptsource"
+		cryptpersist=false
 	fi
 	cryptremove="/sbin/cryptsetup remove \$crypttarget"
 	NEWROOT="/dev/mapper/\$crypttarget"
@@ -205,6 +207,11 @@
 			usplash_write "INPUTQUIET Enter password for \$crypttarget: "
 			PASS="\$(cat /dev/.initramfs/usplash_outfifo)"
 			echo -n "\$PASS" | \$cryptcreate > /dev/null 2>&1
+			\$cryptpersist && echo -n "PASS=\$PASS" > /dev/.initramfs/pass
+		elif \$cryptpersist; then
+			PASS=\$(/lib/cryptsetup/askpass "Enter passphrase:" < /dev/console 2> /dev/console)
+			echo -n "\$PASS" | \$cryptcreate > /dev/console 2>&1
+			echo -n "PASS=\$PASS" > /dev/.initramfs/pass
 		else
 			\$cryptcreate < /dev/console > /dev/console 2>&1
 		fi
EOF

if [ $? -ne 0 ];
then
	echo "An error occured in $0: patching cryptroot script failed" >&2
	exit 1
fi

exit 0

And a [{{#file:cryptdisks.functions.diff}} patch for /lib/cryptsetup/cryptdisks.functions]

--- /lib/cryptsetup/cryptdisks.functions	2008-03-31 16:36:32.000000000 +0200
+++ /lib/cryptsetup/cryptdisks.functions	2008-06-13 23:51:39.000000000 +0200
@@ -299,6 +299,8 @@
 			tried=$(( $tried + 1 ))
 		done
 	else
+		[ "$PASS" != "" ] && \
+		echo -n "$PASS" | cryptsetup $PARAMS luksOpen "$src" "$dst" || \
 		cryptsetup $PARAMS luksOpen "$src" "$dst" <&1 || tried="$TRIES"
 	fi
 
@@ -576,6 +578,10 @@
 	modprobe -qb dm-crypt || true
 	dmsetup mknodes > /dev/null 2>&1 || true
 	log_action_begin_msg "Starting $INITSTATE crypto disks"
+	if [ -f /dev/.initramfs/pass ]; then
+	    . /dev/.initramfs/pass
+	    rm /dev/.initramfs/pass
+	fi
 	mount_fs
 
 	egrep -v "^[[:space:]]*(#|$)" "$TABFILE" | while read dst src key opts; do