You are not logged in.

#1 2012-01-01 18:09:32

ozon-eatar
Member
From: Sweden
Registered: 2011-10-02
Posts: 6

Encrypt partitions with LUKS and keyfiles on USB +swap suspend-to-disk

This guide is used to install your Archlinux system on several encrypted LUKS partitions using keyfiles located on a USB-stick. This also includes how to encrypt swap with a keyfile and suspend-to-disk support.

Table of content

Background
Disclaimer
1. Start the Archlinux live CD
2. Erase your HDD and USB-stick
3. Partition your HDD
4. Format and mount your USB-stick
5. Create keyfiles
6. Create LUKS partitions
7. Open the LUKS partitions
8. Start the Arch installer
9. Install necessery scripts
10. Edit crypttab
11. Done!
12. Extra - Encrypt SWAP with keyfile and suspend-to-disk support
References


Background

It's already supported in Archlinux to have a encrypted root via the encrypt hook, but it only deals with the root partition of a system. Later in the boot proccess rc.sysinit takes care of any remaining encrypted partition via the /etc/crypttab but only if the keys (for which the partitions were encrypted with) are located on the now unencrypted root partition. However, I wanted to be able to keep all of my keyfiles on my USB-stick, not just the key to root. Having the keys outside of an encrypted root is also a necessity if you want to have suspend-to-disk support.


Disclaimer!

I take no responsibility if your system becomes unuseable or if you experience data loss!
Do this at your own risk!

Also note that the keyfiles will be unencrypted on the USB-stick, so if someone steals/copies your USB-stick and gets a hold of your system they will be able to unlock it. This is safe enough for me as I almost always carry my USB-stick with me. If you want things to be even more secure you probably can encorporate this guide on how to use gpg to encrypt your keyfiles.

If you are unfamiliar with encryption with LUKS on Linux, read the Archwiki on the subject, it's quite long and a bit messy in my opinion but all in all very good.

1. Start the Archlinux live CD
Boot up your computer with Archlinux live CD, change keymap and consolefont if you don't use standard but don't start the installer yet.

2. Erase your HDD and USB-stick
Disclaimer: This will DELETE EVERYTHING on your HDD and USB-stick!
In my setup I only have one HDD (/dev/sda) and the USB-stick (/dev/sdb) connected. To erase them I overwrite the entire storagespace with random data:

dd if=/dev/urandom of=/dev/sda bs=4M
dd if=/dev/urandom of=/dev/sdb bs=4M

"bs=4M" is only there to speed up the process a bit, but if your HDD is big (>500GB) it can take many hours to finish the erasure, obviously depending on how fast your HDD is. Also note that if you have several HDDs in your computer the /dev/sdX name can change between boots, for example /dev/sda can become /dev/sdb and so on. So be sure to have identified the rigth HDD before running the command.

3. Partition your HDD and USB-stick
Use fdisk or parted to partition your harddrive and USB to your liking, myself I used this scheme:

HDD
/dev/sda1 - boot
/dev/sda2 - root
/dev/sda3 - swap
/dev/sda4 - tmp
/dev/sda5 - var
/dev/sda6 - home

USB
/dev/sdb1 - "Generic storage"
/dev/sdb2 - keys

I put a small 50MB partiton (/dev/sdb2) at the end of the USB-stick just to have the keys by them selfs, also Windows usually don't find anything but the first partition on USB-sticks, which makes me feel a little more secure when lending it to my friends wink

4. Format and mount your USB-stick
Create an ext2 filesystem on /dev/sdb2 and mount it:

mkfs.etx2 /dev/sdb2
mkdir /media/usb
mount /dev/sdb2 /media/usb

Don't mount anything on /mnt as the Arch installer will be using this directory

5. Create keyfiles
Make a directory on the newly mounted USB-stick, enter it and then we can start creating our keys:

mkdir /media/usb/keys
cd /media/usb/keys

Make one key for every encrypted partition your going to have, in my case; root, swap, tmp, var, home. The boot partition must be unencrypted.

dd if=/dev/urandom of=./root.key bs=512 count=4
dd if=/dev/urandom of=./swap.key bs=512 count=4
...

You can name the folder and the keyfiles to something less obvious, just change the remaining steps accordingly.

6. Create LUKS partitions
Start with verifying that the device mapper module is loaded:

modprobe dm_mod

The basic syntax for creating a LUKS-encrypted partiton is:

cryptsetup -c <desired cipher> -s <key size> -v luksFormat /dev/<partiton to encrypt> /path/to/keyfile

For example I used this for my partitions:

cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -v luksFormat /dev/sda2 ./root.key
cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -v luksFormat /dev/sda3 ./swap.key
...

7. Open the LUKS partitions
To be able to install Arch on the encrypted partitions they need to be opened:

cryptsetup -d /path/to/keyfile luksOpen /dev/<encrypted partition> <device-mapper name>

For example in my case:

cryptsetup -d /media/usb/keys/root.key luksOpen /dev/sda2 eroot
cryptsetup -d /media/usb/keys/swap.key luksOpen /dev/sda3 eswap
...

If you can see /dev/mapper/eroot, /dev/mapper/eswap and so forth, everything has worked.

8. Start the Arch installer
Start the Archlinux installer by issuing the command:

/arch/setup

Follow steps 1 to 3
At step 4 (Prepare hard drive(s), select “3 – Manually Configure block devices, filesystems and mountpoints. Choose /dev/sda1 as /boot, /dev/mapper/eroot for /, /dev/mapper/eswap for swap, /dev/mapper/etmp for /tmp, /dev/mapper/evar for /var and /dev/mapper/ehome for /home.
Format all drives (choose “yes” when asked “do you want to have this filesystem (re)created”). Choose the correct filesystem for all devices; use swap for /dev/mapper/eswap, for the rest, I chose ext3.

Select DONE to start formatting.

At step 5 (Select packages), select grub as boot loader. Select the base group. Add mkinitcpio.

Start step 6 (Install packages).

Go to step 7 (Configure System).
Edit mkinitcpio.conf so in looks like this (the hooks must be in this order!):

HOOKS="... usb encrypt ... filesystems ..."
MODULES="... ext2 ... ext3 ..."

The modules are needed because my root-partition is ext3 and the USB-sticks key partiton is ext2.

Edit /etc/fstab so it looks something like this:

/dev/sda1 /boot ext2 defaults 0 1
/dev/mapper/eroot / ext3 defaults 0 1
/dev/mapper/eswap swap swap defaults 0 1
/dev/mapper/etmp /tmp ext3 defaults 0 1
/dev/mapper/evar /var ext3 defaults 0 1
/dev/mapper/ehome /home ext3 defaults 0 1

It's better to use UUIDs to be safe, my /etc/fstab looks like this:

tmpfs           /tmp    tmpfs   nodev,nosuid    0       0
UUID=0042e70b-c75c-4d90-9fd6-5aae1b6aba70 /tmp reiserfs defaults 0 1
UUID=011c4a3d-d51f-4112-8b7e-3ffa0852c364 /boot ext2 defaults 0 1
UUID=43f90e25-7285-4002-a59d-fb4bbef32636 swap swap defaults 0 0
UUID=46f2307d-3253-4849-babd-c9733338109b /home ext3 defaults 0 1
UUID=c6674288-7f52-458a-8106-40b34f51e5b7 /usr ext3 defaults 0 1
UUID=ed57da12-6cc5-4463-af47-72c66654b9c0 / ext3 defaults 0 1
UUID=f07fd3db-9d59-4832-9d7b-1e6caf104787 /var reiserfs defaults 0 1

The rest you can configure as you normaly would

Go to step 8 (install boot loader).
Be sure to change the kernel line in menu.lst:

kernel /vmlinuz-linux root=/dev/mapper/eroot cryptdevice=/dev/sda2:eroot cryptkey=/dev/sdb1:ext2:/keys/root.key ro

And with UUID:

kernel /vmlinuz-linux root=/dev/mapper/eroot cryptdevice=/dev/disk/by-uuid/6a4d86f5-c194-434d-a9f1-869868f07583:eroot cryptkey=/dev/disk/by-uuid/011c4a3d-d51f-4112-8b7e-3ffa0852c364:ext2:/keys/root.key ro

The syntax for cryptdevice and cryptkey is:

cryptdevice=device:device-mapper-name
cryptkey=device:fs-type:path

Install the bootloader to /dev/sda (HDD)
Now, we can exit the installer.

9. Install necessery scripts
As the encrypt hook in initrd only decrypts the root partition, and rc.sysinit by default only can decrypt non-root partitons with keys located on root we need two scripts. The first script mounts the USB-stick so rc.sysinit can access the keys and the second unmounts the USB-stick so you just can yank it out after successful boot. Both of these needs to be placed in /mnt/etc/rc.d/functions/ (/etc/rc.d/functions/ of the installation).

You only need to adapt two varibles in this file to fit your system; EXT_STO_DEV and EXT_FILESYS

mount_key_dev:

mount_key_dev()
{

        KEY_TMP_DIR="/tmp_cryptionkeys"
        KEY_DEV="USB"
        EXT_STO_DEV="/dev/disk/by-uuid/xxxxxxxxx"
        EXT_FILESYS="ext2"

        echo ":: Accessing cryptkeys on $KEY_DEV"

        findmnt / --options rw &> /dev/null || mount -n -o remount,rw / 

        echo ":: Creating temporary directory..."  
        if [[ -d "$KEY_TMP_DIR" ]]; then 
           echo ":: Directory not created: Directory already exists can't ensure the successful completion of the script"
        else
           mkdir "$KEY_TMP_DIR" &> /dev/null
           if [[ -d "$KEY_TMP_DIR" ]]; then
              echo ":: Directory created"
           else
              echo ":: Directory not created: Reason unknown"
           fi
        fi 

        echo ":: Detecting external storage device..."
        if [[ -L "$EXT_STO_DEV" ]]; then 
           echo ":: Device detected" 
        else
           echo ":: Device not detected"
        fi

        echo ":: Mounting storage device..." 
        if mountpoint -q "$KEY_TMP_DIR"; then 
           echo ":: Mount failed: Directory already a mountpoint"
        else
           mount -t "$EXT_FILESYS" "$EXT_STO_DEV" "$KEY_TMP_DIR" &> /dev/null
           if mountpoint -q "$KEY_TMP_DIR"; then 
              echo ":: Mount successful"
           else
              echo ":: Mount failed: Reason unknown"
           fi
        fi

        findmnt / --options ro &> /dev/null || mount -n -o remount,ro / 
}
add_hook sysinit_udevsettled mount_key_dev
add_hook single_udevsettled mount_key_dev

Nothing needs to be changed in this following file, just check that KEY_TMP_DIR is the same in both files.

umount_key_dev:

umount_key_dev()
{
        KEY_TMP_DIR="/tmp_cryptionkeys"

        findmnt / --options rw &> /dev/null || mount -n -o remount,rw /

        echo ":: Unmounting storage device..."
        if mountpoint -q "$KEY_TMP_DIR"; then 
           umount -n "$KEY_TMP_DIR"
           if mountpoint -q "$KEY_TMP_DIR"; then 
              echo "Unmounting failed: Reason unknown" 
           else
              echo ":: Unmounting successful"
           fi
        else
           echo ":: Unmounting failed: Nothing is mounted on $KEY_TMP_DIR"
        fi

        echo ":: Deleting temporary directory..."
        if [[ -d "$KEY_TMP_DIR" ]]; then
           rmdir "$KEY_TMP_DIR"
           if [[ -d "$KEY_TMP_DIR" ]]; then
              echo ":: Deleting failed: Reason unknown"
           else
              echo ":: Directory successfully deleted"
           fi
        else
           echo ":: Deleting failed: Directory doesn\'t exists"
        fi

        findmnt / --options ro &> /dev/null || mount -n -o remount,ro / 
}
add_hook sysinit_prefsck umount_key_dev
add_hook single_prefsck umount_key_dev

10. Edit /etc/crypttab
We also need to edit /etc/crypttab (which is located in /mnt/etc/crypttab), here we place all non-root encrypted partitions and the path to there respective keyfile:

# NAME          SOURCE DEVICE           PASSWORD                OPTIONS

eswap            /dev/disk/by-uuid/cf0e652e-0c56-4a28-a471-83f4c726375b  /tmp_cryptionkeys/keys/swap.key
eusr             /dev/disk/by-uuid/c212bddc-ada4-4dbf-af11-83ab769c2906  /tmp_cryptionkeys/keys/usr.key
etmp             /dev/disk/by-uuid/cb832eb6-fb96-42d9-8015-ff47d27157fe  /tmp_cryptionkeys/keys/tmp.key
evar             /dev/disk/by-uuid/796a2249-7c74-4560-92a4-eb95ada09b8b  /tmp_cryptionkeys/keys/var.key
ehome            /dev/disk/by-uuid/6af04c0e-b2f8-4624-9955-dbb811374105  /tmp_cryptionkeys/keys/home.key

Note that this are the UUIDs of the unencrypted partitions and not the UUID of the filesystems on the encrypted partitions, I got confused over this the first time I did it. Also note that if you change KEY_TMP_DIR in the scripts in the previous step the path in crypttab (/tmp_cryptionkeys/) needs to change to.

11. Done!
You are now done and can reboot your system! Hopefully it will boot wink

12. Extra - Encrypt SWAP with keyfile and suspend-to-disk support
I have tried the scripts that follow and they work but I have not acually tried to resume from suspend-to-disk

It is easiest to add suspend-to-disk support after you have a working encrypted system.

In the Archwiki it is discouraged to use a keyfile to encrypt swap, thats because the original scripts in the wiki would store the key to the swap in initrd, which is keept on the unencrypted /boot partition. This can be fixed by using a hook in initrd to mount our USB-stick and retrive the keyfile from there.

Create this file /lib/initcpio/hooks/openswap, the only thing you need to change is the varibles in the begining of the script:

# vim: set ft=sh:
run_hook ()
{
        KEY_TMP_DIR="/swapckey"
        EXT_STO_DEV="/dev/disk/by-uuid/xxxxxxxxxx"
        EXT_FILESYS="ext2"
        SWAP_LUKS_NAME="eswap"
        SWAP_DEV="/dev/disk/by-uuid/xxxxxxxxxxx" 
        KEY_PATH="/keys/swap.key"

        echo "[openswap] Creating temporary directory..." 
        if [[ -d "$KEY_TMP_DIR" ]]; then
           echo "Directory not created: Directory already exists can't ensure the successful completion of the script"
        else
           /bin/mkdir "$KEY_TMP_DIR" &> /dev/null
           if [[ -d "$KEY_TMP_DIR" ]]; then
              echo "[openswap] Directory created"
           else
              echo "[openswap] Directory not created: Reason unknown
           fi
        fi

        echo "[openswap] Detecting external storage device..."
        while [[ ! -L "$EXT_STO_DEV" ]]; do
        done 
        echo "[openswap] External storage device detected"

        echo "[openswap] Mounting storage device..."
        if /bin/mountpoint -q "$KEY_TMP_DIR"; then 
           echo "[openswap] Mount failed: Directory already a mountpoint"
        else
           /bin/mount -t "$EXT_FILESYS" "$EXT_STO_DEV" "$KEY_TMP_DIR" &> /dev/null
           if /bin/mountpoint -q "$KEY_TMP_DIR"; then 
              echo "[openswap] Mount successful"
           else
              echo "[openswap] Mount failed: Reason unknown"
           fi
        fi

        echo "[openswap] Detecting swap partition..."
        if [[ -L "$SWAP_DEV" ]]; then 
           echo "[openswap] Swap partition detected"
        else
           echo "[openswap] Swap not detected: Reason unknown"
        fi

        echo "[openswap] Decrypting swap..."
        if [[ -L /dev/mapper/"$SWAP_LUKS_NAME" ]]; then 
           echo "[openswap] Can't decrypt swap: /dev/mapper/$SWAP_LUKS_NAME already in use"
        else
           /bin/cryptsetup -d "$KEY_TMP_DIR""$KEY_PATH" luksOpen "$SWAP_DEV" "$SWAP_LUKS_NAME" &> /dev/null
           echo "[openswap] Swap decrypted"
        fi

        echo "[openswap] Unmounting storage device..."
        if /bin/mountpoint -q "$KEY_TMP_DIR"; then
           /bin/umount "$KEY_TMP_DIR" &> /dev/null
           echo "[openswap] Unmount successful"
        else
           echo "[openswap] Unmount failed: Reason unknown”
        fi

        echo "[openswap] End of script"
}

Also create /lib/initcpio/install/openswap:

# vim: set ft=sh:

build ()
{
        MODULES="ext2"
        BINARIES="/bin/mountpoint"
        FILES=""
        SCRIPT="openswap"
}
help ()
{
cat<<HELPEOF
   This mounts an external storage device so the keyfile to the encrypted swap can be accessed
HELPEOF
}

After these scripts are created you need to edit /etc/mkinitcpio.conf and add openswap and resume (they must be in this order):

HOOKS="... usb encrypt openswap resume filesystems ..."

Also edit /boot/grub/menu.lst, add resume to the kernel line:

kernel /vmlinuz-linux root=/dev/mapper/eroot cryptdevice=/dev/sda2:eroot cryptkey=/dev/sdb1:ext2:/keys/root.key resume=/dev/mapper/eswap ro

That is it! You should now be able to suspend-to-disk smile

References:
https://wiki.archlinux.org/index.php/Sy … _with_LUKS
https://wiki.archlinux.org/index.php/Arch_Boot_Process
http://www.saout.de/misc/dm-crypt/
http://code.google.com/p/cryptsetup/
http://archlinux.me/brain0/2010/02/13/e … rch-linux/
https://wiki.archlinux.org/index.php/Mkinitcpio
https://bbs.archlinux.org/viewtopic.php?id=97498
https://bbs.archlinux.org/viewtopic.php?id=114099
https://bbs.archlinux.org/viewtopic.php?id=120243

EDIT = Corrected some misstakes

Last edited by ozon-eatar (2012-01-14 00:30:38)

Offline

Board footer

Powered by FluxBB