5

Background

I'm attempting to configure automatic LUKS unlock on CentOS 8 Stream. I would like to place a keyfile on the unencrypted boot partitionand and use it to unlock the LUKS protected LVM PV (which contains the root filesystem). I understand that this is a strange thing to want to do and undermines much of the value of disk encryption - but please humor me.

Here's an overview of the current layout:

$ lsblk
NAME                                          MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
nvme0n1                                       259:0    0 931.5G  0 disk  
├─nvme0n1p1                                   259:1    0   256M  0 part  /boot/efi
├─nvme0n1p2                                   259:2    0     1G  0 part  /boot
└─nvme0n1p3                                   259:3    0 930.3G  0 part  
  └─luks-3d33d226-9640-4343-ba5a-b9812dda1465 253:0    0 930.3G  0 crypt 
    └─cs-root                                 253:1    0    20G  0 lvm   /
$ sudo e2label /dev/nvme0n1p2
boot

Today the /etc/crypttab contains the following for booting with a manually entered passphrase (UUIDs redacted for readability) which works just fine:

luks-blah UUID=blah none discard

In order to achieve automatic unlocking I have generated a keyfile /boot/keys/keyfile and added it as a key on the LUKS partition using luksAddKey.

Attempt 1

In my first attempt I changed the crypttab line to this:

luks-blah UUID=blah /keys/keyfile:LABEL=boot discard,keyfile-timeout=10s

This does result in automatic unlocking and mounting of the root filesystem, but the boot process fails and dumps me into rescue mode as the system cannot mount /boot. The reason is that the boot partition has already been mounted (to a randomish location in order to obtain the keyfile: /run/systemd/cryptsetup/keydev-luks-blah).

Attempt 2

I tried changing crypttab to this:

luks-blah UUID=blah /boot/keys/keyfile discard,keyfile-timeout=10s

I thought maybe the boot scripts are smart enough to figure out how to access /boot/keys/keyfile without /boot being mounted yet. This didn't work however, and I just get the prompt to manually enter the passphrase.

Question

Is there a way to unlock the root filesystem using a keyfile stored on a partition that needs to be available for normal mounting?

1

2 Answers 2

5

Here is a solution based on Nikita's suggestion to try placing the keyfile into the initramfs, tweaked to work with CentOS 8.

Note with this approach there is no need to place the raw keyfile on an unencrypted filesystem. It will be copied to the unencrypted (but compressed) initramfs during initramfs generation. This may add a little bit of obfuscation.

1. Update crypttab

Update crypttab to specify the path to the keyfile that we'll place within the initramfs:

luks-blah UUID=blah /boot/keys/keyfile discard,keyfile-timeout=10s

2. Configure dracut

Create a file under /etc/dracut.conf.d that configures copying of the keyfile into initramfs (see man 5 dracut.conf). The keyfile is given the same location in the initramfs.

$ cat /etc/dracut.conf.d/copy-keyfile.conf 
install_items+=/boot/keys/keyfile

Now update initramfs: dracut -f

3. Confirm

Optional: Confirm with lsinitrd that the file is now present in the initramfs. This shows me:

-r-------- 1 root root 32 Aug 9 20:09 boot/keys/keyfile

3

Put a key file into initramfs and then the boot script could find it there.

I never did this in CentOS, though. I don't use LUKS, but this is not very important to demonstrate the idea.

The following is how to do this in Debian.

A /etc/crypttab file looks like this:

lvm0 /dev/md/lvm0 none cipher=aes-xts-plain64,hash=ripemd160,keyscript=/etc/initramfs-tools/lvm0.sh

I use named md raid (superblock version 1.2) as a base device, so it is safe, because the device is recognized effectively by the UUID. The unencrypted device will appear as /dev/mapper/lvm0 in this case and it is LVM PV, as you may have guessed.

The keyscript is the shell script which prints the key to the stdout. The path given here is the path in the root file system (which is encrypted). The initramfs generation script of debian is smart enough to find out the file lvm0.sh needs to be copied into initramfs and it also adjusts the path so the init script actually finds the key script in the initramfs. The key script itself might look like this (don't copy it verbatim, generate your own random string of required length):

#!/bin/sh

cat - <<EOF
egjseoius9usajogj8g...
EOF

The actual setup is the following: a boot partition is on the removable media which is required to boot the computer; the media is removed once computer finishes booting. I built serveral systems based on this idea; since the boot media (flash stick) is the only way to unlock encrypted device, in each case we required the customer to always have at least two copies of the boot media, securely stored.

I also employed the very same concept in Gentoo, however the system is much more customized there and the whole custom initramfs init script was invented. The script contains the command similar to this to unlock the encrypted device:

cryptsetup open /dev/sda3 pv0 --key-file=/etc/keys/pv0.key --allow-discards --type=plain --cipher=aes-xts-plain64 --key-size=256

(also we need to assure initramfs contains the /etc/keys/pv0.key file).

I hope you'll be able to adapt this to CentOS.

2
  • Interesting. I hadn't considered trying to place the keyfile inside the initramfs. Unfortunately the CentOS man page for crypttab do not mention keyscript. I'll investigate and see if I can achieve something equivalent.
    – pauldoo
    Commented Aug 19, 2021 at 10:46
  • Yes, this is not systemd's crypttab. Debian has its own. A caveat. The life wasn't be so interesting and fun if there were no caveats :) Commented Aug 19, 2021 at 10:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .