mirror of
https://github.com/tpm2dev/tpm.dev.tutorials.git
synced 2024-11-24 23:02:11 +00:00
Add introduction to TPMs
This commit is contained in:
parent
3183bc537a
commit
90d9bc2619
2 changed files with 459 additions and 4 deletions
455
Intro/README.md
Normal file
455
Intro/README.md
Normal file
|
@ -0,0 +1,455 @@
|
|||
# Introduction to TPMs
|
||||
|
||||
Trusted Platform Modules (TPMs) are a large and complex topic, made all
|
||||
the more difficult to explain by the intricate relationships between the
|
||||
relevant concepts. This is an attempt at a simple explanation --
|
||||
simpler than reading hundreds of pages of documents, but then too, too
|
||||
light on detail to be immediately useful.
|
||||
|
||||
So what is a TPM? Well, it's a cryptographic co-processor with special
|
||||
features to enable "root of trust measurement" (RTM), remote attestation
|
||||
of system state, unlocking of local resources that are kept encrypted
|
||||
(e.g., filesystems), and more. A TPM can do those things, and it can do
|
||||
it with rich authentication and authorization policies.
|
||||
|
||||
Typically a TPM is a hardware module, a chip, though there are firmware,
|
||||
virtual, and simulated TPMs as well, all implemented in software.
|
||||
|
||||
To simplify things we'll consider only TPM 2.0. Also to simplify things
|
||||
we'll ignore algorithm agility.
|
||||
|
||||
Other parts of this [tutorial](README.md) may cover specific concepts in
|
||||
much more detail.
|
||||
|
||||
# Core Concepts
|
||||
|
||||
Some core concepts in the world of TPMs
|
||||
|
||||
- cryptography:
|
||||
- digest functions
|
||||
- hash extension
|
||||
- HMAC
|
||||
- symmetric encryption
|
||||
- asymmetric encryption and/or signature algorithms
|
||||
- platform configuration registers (PCRs)
|
||||
- cryptographic object naming
|
||||
- immutability of object public areas
|
||||
- key hierarchies
|
||||
- key wrapping
|
||||
- limited resources
|
||||
- tickets
|
||||
- resource management
|
||||
- sessions
|
||||
- authorization
|
||||
- restricted cryptographic keys
|
||||
- policies
|
||||
- other object types
|
||||
- non-volatile (NV) indexes
|
||||
- attestation
|
||||
|
||||
We'll assume reader familiarity with cryptography so we need not explain
|
||||
it.
|
||||
|
||||
Authorization is the most important aspect of a TPM, since that's
|
||||
ultimately what it exists for: to authorize a system or application to
|
||||
perform certain duties when all the desired conditions allow for it.
|
||||
|
||||
TPMs have a very rich set of options for authorization. It's not just
|
||||
[policies](#Policies), but also cryptographic object names used with
|
||||
restricted keys to allow access only to applications that also have
|
||||
other access.
|
||||
|
||||
Where to start? Let's start with hash extension, which may be the only
|
||||
trivial concept in the world of TPMs!
|
||||
|
||||
## Important Notes
|
||||
|
||||
- Chained implications.
|
||||
|
||||
It is important to note the TPM ecosystem's critical dependence on
|
||||
TPMs performing authorization as specified. A lot can be
|
||||
accomplished by chaining cryptographic implications. Sending a
|
||||
secret to a TPM-using application, with the secret encrypted in that
|
||||
TPM's primary endorsement public key is safe when one knows that
|
||||
public key truly is a legitimate hardware TPM's public key: the TPM
|
||||
will not release the secret to the application unless the recipient
|
||||
has some access specified by the sender. Complex chains of events
|
||||
can be secure provided one knows that it involves legitimate hardware
|
||||
TPMs that otherwise could not be secured. Therefore the legitimacy
|
||||
of a TPM that one communicates with is essential.
|
||||
|
||||
- Limited resources.
|
||||
|
||||
Hardware TPMs are very resource-starved. The set of commands defined
|
||||
by the TCG TPM specifications is specifically constructed to a) be
|
||||
small and simple (simple-enough anyways), yet b) enable rich
|
||||
semantics in spite of this.
|
||||
|
||||
These limited resources mean, among other things, that TPMs don't do
|
||||
complex things like PKIX certificate validation path construction, or
|
||||
even PKIX certificate path validation, nor do they implement complex
|
||||
authentication protocols using PKIX, nor Kerberos, nor even simple
|
||||
protocols like JWT. Hardware TPMs can be used to implement portions
|
||||
of such complex protocols (e.g., certificate issuance), but they
|
||||
cannot implement the entirety of such protocols.
|
||||
|
||||
- Hardware TPMs are _slow_.
|
||||
|
||||
- A *lot* of detail is left out here. Nothing is said about how TPMs
|
||||
interface with the system or applications. Little is said about
|
||||
specific commands, and nothing is said about most commands. Nothing
|
||||
is said about TPM software stacks or APIs.
|
||||
|
||||
Our goal is only to help the lay reader understand TPMs well enough
|
||||
at the conceptual level that they will be more comfortable
|
||||
approaching mure more detailed TPM-related tutorials, documents,
|
||||
books, or TCG specifications.
|
||||
|
||||
## Hash Extension
|
||||
|
||||
Hash extension is just appending some data to a current digest-sized
|
||||
value, hashing that, and then calling the output the new current value:
|
||||
|
||||
```
|
||||
v_0 = 0 # size-of-digest-output zero bits
|
||||
v_1 = Extend(v_0, e_0)
|
||||
= H(v_0 || e_0)
|
||||
v_2 = Extend(v_1, e_1)
|
||||
= H(v_1 || e_1)
|
||||
= H(H(v_0 || e_0) || e_1)
|
||||
v_3 = Extend(v_2, e_2)
|
||||
= H(v_2 || e_2)
|
||||
= H(H(v_1 || e_1) || e_2)
|
||||
= H(H(H(v_0 || e_0) || e_1) || e_2)
|
||||
..
|
||||
v_n = Extend(v_n-1, e_n-1)
|
||||
= H(v_n-1 || e_n-1)
|
||||
= H(H(v_n-2 || e_n-2) || e_n-1)
|
||||
= H(H(...) || e_n-1)
|
||||
```
|
||||
|
||||
where `H()` is a cryptographic hash function.
|
||||
|
||||
Hash extension is most of what a PCR is, but hash extension is in other
|
||||
TPM concepts besides PCRs, such as policy naming.
|
||||
|
||||
## Platform Configuration Registers (PCRs)
|
||||
|
||||
A PCR, then, is just a hash output. The only operations on PCRs are:
|
||||
read, extend, and reset. All richness of semantics of PCRs come from
|
||||
how they are used:
|
||||
|
||||
- how they are extended and by what code
|
||||
- what purposes they are read for
|
||||
- attestation
|
||||
- authorization
|
||||
|
||||
## Root of Trust Measurements (RTM)
|
||||
|
||||
When a computer and its TPM start up, most PCRs are set to all-zeros,
|
||||
and then the computer's boot firmware performs a core root of trust
|
||||
measurement (CRTM) to "measure" (i.e., hash) the the next boot stage and
|
||||
extend it into an agreed-upon PCR. The entire boot process should,
|
||||
ideally, perform RTMs. At the end of the boot process some set of PCRs
|
||||
should reflect the totality of the code path taken to complete booting.
|
||||
|
||||
Some PCRs are used to measure the BIOS, others to measure option ROMs,
|
||||
and others to measure the operating system. In principle one could
|
||||
measure the entirety of an operating system and all the code that is
|
||||
installed on the system.
|
||||
|
||||
RTM can be used to ensure that only known-trusted code is executed, and
|
||||
that important resources are not unlocked unless the state of the system
|
||||
when they are needed is "only executed trusted code".
|
||||
|
||||
Note that some PCRs are left to be used by "applications".
|
||||
|
||||
Some terms:
|
||||
|
||||
- core RTM (CRTM) -- initial measurements performed upon power-on
|
||||
- static RTM (SRTM) -- subsequent-to-CRTM measurements of next boot
|
||||
stages
|
||||
- dynamic RTM (DRTM) -- measurements involved in rebooting
|
||||
|
||||
Resource unlocking can be done by creating objects tied to a set of PCRs
|
||||
such that they must each have specific values for the TPM to be willing
|
||||
to unlock (unseal) the object.
|
||||
|
||||
### The PCR Extension Eventlog
|
||||
|
||||
On the "PC platform" (which includes x64 servers) the BIOS keeps a log
|
||||
of all the PCR extensions it has performed. The OS should keep its own
|
||||
log of extensions it performs.
|
||||
|
||||
The eventlog documents how the PCRs evolved to their current state,
|
||||
whatever it might be. Since PCR extension values are typically digests,
|
||||
the eventlog is very dry, but it can still be used to evaluate whether
|
||||
the current PCR values represent a trusted state. For example, one
|
||||
might have a database of known-good and known-bad firmware/ROM digests,
|
||||
then one can check that only known-good ones appear in the eventlog and
|
||||
that reproducing the hash extensions described by the eventlot produces
|
||||
the same PCR values as one can read, and if so it follows that the
|
||||
system has only executed trusted code.
|
||||
|
||||
Note though that PCRs and RTM are not enough on their own to keep a
|
||||
system from executing untrusted code. A system can be configured to
|
||||
allow execution of arbitrary code at some point (e.g., download and
|
||||
execute) and to not extend PCRs accordingly, in which case the execution
|
||||
of untrusted code will not be reflected in any RTM.
|
||||
|
||||
## Object Naming
|
||||
|
||||
TPMs support a variety of types of objects. Objects generally have
|
||||
pointer-like "handles" that they are often used in the TPM APIs. But
|
||||
more importantly, objects have cryptographically-secure names that are
|
||||
used in many cases.
|
||||
|
||||
The cryptographically-secure name of an object is the hash of the
|
||||
object's "public area".
|
||||
|
||||
The public area of, say, an asymmetric key is a data structure that
|
||||
includes the public key (corresponding to the private key), and various
|
||||
attributes of the key (e.g., its algorithm, but also whether it is bound
|
||||
to the TPM where it resides, or to its key hierarchy), unseal policy,
|
||||
and access policy.
|
||||
|
||||
This concept is extremely important. Because object names are the
|
||||
outputs of cryptographically strong digest (hash) functions, they are
|
||||
resistant to collision attacks, first pre-image attacks, and second
|
||||
pre-image attacks -- as strong as the hash algorithm used anyways.
|
||||
Which means that object names cannot be forged easily, which means that
|
||||
they can be used in context where a peer needs certain guarantees, or
|
||||
to defeat active attacks.
|
||||
|
||||
### Immutability of Object Public Areas
|
||||
|
||||
Because the name of an object is a digest of its public area, the public
|
||||
area cannot be changed after creating it. One can delete and then
|
||||
recreate an object in order to "change" its public area, but this
|
||||
necessarily yields a new name (assuming no digest collisions).
|
||||
|
||||
## Key Hierarchies
|
||||
|
||||
TPMs have multiple key hierarchies, all rooted in a primary decrypt-only
|
||||
asymmetric private key derived from a seed, with arbitrarily complex
|
||||
trees of keys below the primary key:
|
||||
|
||||
```
|
||||
seed
|
||||
|
|
||||
|
|
||||
v
|
||||
primary key (asymmetric encryption)
|
||||
|
|
||||
|
|
||||
v
|
||||
secondary keys (of any kind)
|
||||
|
|
||||
|
|
||||
v
|
||||
...
|
||||
```
|
||||
|
||||
There are three built-in hierarchies:
|
||||
|
||||
- platform hierarchy
|
||||
- endorsement hierarchy
|
||||
- storage hierarchy
|
||||
|
||||
of which only the endorsement and storage hierarchies will be of
|
||||
interest to most readers.
|
||||
|
||||
The endorsement hierarchy is used to authenticate (when needed) that a
|
||||
TPM is a legitimate TPM. The primary endorsement key is known as the EK
|
||||
(endorsement key). Hardware TPMs come with a certificate for the EK
|
||||
issued by the TPM's manufacturer. This EK certificate ("EKcert") can be
|
||||
used to authenticate the TPM's legitimacy. The EK's public key
|
||||
("EKpub") can be used to uniquely identify a TPM, and possibly link to
|
||||
the platform's, and even the platform's user(s)' identities.
|
||||
|
||||
## Key Wrapping and Resource Management
|
||||
|
||||
The primary key is always a decrypt-only asymmetric private key, and its
|
||||
corresponding public key is therefore encrypt-only. This is largely
|
||||
because of key wrapping, where a symmetric key or asymmetric private key
|
||||
is encrypted to a TPM's EKpub so that it can be safely sent to that TPM
|
||||
so that that TPM can then decrypt and use that secret.
|
||||
|
||||
As well as wrapping secrets by encryption to public keys, TPMs also use
|
||||
wrapping in a symmetric key known only to the TPM for the purpose of
|
||||
saving keys off the TPM. This is used for resource management: since
|
||||
hardware TPMs have very limited resources, objects need to created or
|
||||
loaded, used, then saved off-TPM to make room for other objects to be
|
||||
loaded (unless they are not to be used again, then saving them is
|
||||
pointless). Only a TPM that saved an object can load it again, but some
|
||||
objects can be exported to other TPMs by encrypting them to their
|
||||
destination TPMs' EKpubs.
|
||||
|
||||
### Controlling Exportability of Keys
|
||||
|
||||
A key that is `fixedTPM` cannot leave the TPM in cleartext. It can be
|
||||
saved off the TPM it resides in, but only that TPM can load it again.
|
||||
|
||||
A key that is `fixedParent` cannot be re-parented, though if its parent
|
||||
is neither `fixedParent` nor `fixedTPM` then the parent and its
|
||||
descendants can be moved as a group to some other TPM.
|
||||
|
||||
## Persistence
|
||||
|
||||
Cryptographic keys are, by default, not stored on non-volatile memory.
|
||||
Hardware TPMs have very little non-volatile (NV) memory. They also have
|
||||
very limited volatile memory as well.
|
||||
|
||||
PCRs always exist, but they get reset on restart.
|
||||
|
||||
Keys can be moved to NV storage.
|
||||
|
||||
## Non-Volatile (NV) Indexes
|
||||
|
||||
TPMs also have a special kind of non-volatile object: NV indexes.
|
||||
|
||||
NV indexes come in multiple flavors for various uses:
|
||||
|
||||
- store public data (e.g., an NV index is used to store the EKcert)
|
||||
- emulate PCRs
|
||||
- monotonic counters
|
||||
- fields of write-once bits (for, e.g., revocation)
|
||||
- ...
|
||||
|
||||
NV indexes can be used standalone, and/or in connection with policies,
|
||||
to enrich application TPM semantics.
|
||||
|
||||
## Authentication and Authorization
|
||||
|
||||
TPMs have multiple ways to authenticate users/entities:
|
||||
|
||||
- plain passwords (legacy)
|
||||
- HMAC based on secret keys or passwords
|
||||
- public key signed attestations of identification by biometric
|
||||
authentication devices
|
||||
|
||||
TPMs have two ways to authorize access to various objects:
|
||||
|
||||
- plain passwords (legacy)
|
||||
- HMAC proof of possession of a secret key or password
|
||||
- arbitrarily complex policies that can make reference to:
|
||||
- PCR state
|
||||
- NV index state
|
||||
- time of day
|
||||
- authentication state
|
||||
- etc.
|
||||
|
||||
### Policies
|
||||
|
||||
A policy consists of a sequence of "commands" that each asserts
|
||||
something of interest.
|
||||
|
||||
Policies are particularly interesting because they are cryptographically
|
||||
named using hash extension with the sequence of "commands" that make up
|
||||
a policy. Therefore no matter how complex and large a policy is, it is
|
||||
always "compressed" to a hash digest.
|
||||
|
||||
It is the responsibility of the application that will attempt to use a
|
||||
policy-protected resource to know what the policy's definition is and
|
||||
restate it to the TPM when it goes to make use of that resource. Thus,
|
||||
and because policies are `O(1)` in storage size, they can be arbitrarily
|
||||
more complex than a TPM's limited resources would otherwise allow.
|
||||
|
||||
All the policy commands that are to be evaluated successfully to grant
|
||||
access have to be known to the entity that wants that access. Of
|
||||
course, that entity will have to satisfy -at access time- the conditions
|
||||
expressed by the relevant policy. The application has to know the
|
||||
policy because the TPM knows only a digest of it.
|
||||
|
||||
### Policy Construction
|
||||
|
||||
Construction of a policy consists of computing it by hash extending an
|
||||
initial all-zeroes value with the commands that make up the policy.
|
||||
|
||||
### Policy Evaluation
|
||||
|
||||
Evaluation of a policy consists of issuing those same commands to the
|
||||
TPM in a session, with those commands either evaluated immediately or
|
||||
deferred to the time of execution of the to-be-authorized command, but
|
||||
the TPM computes the same hash extension as it goes. Once all policy
|
||||
commands being evaluated have succeeded, the resulting hash extension
|
||||
value is compared to the policy that protects the resource(s) being used
|
||||
by the to-be-authorized command, and if it matches, then the command is
|
||||
allowed, otherwise it is not.
|
||||
|
||||
### Indirect Policies
|
||||
|
||||
Because an object's policy is part of its name, that policy cannot be
|
||||
changed after creation. An indirect policy command allows for the
|
||||
inclusion of a policy stored in an NV index.
|
||||
|
||||
### Compound Policies
|
||||
|
||||
Policies consist of a conjunction (logical-AND) of assertions that must
|
||||
be true at evaluation time.
|
||||
|
||||
However, there is a special policy command that allows for alternation
|
||||
(logical-OR). This policy command has a number of alternative policy
|
||||
digests. At evaluation time, one of the alternation digests must match
|
||||
the extension value for the policy commands up to (but excluding) the
|
||||
logical-OR policy command. At evaluation time the caller must have
|
||||
picked one of the alternatives and executed the commands that make it
|
||||
up.
|
||||
|
||||
(Recall that the application has to know the definition of the policy
|
||||
because the TPM knows only the policy's digest.)
|
||||
|
||||
### Rich Policy Semantics
|
||||
|
||||
With all these features, and with all the flexibility allowed by NV
|
||||
indexes, policies can be used to:
|
||||
|
||||
- require that N-of-M users authenticate
|
||||
- enforce bank vault-like time of day restrictions
|
||||
- require multi-factor authentication (password, biometric, smartcard)
|
||||
- check revocation
|
||||
- check system RTM state
|
||||
- distinguish user roles (admin roles get access to some resources,
|
||||
user roles get access to other resources)
|
||||
|
||||
## Sessions
|
||||
|
||||
A session is an object (meaning, among other things, that it can be
|
||||
loaded and unloaded as needed) that represents the current policy
|
||||
construction or evaluation hash extension digest (the `policyDigest`),
|
||||
and the objects that have been granted access.
|
||||
|
||||
## Restricted Cryptographic Keys
|
||||
|
||||
Cryptographic keys can either be unrestricted or restricted.
|
||||
|
||||
An unrestricted signing key can be used to sign arbitrary content.
|
||||
|
||||
A restricted signing key can be used to sign only content that begins
|
||||
with a magic byte sequence, and which the TPM allows only to be used in
|
||||
certain operations.
|
||||
|
||||
A restricted decryption key can only be used to decrypt ciphertexts
|
||||
whose plaintexts have a certain structure. In particular these are used
|
||||
for `TPM2_MakeCredential()`/`TPM2_ActivateCredential()` to allow the
|
||||
TPM-using application to get the plaintext if and only if (IFF) the
|
||||
plaintext cryptographically names an object that the application has
|
||||
access to. This is used to communicate secrets ("credentials") to TPMs.
|
||||
|
||||
## Attestation
|
||||
|
||||
Attestation is the process of demonstrating that a system's current
|
||||
state is "trusted", or the truthfulness of some set of assertions.
|
||||
|
||||
As you can see in our [tutorial on attestation](Attestation/README.md),
|
||||
many TPM concepts can be used to great effect:
|
||||
|
||||
- using PCRs to attest to system state
|
||||
- using policies and sealed-to-PCRs objects to attest to authentication
|
||||
events on the system
|
||||
- using restricted keys to authenticate a TPM and bind it to its host
|
||||
- delivering key material to authenticated systems via their TPMs
|
||||
- unlocking resources following successful attestation
|
||||
- authorization of devices onto a network
|
||||
- etc.
|
||||
|
|
@ -12,10 +12,10 @@ Why GitHub?
|
|||
|
||||
## Current list of tutorials from [TPM.dev] members
|
||||
|
||||
1. Attestation, MakeCredential, ActivateCredential
|
||||
1. Boot with TPM: Secure vs Measured vs Trusted
|
||||
1. Random Number Generator
|
||||
1. TPM Introduction (Work in progress - PR #8)
|
||||
1. [Boot with TPM: Secure vs Measured vs Trusted](Boot-with-TPM/tpmboot.md)
|
||||
1. [Random Number Generator](Random_Number_Generator/article.md)
|
||||
1. [Attestation, MakeCredential, ActivateCredential](Attestation/README.md)
|
||||
1. Introduction to TPM Concepts (Work in progress - PR #8)
|
||||
|
||||
## List of tutorials that will be transfered to GitHub from [TPM.dev]
|
||||
|
||||
|
|
Loading…
Reference in a new issue