dm-crypt with LUKS
Template:Article summary start
- Add the
resumehook to your
etc/mkinitcpio.conffile and rebuild the image afterward:
HOOKS="... encrypt resume ... filesystems ..."
- If you use a USB keyboard to enter your decryption password, then the
keyboardmodule must appear in front of the
encrypthook, as shown below. Otherwise, you will not be able to boot your computer because you couldn't enter your decryption password to decrypt your Linux root partition! (If you still have this problem after adding
usbinput, though this is deprecated.)
HOOKS="... keyboard encrypt ..."
- 1 Encrypting a loopback filesystem
- 2 Encrypting a LVM setup
- 2.1 LVM and dm-crypt manually (short version)
- 3 Specialties
- 4 Resources
Encrypting a loopback filesystem
A loop device enables to map a blockdevice to a file with the standard util-linux tool
losetup. The file can then contain a filesystem, which can be used quite like any other filesystem. A lot of users know Truecrypt as a tool to create encrypted containers. Just about the same functionality can be achieved with a loopback filesystem encrypted with LUKS and is shown in the following example.
Preparation and mapping
First, start by creating an encrypted container!
dd if=/dev/urandom of=/bigsecret bs=1M count=10
This will create the file
bigsecret with a size of 10 megabytes.
losetup /dev/loop0 /bigsecret
This will create the device node
/dev/loop0, so that we can mount/use our container.
cryptsetup luksFormat /dev/loop0
This will ask you for a password for your new container file.
cryptsetup open --type luks /dev/loop0 secret
The encrypted container is now available through the device file
Now we are able to create a partition in the container:
and mount it...
mkdir /mnt/secret mount -t ext2 /dev/mapper/secret /mnt/secret
We can now use the container as if it was a normal partition! To unmount the container:
umount /mnt/secret cryptsetup luksClose secret losetup -d /dev/loop0 # free the loopdevice.
so, if you want to mount the container again, you just apply the following commands:
losetup /dev/loop0 /bigsecret cryptsetup open --type luks /dev/loop0 secret mount -t ext2 /dev/mapper/secret /mnt/secret
Encrypt using a key-file
Let us first generate a 2048 byte random keyfile:
dd if=/dev/urandom of=keyfile bs=1k count=2
We can now format our container using this key
cryptsetup luksFormat /dev/loop0 keyfile
or our partition :
cryptsetup luksFormat /dev/hda2 keyfile
Once formatted, we can now open the LUKS device using the key:
cryptsetup -d keyfile open --type luks /dev/loop0 container
You can now like before format the device
/dev/mapper/container with your favorite filesystem and then mount it just as easily.
The keyfile is now the only key to your file. I personally advise encrypting your keyfile using your private GPG key and storing an off-site secured copy of the file.
Resizing the loopback filesystem
First we should unmount the encrypted container:
umount /mnt/secret cryptsetup luksClose secret losetup -d /dev/loop0 # free the loopdevice.
After this we need to expand our container file with the size of the data we want to add:
dd if=/dev/urandom bs=1M count=1024 | cat - >> /bigsecret
Be careful to really use TWO
>, or you will override your current container!
You could use
/dev/zero instead of
/dev/urandom to significantly speed up the process, but with
/dev/zero your encrypted filesystems will not be as secure. (A better option to create random data quicker than
frandom , available from the AUR).
A faster (almost instant) method than dd is
truncate , but its use has the same security implications as using /dev/zero. The size passed to truncate is the final size to make the file, so don't use a value less than that of the current file or you will lose data. e.g. to increase a 20G file by 10G: truncate -s 30G filename.
Now we have to map the container to the loop device:
losetup /dev/loop0 /bigsecret cryptsetup open --type luks /dev/loop0 secret
After this we will resize the encrypted part of the container to the maximum size of the container file:
cryptsetup resize secret
Finally, we can resize the filesystem. Here is an example for ext2/3/4:
e2fsck -f /dev/mapper/secret # Just doing a filesystem check, because it's a bad idea to resize a broken fs resize2fs /dev/mapper/secret
You can now mount your container again:
mount /dev/mapper/secret /mnt/secret
Encrypting a LVM setup
It is easy to use encryption with LVM. This section describes specific aspects of setting up an encrypted LVM setup and has a mini-howto for users with experiences of using both, cryptsetup and LVM. If you are looking for verbose installation instructions of such a setup, you might want to read Encrypted_LVM first.
If you do not know how to set up LVM, then read Installing with Software RAID or LVM. Using LVM is particularly helpful when a system with multiple partitions is planned. While there are a number of alternatives for unlocking multiple partitions with the same passphrase/key, the default Arch
mkinitcpio hooks do not implement non-standard ways. A combination of the
lvm2 hooks, however, enables to setup a system with numerous logical volumes as partitions while using one passphrase/key to unlock them.
LVM on LUKS
The straight-forward method is to set up LVM on top of the encrypted partition instead of the other way round. Technically the LVM is setup inside one big encrypted blockdevice. Hence, the LVM is not transparent until the blockdevice is unlocked and the underlying volume structure is scanned and mounted during boot.
The most important thing in setting LVM on top of encryption is to configure the initramfs for running both the
encrypt hook and the
lvm2 hook (and those two before the
filesystems hook). In the past, it was necessary to ensure the correct ordering of these hooks in
/etc/mkinitcpio.conf but the order no longer matters with the current implementation of
LUKS on LVM
To use encryption on top of LVM, the LVM volumes are set up first and then used as the base for the encrypted partitions. This way around a mixture of encrypted and non-encrypted volumes/partitions is possible as well.
For encrypted partitions inside an LVM, the LVM-hook has to run first, before the respective encrypted logical volumes can be unlocked. So for this add the
encrypt hook in
/etc/mkinitcpio.conf after the
lvm2 hook, if you chose to set up encrypted partitions on top of LVM.
Both these options are described in more detail in Encrypted_LVM. The following represents the historic guide from before the verbose page.
LVM and dm-crypt manually (short version)
The following short example creates a LUKS on LVM setup and mixes in the use of a key-file for the /home partition and temporary crypt volumes for /tmp and /swap. The latter is considered desirable from a security perspective, because no potentially sensitive temporary data survives the reboot, when the encryption is re-initialised. If you are experienced with LVM, you will be able to ignore/replace LVM- and other specifics according to your plan. For
cryptsetup options, please see above.
Setting up the encrypted system
cryptsetup -d /dev/random -c aes-xts-plain -s 512 create lvm /dev/sda2 dd if=/dev/urandom of=/dev/mapper/lvm cryptsetup remove lvm lvm pvcreate /dev/sda2 lvm vgcreate lvm /dev/sda2 lvm lvcreate -L 10G -n root lvm lvm lvcreate -L 500M -n swap lvm lvm lvcreate -L 500M -n tmp lvm lvm lvcreate -l 100%FREE -n home lvm cryptsetup luksFormat -c aes-xts-plain -s 512 /dev/lvm/root cryptsetup open --type luks /dev/lvm/root root mkreiserfs /dev/mapper/root mount /dev/mapper/root /mnt dd if=/dev/zero of=/dev/sda1 bs=1M mkreiserfs /dev/sda1 mkdir /mnt/boot mount /dev/sda1 /mnt/boot mkdir -p -m 700 /mnt/etc/luks-keys dd if=/dev/random of=/mnt/etc/luks-keys/home bs=1 count=256
Install Arch Linux
Now after setup of the encrypted LVM partitioning, it would be time to install: Arch Install Scripts.
encrypt (in that order) before
filesystems in the
HOOKS array. Again, note that this is setting encryption on top of LVM.
If you want install the system on a usb stick, you need to put
usb just after
Boot options for LUKS-LVM
For the above example, change the kernel options for the root-device auto-configured in the bootloader installation from
More general, the kernel command line for LUKS <-> LVM is constructed like this:
Or like this:
If you want install the system on a usb stick, you need to add
Filesystem mounts system
/dev/mapper/root / reiserfs defaults 0 1 /dev/sda1 /boot reiserfs defaults 0 2 /dev/mapper/tmp /tmp tmpfs defaults 0 0 /dev/mapper/swap none swap sw 0 0
swap /dev/lvm/swap SWAP -c aes-xts-plain -h whirlpool -s 512 tmp /dev/lvm/tmp /dev/urandom -c aes-xts-plain -s 512
Encrypting /home after reboot
cryptsetup luksFormat -c aes-xts-plain -s 512 /dev/lvm/home /etc/luks-keys/home cryptsetup open --type luks -d /etc/luks-keys/home /dev/lvm/home home mkreiserfs /dev/mapper/home mount /dev/mapper/home /home
Filesystem mounts home
home /dev/lvm/home /etc/luks-keys/home
/dev/mapper/home /home reiserfs defaults 0 0
Using GPG or OpenSSL Encrypted Keyfiles
The following forum posts give instructions to use two factor authentication, gpg or openssl encrypted keyfiles, instead of a plaintext keyfile described earlier in this wiki article System Encryption using LUKS with GPG encrypted keys:
- GnuPG: Post regarding GPG encrypted keys This post has the generic instructions.
- OpenSSL: Post regarding OpenSSL encrypted keys This post only has the
- OpenSSL: Post regarding OpenSSL salted bf-cbc encrypted keys This post has the
bfkfinitcpio hooks, install, and encrypted keyfile generator scripts.
- You can follow the above instructions with only two primary partitions one boot partition
(required because of LVM), and one primary LVM partition. Within the LVM partition you can have
as many partitions as you need, but most importantly it should contain at least root, swap, and
home logical volume partitions. This has the added benefit of having only one keyfile for all
your partitions, and having the ability to hibernate your computer (suspend to disk) where the
swap partition is encrypted. If you decide to do so your hooks in
should look like
HOOKS=" ... usb usbinput (etwo or ssldec) encrypt(if using openssl) lvm2 resume ... "
and you should add
"resume=/dev/mapper/<VolumeGroupName>-<LVNameOfSwap>" to your kernel parameters.
- If you need to temporarily store the unecrypted keyfile somewhere, do not store them on an unencrypted disk. Even better make sure to store them to RAM such as
- If you want to use a GPG encrypted keyfile, you need to use a statically compiled GnuPG version 1.4 or you could edit the hooks and use this AUR package gnupg1
- It is possible that an update to OpenSSL could break the custom
ssldecmentioned in the second forum post.
Remote unlocking of the root (or other) partition
If you want to be able to reboot a fully LUKS-encrypted system remotely, or start it with a Wake-on-LAN service, you will need a way to enter a passphrase for the root partition/volume at startup. This can be achieved by running the
net hook along with an SSH server in initrd. Install the AUR package from the AUR and follow the post-installation instructions. Replace the
encrypt hook with
dropbear encryptssh in
/etc/mkinitcpio.conf. Put the
net hook early in the HOOKS array if your DHCP server takes a long time to lease IP addresses.
If you would simply like a nice solution to mount other encrypted partitions (such as
/home)remotely, you may want to look at this forum thread.
Modifying the encrypt hook for a non-root partition
Maybe you have a requirement for using the
encrypt hook on a non-root partition. Arch does not support this out of the box, however, you can easily change the cryptdev and cryptname values in
/lib/initcpio/hooks/encrypt (the first one to your
/dev/sd* partition, the second to the name you want to attribute). That should be enough.
The big advantage is you can have everything automated, while setting up
/etc/crypttab with an external key file (i.e. the keyfile is not on any internal hard drive partition) can be a pain - you need to make sure the USB/FireWire/... device gets mounted before the encrypted partition, which means you have to change the order of
/etc/fstab (at least).
Of course, if the
/etc/crypttab, only one partition is supported, but with some further hacking one should be able to have multiple partitions unlocked.
If you want to do this on a software RAID partition, there is one more thing you need to do. Just setting the
/dev/mdX device in
/lib/initcpio/hooks/encrypt is not enough; the
encrypt hook will fail to find the key for some reason, and not prompt for a passphrase either. It looks like the RAID devices are not brought up until after the
encrypt hook is run. You can solve this by putting the RAID array in
kernel /boot/vmlinuz-linux md=1,/dev/hda5,/dev/hdb5
If you set up your root partition as a RAID, you will notice the similarities with that setup ;-). GRUB can handle multiple array definitions just fine:
kernel /boot/vmlinuz-linux root=/dev/md0 ro md=0,/dev/sda1,/dev/sdb1 md=1,/dev/sda5,/dev/sdb5,/dev/sdc5
Securing the unencrypted boot partition
Referring to an article from the ct-magazine (Issue 3/12, page 146, 01.16.2012 http://www.heise.de/ct/inhalt/2012/03/6/) the following script checks files under
/boot for changes of SHA-1 hash, inode and occupied blocks on the hard drive. It also checks the MBR. The script cannot prevent certain type of attacks, but a lot are made harder. No configuration of the script itself is stored in unencrypted
/boot. With a locked/powered-off crypted system this makes it infeasible for an attacker to recognize that an automatic checksum comparison of the partition is done upon boot.
The script with installation instructions is available here: ftp://ftp.heise.de/pub/ct/listings/1203-146.zip (Author: Juergen Schmidt, ju at heisec.de; License: GPLv2). There is also an AUR package: AUR
- For classical sysvinit: add
/usr/local/bin/chkboot.sh &to your
- For systemd: add a service file and enable the service: systemd. The service file might look like:
[Unit] Description=Check that boot is what we want Requires=basic.target After=basic.target [Service] Type=oneshot ExecStart=/usr/local/bin/chkboot.sh [Install] WantedBy=multi-user.target
There is a small caveat for systemd: At the time of writing the original
chkboot.sh script provided contains an empty space at the beginning of
#!/bin/bash which has to be removed for the service to start successfully.
/usr/local/bin/chkboot_user.sh need to be excuted after login, add it to the autostart (e.g. under KDE -> System Settings -> Startup and Shutdown -> Autostart; Gnome3: gnome-session-properties).
With Arch Linux changes to
/boot are pretty frequent, for example by new kernels rolling-in. Therefore it may be helpful to use the scripts with every full system update. One way to do so:
#!/bin/bash # # Note: Insert your <user> and execute it with sudo for pacman & chkboot to work automagically # echo "Pacman update  Quickcheck before updating" & sudo -u <user> /usr/local/bin/chkboot_user.sh # insert your logged on <user> /usr/local/bin/chkboot.sh sync # sync disks with any results sudo -u <user> /usr/local/bin/chkboot_user.sh # insert your logged on <user> echo "Pacman update  Syncing repos for pacman" pacman -Syu /usr/local/bin/chkboot.sh sync sudo -u <user> /usr/local/bin/chkboot_user.sh # insert your logged on <user> echo "Pacman update  All done, let's roll on ..."
Alternatively to above scripts, a hash check can be set up with AIDE which can be customized via a very flexible configuration file.
While one of these methods should serve the purpose for most users, they do not address all security problems associated with the unencrypted
/boot. One approach which endeavours to provide a fully authenticated boot chain was published with POTTS as an academic thesis to implement the STARK authentication framework.
The POTTS proof-of-concept uses Arch Linux as a base distribution and implements a system boot chain with
- POTTS - a bootmenu for a one-time authentication message prompt
- TrustedGrub - a grub-legacy implementation which authenticates the kernel and initramfs against TPM chip registers
- TRESOR - a kernel patch which implements AES but keeps the master-key not in RAM but in CPU registers during runtime.
As part of the thesis installation instructions based on Arch Linux (iso 2013-01) have been published. If you want to try it, be aware these tools are not in standard repositories and the solution will be time consuming to maintain.