Today I’m diving into the world of Secure Boot, TPM2, and all of the complications that come with wanting a high level of security without having to type a disk encryption key all the time. Ultimately, my goal is to come up with a solution that I can roll out in my Linux-based business environment, but today I’m walking you through the basics of how full disk encryption works with LUKS and enrolling your first key into the TPM.
Contents
Video
Basic LUKS Volume
To learn what I’m doing, I’ll create a LUKS-encrypted volume manually. First, though, make sure you have a disk partition to work on:
# If you need to partition your drive, do so with sgdisk
# Remove existing partition table (MBR + GPT)
# sudo sgdisk --zap-all /dev/sdX
# Create new partition table and one partition full size
# sudo sgdisk -n 1:0:0 -t 1:8309 /dev/sdX
# Or, if you already have a partition table, set the type to 8309 (LUKS) instead of 8300 (LINUX)
# This is what I did
# List partition table
sudo sgdisk -p /dev/sdX
# Set partition 3 to type "Linux LUKS" (8309)
sudo sgdisk -t 1:8309 /dev/sdX
After that, we can format the LUKS partition, then format the ext4 filesystem on top of that partition
# Format your drive partition (mine is mmcblk0p3)
sudo cryptsetup luksFormat --type luks2 /dev/sdX1
# Inspect the LUKS header (just for fun, really)
sudo cryptsetup luksDump /dev/sdX1
# Mount the LUKS volume
# this creates /dev/mapper/vault block device based name we gave it here - vault
sudo cryptsetup open /dev/sdX1 vault
# Create the filesystem on the LUKS block device, named 'vault'
sudo mkfs.ext4 -L vault /dev/mapper/vault
# Create mount point, mount, and test the new device
sudo mkdir -p /mnt/vault
sudo mount /dev/mapper/vault /mnt/vault
echo "hello" | sudo tee /mnt/vault/test.txt
# get status of the volume (for fun)
sudo cryptsetup status vault
sudo ls -l /dev/mapper/
# Unmount ext4 and then close the crypt volume
sudo umount /mnt/vault
sudo cryptsetup close vault
Managing Key Slots
If you want to backup the LUKS header (in case you make a mistake, you can restore the old header with the old keys):
# Backup
sudo cryptsetup luksHeaderBackup /dev/sdX1 --header-backup-file ~/vault-header.img
# Restore
sudo cryptsetup luksHeaderRestore /dev/sdX1 --header-backup-file ~/vault-header.img
Then we have a few options to add keys:
# Add key slot with a passphrase
sudo cryptsetup luksAddKey /dev/sdX1
# You can also force a keyslot if you want
sudo cryptsetup luksAddKey --key-slot 5 /dev/sdX1
# Add key which is defined by a keyfile
# Generate 512 bytes of random as vault.key
# Obviously protect this key better than your home directory
# Pass in --key-file to mount it
sudo dd if=/dev/urandom of=~/vault.key bs=512 count=1
sudo cryptsetup luksAddKey /dev/sdX1 ~/vault.key
# Just a reminder, you can see how many key slots there are
# And you can tell what type of keys they have
sudo cryptsetup luksDump /dev/sdX1
# And you can test your keys using --test-passphrase
sudo cryptsetup open --test-passphrase /dev/sdX1
# Change a passphrase on a key slot
sudo cryptsetup luksChangeKey /dev/sdX1
# Remove a key by supplying the key itself
sudo cryptsetup luksRemoveKey /dev/sdX1
# Remove a key by supplying a different key (specify the slot number)
# Cannoy delete your own key using this command
sudo cryptsetup luksKillSlot /dev/sdX1 1
Enrolling TPM-Bound keys
We’ll use systemd-cryptenroll for this, so make sure it’s working:
# See if we have a working TPM
sudo systemd-cryptenroll --tpm2-device=list
Let’s now use cryptenroll to add a recovery key - this is randomly generated by systemd, gives you a QR code if you want it. It does not delete existing keys - it just adds a new key using randomness. You don’t have to add recovery keys this way, this is just another way to do it.
sudo systemd-cryptenroll --recovery-key /dev/sdX1
And finally, using it to enroll a TPM:
# Bind to TPM PCR 7
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 /dev/sdX1
# Bind to PCR 7 + also require a PIN
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes /dev/sdX1
# Show what we just did
sudo systemd-cryptenroll /dev/sdX1
sudo cryptsetup luksDump /dev/sdX1
# Also, we can mount manually using this command
sudo cryptsetup open --token-only /dev/sdX1 vault
If we are doing this ‘for real’, and want the device auto-unlocked, systemd can manage this for us with the crypttab also:
# Get UUID of vault from luksDump
sudo cryptsetup luksDump /dev/sdX1
# Add vault to crypttab
echo 'vault UUID=<luks-uuid> none tpm2-device=auto,nofail' | sudo tee -a /etc/crypttab
# If you want to mount it immediately without rebooting, do daemon-reload and start
# The service is 'transient' (generated at runtime), so you can't --enable it
sudo systemctl daemon-reload
sudo systemctl start systemd-cryptsetup@vault.service
# If you reboot, the crypto unlock should happen automatically
Fedora Encrypted Root
Fedora’s installer (Anaconda) already sets up the encrypted volume. The passphrase we enter during installation becomes our recovery key. We just need to enroll a new key slot which is TPM bound, optionally using a PIN.
# Bind to PCR 7 + also require a PIN
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes /dev/sdX1
# Edit the crypttab entry so it checks the TPM for that crypto volume
sudo nano /etc/crypttab
# luks-<uuid> UUID=<uuid> none discard,tpm2-device=auto
# (keep the existing options and add tpm2-device=auto)
# Rebuild the initramfs, making sure the TPM2 module is included
sudo dracut --force --regenerate-all --add tpm2-tss