Skip to content

Cryptroot

Encrypted / filesystem

Ubuntu's 18.04 installer makes it possible to setup an encrypted root file system, but doesn't provide a way to automatically decrypt it. update-initramfs skips /etc/crypttab entries for /, and the dracut scripts in the initrd ignore any /etc/crypttab that is installed. Additionally, putting the key directly into the initramfs is not a good idea since it would live in the clear on the /boot partition.

The script in /scripts/local-top/cryptroot also ignores the cryptotops=key=/path/to/key argument and will always read from stdin. To work around this it is necessary to also use a keyscript argument, but not cat directly since it special cases that and will fail to mount the root. /bin/cat instead bypasses that check.

What worked for me:

cryptopts=key=/root.key,source=/dev/vda5,target=sda5_crypt,keyscript=/bin/cat,lvm=yes

However, It turns out that that if you set some config in /etc/initramfs-rools/initramfs.conf and /etc/cryptsetup-initramfs/conf-hook as well as create key files on the disk and update the /etc/crypttab to point to them, then update-initramfs will copy them into the initrd. However, it gives zero errors if things are not correctly to its liking, etc. If all goes well it will create /conf/conf.d/cryptroot configuration file with essentially the same arguments above and with the keyfile in /cryptroot-keyfiles. Very unintuitive and also has three drawbacks: the key is stored in plaintext on the root filesystem, it ends up putting the key material in the initrd also in plaintext, and the initrd is to now specific to this machine and can't be shared between multiple machines.

This does, however, show how to store the configuration in an initrd that can be provided with the config if the kernel options are a problem. It does make for a more complicated auxillary initrd since /conf/conf.d/cryptroot and /cryptroot-keyfiles/root.key have to be created:

mkdir -p test-initrd/cryptroot-keyfiles
echo -n 'abcd@1234!' > test-initrd/cryptroot-keyfiles/sda5_crypt.key
mkdir -p test-initrd/conf/conf.d/
echo 'target=sda5_crypt,source=/dev/sda5,rootdev,lvm=test--vg-root,discard,keyscript=cat,key=/cryptroot-keyfiles/sda5_crypt.key' > test-initrd/conf/conf.d/cryptroot
( cd test-initrd ; find . | cpio -H newc -ov ) > test-initrd.cpio
.
./cryptroot-keyfiles
./cryptroot-keyfiles/sda5_crypt.key
./conf
./conf/conf.d
./conf/conf.d/cryptroot
2 blocks

PXE booting the keys

One way to deliver the keys to the kernel is via a PXE server. This has some security concerns since the keys will be transmitted in the clear, the keys are accessible to any other machines on the network, etc, but those can be worked around with filtering or moving to a more sophisticated attestation and key management system. This is just to show how to can be done.

The important trick is that iPXE can handle multiple initrd arguments and will download all of them. The generic initrd can be used by all the machines and the keys can be placed into device specific files. To create the key initrd, place the passphrase in a file with no newline and then use cpio to create the file in the tftp directory:

echo -n secretpassword > root.key
echo root.key | cpio -H newc -o > hostname.cpio

Create a iPXE config file that will be served to the machine:

#!ipxe
kernel ubuntu-18.04/vmlinuz-4.15.0-55-generic root=/dev/mapper/test--vg-root ro console=ttyS0 _rdinit=/bin/sh cryptopts=key=/root.key,source=/dev/sda5,target=sda5_crypt,keyscript=/bin/cat,lvm=yes
initrd ubuntu-18.04/initrd.img-4.15.0-55-generic
initrd keys/${net0.dhcp/hostname}.cpio
boot

Heads as a bootloader

Heads is a better way to do this since it can interface with the TPM, the network and participate in a much richer attestation protocol. To be written.

2019 Security Linux


Last update: November 8, 2020