Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TPM (Trusted Platform Module)

Overview

A TPM (Trusted Platform Module) is a hardware security chip (or firmware implementation) that provides cryptographic functions: secure key generation, random number generation, PCR (Platform Configuration Register) measurements, and sealed storage. The Linux kernel TPM subsystem (tpm.ko, tpm_crb, tpm_tis) provides userspace access to TPM devices via /dev/tpm0 and /dev/tpmrm0.

TPM is foundational for Secure Boot, Measured Boot, dm-verity, IMA (Integrity Measurement Architecture), and disk encryption key sealing (LUKS + TPM2).

Source: drivers/char/tpm/ Interfaces: /dev/tpm0 (legacy), /dev/tpmrm0 (resource manager) Subsystem: drivers/char/tpm/tpm-chip.c


TPM Versions

FeatureTPM 1.2TPM 2.0
AlgorithmsSHA-1, RSASHA-256/384/512, RSA, ECC
Slots24 PCR banksUnlimited PCR banks
HierarchyOwner, SRKPlatform, Owner, Endorsement, Null
Commands~100~80 (new API)
AuthorizationHMAC sessionsPolicy sessions
Kernel supportLegacyRecommended (Linux 4.0+)
PCR banksSingle (SHA-1)Multiple (SHA-256, SHA-384, etc.)

Architecture

flowchart TD
    subgraph Userspace["Userspace"]
        TPM2TOOLS["tpm2-tools"]
        TSS["TSS (TPM Software Stack)"]
        SWTPM["swtpm (software TPM)"]
        SYSTEMD["systemd-cryptenroll"]
    end

    subgraph Kernel["Kernel (drivers/char/tpm/)"]
        TPM_CORE["tpm-chip.c<br>(TPM subsystem)"]
        TPM_DEV["/dev/tpm0, /dev/tpmrm0"]
        TPM_CRB["tpm_crb<br>(CRB interface)"]
        TPM_TIS["tpm_tis<br>(TIS interface)"]
        TPM_VTPM["tpm_vtpm<br>(virtual TPM)"]
        TPMRM["tpmrm-dev.c<br>(resource manager)"]
    end

    subgraph Hardware["Hardware"]
        HW_TPM["Physical TPM chip<br>(Infineon, STM, Nuvoton)"]
        FW_TPM["Firmware TPM<br>(fTPM in ARM TrustZone)"]
        SW_TPM["Software TPM<br>(swtpm for VMs)"]
    end

    TSS --> TPM2TOOLS
    TPM2TOOLS --> TPM_DEV
    SYSTEMD --> TPM_DEV
    TPM_DEV --> TPM_CORE
    TPMRM --> TPM_CORE
    TPM_CORE --> TPM_CRB
    TPM_CORE --> TPM_TIS
    TPM_CRB --> HW_TPM
    TPM_CRB --> FW_TPM
    TPM_TIS --> HW_TPM
    TPM_VTPM --> SW_TPM

Key Data Structures

struct tpm_chip

/* include/linux/tpm.h */
struct tpm_chip {
    struct device dev;                /* Device model */
    struct cdev cdev;                 /* Character device */
    struct cdev cdev_rm;              /* Resource manager cdev */
    struct rw_semaphore ops_sem;      /* Operations semaphore */
    const struct tpm_class_ops *ops;  /* Driver operations */
    struct tpm_chip *chip;            /* Parent chip (for RM) */
    int dev_num;                      /* /dev/tpm<dev_num> */
    unsigned long flags;              /* TPM_CHIP_FLAG_* */
    int locality;                     /* Current locality */
    struct tpm_buf buf;               /* Command buffer */
    struct mutex buf_lock;            /* Buffer lock */
    struct tpm_space *work_space;     /* TPM space (for sessions) */
    /* ... */
};

struct tpm_class_ops

/* include/linux/tpm.h */
struct tpm_class_ops {
    unsigned int flags;
    int (*recv)(struct tpm_chip *chip, u8 *buf, size_t len);
    int (*send)(struct tpm_chip *chip, u8 *buf, size_t len);
    void (*cancel)(struct tpm_chip *chip);
    u8 (*status)(struct tpm_chip *chip);
    bool (*update_timeouts)(struct tpm_chip *chip, unsigned long *timeout_cap);
    int (*request_locality)(struct tpm_chip *chip, int locality);
    void (*relinquish_locality)(struct tpm_chip *chip, int locality);
    int (*req_canceled)(struct tpm_chip *chip, u8 status);
    /* ... */
};

PCR (Platform Configuration Registers)

PCRs store measurements of boot components. Each PCR value is extended (not overwritten) — the new value is SHA256(old_value || new_measurement).

PCRContentUsed By
0BIOS/UEFI firmwareMeasured Boot
1BIOS/UEFI configurationMeasured Boot
2Option ROMsMeasured Boot
3Option ROM dataMeasured Boot
4Boot loader (MBR/GPT)Secure Boot
5GPT partition tableSecure Boot
6Resume from hibernatePower management
7Secure Boot stateSecure Boot
8Boot loader (kernel cmdline)Linux IMA
10IMA runtime measurementsLinux IMA
14Kernel command line (some distros)Boot integrity

PCR Extension Mechanism

sequenceDiagram
    participant BIOS as UEFI BIOS
    participant TPM as TPM 2.0
    participant BL as Bootloader
    participant Kernel as Linux Kernel
    participant IMA as IMA

    BIOS->>TPM: PCR[0] extend(firmware_hash)
    BIOS->>TPM: PCR[1] extend(config_hash)
    BL->>TPM: PCR[4] extend(bootloader_hash)
    BL->>TPM: PCR[5] extend(partition_table_hash)
    Kernel->>TPM: PCR[8] extend(cmdline_hash)
    IMA->>TPM: PCR[10] extend(file_hash)
# Read PCR values (TPM 2.0)
tpm2_pcrread sha256

# Extend a PCR
tpm2_pcrextend 10 sha256=$(echo -n "measurement" | sha256sum | cut -d' ' -f1)

# Verify PCR values (remote attestation)
tpm2_quote -c 0x81010001 -l sha256:0,2,4,7 -q nonce

# Read specific PCR bank
tpm2_pcrread sha256:0,2,4,7,10

TPM Operations

Key Management

# Create a primary key (TPM 2.0)
tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx

# Create a child key
tpm2_create -C primary.ctx -g sha256 -G rsa -u key.pub -r key.priv

# Load key into TPM
tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx

# Use key for signing
tpm2_sign -c key.ctx -g sha256 -o sig.rss message.dat

# Evict persistent key
tpm2_evictcontrol -C o -c 0x81010001

# Create RSA key with specific attributes
tpm2_create -C primary.ctx -g sha256 -G rsa2048:rsassa \
    -u key.pub -r key.priv -p keypass

Key Hierarchy

flowchart TD
    SRK["Storage Root Key (SRK)<br>Primary Key, Hierarchy: Owner"]
    SK1["Sealed Key 1<br>(LUKS passphrase)"]
    SK2["Signing Key<br>(TLS cert)"]
    DK1["Data Key<br>(Symmetric AES)"]
    DK2["Attestation Key<br>(EK-based)"]

    SRK --> SK1
    SRK --> SK2
    SK2 --> DK1
    SRK --> DK2

    style SRK fill:#f96,stroke:#333
    style SK1 fill:#9cf,stroke:#333
    style SK2 fill:#9cf,stroke:#333
    style DK1 fill:#9f9,stroke:#333
    style DK2 fill:#9f9,stroke:#333

Sealed Storage (Key Sealing)

# Seal data to specific PCR values
tpm2_createprimary -C o -c primary.ctx
tpm2_create -C primary.ctx -i secret.dat -u sealed.pub -r sealed.priv \
    -L pcr.policy

# Unseal (only succeeds if PCR values match)
tpm2_load -C primary.ctx -u sealed.pub -r sealed.priv -c sealed.ctx
tpm2_unseal -c sealed.ctx -p pcr:sha256:0,2,4,7

Random Number Generation

# Generate random bytes
tpm2_getrandom 32 -o random.bin

# Use TPM RNG for system entropy
# Kernel automatically mixes TPM RNG into /dev/random

Userspace Interfaces

/dev/tpm0 vs /dev/tpmrm0

DeviceDescriptionUse Case
/dev/tpm0Direct TPM accessSingle-user, legacy
/dev/tpmrm0Resource ManagerMulti-process, recommended

The resource manager (/dev/tpmrm0) handles TPM context switching between processes, allowing concurrent access. It manages session slots and handle namespaces.

sequenceDiagram
    participant P1 as Process 1
    participant P2 as Process 2
    participant RM as Resource Manager (/dev/tpmrm0)
    participant TPM as TPM Hardware

    P1->>RM: TPM2_CreatePrimary()
    RM->>RM: Save P1's context
    RM->>TPM: Forward command
    TPM-->>RM: Response (handle 0x80000001)
    RM-->>P1: Response

    P2->>RM: TPM2_GetRandom()
    RM->>RM: Save P2's context
    RM->>TPM: Forward command
    TPM-->>RM: Response
    RM-->>P2: Response

    P1->>RM: TPM2_Sign(handle)
    RM->>RM: Restore P1's context
    RM->>TPM: Forward command
    TPM-->>RM: Response
    RM-->>P1: Response

Kernel Interfaces

# Check TPM device
ls /dev/tpm*
ls /sys/class/tpm/

# TPM device info
cat /sys/class/tpm/tpm0/device/description
cat /sys/class/tpm/tpm0/device/pcrs

# TPM version
cat /sys/class/tpm/tpm0/tpm_version_major

# TPM enabled state
cat /sys/class/tpm/tpm0/enabled

# TPM active PCR banks
cat /sys/class/tpm/tpm0/pcr-sha256

TPM in Linux Security

Secure Boot + Measured Boot

flowchart TD
    A[Power On] --> B[BIOS measures into PCR 0-3]
    B --> C[Boot loader measured into PCR 4]
    C --> D[Kernel measured into PCR 5]
    D --> E[Initrd measured into PCR 5]
    E --> F[IMA measures files into PCR 10]
    F --> G[System running]
    G --> H{PCR values match expected?}
    H -->|Yes| I[Normal operation]
    H -->|No| J[Sealed keys unavailable]

IMA + TPM

IMA (Integrity Measurement Architecture) uses TPM to store file hashes:

# Check IMA measurements
cat /sys/kernel/security/ima/ascii_runtime_measurements

# IMA policy
cat /sys/kernel/security/ima/policy
# measure func=BPRM_CHECK
# measure func=FILE_MMAP mask=MAY_EXEC

# IMA appraisal (enforce integrity)
# appraise func=BPRM_CHECK appraise_type=imasig

LUKS + TPM

Seal disk encryption key to TPM:

# Seal LUKS key to TPM
systemd-cryptenroll /dev/sda1 --tpm2-device=auto

# Unlock at boot (automatic, no passphrase)
# initrd uses TPM to unseal key

# Bind to specific PCR values
systemd-cryptenroll /dev/sda1 --tpm2-device=auto \
    --tpm2-pcrs=0+2+4+7

# With PIN (two-factor)
systemd-cryptenroll /dev/sda1 --tpm2-device=auto \
    --tpm2-with-pin=yes

Threat Model

What TPM Protects Against

ThreatMitigation
Boot chain tamperingPCR measurements detect modified firmware/bootloader
Disk key extractionKeys sealed in TPM hardware, not extractable
Unauthorized key usagePolicy-bound keys require specific PCR state
Weak entropyHardware RNG provides true random numbers
Remote attestationQuote operation proves system state

Attack Surface

flowchart TD
    subgraph Attacks["TPM Attack Surface"]
        TIMING["Timing attacks<br>(TPM-Fail, CVE-2019-11090)"]
        LOCALITY["Locality attacks<br>(TPM-TIS)"]
        FTPM["fTPM vulnerabilities<br>(AMD, Intel)"]
        PHYSICAL["Physical attacks<br>(bus sniffing, cold boot)"]
        SW["Software stack bugs<br>(TSS, tpm2-tools)"]
        PCR["PCR manipulation<br>(reset/extend races)"]
    end

    subgraph Mitigations["Mitigations"]
        HW_TPM["Use discrete TPM chip"]
        SECUREBOOT["Secure Boot chain"]
        LOCKDOWN["Kernel lockdown"]
        PIN["TPM2 + PIN (2FA)"]
    end

    TIMING --> HW_TPM
    FTPM --> HW_TPM
    LOCALITY --> LOCKDOWN
    PHYSICAL --> SECUREBOOT
    PCR --> PIN

Known Vulnerabilities

CVEYearImpactAffected
CVE-2019-110902019RSA key extraction via timingIntel fTPM
CVE-2019-110912019Timing side-channelIntel fTPM
CVE-2023-10172023Out-of-bounds read in TPM 2.0Reference TPM 2.0 spec
CVE-2023-10182023Out-of-bounds write in TPM 2.0Reference TPM 2.0 spec

TPM-Fail (2019): Researchers demonstrated timing side-channel attacks against Intel fTPM and STMicroelectronics discrete TPM, extracting ECDSA signing keys. Mitigation: use constant-time operations, update firmware.


Kernel Internals

TPM Driver Initialization

sequenceDiagram
    participant Boot as Boot
    participant ACPI as ACPI
    participant TIS as tpm_tis / tpm_crb
    participant Core as tpm-chip.c
    participant Dev as /dev/tpm0

    Boot->>ACPI: Parse TPM2 ACPI table
    ACPI->>TIS: Probe TPM device
    TIS->>TIS: Request locality 0
    TIS->>TIS: Read TPM capabilities
    TIS->>Core: tpm_chip_register()
    Core->>Core: Create /dev/tpm0
    Core->>Core: Create /dev/tpmrm0
    Core-->>Dev: Device ready

TPM-TIS (TPM Interface Specification)

TIS is the legacy hardware interface for discrete TPMs:

/* drivers/char/tpm/tpm-tis-core.c */
struct tpm_tis_data {
    int irq;
    unsigned int locality;
    u16 manufacturer_id;
    int region_size;
    /* ... */
};

/* Locality access */
static int tpm_tis_request_locality(struct tpm_chip *chip, int l)
{
    /* Write ACCESS_REQUEST to locality register */
    /* Wait for ACCESS_ACTIVE bit */
    /* TPM-TIS supports localities 0-4 */
}

TPM-CRB (Command Response Buffer)

CRB is the modern hardware interface, required for TPM 2.0:

/* drivers/char/tpm/tpm-crb.c */
struct crb_priv {
    struct tpm_tis_data priv;
    u8 __iomem *cmd;
    u8 __iomem *rsp;
    u32 cmd_size;
    u32 smc_func_id;
    /* ... */
};

/* CRB uses memory-mapped registers */
/* cmd buffer: write TPM command */
/* rsp buffer: read TPM response */
/* No locality model (simpler than TIS) */

Resource Manager Internals

/* drivers/char/tpm/tpmrm-dev.c */
static ssize_t tpmrm_write(struct file *file, const char __user *buf,
                           size_t size, loff_t *off)
{
    struct tpm_chip *chip = file->private_data;
    struct tpm_space *space = &chip->work_space;

    /* Map virtual handles to physical handles */
    /* Swap context before sending to TPM */
    tpm2_flush_context_cmd(chip, space->context_tbl[i], 0);
    /* ... */
}

Kernel TPM API

/* include/linux/tpm.h */
int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
                   const u8 *hash);          /* Extend PCR */
int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
                 u8 *res_buf);               /* Read PCR */
int tpm_get_random(struct tpm_chip *chip, u8 *out,
                   size_t max);               /* Get random */
int tpm_seal_trusted(struct tpm_chip *chip,
                     struct trusted_key_payload *payload,
                     struct trusted_key_options *options);
int tpm_unseal_trusted(struct tpm_chip *chip,
                       struct trusted_key_payload *payload,
                       struct trusted_key_options *options);

Firmware TPM (fTPM)

fTPM implementations run in a trusted execution environment (TEE) rather than a discrete chip:

ImplementationPlatformTEENotes
Intel PTTIntel CPUs (Haswell+)Intel MEFirmware-based, no discrete chip
AMD fTPMAMD CPUs (Zen+)AMD PSP/ASPVulnerable to timing attacks (CVE-2019-*)
ARM TrustZone fTPMARM SoCsOP-TEEMicrosoft reference implementation
Google TitanPixel devicesTitan MCustom hardware security chip

fTPM vs Discrete TPM

AspectfTPMDiscrete TPM
CostFree (in CPU)$1-5 chip
PerformanceFaster (on-die)Slower (SPI/LPC bus)
Physical attack resistanceLower (shared silicon)Higher (dedicated chip)
Firmware updatesVia CPU microcodeVia TPM firmware
Side-channel resistanceLower (timing)Higher (constant-time)
FIPS certificationRareCommon

TPM 2.0 Policy Sessions

TPM 2.0 uses policy sessions for complex authorization:

# Create a policy session requiring specific PCR values
tpm2_startauthsession -S session.ctx
tpm2_policypcr -S session.ctx -l sha256:0,2,4,7 -L pcr.policy
tpm2_policyauthvalue -S session.ctx
tpm2_flushcontext session.ctx

# Use policy to unseal
tpm2_startauthsession --policy-session -S session.ctx
tpm2_policypcr -S session.ctx -l sha256:0,2,4,7
tpm2_policyauthvalue -S session.ctx
tpm2_unseal -c sealed.ctx -p session:session.ctx
tpm2_flushcontext session.ctx

Policy Types

PolicyCommandUse Case
PCR-basedtpm2_policypcrBind to boot state
Passwordtpm2_policyauthvalueRequire passphrase
Countertpm2_policycountersignedAnti-rollback
Localitytpm2_policylocalityRestrict to specific locality
NV-basedtpm2_policyorNV index conditions
Signedtpm2_policyauthorizeDelegate authorization

Virtual TPM for VMs

# Create software TPM for QEMU/KVM
swtpm socket --tpmstate dir=/tmp/tpm \
    --ctrl type=unixio,path=/tmp/tpm.sock \
    --tpm2 --log level=20

# QEMU with vTPM
qemu-system-x86_64 \
    -chardev socket,id=chrtpm,path=/tmp/tpm.sock \
    -tpmdev emulator,id=tpm0,chardev=chrtpm \
    -device tpm-tis,tpmdev=tpm0 \
    -drive file=vm.qcow2,format=qcow2

# Verify inside VM
cat /sys/class/tpm/tpm0/tpm_version_major
# 2

Troubleshooting

# Check if TPM is detected
dmesg | grep -i tpm

# Load TPM modules
modprobe tpm_crb  # CRB interface (modern)
modprobe tpm_tis  # TIS interface (older)

# Test TPM
tpm2_selftest

# TPM tools diagnostics
tpm2_getcap properties-fixed

# Check TPM errors
dmesg | grep -i "tpm.*error"

# Verify TPM is accessible
tpm2_getrandom 4 --hex

# Check TPM ownership
tpm2_getcap handles-persistent

# List loaded keys
tpm2_getcap handles-transient

# Measure boot chain
systemd-analyze security

# Check sealed key status
cryptsetup luksDump /dev/sda1 | grep -i tpm

Performance Diagnostics

# Measure TPM command latency
time tpm2_getrandom 32 --hex

# Typical latency: 1-5ms for hardware TPM
# fTPM latency: <1ms (on-die)

# Check for TPM timeouts
dmesg | grep -i "tpm.*timeout"

# TPM command statistics (if available)
cat /sys/class/tpm/tpm0/ppi/version

Kernel Configuration

# Required for TPM support
CONFIG_TCG_TPM=y               # Core TPM driver
CONFIG_TCG_TIS_CORE=y          # TIS core
CONFIG_TCG_TIS=y               # TIS interface (SPI)
CONFIG_TCG_TIS_SPI=y           # SPI-attached TPM
CONFIG_TCG_CRB=y               # CRB interface (ACPI)
CONFIG_TCG_VTPM_PROXY=y        # Virtual TPM proxy
CONFIG_TCG_TIS_ST33ZP24_SPI=y  # ST33ZP24 SPI TPM
CONFIG_TCG_XEN=y               # Xen vTPM
CONFIG_TCG_ATMEL=y             # Atmel TPM
CONFIG_TCG_INFINEON=y          # Infineon TPM
CONFIG_TCG_NUVOTON=y           # Nuvoton TPM
CONFIG_TCG_IBMVTPM=y           # IBM vTPM (Power)

# For trusted keys
CONFIG_TRUSTED_KEYS=y          # Kernel trusted key type
CONFIG_ENCRYPTED_KEYS=y        # Encrypted key type
CONFIG_KEYS=y                  # Key management subsystem
CONFIG_TPM_KEY_PARSER=y        # TPM key blob parser

Source Files

FileContents
drivers/char/tpm/tpm-chip.cTPM subsystem core
drivers/char/tpm/tpm-crb.cCRB (Command Response Buffer) interface
drivers/char/tpm/tpm-tis.cTIS (TPM Interface Specification)
drivers/char/tpm/tpm-tis-core.cTIS core logic
drivers/char/tpm/tpmrm-dev.cResource manager device
drivers/char/tpm/tpm2-space.cTPM 2.0 session/context management
drivers/char/tpm/tpm_vtpm.cVirtual TPM driver
include/linux/tpm.hTPM API header
security/keys/trusted-keys/Kernel trusted key subsystem
security/keys/encrypted-keys/Encrypted key subsystem

Further Reading


See Also