Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Decrypt LUKS2-encrypted root partitions with TPM2

This guide is written for Arch Linux.

Requirements

  • systemd version 248 or newer
  • Use mkinitcpio for initramfs generation

Preparation

You need to find out what kernel module/driver is needed for your TPM.

# Note the DRIVER (`tpm_*`, e.g. `tpm_tis`) for your TPM
systemd-cryptenroll --tpm2-device=list

Configure mkinitcpio

You need to edit /etc/mkinitcpio.conf. Basically, you'll switch to systemd hooks and add tpm_X (replace with your actual TPM driver name) to MODULES.

For more information on configuring mkinitcpio, check out the mkinitcpio page on ArchWiki.

Add TPM module

Look for a line that starts with MODULES= in /etc/mkinitcpio.conf, and add tpm_X (replace with your actual TPM driver name) inside the parentheses.

For example, if you have this line in /etc/mkinitcpio.conf

MODULES=(i915)

Change it to this

MODULES=(i915 tpm_tis)

Switch to systemd hooks

Replace the following HOOKS:

Original Replace with
udev, usr, resume systemd
keymap, consolefont sd-vconsole
encrypt sd-encrypt

Place the replacement HOOKS in the original place of the original HOOKS.

For example, if you have this line in /etc/mkinitcpio.conf

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

Change it to this

HOOKS=(base systemd autodetect modconf block keyboard sd-encrypt filesystems fsck)

At the minimum, you should have these hooks:

HOOKS=(base systemd modconf block keyboard sd-encrypt filesystems fsck)

Rebuild initramfs

sudo mkinitcpio -P

Edit kernel cmdline

At the minimum, you should have

rd.luks.uuid=your-uuid rd.luks.options=tpm2-device=auto

Notes:

  • You may use rd.luks.name=your-uuid=name instead of rd.luks.uuid=your-uuid to mount the LUKS volume with a specific name
  • You may include other options after tpm2-device=auto. Options should be comma-separated.

Enroll a TPM-based key to the LUKS volume

See man systemd-cryptenroll for a full list of available options.

# Auto-detect the available TPM and use PCR 0,2,4,7 for verification
# Replace /dev/block-device with your LUKS volume
sudo systemd-cryptenroll /dev/block-device --tpm2-device=auto --tpm2-pcrs=0,2,4,7

With PCR 0,2,4,7, these are validated at boot time:

  • System firmware executable (0)
  • Kernel (2)
  • Bootloader (4)
  • Secure boot state (7)

If you're using PCR 2 and multiple kernels, you need to enroll a key within each kernel.

Reboot and test

Your LUKS volume should automatically decrypt.


Upgraded firmware, kernel, or bootloader?

  • PCR 0,2,4,7 validates the firmware, kernel, and bootloader before releasing the decryption key.
  • If you upgraded firmware, kernel, or bootloader, TPM will not release the key. As a result, auto decryption will fail, and you'll be prompted for a passphrase.
  • You need to wipe the old key and enroll a new key.

Update TPM-based key

# wipe all TPM2 keys and enroll a new key with PCR 0,2,4
systemd-cryptenroll /dev/block-device --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=0,2,4,7
@kishorv06

This comment has been minimized.

Copy link

@kishorv06 kishorv06 commented Jun 15, 2021

Wonderful. It is a really well written guide. 👏

Previously I was using clevis for this purpose. I even wrote mkinitcpio-clevis-hook to get it working. It did the job, but clevis took a few seconds to unlock. This one is way more faster.

One suggestion I have is to make that "Replacing hooks" section a bit more easier to understand. A noobie might find it confusing whether they should add systemd where ever they find udev, usr or resume. Or should they just add it once to the list. Also an example on how to add MODULES would be helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment