disk encryption
securitydata_securitydisk_encryption

Ratio: Why?

Encryption comes at a price: You will have to spend time on it, because you have to decide how to do it and you will permanently use computing resources when using it. But what seems to be unattractive can pay out in situations, when your drive can be accessed by any foreigners, which might include:

  • a person who has stolen it from you
  • if your drive has failed and you returned it for guarantee the manufacturer will not repair exactly your drive, but will in most cases collect them and send you an already repaired drive back, which someone else had sent in before

Choosing an encryption algorithm

This really is a problem, because you never know which algorithm will be proven to be insecure tomorrow. Sadly the cryptsetup command expects a not well documented format for its --cipher parameter. The man page just says that it defaults to aes-xts-plain64 when using LUKS. I found two methods to find out which encryptions are supported by your kernel. First and recommend is the usage of

cryptsetup benchmark

which is supposed to compare the performance of those implementations on your hardware. In rare cases you might find some more with

sudo find /lib/modules/`uname -r`/kernel/crypto/* -type f -printf '%20ft' -exec modinfo -d '{}' \; | egrep -i "(cipher|crypto).*algorithm"

mount on boot

prepare your usb stick

This will erase all data and label your stick 'usb-key':

mkfs.ext2 -L usb-key /dev/sdX

automatically mount the usb stick

I suggest you use the following line to mount the stick. It will create a directory /mnt/.usb-key on itsown giving it rw- --- --- permissions by default and it will silently ignore a missing stick:

# /etc/fstab
LABEL=usb-key /mnt/.usb-key ext2 defaults,nofail,x-mount.mkdir=600 0 0

The trick will then be, that current systems are using systemd even to mount entries found in the fstab and thus allowing us to define dependencies.

automatically mount

Because there is no support for external luks headers available in systemd at the time of writing (also there is a patch) we need another solution in order to mount the stick before opening the luks-device and mounting it. I used a service to do so:

# /usr/lib/systemd/system/encrypt.service
[Unit]
Description=encryption
Requires=mnt-usbkey.mount

[Service]
ExecStartPre=/sbin/cryptsetup --header /mnt/.usb-key/.luks/luks-header.raw --key-file /mnt/.usb-key/.luks/entropy.key --type luks open /dev/zpool/crypted crypted
ExecStartPre=/bin/umount /mnt/.usb-key/
ExecStartPre=/bin/rmdir /mnt/.usb-key/
ExecStart=/bin/mount /dev/mapper/crypted /mnt/crypted
Type=oneshot
RemainAfterExit=yes
ExecStop=/bin/umount /dev/mapper/crypted
ExecStopPost=/sbin/cryptsetup luksClose crypted

[Install]
WantedBy=multi-user.target

Unlock using the master key

cryptsetup --type plain --cipher=twofish-xts-plain64 --key-size=512 --key-file=/media/masterkey.raw open /dev/sde sde
cryptsetup --type plain --cipher=twofish-xts-plain64 --key-size=512 --hash=plain --key-file=/media/masterkey.raw open /dev/sde sde 
/usr/lib/systemd/systemd-cryptsetup attach sde /dev/disk/by-id/[your-device] /[file-with-header] plain,hash=plain,cipher=twofish-xts-plain64,size=512

Recover a lost key

It is trivial, that as long as your device is accessible the key must be somewhere in the random access memory and can be read. You don't have to work for the NSA to find it, because dmcrypt provides everything you need:

dmsetup table --showkeys /dev/mapper/name-of-cryptdevice

will output everything you need to reproduce a key, which can be used independant from LUKS and is an ascii representation of what is meant to be binary. So copy the key into the hexeditor of your choice (or do with xxd) and create a new LUKS header like so:

echo 'yourverysecretkey' | xxd -r -p > masterkey.raw
cryptsetup luksFormat --master-key-file masterkey.raw --header new_luks_header.raw
dd if=new_luks_header.raw of=/dev/sdluksdevice

From man cryptsetup: For luksFormat this allows creating a LUKS header with this specific master key. If the master key was taken from an existing LUKS header and all other parameters are the same, then the new header decrypts the data encrypted with the header the master key was taken from This method is also described officially

Kernel command line

In order to mount the root file system from an encrypted disk a linux kernel usually maps a representative device for the encrypted physical disk under /dev/mapper. The name for the disk there can be freely chosen and there are many ways to do that. The manual method is described above and simply uses cryptsetup open <device> name. But to boot the system it is impractical and there are two big approaches to get this done automatically: systemd and kernel parameters.

systemd

Arch linux has a sd-encrypt hook to replace the encrypt hook. It should work out of the box, but if an initramfs*.img file is copied from another machine without the correct /etc/crypttab entries, there is no way for the image to know which disk should be made available as a root file system, but it can be told where to find it with kernel parameters:

rd.luks.uuid=XXXX-XXXX-XXXX-XXXX
rd.luks.name=XXXX-XXXX-XXXX-XXXX=somename
root=/dev/mapper/somename

kernel

The kernel component responsible for encryption is called the crypt target of the device mapper or dm-crypt in short. It is a little easier to use as the systemd approach above, e.g. with:

cryptdevice=UUID=XXXX-XXXX-XXXX-XXXX=name root=/dev/mapper/name
cryptdevice=/dev/sda1=mysda1 root=/dev/mapper/mysda1
top