cpg

External root disk encryption on the Raspberry Pi

2023-11-27 #hardware

Booting on an encrypted external disk with the Raspberry Pi, with keys on an external medium as a bonus

This is an n+1 th guide on setting up a Raspberry Pi to boot on an encrypted external disk, to complement n other guides, including:

Enabling boot on USB

Either use the official Raspberry Pi Imager utility or do

# echo "program_usb_boot_mode=1" >> /boot/config.txt

on an existing installation, and reboot.

Installing cryptsetup on the disk image

Get a disk image of Raspberry Pi OS on https://www.raspberrypi.com/software/operating-systems. The Lite version will also work fine.

Restore it on the destination disk, and boot the Pi.

Install cryptsetup, which is not present in the original image:

# apt install cryptsetup cryptsetup-initramfs
# shutdown -h now

Encrypting the volume

In the previous step, the root partition got expanded to the size of the disk by the installer. We have to undo that to avoid spending a day encrypting a large mostly empty partition.

This is most easily done with gparted and its very good support for encrypted volumes.

Once the partition is resized, encrypt it, replacing sdb2 by the name of the root partition you just resized:

# lsblk -f # Note the partition name and its UUID
# cryptsetup-reencrypt --new --reduce-device-size=16M --type=luks2 \
   -c xchacha12,aes-adiantum-plain64 -s 256 -h sha512 --use-urandom /dev/sdb2

This should take roughly 30 minutes.

After that, you can expand again the now-encrypted partition with gparted.

Configuring crypttab and fstab

With the partition mounted, set /etc/crypttab to

rootfs UUID=XXX none

replacing XXX by the UUID of the encrypted root partition (with FSTYPE equal to crypto_LU).

Change the /etc/fstab line about the rootfs partition to

/dev/mapper/rootfs  /               ext4    defaults,noatime  0       0

On the boot partition, add the following to the kernel parameters in cmdline.txt:

cryptdevice=UUID=XXX:rootfs

replacing again XXX by the partition UUID above.

Unattended decrypt with key on an external device (optional)

The following step is optional; it allows reading the decryption key from an external medium (USB key, SD card) rather than using an interactive prompt.

Mount your external medium, label the partition, generate a key, and add it to the encrypted partition

# sudo e2label /dev/sdc2 sd # Label the device
# dd if=/dev/urandom of=/mnt/sd/key bs=4096 count=1
# cryptsetup luksAddKey /dev/sdc2 /mnt/sd/key

replacing sdc2 by the partition name of your external medium.

To your cmdline.txt, add

cryptkey=/dev/disk/by-label/sd:ext4:/key.txt

At boot, the partition will automatically be mounted to read the key. If this fails, decrypting the root partition will fallback to a prompt.

Boot and update initramfs

Finally, boot again the Pi with the disk attached.

On this first boot, decrypting the volume will fail and an initramfs prompt will be open (possibly after a minute or so of retries). Open the volume manually:

# lsblk # Note partition name
# cryptsetup luksOpen /dev/sba2 rootfs
# exit

This should allow booting normally, after which you can execute

# update-initramfs -u

The next reboot should then work properly, with or without password prompt depending on whether you followed the optional step.