LUKS

Encrypt a Partition

To encrypt e.g. /dev/sda3:

DEVICE=/dev/sda3
cryptsetup --verify-passphrase luksFormat $DEVICE
cryptsetup luksOpen $DEVICE cryptcontainer
mkfs.ext4 -L data /dev/mapper/cryptcontainer

Mount an encrypted Partition

To mount e.g. /dev/sda3:

DEVICE=/dev/sda3
MOUNTPOINT=/mnt/luks
cryptsetup luksOpen $DEVICE cryptcontainer
mkdir -p $MOUNTPOINT
mount /dev/mapper/cryptcontainer $MOUNTPOINT

Unmount an encrypted Partition

To unmount it:

MOUNTPOINT=/mnt/luks
umount $MOUNTPOINT
cryptsetup luksClose cryptcontainer

Linux Installation with Full Disk Encryption

The below commands are a condensed version of the information that can be found in the Arch Wiki and on Pavel Kogan's Blog

I used them with an Arch installation.

# Partition the disk 
cfdisk /dev/sda
# create partition for whole disk of type Linux
# write partition table
# quit

cryptsetup luksFormat /dev/sda1
cryptsetup luksOpen /dev/sda1 lvm
pvcreate /dev/mapper/lvm
vgcreate vg /dev/mapper/lvm
# Adjust size for swap as needed
lvcreate -L 6G vg -n swap
# Adjust size for root fs and partition label as needed
lvcreate -L 75G vg -n os
# The rest is used for the data partition
lvcreate -l +100%FREE vg -n data
# create swap
mkswap -L swap /dev/mapper/vg-swap
# Formatting
mkfs.ext4 /dev/mapper/vg-os
mkfs.ext4 /dev/mapper/vg-data
# Mount the partitions to prepare for chroot
mount /dev/mapper/vg-os /mnt
mkdir -p /mnt/srv/my-data
mount /dev/mapper/vg-data /mnt/srv/my-data
swapon /dev/mapper/vg-swap

Now install the base system

The below info is mainly taken from Pavel Kogan's great guide on full disk encryption.

First, create a crypto key file to avoid having to type the crypt password twice upon boot:

dd bs=512 count=4 if=/dev/urandom of=/crypto_keyfile.bin
cryptsetup luksAddKey /dev/sda1 /crypto_keyfile.bin
chmod 000 /crypto_keyfile.bin  # actually, even root doesn't need to access this
chmod -R g-rwx,o-rwx /boot     # just to be safe

Add the lvm2 and encrypt hooks to /etc/mkinitcpio.conf My hooks line ended up looking as follows:

HOOKS="base udev autodetect modconf block encrypt lvm2 filesystems keyboard fsck"

Set the FILES option to the crypto keyfile just generated.

FILES=/crypto_keyfile.bin

Then, enable cryptodisks in /etc/default/grub Note the y, (not 1 !!) (The exact name of the variable seems to vary, so far I encountered the two below, just set them both to be sure)

GRUB_ENABLE_CRYPTODISK=y
GRUB_CRYPTODISK_ENABLE=y

... and the cryptdevice kernel parameter

GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda1:lvm"

Then run

mkinitcpio -p linux

And finally

grub-mkconfig -o /boot/grub/grub.cfg
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=arch --recheck --debug /dev/sda

To reopen the volumes from a live system later on:

cryptsetup luksOpen /dev/sda1 lvm
# vgscan # to look for volume groups
vgchange -ay vg
# ls /dev/mapper/ # to show volumes
mount /dev/mapper/vg-os /mnt/
mount --rbind /dev /mnt/dev
mount --rbind /proc /mnt/proc
mount --rbind /sys /mnt/sys
mount --rbind /dev/pts /mnt/dev/pts
chroot /mnt /bin/bash

Alternative Initial Ram Filesystem creation with Dracut

The below worked on void-linux: Instead of mkinitcpio the initial ramdisk is created with dracut. The following config was needed:

Add the luks key kernel parameter in /etc/default/grub:

GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda1:lvm"

Create an entry in /etc/crypttab (which will be included in the initialramfs so the crypto keyfile can be found).

Mind the counter-intuitive underscore in vg_os!!! Eventhough the device shows up as /dev/mapper/vg-os (with a dash) you MUST use an underscore in /etc/crypttab.

# crypttab: mappings for encrypted partitions
#
# Each mapped device will be created in /dev/mapper, so your /etc/fstab
# should use the /dev/mapper/<name> paths for encrypted devices.
#
# NOTE: Do not list your root (/) partition here.

# <name>       <device>         <password>              <options>
vg_os        /dev/sda1        /crypto_keyfile.bin     luks

Now, for the keyfile to be available in the initial ramfilesystem, make dracut include it in the initial ramdisk by creating a dracut configuration file /etc/dracut.conf.d/10-crypt.conf:

install_items+="/crypto_keyfile.bin"

Dracut with unencrypted boot

Do NOT add an entry for the rootfs in /etc/crypttab. Otherwise you will be asked for the passphrase twice. (Once by the initialramfs and then during the actual os startup) Instead, activate automatic assembly of special device with the rd.auto kernel parameter in /etc/default/grub:

GRUB_CMDLINE_LINUX="rd.auto=1"

This will make dracut build the initial ramdisk such that it automatically asks you for the crypto passphrase of the rootfs. Now, short of using /etc/crypttab I have not found a way to specify the name to be used for the decrypted device. This is annoying at two places:

1) fstab -> Here it can be easily addressed by using disk labels

LABEL=void_rootfs /   xfs    defaults    0   2

2) Grub configuration. grub-mkconfig seems to determine the value for the root= parameter based on the device that is currently mounted as the rootfs. (It might be possible to change this behavior but I haven't bothered finding out how). This is a problem when you run it for the very first time in a chroot if you have manually unlocked the crypto device and given it a random name. So for grub-mkconfig to do the right thing you need to chroot into the system with the crypto device being opened under the name it will be given by the initramfs. Using the kernel parameters "rd.shell rd.debug lug_buf_len=1M" I found that dracut names the device according to the following scheme: "luks-"

So, assuming that your crypto partition's UUID is 13068607-1f0d-4121-8449-23ed358c2f82 the procedure to build the "right" grub.cfg would be:

CRYPT_DEV=UUID="13068607-1f0d-4121-8449-23ed358c2f82"
cryptsetup luksOpen /dev/disk/by-uuid/${UUID} luks-${UUID}
# chroot into /dev/mapper/luks-${UUID}
# run grub-mkconfig / grub-install / dracut

Adding/Removing Slots

Slots can be listed with

cryptsetup luksDump /dev/sda1

And removed with

cryptsetup luksKillSlot `<device>` `<SLOT ID>

A new key can be added with

cryptsetup luksAddKey <device> (/path/to/<additionalkeyfile>) -d /path/to/<keyfile>

Creating a Container File

container_name=my_container
container_file=/path/to/cryptcontainers/${container_name}
container_mpt=/path/to/mountpoint
size_mb=56
dd if=/dev/urandom of=$container_file bs=1M count=$size_mb
sudo cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -y luksFormat $container_file
sudo cryptsetup luksOpen $container_file $container_name
sudo mkfs.ext4 /dev/mapper/$container_name
sudo mount -t ext4 /dev/mapper/$container_name $container_mpt
sudo chown -R ${USER} $container_mpt
sudo umount $container_mpt
sudo cryptsetup close $container_name