Trusted Platform Modules revisited
Today i will not offer you code or snippets, this post is just for your information, why i do that? I will come to that in a second.
So what is this all about? This article is about Trusted Platform Modules (or TPM).
These are small modules that may be build into your computer. Most modern laptops are equipped with such a module, or not it depends on your manufacturer. You may have heard about TPMs in another, evil context. In some kind associated with the terms "TCPA" (old, deprecated name), "DRM" (digital rights management), "evil", "bill gates", "music industry controls your computer" and so on ;-)
Read this and you will know that there is nothing evil about TPMs, they are quite useful
I'm currently working on a projects to develop a native C# library to communicate with TPMs on different platforms with enhanced features. Before i (we) started working on this library i had nothing to do with TPMs. On my research-way i got confronted with many preconceptions about the functionality of these modules.
My first mission is to devitalize the existing accusions.
Facts and features
- TPMs are passive devices: There is no way for TPMs to interact, disturb or even control the host system on its own. The TPM only responds to requests sent by the host system.
- Disabled by default: The specification says that the module has to be disabled by default
- No need to expose private data (see the Endorsement key section below for further details)
What can TPMs be used for?
They provide security related function, like asymmetric key creation, secure data signing, binding data to a specific state of the host system, and much more. But first we need some basic principles.
Key hierachy, top down
If we talk about keys here, we always talk about asymmetric keys. Current TPMs only support RSA as the asymmetric crypto algorithm of choice, but i think that with newer releases (>1.2) at least ECC (elliptic curve cryptography) will also be available.
What follows is a picture of the key hierachy that is maintained by the TPM. I will then go into detail of the layers of the hierachy.
- Endorsement key: As you can see the whole (local) hierachy starts at the EK. The endorsement key is unique to your TPM and can (under normal circumstances) not be changed. This key is injected by the TPM vendor and never leaves your TPM. Because the EK is unique to your TPM and will never change, it also is privacy relevant.
- Storage root key: TPMs fresh out of the fab are quite useless, they only have their EK stored inside. The first thing you need to do to be able to use all this nice features is to taktover the ownership of the TPM. During this process you inject two secret values into the TPM. The first one is the owner secret which is needed later to do some special TPM tasks and administration tasks. But be aware of that the owner of the TPM is NOT a superuser, meaning that the owner cannot e.g. decrypt data without knowing the secret for the key.
The second one it the SRK-usage secret. That's the important point of the take ownership operation, it generates your SRK inside the TPM and protects the usage of the key with the supplied secret.
- These two keys are the only fixed structure in the key hierachy. The lower part could also look completly different, so this is just a sample hierachy. But properties that apply to all key hierachies are that each key has a specific usage type. So if you take a key hierachy like above where each user has its own set of key which are direct children of the SRK, you can say that a user needs a different key for signing than he would need for binding (described later).
Key creation and storage
Imagine a company which wants all emails that go out to be signed by a single TPM. So every user would need its own set of TPM keys. I would say each user would at least need a storage key and a signing key (and even more for other purposes). If this company has a few employees the TPM would soon run out of memory as more keys get created. That's the reason why keys do not reside inside the TPM, they get exported on creation, but they are not usable outside the TPM.
But first a few words on creation. To create a new key it is neccessary to load its parent key. To load its parent key it is neccessary to load the parent's parent key... and so on. Once the desired key is loaded you can create a new key. Each key has a usage secret attached which is needed to later on use the key. And on creation the private part of the key (and the usage secret of the key of course) gets encrypted with the public part of the parent key. That's the reason why the exported key data cannot be used. It first needs to be loaded back into the TPM, the TPM then needs the parent key with th correct usage secret of the parent to be able to decrypt the private part of the key you want to use. I know this really sounds weird, but at the moment it's the only practical solution to be sure that the TPM is the only one who can use the private part of the key.
Once you have your keys created you can use them for the purpose they are desired to
Signing is done inside the TPM in a secure way.
Binding vs. Sealing
TPMs support two operations that are quite similar but not the same
First binding. This is the process of binding some data to a specific TPM, so it can only be decoded by the user of the binding key on that TPM. You give some data and a previously created binding key to the TPM, the TPM will then encrypt the data for you and return the encrypted data. Without the binding key AND the TPM you have no chance of retrieving this data because you cannot read the private part of your binding key, so you need to unbind you encrypted data to get back the plaintext.
Sealing in contrast is the process of binding data to a specific TPM and specific configuration of the platform. To reveal your sealed data you need to be able to load the sealing key and the platform needs to be in the same "trusted state".
How to determine the state of the platform?
My opinion is that currently no practical solution for that problem exists. Theoretically and
TPMs have some so called Platform Configuration Registers (PCRs) builtin. These registers have known values on power on. On Computer boot every program that is run (starting at the bios -> boot loader -> kernel -> ...) is measured into a predefined PCR. There is not one PCR per program, typically there are only about 24 of such registers, so you measure each stage into its own PCR. e.g. PCR#0 is used for bios, PCR#1 for boot loader PCR#2 for kernel PCR#3 for programs,...
Measuring basically only is the process of calculating the hash of a program and sending this hash to the TPM which then "extends" the selected PCR. I will not go into detail of this process because thats already too specific but you can imagine that the whole system gets really slow.
I think you should basically understand the process of key creation, signing, binding and sealing now. Of course you do not need to code the communication from your application to the TPM yourself this is already done by some other and generally is called the "Trusted Software Stack" like trousers, jTSS and so on. But believe me these stacks are all quite complicated. That's the reason why we started a project at university which will end in a month or so and will provide a SIMPLE and USABLE software stack written in pure C# (no wrapper around something else). I'm not quite sure if i'm allowed to publish this stack here, but if so you will know.
How to test?
To be able to play around with TPMs you either need a TPM builtin or you download and installTPM Emulator.
You will also need a Trusted Software Stack. I would suggest to use TrouSers.