Demystifying Trusted Platform Modules, Part 2

This is part 2 of a 6-part series on Trusted Platform Modules. If you missed part 1, be sure to check that out first!

Summit Embedded Blog: TPM Series

  1. TPM Set-up/Overview

  2. Inspect the Non-Private Contents of a TPM (this post)

  3. Store Non-Private Data (NVRAM)

  4. Encrypt & Decrypt Data

  5. Generate a Device Identity Certificate

  6. Sign Data With A Certificate

Inspect the Non-Private Contents of a TPM

In the last post, we set up a RaspberryPi with an OPTIGA SLB9670 TPM2.0 eval board. Next, lets initialize it with some data that we’ll use in future posts.

This is the most important post to “demystify” TPMs. You’ll learn your way around the device & its commands, and see that it’s not that complicated.

List General Capabilities (caps)

Just run

sudo tpm2_getcap --list;

This lists all the general things your TPM can do. You can add items from the list as arguments to tpm2_getcap commands if you want to play around more. We’ll dive into the four most important ones next:

  1. handles-nv-index

  2. handles-persistent

  3. handles-transient

  4. handles-permanent

Note that they all involve “handles”. Think of handles as a memory address (though they aren’t a set number of bytes like true memory addresses). We can store different pieces of info in different handles. We’ll dive further into handles later, but first let’s try an example: Let’s read some data that Infineon stored in NV memory for us:

Reading Non-Volatile Data

One major point of confusion is that people often think any data in a TPM is sealed and you can never read it. That’s only partly true. There are unreadable regions that we’ll dive into later. But there is a small amount (6882 bytes on an SLB9670) of memory that CAN be read back. It’s called “NV” data because it persists across reboots (and hard drive flashes!). This is for bits of important data that you DO want to be able to read, such as a serial number, MAC address, public bits of a device’s identity certificate, etc.

Let’s see what’s in there with

sudo tpm2_getcap handles-nv-index;

This will print several handles starting with 0x1…. (or 0x01 without the leading zero). You’ll likely see 0x01C00002 and 0x01C0000A, which are some Endorsement certs that Infineon providse to prove it’s a legitimate Infineon device. Let’s inspect one with:

sudo tpm2_nvread 0x01C00002 | openssl x509 -in /dev/stdin -inform der;

You’ll see a standard x509 certificate in the usual base64 form. We had to pipe that to openssl to make it somewhat human readable. You can convert this base64 format to a more human-readable form by adding the -text argument to the above openssl form. If you do, you’ll see that it’s signed by Infineon.

You can store plaintext strings in NVRAM as well, such as serial numbers, device name, etc.

What are “handles” again?

You can think of handles as addresses for various pieces of data. If you really want to know more, you can read about all the possible ranges in the TPM2.0 Library/Specification (see “Part 1: Architecture”, chapter 13). But we’ll condense it into a summary here:

0x01**_**** - NV Handles: as we saw above, this is a range where one can store data that is able to be read back (see Appendix: Hierarchies section below about some settings that might restrict who can read it back). Both the TPM manufacturer and the user can store data here

0x04**_**** - Permanent Handles: These are handles for secrets that are permanently written by the manufacturer, such as endorsement keys. They can survive a TPM clear. Other than that, they’re very similar to Persistent Handles. So let’s skip right to persistent handles and things will make more sense…

0x81****** - Persistent Handles: These are the user secrets. If you’re using a TPM in your device, this is the main function you’re after. Each handle is a reference to a secret key that is stored in the TPM and cannot be read back. These are persistent across power cycles, but they are cleared with a tpm2_clear command.

Other handles include session handles & transient handles which are, as it sounds, temporary and don’t persist across power cycles. Those are more advanced features that are outside the scope of this blog.

Lastly, PCR handles are worth noting briefly. They are “Platform Control Registers”, which store hashes of data that is unique to your device. It can be used by Secure Boot, among other features, that seek to verify that the TPM is still installed in the original device. This is another advanced feature that is beyond the scope of this blog. Just know that it’s ok to use a TPM without configuring the PCR hashes, but it may be possible for someone to de-solder the TPM from your device and install it in a different device. The attacker still can’t read the secret values inside, but they could manually run commands (like we’re about to do) to make the TPM sign & decrypt things. They would still need the password for your hierarchies, if you choose to configure those. If you just thought, “But what is a hierarchy?”, see the appendix below.

Reading Secret Data

Handle range: 0x81**_**** (for most handles we are concerned with)

Reading secret data? What, what?!? I thought the whole point of TPMs is that you can’t read secret data.

Well that’s correct, you can’t read the secret part. But it would be pretty useless (especially for asymmetric keys) to store away some value and not be able to read it’s corresponding public key (or general meta data for symmetric keys).

Recall that, with asymmetric keys, you can share a public key and anyone in the world can use that public key to encrypt a message to you. The private key is only needed to decrypt that message. So you want to be able to read and share the public key that corresponds to the secret in your TPM. We’ll go through an example in a future post, but for now just know that the command would be:

sudo tpm2_readpublic -c 0x81000000 -f pem -o public.pem

to export a public key’s PEM file for the secret stored at handle 0x81000000.

Appendix: Hierarchies

One last TPM concept that’s important to know: the concept of hierarchies. There are five of them:

  1. Endorsement Hierarchy

  2. Platform Hierarchy

  3. Owner Hierarchy

  4. Lockout Hierarchy

  5. Null Hierarchy

These are essentially “roles”. Think about it like this, using a consumer PC as an example:

  1. A chip-maker creates the TPM chip and sends it to a manufacturer

  2. A manufacturer (think HP, Lenovo, etc) creates the PC (using a TPM chip and many other chips), installs an operating system, and ships the PC to the user.

  3. The user configures the OS and configures possibly custom applications that need secure storage.

So now we can see the need for the different hierarchies.

  1. The TPM chip manufacturer stores certificates in the Endorsement Hierarchy to prove the TPM chip is trustworthy, not made by a 3rd-party trying to commit a supply-chain attack.

  2. Likewise, the PC manufacturer uses the Platform Hierarchy to store certificates proving the entire motherboard was assembled by a trustworthy company.

  3. Lastly, the owner of the PC controls the Owner Hierarchy. The OS uses the owner hierarchy because the end-user can choose what OS to install and, more importantly, choose what features they want (such as Secure Boot, which stores secrets in the TPM).

  4. Lockout Hierarchy - you can set a different password to unlock the TPM when someone tries to use the other hierarchy too many times.

  5. Oh and that Null Hierarchy… that’s used for temporary TPM data that doesn’t need a password.

More details are beyond the scope of this blog. But now you’re familiar when you see the “-C o”, ”-C p”, and ”-C e” arguments in TPM commands.

Previous
Previous

Demystifying Trusted Platform Modules, Part 3

Next
Next

Demystifying Trusted Platform Modules, Part 1