Dm-crypt full disk encryption

This article aims to get started with DM-Crypt LUKS to be able to install a new system from scratch, using Gentoo installation documents for example, and generate an initramfs with that in no time. For those new to this DM stands for Device-mapper, a kernel module for logical volume management. So this article will skip right away the premises on why to encrypt a system with DM-Crypt LUKS and on security insights. That said, encrypting a system with DM-Crypt LUKS will immediately put you in a position to choose between security versus usability, and secure versus system speed/responsiveness.

Which cipher:hash combination?
The default cipher for LUKS is nowadays, i.e. AES as cipher and XTS as mode of operation. This should be changed only under very rare circumstances. The default is a very reasonable choice security wise and by far the best choice performance wise that can deliver between 2-3 GiB/s encryption/decryption speed on CPUs with AES-NI (for CPUs introduced around 2015). XTS uses two AES keys, hence possible key sizes are  and.

Default choice of cipher and key size can be overriden by the command line parameters  and , for example

If you want to know more about the performance on a given set of cipher and mode of operation you can run. Issuing the command without  and   runs the benchmark for a number of different choices. For example, a (slightly shortened) output for a mid-2014 Intel Core i7 CPU might look like:

What choice of hash for key derivation?
LUKS uses PBKDF2 for key derivation. In essence, the supplied passphrase by the user is combined with a salt and hashed a specified number of rounds. This key stretching makes the password more secure against brute force attacks. The hash function used in PBKDF2 can be set via  (the default is  ). The total number of iterations is determined by the speed of the current hardware and can be influenced by setting the number of milliseconds that shall be spent in PBKDF2 passphrase processing by. To increase the default from 2s to 3s and use sha512 one could for example use

On passphrases, detached LUKS headers, and (encrypted) keyfiles
A reasonably long passphrase (use, e.g., 8-12 common random words, see xkcd on that subject) in combination with PBKDF2 for key stretching can be considered a reasonably secure setup.

Additional protection against brute force attacks can be achieved by setting up a an external USB flash drive to store essential decryption information (like a keyfile, or the LUKS header itself). The flash drive then has the equivalent function of a physical key; opening the encrypted partition is only possible if both, flash drive and passphrase, are provided. However, this comes with a significant downside in terms of complexity, for example for setting up full disk encryption, or potential to loose decryption keys (by loosing the USB flash drive).

Detached LUKS header
It is possible to encrypt a partition with detached LUKS header (where all information about password derivation is stored) that is stored at (physically) different location, e.g., a USB flash drive. This leaves an attacker that is not in possession of the flash drive with no information about key derivation and encryption algorithms used. This makes brute force attacks potentially more difficult.

The following commands format create a detached header file  while formatting a partition:

In order to open the encrypted device

See the cryptsetup man page for more details.

Generating a GnuPG encrypted keyfile
The more traditional approach (that is also supported by genkernel) is to use a GnuPG encrypted keyfile (that contains sufficient entropy). The following command create such a file and format an encrypted partition.

In order to open the encrypted device

Preparing the disk(s)
Preparing the disk(s) is the only thing that deviates from the official installation documents along with generating an initramfs. You may want to add a proper amount of entropy to new disks through some mechanism such as `cat /dev/random | wcs > /dev/XXX' or using other more usable methods be it secure erasing disks. The drawback is... a very long time to complete such a task.

A usable alternative and straight forward method is to set up DM-Crypt LUKS and then zero-ing the whole disk: e.g. after LUKS formating the disks run the following command.

Of course you have to replace root by the actual mapping name. This method will save several hours of secure erasing disks or dozen of hours to set up enough randomness or entropy. This step might be necessary or even required depending on the plausible deniability requirements. Just make sure, afterwards, to not use specific block device commands like TRIM which will destroy this tedious effort. Anyway, nobody would ever want to do this with SSDs, so this is a non issue.

With the previous section, remains encrypting the physical devices. Before doing just that, one should consider the order of DM stack depending of using RAID, LVM or a modern file system that include both in the file system layer like ZFS.

Using RAID and/or LVM together make it easier to only encrypt the resulting logical volume especially for RAID. If using LVM with fewer logical volume than the number of physical volume, it makes sense to crypt the logical volume. There's no practical advantages to use LUKS on the underlaying volumes of RAID arrays but to raise the complexity while lowing usability.

With a modern file system like ZFS, there's not choice but encrypt the physical volume or vdev in ZFS terms.

Before encrypting the devices, considering the partition should be taken into account as many bootloader does not support LUKS. GRUB2 should support LUKS formated devices although I did not try to load kernel+initramfs yet. So some spare space should be allocated for `/boot' if necessary.

GRUB2 also support ZFS so in that case, one could encrypt with '--align-payload 0 --header /dev/|/path/to/file', the whole disk, to set up a more secure setup and be able to claim the "plausible deniability" because nothing in the disk can prove that the disk is encrypted. This, however, require >=sys-fs/cryptsetup-1.4.0.

GnuPG crypted key file should be piped to cryptsetup with something like `gpg -qd /path/to/key |' while LUKS crypted key file via loop back device is given like a regular key file after decryption.

When done, creating logical volume if using LVM or adding the crypted cyphertext to a vdev can be done then.

Generating an initramfs
After encrypting system or disk(s), one will need an initramfs so that rootfs can be mounted in there and then pass the control to real init. There are a few generic initramfs builder that can be used to accomplish the task such as dracut, mkinitcpio (there's an ebuild ad thread in the forums) sys-kernel/mkinitramfs-ll or even [cryptsetup] (or the next variant) which has LUKS support.

Genkernel/Genkernel-next
To use or, edit  to enable the cryptsetup USE flag before emerging it. The static USE flag may also be enabled on the so that genkernel will use the system binaries (otherwise it will build its own private copy). The following example will build only an initramfs (not an entire kernel) and enable support for luks. Even if you don't use lvm, `--lvm' option is required to include necessary udev rules.

The genkernel manpage outlines other options depending on system requirements.

The initrd will require parameters to tell it how to decrypt the drive, and they are supplied the same way as other kernel parameters. For example:

Further information can be found in the Genkernel Manual.

Dracut
The package was ported from the RedHat project and serves a similar tool for generating an initramfs. Since it is currently in ~arch for testing, users will need to edit to emerge it. Before doing so, the variable DRACUT_MODULES="crypt" should be added to. Other modules may be desired, please refer to Dracut. Generally, the following command will generate a usable default initramfs.

The initrd will require parameters to tell it how to decrypt the drive, and they are supplied the same way as other kernel parameters. For example:

For a comprehensive list of luks options within dracut please see the section in the Dracut Manual.

Mkinitramfs-LL
The unofficial sys-kernel/mkinitramfs-ll (found in tokiclover's bar-overlay) is a lightweight and modular variant of the previous well known initramfs generating tools which comes with udev free dependency. It depends only on busybox with mdev by default and depends on extra packages for additional functionalities. So, nor bash, coreutils nor util-linux is bundled into the initramfs. Extra flexibilities are offered as well, like the possibility to have DM-Crypt LUKS on top of LVM or vice versa, btrfs or ZFS on top of DM-Crypt LUKS, DM-Crypt LUKS on top of RAID, detached header (to a device or a file) for dm-crypt LUKS et al.

Use the following GRUB2 configuration excerpt to get going for LVM/LUKS and regular key file on a removable device setup.

Custom
Now, with a complicated setup one could have to build his/her own to satisfy specific requirements. This where modular or advanced initramfs package shine such as mkinitramfs-ll dracut or mkinitcpio.

The following is a simple script that will build an initramfs with LUKS support for the running kernel or for the kernel version passed as argument 1. Be careful as this will build the initramfs image and copy it into so you need to have that mounted (and if you have an existing initramfs for this kernel, it might get overwritten).

And the following is a simple init script which will mount rootfs in initramfs environment. The following script and the previous are adapted from mkinitramfs-ll.

See mkintramfs-ll/init for a fully featured init script.

Notice that the previous init script support LABEL UUID and raw block device name sd[a-z][0-9] with or without the /dev/ prefix. One can even provide part of a LABEL or UUID, getdev will just return the block device rightly.

Finally, you need to tweak the bootloader to use the initramfs - e.g. for Grub, something like this should work.