Skip to main content

Trusted Platform Module

The Trusted Platform Module (TPM) is an international standard for a secure cryptoprocessor, which is a dedicated microprocessor designed to secure hardware by integrating cryptographic keys into devices.

In practice a TPM can be used for various different security applications, for example in conjunction with Secure Boot, encryption key storage and random number generation.

To start using a TPM, it has to be present on your hardware (an fTPM or a dedicated device connected to a header on your mainboard) and enabled in the device's firmware settings.

List of Platform Configuration Registers

Platform Configuration Registers (PCRs) hold cryptographic hashes that record the precise state of the system. While these registers can be read at any time, they can only be modified via an "extend" operation, blending new data with the preceding hashes to create an unalterable, cumulative cryptographic chain.

By verifying these measurements between boots, the system can detect unauthorized hardware or software tampering, for example in the scenario of an Evil Maid attack. If any component has been tampered with (i.e. the hash chain deviates from a previously known good configuration), the TPM will not release its secrets. Once the PCRs prove that the correct, untampered operating system has booted, they can be safely trusted to automatically unlock your disk encryption keys.

The UAPI Group describes the TPM PCRs as follows:

PCR Measured Component Notes
PCR0 Core System Firmware BIOS/UEFI executable code; changes on firmware update.
PCR1 System Firmware Config Firmware settings, hardware config, and boot order.
PCR2 Extended Executable Code Option ROMs of PCIe cards, GPUs, RAID controllers, etc.
PCR3 Extended Configuration Device data from the UEFI Boot Device Select (BDS) phase.
PCR4 Boot Manager Code Bootloader binary (e.g. GRUB, systemd-boot) and boot attempts.
PCR5 Boot Manager Config Bootloader configuration and the GPT partition table.
PCR6 State Transitions ACPI power states and S4/S5 suspend/resume events.
PCR7 Secure Boot State Secure Boot status and database keys (PK, KEK, db, dbx).
PCR8 Kernel Command Line Literal kernel parameters passed by the bootloader.
PCR9 Initramfs / Initrd External initramfs/initrd image passed by the bootloader.
PCR10 IMA Linux Integrity Measurement Architecture (IMA) log.
PCR11 Unified Kernel Image (UKI) UKI components (kernel, initrd, cmdline) via systemd-stub.
PCR12 Boot Credentials / Overrides Systemd boot credentials and UKI command-line extensions.
PCR13 System Extensions System extension (sysext) and config (confext) overlays.
PCR14 Shim / MOK Shim bootloader binary and Machine Owner Key (MOK) certificates.
PCR15 System Identity Operating system state (machine ID, LUKS keys, root UUID).

For further details on how PCR 11-13 are used, see systemd-stub(7).

Usage

TPM2-based LUKS key

The most common practical application for a TPM on Linux is securing LUKS disk encryption. Integrating the TPM chip directly into a LUKS setup ties the security of the encrypted volume to the physical integrity of the hardware. This integration is handled via systemd-cryptenroll, which offers the option to either fully automate decryption at boot or require a hardware-backed PIN.

During enrollment, systemd-cryptenroll generates a unique, secure unlock key and sends it to the TPM alongside a policy tied to specific PCR states which record the boot configuration of the system. The TPM encrypts (or "seals") this key using its own unique hardware, producing a protected data blob. This blob is then stored directly inside the LUKS volume's metadata header.

At boot, systemd-cryptsetup passes this blob back to the TPM. The TPM immediately measures the current, real-time PCR values to ensure no firmware, bootloader files, or core configurations have been altered. If the current PCR measurements match the policy bound to the blob, the TPM decrypts the blob and unlocks the LUKS partition; either instantly or upon the entry of a designated PIN. If a mismatch is detected, indicating the boot path has been tampered with, the TPM will deny the decryption request, making the system fall back to other configured methods of unlocking the volume.

WARNING: When using this method on your root volume, there are a few caveats to be aware of.

Provided the PCR banks you chose to seal against are considered valid by the system, the TPM will automatically unlock the LUKS volume at boot without the need to enter a passphrase.

However, this also means that in case of theft, it's as if you didn't encrypt the system to begin with. Since the computer just has to be booted up to gain access to the decrypted data, all benefits of data-at-rest encryption are nullified.

It is therefore strongly recommended to at least pass the --tpm2-with-pin=yes option to systemd-cryptenroll to still have a mechanism for user authentication. Despite the name of the option, alphanumeric values can be supplied during interactive enrollment.

Also, make sure the system is in the exact state it should be for normal booting, i.e. the entire system is exactly set up the way you want it and there will be no further changes to core components, especially Secure Boot keys.

Enrolling a new key

Certain preconditions are necessary to use TPM2 in conjunction with a LUKS encrypted volume:

  • tpm2-tss must be installed
  • the volume uses LUKS2 encryption (default when using cryptsetup)
  • the initramfs must be systemd-based (mkinitcpio hooks: systemd and sd-encrypt)

Install the tpm2-tss package from the repositories to provide the necessary TPM software stack tooling:

pacman -S tpm2-tss

List the TPM2 devices available on your machine:

systemd-cryptenroll --tpm2-device=list

NOTE: If no devices are listed, make sure the TPM is enabled in your device's firmware settings. Devices from 2016 onwards usually have a TPM 2.0, as it is a requirement from Microsoft for Windows 10 certification for hardware manufacturers.

To enroll a new TPM-based key into a LUKS slot, specify the TPM device and the PCRs to seal against, followed by the LUKS volume to save a new slot to:

ATTENTION: While binding a LUKS key to a broader set of PCRs increases system security by verifying more stages of the boot process, this hardening comes at the direct expense of system flexibility. On a rapid rolling-release distribution like Arch Linux, an overly restrictive PCR policy is virtually guaranteed to cause regular boot-time breakages. For instance, in a standard modern setup utilizing systemd-boot, UKIs, and Secure Boot, binding to volatile registers like PCR 4 (bootloader binary) or PCR 11 (hash of UKI) means that routine system updates will constantly alter these measurements, invalidating the automated decryption policy and reverting the boot process to a manual passphrase prompt.

NOTE: In the unlikely event that your machine has more than 1 TPM device, supply its resource manager device node, e.g. --tpm2-device=/dev/tpmrm0.

systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes /dev/disk/by-label/cryptroot

systemd-cryptenroll will require to authenticate the addition of a TPM2 token by prompting for an existing passphrase, followed by asking to enter a new TPM2 PIN. This PIN will become the new authentication method at boot. If validation fails for whatever reason, it will fall back to a regular passphrase.

Recovery key

When planning to rely only on TPM unlocking of LUKS volumes, it is also generally advised to add a recovery key, in case TPM validation fails for whatever reason.

A recovery key is generated automatically with a character set that's easy to type in while still having high entropy (brute force mitigation).

To generate a recovery key and have it saved to a slot in the LUKS device:

systemd-cryptenroll --recovery-key /dev/disk/by-label/cryptroot

Unlocking at boot

Making systemd use the TPM to unlock the volume can be done in one of two ways:

  1. add kernel parameters, telling systemd which device to unlock with the TPM
  2. use a /etc/crypttab.initramfs file to be included in the initramfs to point systemd to the correct volume

For the kernel command line, add the following:

NOTE: In the unlikely event that your machine has more than 1 TPM device, supply its resource manager device node, e.g. tpm2-device=/dev/tpmrm0.

rd.luks.options=tpm2-device=auto

If you'd rather use a crypttab.initramfs file, add tpm2-device=auto to the <options> field:

# <name>	<device>									<passphrase>	<options>
root		UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX	none			tpm2-device=auto