User:Diabonas/Trusted Platform Module

From ArchWiki

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 and key storage.

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.

Versions

There are two very different TPM specifications: 1.2 and 2.0, which also use different software stacks.

  • TPM 1.2 uses the "TrouSerS" TSS (TCG software stack) by IBM, which is packaged as trousersAUR (tcsd) and tpm-toolsAUR (userspace). All software access the TPM through the tcsd daemon.
  • TPM 2.0 allows direct access via /dev/tpm0 (one client at a time), managed access through the tpm2-abrmd resource manager daemon, or kernel-managed access via /dev/tpmrm0. There are two choices of userspace tools, tpm2-tools by Intel and ibm-tssAUR by IBM.

TPM 2.0 requires UEFI (native); BIOS or CSM systems can only use TPM 1.2.

Some TPM chips can be switched between 1.2 and 2.0 through a firmware upgrade (which can be done only a limited number of times).

Using TPM 2.0

The following examples focus on the Intel software stack.

Usage

Install tpm2-tools. To test whether a connection to the TPM can be established successfully, issue e.g.

$ tpm2_getrandom 20

If this prints out a stream of (possibly unreadble) random characters, everything works as expected.

If you want to be able to communicate with the TPM without root access, either add yourself to the tss user group group or install tpm2-abrmd.

Storing secrets in the TPM

For storing a secret in the TPM, there are two possibilities:

  1. Create a file that is encrypted using a key that is only stored in the TPM. In order to retrieve the secret, the encrypted file is supplied to the TPM which decrypts the file and returns the secret. No persistent data is stored directly in the TPM, but the size of the secret is limited to 128 bytes. To store the secret, use
    tpm2_createprimary --key-algorithm=ecc --key-context=primary.ctx
    echo "my secret" | tpm2_create --parent-context=primary.ctx --sealing-input=- --public=secret.pub --private=secret.priv
    

    To retrieve the secret:

    tpm2_createprimary --key-algorithm=ecc --key-context=primary.ctx
    tpm2_load --parent-context=primary.ctx  --public=secret.pub --private=secret.priv --key-context=secret.ctx
    tpm2_unseal --object-context=secret.ctx
  2. Store the secret persistently in the TPMs persistent memory. This is useful e.g. for storing a key file for disk encryption because you can retrieve it during boot without using additional files. Note that the available memory is limited in size and is not designed for extremely frequent rewrites. To reserve a 10 byte memory area at the address 0x2000A and write a secret to it, use
    tpm2_nvdefine --size 10 --attributes 'authread|authwrite' 0x2000A
    echo "my secret" | tpm2_nvwrite --input=- 0x2000A
    

    To retrieve the secret:

    tpm2_nvread 0x2000A
    

Restricting access based on the system state

By default, anybody with access to the TPM can retrieve the stored secrets. It is possible to limit access to secrets based on the current system state, which is measured by the UEFI firmware into the TPM in so-called Platform Configuration Registers (PCRs): for example, PCR 0 contains a hash of the UEFI firmware, PCR 4 hashes all the executed EFI binaries, PCR 7 contains all the certificates used to authenticate Secure Boot, ... To create a policy that is only fulfilled when the current state of PCRs 0,2,3 and 7 is matched, use

tpm2_createpolicy --policy-pcr --pcr-list=sha256:0,2,3,7 --policy=pcr.pol

In order to create a secret that can only be retrieved when the policy is fulfilled, the examples above need to be modified as follows:

tpm2_createprimary --key-algorithm=ecc --key-context=primary.ctx
echo "my secret" | tpm2_create --parent-context=primary.ctx --sealing-input=- --public=secret.pub --private=secret.priv --policy=pcr.pol
tpm2_load --parent-context=primary.ctx  --public=secret.pub --private=secret.priv --key-context=secret.ctx
tpm2_unseal --object-context=secret.ctx --auth=pcr:sha256:0,2,3,7

or if you are using persistent TPM storage

tpm2_nvdefine --size 10 --attributes='policyread|authwrite' --policy=pcr.pol 0x2000A
echo "my secret" | tpm2_nvwrite --input=- 0x2000A
tpm2_nvread --auth=pcr:sha256:0,2,3,7 0x2000A

After forcing a change of the PCR state by using

tpm2_pcrextend 7:sha256=0000000000000000000000000000000000000000000000000000000000000000

retrieving the secret with tpm2_unseal/tpm2_nvread will fail. The PCR state is reset after each reboot, so after rebooting the secret will be accessible once again provided nothing in the boot process has changed.

Using a TPM simulator

On systems without a physical TPM, a virtual TPM provided by ibm-sw-tpm2 can be used. Start the simulator with tpm_server and initialise it using tpm2_startup --clear, then you will be available to execute the examples given above. The tools will automatically use the simulator if no physical TPM is available. If you want to use the simulator for experiments even if a physical TPM is present, you can force its use by exporting the environment variable TPM2TOOLS_TCTI=mssim.

Using TPM 1.2

Drivers

TPM drivers are natively supported in modern kernels, but might need to be loaded:

# modprobe tpm

Depending on your chipset, you might also need to load one of the following:

# modprobe tpm_{atmel,infineon,nsc,tis,crb}

Usage

TPM 1.2 is managed by tcsd, a userspace daemon that manages Trusted Computing resources and should be (according to the TSS spec) the only portal to the TPM device driver. tcsd is part of the trousersAUR AUR package, which was created and released by IBM, and can be configured via /etc/tcsd.conf.

To start tcsd and watch the output, run:

# tcsd -f

or simply start and enable tcsd.service.

Once tcsd is running you might also want to install tpm-toolsAUR which provides many of the command line tools for managing the TPM.

Some other tools of interest:

  • tpmmanager — A Qt front-end to tpm-tools
http://sourceforge.net/projects/tpmmanager || tpmmanagerAUR
  • openssl_tpm_engine — OpenSSL engine which interfaces with the TSS API
http://sourceforge.net/projects/trousers || openssl_tpm_engineAUR[broken link: package not found]
  • tpm_keyring2 — A key manager for TPM based eCryptfs keys
http://sourceforge.net/projects/trousers || tpm_keyring2AUR[broken link: package not found]
  • opencryptoki — A PKCS#11 implementation for Linux. It includes drivers and libraries to enable IBM cryptographic hardware as well as a software token for testing.
http://sourceforge.net/projects/opencryptoki || opencryptokiAUR

Basics

Start off by getting basic version info:

$ tpm_version

and running a selftest:

$ tpm_selftest -l info
 TPM Test Results: 00000000 ...
 tpm_selftest succeeded

Securing SSH Keys

There are several methods to use TPM to secure keys, but here we show a simple method based on simple-tpm-pk11-gitAUR.

First, create a new directory and generate the key:

$ mkdir ~/.simple-tpm-pk11
$ stpm-keygen -o ~/.simple-tpm-pk11/my.key

Point the config to the key:

~/.simple-tpm-pk11/config
key my.key

Now configure SSH to use the right PKCS11 provider:

~/.ssh/config
Host *
    PKCS11Provider /usr/lib/libsimple-tpm-pk11.so

It's now possible to generate keys with the PKCS11 provider:

$ ssh-keygen -D /usr/lib/libsimple-tpm-pk11.so
Note: This method currently does not allow for multiple keys to be generated and used.

Troubleshooting

tcsd.service failed to start

The tcsd.service service may not start correctly due to permission issues.[1]. It is possible to fix this using:

# chown tss:tss /dev/tpm*
# chown -R tss:tss /var/lib/tpm

See also