Trusted Platform Module
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 such as secure boot, key storage and random number generation.
TPM is naturally supported only on devices that have TPM hardware support. If your hardware has TPM support but it is not showing up, it might need to be enabled in the BIOS settings.
List of Platform Configuration Registers
Platform Configuration Registers (PCR) contain hashes that can be read at any time but can only be written via the extend operation, which depends on the previous hash value, thus making a sort of blockchain. They are intended to be used for platform hardware and software integrity checking between boots (e.g. protection against Evil Maid attack). They can be used to unlock encryption keys and proving that the correct OS was booted.
The TCG PC Client Specific Platform Firmware Profile Specification defines the registers in use:
PCR | Use | Notes |
---|---|---|
PCR0 | Core System Firmware executable code (aka Firmware) | May change if you upgrade your UEFI |
PCR1 | Core System Firmware data (aka UEFI settings) | |
PCR2 | Extended or pluggable executable code | |
PCR3 | Extended or pluggable firmware data | Set during Boot Device Select UEFI boot phase |
PCR4 | Boot Manager Code and Boot Attempts | Measures the boot manager and the devices that the firmware tried to boot from |
PCR5 | Boot Manager Configuration and Data | Can measure configuration of boot loaders; includes the GPT Partition Table |
PCR6 | Resume from S4 and S5 Power State Events | |
PCR7 | Secure Boot State | Contains the full contents of PK/KEK/db, as well as the specific certificates used to validate each boot application |
PCR8 | Hash of the kernel command line | Supported by grub and systemd-boot |
PCR9 | Hash of the initrd | Kernel 6.1 might measure the kernel cmdline |
PCR10 | Reserved for Future Use | |
PCR11 | Hash of the Unified kernel image | see systemd-stub |
PCR12 | Overridden kernel command line, Credentials | see systemd-stub |
PCR13 | System Extensions | see systemd-stub |
PCR14 | Unused | |
PCR15 | Unused | |
PCR16 | Debug | May be used and reset at any time. May be absent from an official firmware release. |
PCR23 | Application Support | The OS can set and reset this PCR. |
Packages
Package | Usage |
---|---|
tpm2-tss |
Implementation of the TCG Trusted Platform Module 2.0 Software Stack (TSS2) |
tpm2-tools |
Trusted Platform Module 2.0 tools based on tpm2-tss |
tpm2-abrmd |
Access Broker and Resource Management Daemon |
tpm2-tss-engine |
OpenSSL engine for Trusted Platform Module 2.0 devices |
tpm2-pkcs11 |
PKCS#11 interface for Trusted Platform Module 2.0 hardware |
tpm2-totp |
Attest the trustworthiness of a device against a human using time-based one-time passwords |
Configuration
- Add user to the
tss
groupsudo usermod -aG tss $USER
- Enable access broker
sudo systemctl enable --now tpm2-abrmd
- Logout and login again
Usage
TPM2-based LUKS key
You can use the trusted platform module in your computer as a key store to unlock LUKS encrypted volumes with them.
Arch Linux comes with systemd
which itself comes with systemd-cryptenroll
and allows you to specify a TPM2 device for key storage.
Using a TPM for this purpose automates the process of unlocking your LUKS volumes, given that certain conditions are met, e.g. the firmare of the machine and the Secure Boot state.
WARNING: When using this method on your root volume, there are a few caveats to be aware of.
Provided the PCR slots 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 password.
However, this also means that in case of theft, the data is no longer protected by the encryption. Furthermore, this also makes you more vulnerable to cold boot attacks, since the computer just has to be booted up to gain access to the decrypted data, without even the need to tamper with the device in order to crack the encryption.
It is therefore strongly recommended to at least pass the --tpm2-with-pin
option to systemd-cryptenroll
to still have a mechanism for user verification (available with systemd
version 251).
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
andsd-encrypt
)
Start by getting a list of TPM2 devices available in your machine:
TIP: If there are no devices listed, make sure the TPM is enabled in your device's firmware. Devices from 2016 onwards usually have a TPM 2.0, as it is a requirement from Microsoft for Windows 10 certification for hardware manufacturers.
systemd-cryptenroll --tpm2-device=list
To enroll a new TPM-based key into a LUKS slot specify the TPM device to generate the key from and the PCRs to seal against, followed by the LUKS volume to save a new slot to (using /dev/nvme0n1p2
as an example):
TIP: If your device only has one TPM (which is usually the case) you can supply --tpm2-device=auto
to use the only device available.
systemd-cryptenroll --tpm2-device=/path/to/tpm2_device --tpm2-pcrs=0+7 --tpm2-with-pin /dev/nvme0n1p2
It will ask you for a PIN to enter, which you will be asked to put in every time you boot the system.
Recovery key
It is also generally advisable to let systemd-cryptenroll
generate a recovery key, in case the key stored in the TPM doesn't validate anymore for whatever reason.
A recovery key is generated automatically with a character set that's easy to type in while still having high entropy.
To generate a recovery key and have it saved to a slot in the LUKS device (using /dev/nvme0n1p2
as an example):
systemd-cryptenroll --recovery-key /dev/nvme0n1p2
Kernel parameters
To actually make systemd use the TPM for unlocking your volume certain kernel parameters have to be set.
In your kernel command line, add the following:
TIP: Again, if your device only has one TPM you can supply tpm2-device=auto
to use the only device available.
rd.luks.options=tpm2-device=/path/to/tpm2_device
TOPT code during boot
You can use tpm2-totp
as a means for attestation that the system you are trying to boot is trustworthy by making it display a TOTP code during boot. If the code displayed during boot matches the one in your TOTP app, the system can be considered untampered. Otherwise you have to assume the system is no longer trustworthy and has been tampered with in one way or another.
ATTENTION: If you want to use tpm2-totp
in conjunction with Plymouth you will have to use the tpm2-totp-git
package from the AUR, since Arch Linux does not officially support Plymouth and the Repo package lacks the initcpio hooks needed for Plymouth support.
Use the plymouth-tpm2-totp
hook in conjunction with the encrypt
hook, or sd-plymouth-tpm2-totp
in conjunction with the sd-encrypt
hook.
Generate authentication code and seal against PCRs 0 (hash of UEFI firmware) and 7 (Secure Boot state):
sudo tpm2-totp --pcrs=0,7 generate # official package
sudo tpm2-totp --pcrs=0,7 init # AUR package
This will output a QR code on the terminal that you can scan with your TOTP app of choice.
Test your TOTP by requesting a 6-digit code to be printed and compare with your TOTP app to verify the codes match:
tpm2-totp calculate # official package
tpm2-totp show # AUR package
Add the tpm2-totp
hook to the HOOKS array in /etc/mkinitcpio.conf
before the encrypt
hook, else you won't be able to see the TOTP during boot.