7 cool things to do with your TPM on Linux

by Martin Monperrus

Intro

A TPM is a hardware component that provides cryptographic functionality for enhanced security on modern computer systems, it stands for “Trusted Platform Module”. For a number of years, most business computers have been equipped with a TPM, because many government agencies (eg DoD) and businesses make them mandatory.

On Linux, TPMs are supported via a combination of BIOS code and kernel code.

Applications can talk to the TPM via different channels:

A TPM has many use cases, this post goes over a few of them.

Disk encryption

To set up disk encryption with a TPM on Linux, you would typically use software tools like LUKS (Linux Unified Key Setup) or dm-crypt, which are commonly available in Linux distributions.

By storing the encryption keys in the TPM, you make sure that nobody can decrypt the disk by detaching it from the computer. To read the disk, one needs the pair of physical components disk+TPM.

See for example, LUKS with TPM in Ubuntu

Authentication to SSH servers

Authenticate to an SSH server with a TPM is equivalent to authenticate via a hardware key (such as a Yubikey). The idea is to generate the key on the TPM and then add it to authorized_keys on the server.

See Protecting SSH keys with TPM 2.0 on Debian

Act as FIDO U2H security key

A TPM stores keys, exactly as an external key. It is possible to use your TPM as FIDO U2H key device. Then, you connect to your favorite secure website (your bank, your cryptoexchange, your email) via your TPM. Since one must always have two security keys (main and backup), you need to only buy one key, the TPM being the other (not entirely true if you use your phone as security key, see passkeys).

For this you need https://github.com/psanford/tpm-fido to do the translation.

Store your GPG keys

A TPM can handle GPG keys, to do email encryption for example. For this, you need one of those:

Super short tutorial (YMMV) with GPG on OpenSuse:

tpm2daemon --daemon
gpg --quick-generate-key "<you@example.net>" rsa2048
gpg --edit-key you@example.net
> keytotpm
echo foo | gpg -s

Secure boot

For critical machines, one needs to make sure that the booted kernel is the right one, something called “Secure Boot”. A TPM is a key component for that, responsible to handle the key.

See The ultimate guide to Secure Boot

Remote Attestation

Even if one boots a known kernel, an attacker may be able to tamper with the code later on. For countering, one needs to constantly monitor the execution and checks that everything is OK. This is something called “Measured Boot” and “Remote Attestation”. A TPM has supports to store sequence of events in special registers called PCR (for “Platform Configuration Register”) with cryptographic integrity.

See What Can You Do with a TPM? (Redhat)

Act as random number generator

Good random number generators are always physical (and not only software based as pseudo-random number generators are). Most TPMs have support for this.

$ tpm2_getrandom  --hex 16
73aceda0cb63f0e1edb4a2adf295e98c

# using the TPM OpenSSL provider https://github.com/tpm2-software/tpm2-openssl
$ openssl rand  -provider tpm2 --hex  30
a42fc61dcbaabdeaf8f4078281e63c928eaeba760eb6dab2f4afecc700f0

See Random Numbers via TPM2 Tools

Troubleshooting

Is your TPM activated in the BIOS? (eg How to Enable the TPM | Dell)

# dmesg | grep -i tpm
[    0.011376] ACPI: TPM2 0x00000000789D22D8 000034 (v04 DELL\x CBX3     00000001 AMI  00000000)
[    0.011417] ACPI: Reserving TPM2 table memory at [mem 0x789d22d8-0x789d230b]
[    0.609138] tpm_tis MSFT0101:00: 2.0 TPM (device-id 0x0, rev-id 78)

Which TPM version do you use? TPM has two versions, 1 and 2, in this post, I focus on TPM version 2:

$ cat /sys/class/tpm/tpm0/tpm_version_major 
2

Could you use your TPM with OpenSSL?

$ openssl list -providers -provider tpm2
Providers:
  default
    name: OpenSSL Default Provider
    version: 3.0.2
    status: active
  legacy
    name: OpenSSL Legacy Provider
    version: 3.0.2
    status: active
  tpm2
    name: TPM 2.0 Provider
    version: 
    status: active

What algorithms are supported by your TPM?

$ tpm2_getcap algorithms
rsa:
  value:      0x1
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     1
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     0
sha1:
  value:      0x4
  asymmetric: 0
  symmetric:  0
  hash:       1
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     0
hmac:
  value:      0x5
  asymmetric: 0
  symmetric:  0
  hash:       1
  object:     0
  reserved:   0x0
  signing:    1
  encrypting: 0
  method:     0
aes:
  value:      0x6
  asymmetric: 0
  symmetric:  1
  hash:       0
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     0
mgf1:
  value:      0x7
  asymmetric: 0
  symmetric:  0
  hash:       1
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     1
keyedhash:
  value:      0x8
  asymmetric: 0
  symmetric:  0
  hash:       1
  object:     1
  reserved:   0x0
  signing:    1
  encrypting: 1
  method:     0
xor:
  value:      0xA
  asymmetric: 0
  symmetric:  1
  hash:       1
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     0
sha256:
  value:      0xB
  asymmetric: 0
  symmetric:  0
  hash:       1
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     0
rsassa:
  value:      0x14
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     0
  reserved:   0x0
  signing:    1
  encrypting: 0
  method:     0
rsaes:
  value:      0x15
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 1
  method:     0
rsapss:
  value:      0x16
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     0
  reserved:   0x0
  signing:    1
  encrypting: 0
  method:     0
oaep:
  value:      0x17
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 1
  method:     0
ecdsa:
  value:      0x18
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     0
  reserved:   0x0
  signing:    1
  encrypting: 0
  method:     1
ecdh:
  value:      0x19
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     1
ecdaa:
  value:      0x1A
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     0
  reserved:   0x0
  signing:    1
  encrypting: 0
  method:     0
ecschnorr:
  value:      0x1C
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     0
  reserved:   0x0
  signing:    1
  encrypting: 0
  method:     0
kdf1_sp800_56a:
  value:      0x20
  asymmetric: 0
  symmetric:  0
  hash:       1
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     1
kdf1_sp800_108:
  value:      0x22
  asymmetric: 0
  symmetric:  0
  hash:       1
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     1
ecc:
  value:      0x23
  asymmetric: 1
  symmetric:  0
  hash:       0
  object:     1
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     0
symcipher:
  value:      0x25
  asymmetric: 0
  symmetric:  0
  hash:       0
  object:     1
  reserved:   0x0
  signing:    0
  encrypting: 0
  method:     0
ctr:
  value:      0x40
  asymmetric: 0
  symmetric:  1
  hash:       0
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 1
  method:     0
ofb:
  value:      0x41
  asymmetric: 0
  symmetric:  1
  hash:       0
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 1
  method:     0
cbc:
  value:      0x42
  asymmetric: 0
  symmetric:  1
  hash:       0
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 1
  method:     0
cfb:
  value:      0x43
  asymmetric: 0
  symmetric:  1
  hash:       0
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 1
  method:     0
ecb:
  value:      0x44
  asymmetric: 0
  symmetric:  1
  hash:       0
  object:     0
  reserved:   0x0
  signing:    0
  encrypting: 1
  method:     0
Tagged as: