(re)encrypting in place: a LUKS story
posted Feb 01, 2024 02:30 UTC+02:00 by huskee
i like encryption. we all love encryption, because we all like our data to be safe from snoopers and evil-doers. so i decided to encrypt both of my partitions (~60GB root and ~120GB home, both btrfs), but there was one problem:
i didn't want to format anything!
it took a bit of looking around, but I found a (quasi)sane solution to my problem. and it goes like this (at least for openSUSE Tumbleweed):
preparations
BACKUP. YOUR. DATA. BEFORE. DOING. THIS. (i didn't, but do as i say, not as i do. ALWAYS backup stuff you want to keep)
you'll need a live usb of some kind. boot from it, open your terminal, say your prayers and:
btrfs check /dev/[root partition]
btrfs check /dev/[home partition]
make sure those partitions are squeaky clean. then, reduce their size by 32MB:
btrfs fi resize -32m /dev/[root partition]
btrfs fi resize -32m /dev/[home partition]
doing the deed
it's finally time to encrypt! this takes a surprisingly short time, but it works like a charm:
cryptsetup reencrypt --encrypt --type luks1 --reduce-device-size 32m /dev/[root partition]
cryptsetup reencrypt --encrypt --type luks2 --reduce-device-size 32m /dev/[home partition]
make sure you remember your passphrases.
IMPORTANT: if you're using GRUB2, the root partition encryption type must be LUKS1! otherwise, you won't be able to boot from it!
if you accidentally encrypt it as LUKS2, convert the key to PBKDF2 and then convert the encryption to LUKS1:
cryptsetup luksConvertKey --pbkdf=pbkdf2 /dev/[root partition]
cryptsetup convert /dev/[root partition] --type luks1
you have succesfully encrypted your partitions! now, on to:
setting up mounting & booting
if you reboot right now, both your bootloader and initrd will have multiple strokes. you have changed the partition structure of the drive, so now you gotta fix it up. start by opening both partitions and setting up a chroot:
cryptsetup open /dev/[root partition] cr_root
cryptsetup open /dev/[home partition] cr_home
mount /dev/mapper/cr_root /mnt
mount /dev/mapper/cr_home /mnt/home
mount --bind /dev /mnt/dev
mount --bind /sys /mnt/sys
mount --bind /proc /mnt/proc
mount /dev/[efi partition] /mnt/boot/efi
chroot /mnt
next, we're grabbing the UUIDs for the partitions we encrypted. you're looking for the entries with type crypto_LUKS
. copy the UUIDs for both partitions, and edit /etc/crypttab
with your favorite text editor (it better be nvim):
cr_root [root partition UUID] /etc/cryptsetup-keys.d/cr_root
cr_home [home partition UUID] /etc/cryptsetup-keys.d/cr_home
notice the files referenced after the UUIDs? later, we'll use those for auto decryption.
now, edit /etc/fstab, and replace all references to the partitions with their /dev/mapper
counterparts:
/dev/mapper/cr_root / btrfs defaults 0 0
/dev/mapper/cr_root /var btrfs subvol=/@/var 0 0
/dev/mapper/cr_root /usr/local btrfs subvol=/@/usr/local 0 0
/dev/mapper/cr_root /srv btrfs subvol=/@/srv 0 0
/dev/mapper/cr_root /root btrfs subvol=/@/root 0 0
/dev/mapper/cr_root /opt btrfs subvol=/@/opt 0 0
/dev/mapper/cr_home /home btrfs defaults 0 2
/dev/mapper/cr_root /boot/grub2/x86_64-efi btrfs subvol=/@/boot/grub2/x86_64-efi 0 0
/dev/mapper/cr_root /boot/grub2/i386-pc btrfs subvol=/@/boot/grub2/i386-pc 0 0
UUID=C914-6425 /boot/efi vfat utf8 0 2
/dev/mapper/cr_root /.snapshots btrfs subvol=/@/.snapshots 0 0
you're almost ready to reboot. the next step is to update both your bootloader and initrd to work with the encrypted partitions. edit /etc/default/grub
and add the line
GRUB_ENABLE_CRYPTODISK=y
after that, reinstall and reconfigure GRUB:
grub2-install --target=x86_64-efi
grub2-mkconfig -o /boot/efi/EFI/opensuse/grub.cfg
and rebuild your initrd:
dracut -f
exit the chroot and reboot. if all went well, you should be greeted with this prompt:
Enter passphrase for hd0,gptx ([root partition UUID])
enter the passphrase you selected for the root partition. you'll now get to your familiar grub prompt. on this first boot, you'll be prompted for passwords for both encrypted partitions, but we'll fix this.
niceties: auto decryption
remember me?
cr_root [root partition UUID] /etc/cryptsetup-keys.d/cr_root
cr_home [home partition UUID] /etc/cryptsetup-keys.d/cr_home
time to create those files and add them as decryption keys:
openssl genrsa -out /etc/cryptsetup-keys.d/cr_root 4096
openssl genrsa -out /etc/cryptsetup-keys.d/cr_home 4096
cryptsetup luksAddKey /dev/[root partition] /etc/cryptsetup-keys.d/cr_root
cryptsetup luksAddKey /dev/[home partition] /etc/cryptsetup-keys.d/cr_home
chmod 600 /etc/cryptsetup-keys.d/cr_root
chmod 600 /etc/cryptsetup-keys.d/cr_home
you will be prompted for the passphrases you set for each partition.
the home partition is now set up for auto decryption! the root needs some more work. as we've encrypted /boot
, you'll be asked for the passphrase twice: once when GRUB2 is loading, and once when initrd tries to open the drive. to avoid this, we need to add the /etc/cryptsetup-keys.d/cr_root
keyfile to the initrd:
echo -e 'install_files+=" /etc/cryptsetup-keys.d/cr_root "' > /etc/dracut.conf.d/99-cryptsetup.conf
dracut -f
IMPORTANT: be careful to include the spaces inbetween the quotes and the path. dracut finds these really important.
time to reboot! now you should get only one password prompt from GRUB2, as all the others will be covered by the keys.
niceties 2: speeding up GRUB2 decryption times
IMPORTANT: this only works for LUKS2
LUKS uses key derivation to make your passphrases and keys even safer-er. however, key derivation is a rather costly (computingwise) operation, and GRUB2 especially struggles significantly, with load times going up to 50-60 seconds after entering the passphrase. you can mitigate this (at the expense of somewhat lowering the security of your encryption) by reducing the key derivation iterations for the passphrase:
cryptsetup luksConvertKey --pbkdf-force-iterations=1000 /dev/[root partition] --key-slot 0
1000 is the absolute minimum, so experiment a bit to find a middle ground between speed and safety (brute force resistance scales linearly with iterations).
non-niceties: troubleshooting
- GRUB2 craps itself on wrong password
someone really needs to reimplement this. this is how you get out of the grub rescue>
prison:
cryptomount (hd0,gptx) // your root partition, grab this identifier from the "enter passphrase" prompt
insmod normal
normal
- partitions don't auto decrypt
check:
- if the keyfiles exist
- if they're correctly referenced at
/etc/crypttab
- if the root keyfile is in the initrd
- the system logs (
journalctl -e | grep crypt
) to see what's wrong