Opening a LUKS encryptrd partition with your TPM

Posted on Jan 06, 2020 by Vincent TruchseƟ

In my last post I described how I was enabling secure-boot on my ArchLinux machine. While this prevents malware to be injected into the bootloader or initramfs while the system is powered off, this article describes the use of your machine’s Trusted Platform Module to unlock the LUKS-partition with a short pin instead of a long password without loosing security.

To learn more about the TPM in general I advise to watch this talk.

Concept

The Concept is fairly simple. An additional key is setup in an empty slot of the LUKS-Header. This Key gets encrypted with the TPM and placed into the unencrypted esp-partition. On boot, the TPM decrypts this secret and passes it to LUKS to unlock the partition.
Since the TPM’s keys are not readable from outside the chip and it provides a brute-force-protection you can use a short and easy to type password instead of your (hopefully) 512-character passphrase.

Preperation

Setting up the TPM

In order to use the steps below, the TPM must be activated and set into TPM2.0 mode. This is simply a BIOS-setting and varies from mainboard to mainboard.

Preperations

First, install the following packages:

  • luks-tpm2

  • mkinitcpio-tpm2-encrypt

Add your user to the tss group to perform some of the commands without root-priviledges.
Now, you must check, which PCR-Values are being used and verify they don’t change. Run tpm2_pcrread > pcr.txt and reboot. Afterwards compare pcr.txt with the output of tpm2_pcrread and verify that those values are still the same.
Also check, which values are being used at all. In my case, only the sha1 banks were used. Since the banks 0-7 were used I decided to go for 0, 2, 4 and 7.

In my /etc/default/luks-tpm2, this looks somewhat like this:

#TMPFS_MOUNT="/root/keyfs"
SEALED_KEY_PUBLIC="/boot/esp/keyfile.pub"
SEALED_KEY_PRIVATE="/boot/esp/keyfile.priv"
#PARENT_HANDLE="0x81000001"
PARENT_KEY_PROMPT="1"
#PARENT_KEY_PATH=""
#NVRAM_INDEX=""
#KEY_SIZE=32
#TPM_KEY_SLOT=1
#RESET_KEY_SLOT=2
PCRS="sha1:0,2,4,7"
UNSEAL_PCRS="sha1:0,2,4,7"
#TPM2TOOLS_TCTI="device:/dev/tpmrm0"

Initializing the TPM

Before sealing any keys, we must generate and store a secret inside the TPM. To do so, you need the following commands:

tpm2_createprimary -c primary.ctx -p <new tpm password>
tpm2_evictcontrol -c primary.ctx 0x81000001

Initializing luks-tpm

To initialize luks-tpm, simply run sudo luks-tpm2 init. Because we still have to rebuild the initramfs, just run sudo luks-tpm2 temp to set a temporary passphrase for the next reboot (this saves us some typing).

Configuring the initramfs

In order to unlock the LUKS-Partition in early boot, you must add the tpm2 hook in /etc/mkinitcpio.conf like this:

HOOKS=(base udev autodetect modconf keyboard block tpm2 encrypt lvm2 filesystems resume fsck)

Also, add vfat to the modules-section.
Now, you can rebuild the initramfs by running sudo mkinitramfs -P.

Note
If you happen to use secureboot (as described here) you need to run the signing-script now.

Finalizing

Now, simply reboot. You will get prompted to enter your password, which will fail because the PCR-Values have changed. After not being able to decrypt the keyfile via TPM you can enter a regular passphrase (i.e. the one you just setup as temporary one) and boot up.
After booting, simply run sudo luks-tpm2 reset do re-seal a new key and remove the temporary passphrase. This has to be done after every time a change has been made to the bootloader, kernel or intramfs.

Tags: linuxarchboot