LUKS Encrypted Drives in Ubuntu
There are many creative and different ways to encrypt a linux system. This guide covers setup on Ubuntu 20.04.6. See the Arch Linux documentation on dm-crypt for an overview of the various options.
Table of Contents
- Prerequisites
- Warnings
- Encrypted Root and Boot Drive, Unlock with Password at Boot
- Use a FIDO U2F Yubi Key to Unlock at Boot
- Automatic Decryption at Boot Using TPM and Secure Boot
Prerequisites
- Ubuntu Desktop/Server 20.04.6 with SSH access and LVM and XFS filesystem.
- FIDO U2F Security key such as a yubikey, anykey, or nitrokey.
Note: The XFS file system is used for XenFi hubs because of its support for parallel I/O operations.
WARNINGS
In any scenario, never use file system repair software such as fsck directly on an encrypted volume, or it will destroy any means to recover the key used to decrypt your files. Such tools must be used on the decrypted (opened) device instead.
GRUB’s support for LUKS2 is limited. Use LUKS1 (cryptsetup luksFormat –type luks1) for partitions that GRUB will need to unlock.
The LUKS2 format has a high RAM usage per design, defaulting to 1GB per encrypted mapper. Machines with low RAM and/or multiple LUKS2 partitions unlocked in parallel may error on boot. See the –pbkdf-memory option to control memory usage.
For LUKS1, only PBKDF2 is accepted. PBKDF2 is the default for both Luks 1 and 2.
Encrypted Root and Boot Drive, Unlock with Password at Boot
Why encrypt a boot partition? Isnt encrypting the root partition with LVM enough? Encrypting just the root partition that has LVM on it is sufficient in most cases and would likely work for us too. However, encrypting the boot partition adds an additional layer of obfuscation. It prevents an attacker who is in possession of the device from being able to start the boot process and identify metadata such as OS name and version. That metadata could be useful for identifying an attack vector to break past the encryption.
Boot using a Ubuntu Desktop installer. Choose the option to try ubuntu and then open a terminal. We must first create the partitions for ubuntu and configure LUKS before installing Ubuntu itself to the drive and partitions.
In the terminal session, use fdisk or gparted to create the following drive partitions:
Mountpoint Partition Name Partition Type Partition Size Encrypted /dev/sda1 Boot Linux reserved 800 MB Yes /dev/sda2 Grub BIOS boot partition 5 MB No /dev/sda3 EFI EFI System 200 MB No /dev/sda4 Rootfs Linux filesystem The rest of the available drive space Yes Encrypt the boot and rootfs partitions. Use LUKSv1 for boot and LUKSv2 for rootfs. Provide a password to decrypt each drive.
cryptsetup --type luks1 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --use-random luksFormat /dev/sda1 cryptsetup --type luks2 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --use-random luksFormat /dev/sda4Open the newly encrypted partitions:
cryptsetup open /dev/sda1 LUKS_BOOT cryptsetup open /dev/sda4 LUKS_ROOTCreate the file system for the boot partition:
mkfs.ext4 -L boot /dev/mapper/LUKS_BOOTCreate the EFI file system:
mkfs.vfat -F 16 -n EFI /dev/sda3Create the logical volumes in
/dev/sda4. These commands create a swap partition thats 4GB and then uses 80% of the remaining free space to create the root partition to install the OS on. This leaves a little extra storage space in case you need to expand/create more partitions later on. See the swap chart for recommended swap partition sizes.pvcreate /dev/mapper/LUKS_ROOT vgcreate vg-ubuntu /dev/mapper/LUKS_ROOT lvcreate -L 4G -n swap "vg-ubuntu" lvcreate -l 80%FREE -n root "vg-ubuntu"Swap Chart
Amount of RAM in System Recommended Swap space Recommended Swap space if allowing for hibernation <2gb 2 times the amount of RAM 3 times the amount of RAM >2gb - 8gb Equal to the amount of RAM 2 times the amount of RAM >8gb - 64gb At least 4gb 1.5 times the amount of RAM >64gb At least 4gb Hibernation not recommended Run the following command to configure GRUB to use an encrypted filesystem. The command will wait in the background while you run the installer and will update the configuration file once it detects its creation. Do not reboot or shutdown. This has to be done before the installer reaches the Install Bootloader stage at the end of the installation process.
while [ ! -d /target/etc/default/grub.d ]; do sleep 1; done; echo "GRUB_ENABLE_CRYPTODISK=y" > /target/etc/default/grub.d/local.cfgChoose to do a minimal installation. On
Installation Type, chooseSomething elseand click continue. You should see the partitions and LVM that was setup.Locate the entry for
/dev/mapper/vg--ubuntu-rootand change it to XFS and the mount point to/.Select the swap entry next and change it to
swap area.Select the entry for
/dev/mapper/LUKS_BOOTand change it to EXT4 and mount point/boot.Select
/dev/sdaas the boot device as this is where all of our partitions have been configured.Click install now to start installing ubuntu to the encrypted drive.
Once installation has finished, click continue testing and create a chroot environment for running the next commands and mount all of the configured drives to it.
mount /dev/mapper/vg--ubuntu-root /target for n in proc sys dev etc/resolv.conf; do mount --rbind /$n /target/$n; done chroot /target mount -aMake sure that
cryptsetup-initramfsis installed.sudo apt update && sudo apt install -y cryptsetup-initramfsConfigure initramfs to use a keyfile stored inside the encrypted boot partition to decrypt and use the root partition. This is safe because these files are themselves stored in the encrypted /boot/ which is unlocked by the GRUB boot-loader (which asks you to type the pass-phrase) which then loads the kernel and initrd.img into RAM before handing execution over to the kernel.
echo "KEYFILE_PATTERN=/etc/luks/*.keyfile" >> /etc/cryptsetup-initramfs/conf-hook echo "UMASK=0077" >> /etc/initramfs-tools/initramfs.confCreate a random key of 4096 bits (512 bytes) and add it to the LUKS volumes.
mkdir /etc/luks dd if=/dev/random of=/etc/luks/boot_os.keyfile bs=512 count=1 chmod u=rx,go-rwx /etc/luks chmod u=r,go-rwx /etc/luks/boot_os.keyfile cryptsetup luksAddKey /dev/sda1 /etc/luks/boot_os.keyfile cryptsetup luksAddKey /dev/sda4 /etc/luks/boot_os.keyfile echo "LUKS_BOOT UUID=$(blkid -s UUID -o value /dev/sda1) /etc/luks/boot_os.keyfile luks,discard" >> /etc/crypttab echo "LUKS_ROOT UUID=$(blkid -s UUID -o value /dev/sda4) /etc/luks/boot_os.keyfile luks,discard" >> /etc/crypttabUpdate initramfs and reboot, you should be presented with a password to unlock the drives and continue the boot process.
update-initramfs -u -k all
Use a FIDO U2F Yubi Key to Unlock at Boot
The following steps setup a Ubuntu system with LUKS encryption across the entire OS. Unlocking of the drive at boot is done using a FIDO U2F yubi key.
Follow the steps in the section Encrypted Root and Boot Drive, Unlock with Password at Boot. The steps in this section assume you already have a Ubuntu instance with Full Disk Encryption (FDE) thats unlocked with a password.
Install ykman:
sudo apt-add-repository ppa:yubico/stable sudo apt update && sudo apt install yubikey-manager yubikey-luksCheck if the yubikey supports hmac-secret extension:
ykman --diagnose 2>&1 | grep hmac-secrethmac-secretwill be printed to the screen if supported.Backup the existing LUKS header for the boot partition:
cryptsetup luksHeaderBackup /dev/sda1 --header-backup-file ~/luks_boot.bak cryptsetup luksHeaderBackup /dev/sda4 --header-backup-file ~/luks_root.bakInitialize yubikey slot for hmac. We are using slot 2 so that slot 1 can be reserved for OTP or other use cases.
ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible -ochal-btn-trigEnroll the yubikey with luks for each encrypted partition. This command writes to slot 7 of the LUKS configuration and allows using the yubikey to decrypt the boot partition when the OS is started. Do not use the same slot, you can only have one enrollment per slot.
yubikey-luks-enroll -d /dev/sda1 -s 6 yubikey-luks-enroll -d /dev/sda4 -s 7Update
/etc/crypttaband addkeyscript=/usr/share/yubikey-luks/ykluks-keyscriptto the line item for LUKS_BOOT. It should look something like this at the end:LUKS_BOOT UUID=0ed8cdc2-bbd6-4579-a9e2-7ebaba348eff /etc/luks/boot_os.keyfile luks,keyscript=/usr/share/yubikey-luks/ykluks-keyscript,discard LUKS_ROOT UUID=dde8d7ce-41c3-42e6-855c-3b50d5c7cbab /etc/luks/boot_os.keyfile luks,keyscript=/usr/share/yubikey-luks/ykluks-keyscript,discardUpdate initramfs and reboot, you should be prompted to tap the yubikey to decrypt the system.
sudo update-initramfs -u
Automatic Decryption at Boot Using TPM and Secure Boot
If you are using Ubuntu 21.10 or later, then you need to use systemd unlock instead of clevis.
Create a Ubuntu machine that has Secure Boot, UEFI/EFI, and TPM 2.0 enabled.
Boot using a Ubuntu Desktop installer. Choose the option to try ubuntu and then open a terminal. We must first create the partitions for ubuntu and configure LUKS before installing Ubuntu itself to the drive and partitions.
In the terminal session, use fdisk or gparted to create the following drive partitions:
Mountpoint Partition Name Partition Type Partition Size Encrypted /dev/sda1 EFI EFI System 512 MB Yes /dev/sda2 boot Linux filesystem 1.5 GB No /dev/sda3 rootfs Linux filesystem The rest of the available drive space Yes Encrypt and mount the root filesystem:
cryptsetup --type luks2 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --use-random luksFormat /dev/sda3 cryptsetup open /dev/sda3 rootCreate the logical volumes in
/dev/sda3. These commands create a swap partition thats 4GB and then uses 80% of the remaining free space to create the root partition to install the OS on. This leaves a little extra storage space in case you need to expand/create more partitions later on. See the swap chart for recommended swap partition sizes.pvcreate /dev/mapper/root vgcreate vg-ubuntu /dev/mapper/root lvcreate -L 4G -n swap "vg-ubuntu" lvcreate -l 80%FREE -n root "vg-ubuntu"Swap Chart
Amount of RAM in System Recommended Swap space Recommended Swap space if allowing for hibernation <2gb 2 times the amount of RAM 3 times the amount of RAM >2gb - 8gb Equal to the amount of RAM 2 times the amount of RAM >8gb - 64gb At least 4gb 1.5 times the amount of RAM >64gb At least 4gb Hibernation not recommended Create the EFI file system:
mkfs.vfat -F 16 -n EFI /dev/sda1Start the ubuntu installer and choose to do a minimal installation. On
Installation Type, chooseSomething elseand click continue. You should see the partitions that was setup.Locate the entry for
/dev/mapper/rootand change it to XFS and the mount point to/. Mark the partition for formatting. Then locate the entry for/dev/sda2and update it to ext4 and mount point to/boot.Complete installation and reboot. Start the machine and login to your new Ubuntu instance.
Check that secure boot and tpm are enabled:
dmesg | grep TPM; echo -e "\nSecureBoot Status:\n$(mokutil --sb-state)"Install the tpm-tools and clevis libraries:
sudo apt update && sudo apt -y install tpm2-tools clevis clevis-tpm2 clevis-luks clevis-udisks2 clevis-systemd clevis-initramfsCheck the PCR values for your systems TPM:
sudo udevadm trigger sudo tpm2_pcrreadYou should get some output listing different hash algorithms. If there are no numbers next to the hash, you can’t use it for your key. SHA256 is a good hash algorithm and should be supported in most cases.
List of PCR Registers:
PCR Use 0 Core System Firmware executable code (aka Firmware) 1 Core System Firmware data (aka UEFI settings) 2 Extended or pluggable executable code 3 Extended or pluggable firmware data 4 Boot Manager 5 GPT/Partition Table 6 Resume from S4 and S5 Power State Events 7 Secure Boot State 8 Hash of the kernel command line 9-10 Reserved for future use 11 Bitlocker Access Control 12 Data events and highly volatile events 13 Boot Module Details 14 Boot Authorities 15-23 Reserved for Future Use Add a key to the LUKS partition from clevis thats tied to the TPM. Generally speaking, most secure boot implementations seem to use PCR registers 0, 1, and 7.
clevis luks bind -d /dev/sda3 tpm2 '{"pcr_bank":"sha256","pcr_ids":"0,1,7"}'Update initramfs and reboot:
update-initramfs -u -k 'all' reboot now