TPM Fundamentals
Trusted Platform Module — sealing secrets to hardware state
What a TPM Actually Is
A Trusted Platform Module is a dedicated secure crypto-processor specified by the Trusted Computing Group (TCG). Its purpose is narrow but fundamental: perform cryptographic operations and store keys and integrity measurements inside tamper-resistant hardware, so that even a fully compromised operating system cannot extract or forge them.
The Threat Model
The TPM treats the host CPU, kernel, and firmware as potentially untrusted. Its entire design is built around the idea that software on the main CPU may lie — so any secret worth protecting must never live there in usable form, and any measurement worth trusting must be captured by a separate observer.
What the Chip Does
- Generate keys that physically never leave the chip — the private key is created inside the TPM and can only be used through TPM commands.
- Sign, encrypt, decrypt, hash using those keys on behalf of the host.
- Store integrity measurements (hashes) in special registers (PCRs).
- Attest to platform state — produce a signed statement of what has been measured.
- Enforce policies on when a key can be used (e.g. only if PCRs match a sealed value, or only if a PIN is provided).
Note
Not a crypto accelerator: TPMs are slow — often SPI-connected at megahertz speeds with tiny RAM. They are called occasionally, not in data paths. Use the CPU's AES-NI for bulk crypto and the TPM only for key protection, sealing, and attestation.
TPM 1.2 vs TPM 2.0
TPM 2.0 is a redesign, not an increment. It replaces a fixed, rigid spec with a flexible algorithm-agile architecture. If you are enrolling a disk today, you are almost certainly on TPM 2.0 — TPM 1.2 is deprecated.
| Aspect | TPM 1.2 | TPM 2.0 |
|---|---|---|
| Hash algorithms | SHA-1 only | SHA-1, SHA-256, SHA-384, SHA-512 (per-bank) |
| Asymmetric keys | RSA only (2048) | RSA + ECC (NIST P-256, P-384) |
| Hierarchies | Single owner | Platform, Storage, Endorsement, Null |
| Algorithm agility | None — fixed spec | Profiles; new algorithms can be added |
| PCR banks | One (SHA-1) | One bank per hash algorithm |
| Status | Deprecated | Recommended; required by Windows 11 |
Warning
SHA-1 deprecation: Many TPM 2.0 chips still expose a SHA-1 PCR bank for compatibility. Do not seal to it — use the SHA-256 bank exclusively.
Physical Types
Discrete TPM (dTPM)
A dedicated chip soldered to the motherboard, connected via LPC or SPI. Vendors: Infineon SLB 9670, STMicro ST33, Nuvoton NPCT. Physically isolated silicon, its own RAM and ROM.
Strength: strongest tamper resistance; probing requires physical attack on the chip itself. Certified against FIPS 140-2 / Common Criteria.
Firmware TPM (fTPM)
Runs as firmware inside the CPU's secure enclave. Intel calls this PTT (Platform Trust Technology, inside the ME); AMD calls it fTPM (inside the PSP). No separate chip.
Trade-off: shares the CPU die, so side-channel attacks against the CPU (e.g. voltage glitching) can reach it. Good enough for most commodity servers and laptops.
Software TPM (swtpm)
Pure-software emulation, used inside VMs. QEMU + swtpm provide a virtual TPM 2.0 to the guest over a socket. Proxmox exposes this as "Add TPM State" on a VM.
Trust boundary: only as strong as the hypervisor. The TPM's keys live on the host disk — this is isolation, not hardware rooting.
Hierarchies (TPM 2.0)
TPM 2.0 partitions the chip into four hierarchies. Each is an independent tree of keys with its own primary seed, its own owner password, and its own enable/disable flag. This separation ensures the platform firmware, the OS, and the manufacturer do not step on each other.
TPM2_HierarchyControl
Note
Ownership matters: Each hierarchy has its own owner hierarchy password (the "authValue"). Setting or clearing it via tpm2_changeauth or a BIOS "Clear TPM" operation wipes keys rooted in that hierarchy. A BIOS "Clear TPM" typically clears Storage and Endorsement — any LUKS slot sealed under them becomes unrecoverable.
PCRs — The Core Concept
Platform Configuration Registers are fixed-size registers (one hash-width each) that record integrity measurements of what has booted. They are the mechanism that makes "sealing to platform state" possible.
Extend-only, never written
You cannot write an arbitrary value into a PCR. The only operation is extend:
PCR[n] ← H( PCR[n] ‖ new_data )This is an append-only hash chain. Given the sequence of extensions you can reproduce the final PCR value, but you cannot produce a target PCR value without replaying the exact same sequence.
Reset only at power-on
PCRs 0-22 are reset only when the chip is powered off. No software command can roll them back. A malicious kernel cannot "undo" a measurement of itself. PCR 23 is the exception — an application-scoped debug register that can be reset at runtime.
TPM 2.0 maintains a separate bank of 24 PCRs per hash algorithm. The SHA-256 bank is what everything modern uses. Every extend operation propagates to every enabled bank simultaneously (same input, different hash).
Standard PCR Assignments
From the TCG PC Client Platform Firmware Profile:
| PCR | What it measures | Who extends it | Changes on... |
|---|---|---|---|
| 0 | Firmware executable code (UEFI CRTM + core) | Firmware | BIOS/UEFI update |
| 1 | Firmware configuration / data (NVRAM) | Firmware | BIOS setting changes |
| 2 | Option ROM executable code | Firmware | GPU / HBA / NIC firmware changes |
| 3 | Option ROM configuration / data | Firmware | Add-in card config |
| 4 | Boot Manager / bootloader code (shim, GRUB) | Firmware | Bootloader update |
| 5 | Boot manager config (boot entries, EFI vars) | Firmware | Boot order / entry edits |
| 6 | Platform-specific (host platform events) | Firmware (often unused) | Rare |
| 7 | Secure Boot policy: PK, KEK, db, dbx, MOK list | Firmware | SB on/off, new MOK, dbx update |
| 8 | Bootloader-measured: kernel command line (GRUB) | Bootloader | Kernel cmdline change |
| 9 | Bootloader-measured: kernel + initrd | Bootloader | Kernel / initramfs update |
| 10 | IMA (Integrity Measurement Architecture) | Kernel | Every IMA-tracked file access |
| 11 | Unified Kernel Image (UKI) measurement | systemd-stub | UKI update |
| 14 | shim's MOK (Machine Owner Key) list | shim | MOK enrollment |
| 23 | Debug / application (resettable) | Userspace | At will |
Measured Boot
Measured boot is the chain of extensions that fills PCRs 0-9. Each stage of the boot process hashes the next stage before transferring control to it, and extends that hash into the appropriate PCR. The TPM accumulates an unforgeable fingerprint of exactly what ran.
Core Root of Trust for Measurement (CRTM)
The very first measurement must come from something that cannot be compromised before it measures itself — the CRTM, a small piece of immutable firmware (typically ROM) that boots first. It measures itself and the rest of the firmware into PCR 0, then hands off.
The Measurement Chain
CRTM / UEFI
Measures firmware code & config
→ PCR 0, 1, 2, 3UEFI
Hashes shim, logs SB policy
→ PCR 4, 7shim
Hashes GRUB + MOK list
→ PCR 4, 14GRUB
Hashes kernel cmdline
→ PCR 8GRUB
Hashes kernel + initrd
→ PCR 9Kernel
(Optional) IMA extends PCR 10
Tip
Key property: because each PCR is a hash chain that can only be reset at power-on, the final vector of PCR values is a unique fingerprint of the entire boot path. Any substitution anywhere in the chain produces a different final PCR — which is exactly what sealing exploits.
Sealing & Unsealing
Sealing is encrypting a blob of data under a TPM-internal key with a policy that restricts when the TPM will release the plaintext. The most common policy is PolicyPCR: "only unseal if the current PCR values match these specific values".
- Generate secret
Kon host (or inside TPM). - Read current PCR values for chosen selection.
- Build a policy digest binding to those PCRs.
- TPM encrypts
Kunder the Storage Root Key with the policy attached. - Store the resulting ciphertext ("sealed blob") on plain disk — it is useless without the TPM.
- Host hands the sealed blob + policy to the TPM.
- TPM computes current PCR digest.
- Compares against the sealed policy digest.
- Match → decrypts
K, returns it. - Mismatch → returns
TPM_RC_POLICY_FAIL, never touches the plaintext.
The secret K never appears outside the TPM unless the policy is satisfied. If a malicious bootloader is substituted, PCR 4 changes, the digest differs, and unseal fails. The attacker has the ciphertext but cannot decrypt it — and cannot lie to the TPM about PCR values, because the TPM checks them itself.
$ tpm2_createprimary -C o -c primary.ctx
$ tpm2_create -C primary.ctx -u seal.pub -r seal.priv \
-i secret.bin \
-L policy.digest
$ # later, at boot:
$ tpm2_load -C primary.ctx -u seal.pub -r seal.priv -c seal.ctx
$ tpm2_unseal -c seal.ctx -p "policypcr:sha256:7=abcd..."
<secret bytes>
Remote Attestation
Sealing is local — the TPM gates access to a secret based on its own PCRs. Remote attestation is the network version: the TPM produces a signed statement of its PCR values that a remote verifier can check.
- A Quote is signed by an Attestation Identity Key (AIK), which is itself certified as belonging to a TPM by a chain rooted at the Endorsement Key (EK).
- The verifier checks the signature (proving the quote came from a genuine TPM) and compares the reported PCR values against known-good "golden" values.
- A fresh nonce in the request prevents replay.
- Use case: zero-trust bootstrapping — a newly-booted server proves its firmware/kernel state to a KMS before receiving workload secrets.
Note
Operational reality: attestation is dramatically more complex to deploy than local sealing. You need an EK cert store, an AIK enrollment service, a policy engine, and golden value management across fleet updates. It shows up mostly in confidential computing and high-assurance environments.
The tpm2-tools Suite
| Command | Purpose |
|---|---|
tpm2_pcrread | Dump all PCRs in a bank (e.g. tpm2_pcrread sha256) |
tpm2_pcrextend | Test-extend a PCR (useful on PCR 23 for experimenting) |
tpm2_createprimary | Create a primary (SRK-like) object in a hierarchy |
tpm2_create | Create a child key / sealed object under a primary |
tpm2_seal / tpm2_unseal | Seal and unseal data under a policy |
tpm2_policypcr | Build a PCR policy digest for sealing |
tpm2_eventlog | Parse the UEFI event log into human-readable form |
tpm2_getcap | Query capabilities: algorithms, PCR banks, handles |
Reading PCRs
$ tpm2_pcrread sha256
sha256:
0 : 0x5B8D8A2E9E11C5A4A2D3F10B... (firmware)
1 : 0x9F4C67E1B2E9A17D4F0C8B25... (firmware config)
2 : 0x3D4B5C6D7E8F9A0B1C2D3E4F... (option ROMs)
3 : 0x0000000000000000000000... (unextended)
4 : 0xA1B2C3D4E5F67890A1B2C3D4... (shim + grub)
5 : 0x11223344556677889900AABB... (boot mgr cfg)
7 : 0x7F8E6D5C4B3A29180A1B2C3D... (SB policy)
8 : 0xDEADBEEF0000000000000000... (cmdline)
9 : 0xCAFEBABE0000000000000000... (kernel+initrd)
10 : 0x0000000000000000000000... (IMA disabled)
23 : 0x0000000000000000000000... (resettable)
The Event Log
The firmware publishes a log of what it extended and why to /sys/kernel/security/tpm0/binary_bios_measurements. The PCRs are the authoritative hash; the event log is the (untrusted but useful) narrative. Replaying the log should reproduce the PCR values — if it doesn't, the log has been tampered with (or the TPM was extended by something that didn't log).
$ tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements
---
events:
- EventNum: 0
PCRIndex: 0
EventType: EV_S_CRTM_VERSION
Digest: "5b8d8a2e9e11c5a4..."
Event: "UEFI v2.70 (EDK II, 2023-11-01)"
- EventNum: 3
PCRIndex: 4
EventType: EV_EFI_BOOT_SERVICES_APPLICATION
Digest: "a1b2c3d4e5f67890..."
Event: "\EFI\ubuntu\shimx64.efi"
- EventNum: 7
PCRIndex: 7
EventType: EV_EFI_VARIABLE_DRIVER_CONFIG
Digest: "7f8e6d5c4b3a2918..."
Event: "SecureBoot = 1"
...
Device Nodes & the Resource Manager
/dev/tpm0 — raw
- Direct access to the TPM command interface.
- Single-open: only one process at a time — concurrent users block each other.
- Requires root.
- Caller must manage transient object slots manually; no arbitration.
- Generally do not use unless you are writing a resource manager.
/dev/tpmrm0 — Resource Manager
- Introduced in Linux 4.12; provided by the kernel itself.
- Multiplexes multiple userspace clients transparently.
- Swaps transient TPM objects in and out of the chip's limited slots.
- What
tpm2-toolsuse by default (--tcti=device:/dev/tpmrm0). - Supersedes the older userspace
tpm2-abrmddaemon on modern distros.
Detecting a TPM
$ ls /dev/tpm*
/dev/tpm0 /dev/tpmrm0
$ cat /sys/class/tpm/tpm0/tpm_version_major
2
$ cat /sys/class/tpm/tpm0/device/description 2>/dev/null
STMicroelectronics ST33
$ systemd-cryptenroll --tpm2-device=list
PATH DEVICE DRIVER
/dev/tpmrm0 STMicro ST33 tpm_crb
Tip
Proxmox note: On a VM, Hardware → Add → TPM State attaches a swtpm-backed device. The guest sees /dev/tpmrm0 identically to a physical machine, but the TPM's keys live in a file under /var/lib/vz/images/<vmid>/. Back that file up alongside the VM disks — and encrypt it, because anyone with it owns the "TPM".
Where This Leads
The next page builds directly on these primitives: UEFI Secure Boot provides the enforcement half (won't run unsigned code), measured boot into PCRs provides the recording half, and systemd-cryptenroll seals a LUKS key slot under a PCR policy so that a disk auto-unlocks only when the expected boot chain ran. Storage 06 covered LUKS2 and its key slots; everything in this capstone is adding a TPM-sealed slot to that picture.