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 corporates 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:
- via device
/dev/tpm0
(one client at a time) (check for read-write attributes) - via device kernel-managed
/dev/tpmrm0
(check for read-write attributes) - via resource manager daemon
tpm2-abrmd
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:
- use a recent version of GPG, >= 2.3, see Using a TPM with GnuPG 2.3
- use GPG via PKCS11, using gnupg-pkcs11-scd and tpm2-pkcs11.
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