Automatic LUKS 2 disk decryption with TPM 2 on Fedora - kowalski7cc

Automatic LUKS 2 disk decryption with TPM 2 on Fedora

Photo courtesy of George Becker
Photo courtesy of George Becker

You just switched to Linux after years of Windows, and after setting up full disk encryption with LUKS2, you already miss one handy Windows feature: BitLocker and its automatic disk unlock.

Today we will learn how to approximate its behavior under the popular Linux distribution Fedora

If you are using an old version of Fedora, you must use clevis to bind the TPM2 (TPM 1.0 is not supported and never will be) key to the LUKS volume, but if you are using Fedora 35 or later, you can use the new systemd-cryptenroll command.

First chech for available TPM2 devices:

systemd-cryptenroll --tpm2-device=list

And check for Secure Boot status, you need to enable it in order to prevent tampering with the boot process:

mokutil --sb-state

If you have a TPM2 device, you can use the following command to bind the TPM2 key to the LUKS volume:

sudo systemd-cryptenroll --wipe-slot tpm2 --tpm2-device auto --tpm2-pcrs "0+1+2+3+4+5+7+9" /dev/nvme0n1p3

where --tpm2-pcrs is the list of PCRs to use for the binding, you can find more information about PCRs later in this article.

You need to update the /etc/crypttab file to unlock the volume at boot:

luks-7a02e564-b7fa-4837-a3ec-3b83752c3a20 UUID=1f7f5ba4-01f8-419e-ae48-5daaa69bd1e6 none discard,tpm2-device=auto

On earlier versions of Fedora (before 36), you may update dracut to include libtss2 in the initramfs:

Create a file /etc/dracut.conf.d/tss2.conf with the following content:

install_optional_items+=" /usr/lib64/libtss2* "

and then regenerate the initramfs:

dracut -f

You can also add a recovery key to the LUKS volume. It's the same as the normal key, but it's generated with higher entropy.

systemd-cryptenroll --recovery-key /dev/nvme0n1p3

Clevis installation and configuration

The things we need (besides the LUKS2 installation we already did) to accomplish this task are the Trusted Platform Module

First things first, we need to install the Clevis framework and the needed plugins with Fedora's DNF package manager with this simple command:

sudo dnf install clevis clevis-luks clevis-dracut clevis-udisks2 clevis-systemd

Then we need to find the LUKS volume to bind, we can use the tool lsblk to find the volume (In my case it was nvme0n1p3).

[kowalski7cc@Kaos ~]$ lsblk
NAME                                          MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
nvme0n1                                       259:0    0   477G  0 disk
├─nvme0n1p1                                   259:1    0   600M  0 part  /boot/efi
├─nvme0n1p2                                   259:2    0     1G  0 part  /boot
└─nvme0n1p3                                   259:3    0 475,4G  0 part
  └─luks-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 253:0    0 475,3G  0 crypt
    ├─fedora_localhost--live-root             253:1    0    70G  0 lvm   /
    ├─fedora_localhost--live-swap             253:2    0   7,8G  0 lvm   [SWAP]
    └─fedora_localhost--live-home             253:3    0 397,6G  0 lvm   /home

If we are right we should have an output like this using the tool cryptsetup:

[kowalski7cc@Kaos ~]$ sudo cryptsetup luksDump /dev/nvme0n1p3
[sudo] password di kowalski7cc:
LUKS header information
Version:        2
Epoch:          3
Metadata area:  16384 [bytes]
Keyslots area:  16744448 [bytes]
UUID:           xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Label:          (no label)
Subsystem:      (no subsystem)
Flags:          (no flags)


To make sure our boot has not tampered, we must choose some PCRs to validate against the boot.

Here is a table with the IDs and a small description of its usage:

PCR ID Description
0 Firmware
1 Firmware configuration
2 Option ROMs
3 Option ROMs configuration
5 MBR Configuration
6 State transition
7 Platform-specific
8 - 15 Operating System reserved
16 Debug
23 Applications

Finally we can use the following command to set up the decryption key usin the TPM PCRs:

sudo clevis luks bind -d /dev/nvme0n1p3 tpm2 '{"pcr_ids":"0,1,2,3,4,5,6,7"}'

If it's correct, it will ask for your LUKS encryption password and add the Clevis key to the LUKS header.

Key upgrade procedure

When we do a kernel upgrade, probably our saved key will be invalidated. At this point, we need first to locate the Clevis key slot in the LUKS header.

We can use the command cryptsetup luksDump like before to locate it.

[kowalski7cc@Kaos ~]$  sudo cryptsetup luksDump /dev/nvme0n1p3
[sudo] password di kowalski7cc:
LUKS header information
Version:        2
Epoch:          7
  0: clevis
  Keyslot:  1

We can see that clevis is using Keyslot 1, so we can proceed with

sudo clevis luks unbind -d /dev/nvme0n1p3 -s 1

Then we can use sudo clevis luks bind... again to set up the new key.

Some notes and small thoughts about security