Difference between revisions of "LUKS"

From YobiWiki
Jump to navigation Jump to search
 
(4 intermediate revisions by the same user not shown)
Line 5: Line 5:
 
== To encrypt the swap==
 
== To encrypt the swap==
 
apt-get install cryptsetup
 
apt-get install cryptsetup
Follow instructions of /usr/share/doc/cryptsetup/CryptoSwap.HowTo
+
Follow instructions of /usr/share/doc/cryptsetup/README.Debian.gz
 
<br>The diff is that I had to destroy the content of the swap partition before /etc/init.d/cryptdisks otherwise cryptsetup refuses to work.
 
<br>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 ===
+
== To encrypt disks ==
 
Creation
 
Creation
 
cryptsetup luksFormat /dev/hdaX
 
cryptsetup luksFormat /dev/hdaX
Line 13: Line 14:
 
mkfs.ext3 /dev/mapper/hdaX
 
mkfs.ext3 /dev/mapper/hdaX
 
cryptsetup luksClose hdaX
 
cryptsetup luksClose hdaX
  +
Adding more passphrases (8 slots are available, keyfiles can also be used)
  +
cryptsetup luksAdd /dev/hdaX
 
Usage
 
Usage
 
cryptsetup luksOpen /dev/hdaX hdaX && mount -t ext3 /dev/mapper/hdaX /mnt/
 
cryptsetup luksOpen /dev/hdaX hdaX && mount -t ext3 /dev/mapper/hdaX /mnt/
 
umount /mnt && cryptsetup luksClose hdaX
 
umount /mnt && cryptsetup luksClose hdaX
  +
 
==To encrypt the root fs==
 
==To encrypt the root fs==
 
===Get packages===
 
===Get packages===
Line 79: Line 83:
   
 
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:
 
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:
  +
  +
UPDATE: large changes between cryptsetup 2:1.0.6-1 and 2:1.0.6-4 required me to re-write the following hacks, check in the page history if you need an older version
   
 
[{{#file:cryptoroot_persist}} /etc/initramfs-tools/hooks/cryptoroot_persist] (make it executable)
 
[{{#file:cryptoroot_persist}} /etc/initramfs-tools/hooks/cryptoroot_persist] (make it executable)
Line 102: Line 108:
 
;;
 
;;
 
esac
 
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
 
# Patch cryptroot script to export LUKS passphrase
 
cat << EOF | patch -p0
 
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:58:53.000000000 +0200
+++ $DESTDIR/scripts/local-top/cryptroot 2008-06-13 23:45:27.000000000 +0200
+
+++ $DESTDIR/scripts/local-top/cryptroot 2008-06-13 23:45:27.000000000 +0200
@@ -182,8 +182,10 @@
+
@@ -203,8 +203,10 @@
# Prepare commands
+
# Prepare commands
if /sbin/cryptsetup isLuks \$cryptsource > /dev/null 2>&1; then
+
if /sbin/cryptsetup isLuks \$cryptsource > /dev/null 2>&1; then
cryptcreate="/sbin/cryptsetup -T 1 luksOpen \$cryptsource \$crypttarget"
+
cryptcreate="/sbin/cryptsetup -T 1 luksOpen \$cryptsource \$crypttarget"
+ cryptpersist=true
+
+ cryptpersist=true
else
+
else
cryptcreate="/sbin/cryptsetup -T 1 -c \$cryptcipher -s \$cryptsize -h \$crypthash create \$crypttarget \$cryptsource"
+
cryptcreate="/sbin/cryptsetup -T 1 -c \$cryptcipher -s \$cryptsize -h \$crypthash create \$crypttarget \$cryptsource"
+ cryptpersist=false
+
+ cryptpersist=false
fi
+
fi
cryptremove="/sbin/cryptsetup remove \$crypttarget"
+
cryptremove="/sbin/cryptsetup remove \$crypttarget"
NEWROOT="/dev/mapper/\$crypttarget"
+
NEWROOT="/dev/mapper/\$crypttarget"
@@ -205,6 +207,11 @@
+
@@ -229,11 +231,20 @@
  +
fi
usplash_write "INPUTQUIET Enter password for \$crypttarget: "
 
  +
PASS="\$(cat /dev/.initramfs/usplash_outfifo)"
 
  +
echo -n "\$PASS" | \$cryptcreate > /dev/null 2>&1
 
 
+ if \$cryptpersist; then
+ \$cryptpersist && echo -n "PASS=\$PASS" > /dev/.initramfs/pass
 
  +
+ PASS=\$(crypttarget="\$crypttarget" cryptsource="\$cryptsource" \$cryptkeyscript "\$cryptkey")
+ elif \$cryptpersist; then
 
  +
+ if ! echo -n "\$PASS" | \$cryptcreate --key-file=- ; then
+ PASS=\$(/lib/cryptsetup/askpass "Enter passphrase:" < /dev/console 2> /dev/console)
 
  +
+ message "cryptsetup: cryptsetup failed, bad password or options?"
+ echo -n "\$PASS" | \$cryptcreate > /dev/console 2>&1
 
  +
+ continue
+ echo -n "PASS=\$PASS" > /dev/.initramfs/pass
 
  +
+ fi
else
 
 
+ echo -n "PASS=\$PASS" > /dev/.initramfs/pass
\$cryptcreate < /dev/console > /dev/console 2>&1
 
  +
+ else
fi
 
  +
if ! crypttarget="\$crypttarget" cryptsource="\$cryptsource" \\
  +
\$cryptkeyscript "\$cryptkey" | \$cryptcreate --key-file=- ; then
  +
message "cryptsetup: cryptsetup failed, bad password or options?"
  +
continue
  +
fi
  +
+ fi
  +
  +
if [ ! -e "\$NEWROOT" ]; then
  +
message "cryptsetup: unknown error setting up device mapping"
 
EOF
 
EOF
   
 
if [ $? -ne 0 ];
 
if [ $? -ne 0 ];
 
then
 
then
echo "An error occured in $0: patching cryptroot script failed" >&2
+
echo "An error occured in $0: patching cryptroot script failed" >&2
exit 1
+
exit 1
 
fi
 
fi
   
Line 150: Line 157:
 
And a [{{#file:cryptdisks.functions.diff}} patch for /lib/cryptsetup/cryptdisks.functions]
 
And a [{{#file:cryptdisks.functions.diff}} patch for /lib/cryptsetup/cryptdisks.functions]
 
<source lang=diff>
 
<source lang=diff>
--- /lib/cryptsetup/cryptdisks.functions 2008-03-31 16:36:32.000000000 +0200
+
--- /lib/cryptsetup/cryptdisks.functions 2008-08-10 13:15:10.000000000 +0200
+++ /lib/cryptsetup/cryptdisks.functions 2008-06-13 23:51:39.000000000 +0200
+
+++ /lib/cryptsetup/cryptdisks.functions 2008-08-10 13:20:37.000000000 +0200
@@ -299,6 +299,8 @@
+
@@ -313,6 +313,11 @@
  +
PARAMS="$PARAMS --key-file=$key"
tried=$(( $tried + 1 ))
 
done
 
else
 
+ [ "$PASS" != "" ] && \
 
+ echo -n "$PASS" | cryptsetup $PARAMS luksOpen "$src" "$dst" || \
 
cryptsetup $PARAMS luksOpen "$src" "$dst" <&1 || tried="$TRIES"
 
fi
 
 
 
  +
while [ "$tried" -lt "$TRIES" ]; do
@@ -576,6 +578,10 @@
 
 
+ if [ "$PASS" != "" ]; then
modprobe -qb dm-crypt || true
 
 
+ if echo -n "$PASS" | cryptsetup $PARAMS luksOpen "$src" "$dst"; then
dmsetup mknodes > /dev/null 2>&1 || true
 
  +
+ break
log_action_begin_msg "Starting $INITSTATE crypto disks"
 
  +
+ fi
+ if [ -f /dev/.initramfs/pass ]; then
 
+ . /dev/.initramfs/pass
+
+ fi
  +
if [ -n "$KEYSCRIPT" ]; then
+ rm /dev/.initramfs/pass
 
  +
if "$KEYSCRIPT" "$keyscriptarg" | cryptsetup $PARAMS luksOpen "$src" "$dst"; then
+ fi
 
  +
break
mount_fs
 
 
@@ -619,6 +624,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
+
egrep -v "^[[:space:]]*(#|$)" "$TABFILE" | while read dst src key opts; do
 
</source>
 
</source>
 
We can go one step further by
 
We can go one step further by
  +
 
===Enabling autologin===
 
===Enabling autologin===
 
Indeed we already did the hardest security step: providing the LUKS password, so why should I prove I know my user password as well, sth so easy to circumvent with a LiveCD...
 
Indeed we already did the hardest security step: providing the LUKS password, so why should I prove I know my user password as well, sth so easy to circumvent with a LiveCD...

Latest revision as of 15:22, 4 January 2017

Documentation

To encrypt the swap

apt-get install cryptsetup

Follow instructions of /usr/share/doc/cryptsetup/README.Debian.gz
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

Adding more passphrases (8 slots are available, keyfiles can also be used)

cryptsetup luksAdd /dev/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:

UPDATE: large changes between cryptsetup 2:1.0.6-1 and 2:1.0.6-4 required me to re-write the following hacks, check in the page history if you need an older version

[{{#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

# 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
@@ -203,8 +203,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"
@@ -229,11 +231,20 @@
                fi
 
 
+               if \$cryptpersist; then
+                       PASS=\$(crypttarget="\$crypttarget" cryptsource="\$cryptsource" \$cryptkeyscript "\$cryptkey")
+                       if ! echo -n "\$PASS" | \$cryptcreate --key-file=- ; then
+                               message "cryptsetup: cryptsetup failed, bad password or options?"
+                               continue
+                       fi
+                       echo -n "PASS=\$PASS" > /dev/.initramfs/pass
+               else
                if ! crypttarget="\$crypttarget" cryptsource="\$cryptsource" \\
                     \$cryptkeyscript "\$cryptkey" | \$cryptcreate --key-file=- ; then
                        message "cryptsetup: cryptsetup failed, bad password or options?"
                        continue
                fi
+               fi
 
                if [ ! -e "\$NEWROOT" ]; then
                        message "cryptsetup: unknown error setting up device mapping"
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-08-10 13:15:10.000000000 +0200
+++ /lib/cryptsetup/cryptdisks.functions        2008-08-10 13:20:37.000000000 +0200
@@ -313,6 +313,11 @@
        PARAMS="$PARAMS --key-file=$key"
 
        while [ "$tried" -lt "$TRIES" ]; do
+               if [ "$PASS" != "" ]; then
+                       if echo -n "$PASS" | cryptsetup $PARAMS luksOpen "$src" "$dst"; then
+                               break
+                       fi
+               fi
                if [ -n "$KEYSCRIPT" ]; then
                        if "$KEYSCRIPT" "$keyscriptarg" | cryptsetup $PARAMS luksOpen "$src" "$dst"; then
                                break
@@ -619,6 +624,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

We can go one step further by

Enabling autologin

Indeed we already did the hardest security step: providing the LUKS password, so why should I prove I know my user password as well, sth so easy to circumvent with a LiveCD...
To enable autologin, you can use GDM or KDM facilities or (as I'm used of launching startx manually) you can choose a lighter way:
Add to /etc/inittab:

9:2345:respawn:/sbin/getty -L -n -l /usr/local/sbin/autologin 38400 tty9

This will launch another getty on tty9 without login prompt but a call to a handmade script /usr/local/sbin/autologin:

#!/bin/sh
/bin/login -f phil AUTOX=true

And so if you want startx to be called automatically you can add to your ~/.bash_profile:

if [[ $AUTOX = true ]]
then
    AUTOX=false
    startx
    logout
fi

This method was taken from an article in Linux Mag France no 107. I added the AUTOX=false otherwise calls to "xterm -ls" in the graphical session would fail.