mirror of
https://github.com/tpm2dev/tpm.dev.tutorials.git
synced 2024-11-14 10:42:11 +00:00
d0cbddfea4
Add sample encrypt-to-TPM scripts and parameter encryption introduction
1017 lines
39 KiB
Markdown
1017 lines
39 KiB
Markdown
# 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 -- much
|
|
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.
|
|
|
|
> The standards development organization that publishes TPM specifications
|
|
> is the [Trusted Computing Group (TCG)](https://trustedcomputinggroup.org).
|
|
|
|
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.
|
|
|
|
Other parts of this [tutorial](README.md) may cover specific concepts in
|
|
much more detail.
|
|
|
|
# Goals
|
|
|
|
The goal of this introductory material is to help readers new to TPMs to
|
|
understand them well enough to approach the subjects of:
|
|
|
|
- [attestation](/Attestation/README.md)
|
|
- [secure boot](/Boot-with-TPM/README.md)
|
|
|
|
and to think about the sorts of things that one can do with TPMs in
|
|
general, which include:
|
|
|
|
- device on-boarding
|
|
- ascertaining the state of a device (e.g., has it executed only
|
|
trusted code)
|
|
- unlocking of devices using TPM-based authentication and authorization
|
|
policies (e.g., unlocking a laptop on boot multiple factors such as
|
|
biometrics, smartcards, passwords, time of day, even interaction with
|
|
remote services)
|
|
- using a TPM as a source of entropy for a running OS
|
|
|
|
> NOTE: At this time this introduction is very much a layman's
|
|
> introduction, and only an introduction. Readers seeking to do
|
|
> software development using TPMs will want to make use of [TCG
|
|
> specifications and other resources](#Other-Resources).
|
|
|
|
## Use Cases
|
|
|
|
Here are _some_ use cases that TPMs can be applied to
|
|
|
|
- off-line root of trust measurement (RTM) to check that a device is
|
|
healthy
|
|
|
|
("off-line" meaning "no network needed")
|
|
|
|
- encrypted storage
|
|
|
|
- online RTM to check that a device is healthy and authorize it to have
|
|
access to a network
|
|
|
|
("online" meaning "demonstrate health via networked interaction with
|
|
other devices")
|
|
|
|
- encrypted storage
|
|
|
|
- hardware security module (HSM)
|
|
|
|
- certification authority (CA)
|
|
- TPMs as smartcards
|
|
|
|
- authentication and authorization of console and/or remote user logins
|
|
|
|
- e.g., require biometrics, smartcard, admin credentials, multiple
|
|
users' authentication, time-of-day restrictions, etc.
|
|
|
|
- entropy source (random number generator)
|
|
|
|
- cryptographic co-processor
|
|
|
|
## Glossary
|
|
|
|
> For a glossary, see section 4 of [TCG TPM 2.0 Library part 1:
|
|
> Architecture](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf).
|
|
|
|
# Core Concepts
|
|
|
|
Some core concepts in the world of TPMs:
|
|
|
|
> NOTE: We will not cover all of these here.
|
|
|
|
- cryptography
|
|
- hash extension
|
|
- cryptographic object naming
|
|
- platform configuration registers (PCRs)
|
|
- immutability of object public areas
|
|
- key hierarchies
|
|
- key wrapping
|
|
- restricted cryptographic keys
|
|
- limited resources
|
|
- sessions and authorization
|
|
- other object types, mainly non-volatile (NV) indexes
|
|
- attestation
|
|
|
|
We'll assume reader familiarity with the basics of cryptography -- the
|
|
basics of cryptographic primitives as interfaces, but not their
|
|
internals. E.g., hash functions, symmetric encryption, asymmetric
|
|
encryption, and digital signatures.
|
|
|
|
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.
|
|
|
|
## 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.
|
|
|
|
Each extension value can be arbitrarily large, and the TPM will use the
|
|
traditional `Init`/`Update`/`Final` approach to making digest
|
|
computation online.
|
|
|
|
Note that `H(e0 || e1 || e2) != Extend(Extend(Extend(0, e0), e1), e2)`.
|
|
Hash extension makes "message" boundaries strong.
|
|
|
|
Hash extension is most of what a PCR is, but hash extension is used in
|
|
other TPM concepts besides PCRs, such as policy naming.
|
|
|
|
## Coping with Severe Resource Limits Using Digests and Hash Extension
|
|
|
|
Hardware TPMs are extremely limited in memory and non-volatile memory
|
|
capacity. As a result they cannot hold large entities.
|
|
|
|
A common theme in TPMs is the use of digests, and hash extension digests
|
|
in particular, as a stand-in for large entities that might not fit at
|
|
once on the TPM.
|
|
|
|
TPMs use digests as stand-ins for large entities of various types:
|
|
|
|
- eventlogs
|
|
- policies
|
|
- auditing
|
|
|
|
We'll discuss at least two of those: event logs, and policies.
|
|
|
|
## Platform Configuration Registers (PCRs)
|
|
|
|
A PCR, then, is just a hash extension output. The only operations on
|
|
PCRs are: read, extend, and reset. All richness of semantics of PCRs
|
|
come from how they are used:
|
|
|
|
- what the governing TCG platform specification says about them
|
|
- what they are extended with and by what code (in what locality)
|
|
- what purposes they are read for
|
|
- attestation
|
|
- authorization
|
|
|
|
Note that a PCR value by itself is devoid of meaning. To add meaning
|
|
one must have access to the list of discrete values extended into the
|
|
PCR, as well as the order in which they were extended into the PCR. And
|
|
one must know the meaning of each such value.
|
|
|
|
### Eventlogs
|
|
|
|
Any TPM-using platform has to provide a way to keep a log of PCR hash
|
|
extension values. Such a log is known as the "eventlog".
|
|
|
|
The TPM itself cannot hold this log -- the TPM is too
|
|
resource-constrained.
|
|
|
|
## 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. Each platform has a
|
|
specification for which PCRs are used or reserved for what purposes. 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 "has only executed trusted code to get here".
|
|
|
|
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 of PCRs reserved to the OS. Each
|
|
application has to keep a log of the extensions of the PCRs allocated to
|
|
it. Again, the TPM itself cannot do this.
|
|
|
|
The eventlog documents how each PCR 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 eventlog produces
|
|
the same PCR values as one can read, and if so it follows that the
|
|
system has only executed trusted code to arrive at the state identified
|
|
by the PCRs.
|
|
|
|
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.
|
|
|
|
## Tickets
|
|
|
|
> Tickets are yet another device for coping with TPMs having limited
|
|
> resources. Interaction with TPMs is via request/response
|
|
> commands, and tickets are largely about making TPMs stateless between
|
|
> related commands.
|
|
|
|
To avoid having to re-perform various operations -or remember having
|
|
performed them- between command invocations, a TPM can produce a
|
|
"ticket" that consists of an HMAC over a TPM-generated assertion, keyed
|
|
by a key known only to the TPM, and return it to the caller who can then
|
|
present it in a subsequent command related to the first.
|
|
|
|
For example, when signing data the TPM will first digest the data to
|
|
sign over several commands and generate a ticket saying it did produce
|
|
that digest, then later it can sign the digest after validating the
|
|
ticket that it produced.
|
|
|
|
Another example is a policy ticket, which allows one to avoid having to
|
|
re-authenticate (e.g., with smartcard, biometrics, passwords) on every
|
|
command for small window of time.
|
|
|
|
> When would a user be authenticated? Well, typically at boot time, or
|
|
> maybe at wake from sleep/hibernate time. A laptop could be configured
|
|
> to require a user to authenticate with biometrics and possibly a
|
|
> password or a smartcard. Note that such policies are not required by
|
|
> the specifications, but rather something that one can choose to use.
|
|
|
|
> There are five types of tickets. We won't cover them here. Readers
|
|
> who end up needing to know about them can look at section 11.4.6.3 of
|
|
> `TCG TPM 2.0 Library, part 1: Architecture`.
|
|
|
|
## Cryptographic 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.
|
|
|
|
### Cryptographic Object Naming as a Binding
|
|
|
|
> This section comes too soon, since it relates to attestation and
|
|
> restricted keys. Still, it may be useful to illustrate cryptographic
|
|
> object naming with one particularly important use of it.
|
|
|
|
A pair of functions,
|
|
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) and
|
|
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md),
|
|
illustrate the use of cryptographic object naming as a binding or a sort
|
|
of authorization function.
|
|
|
|
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) can be
|
|
used to encrypt a datum (a "credential") to a target TPM such that the
|
|
target will _only be willing to decrypt it_ if *and only if* the
|
|
application calling `TPM2_ActivateCredential()` to decrypt that
|
|
credential has access to some key named by the sender, and that name is
|
|
a cryptographic name that the sender can and must compute for itself.
|
|
|
|
The semantics of these two functions can be used to defeat a
|
|
cut-and-paste attack in attestation protocols.
|
|
|
|
## Key Hierarchies
|
|
|
|
TPMs have multiple key hierarchies, each with zero, one or more primary
|
|
keys, each with zero, one, or more children keys:
|
|
|
|
```
|
|
seed
|
|
/|\
|
|
/ | \
|
|
v v v
|
|
primary key (asymmetric encryption)
|
|
/|\
|
|
/ | \
|
|
v v v
|
|
secondary keys (of any kind)
|
|
/|\
|
|
/ | \
|
|
v v v
|
|
...
|
|
```
|
|
|
|
Keys that have no parent are primary keys.
|
|
|
|
There are four built-in hierarchies:
|
|
|
|
- platform hierarchy
|
|
- endorsement hierarchy
|
|
- storage hierarchy
|
|
- null 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.
|
|
|
|
The [`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) command creates
|
|
primary key objects deterministically from the hierarchy's seed and the
|
|
"template" used to create the key (which includes a "unique" area that
|
|
provides "entropy" to the key derivation function).
|
|
|
|
The [`TPM2_Create()`](TPM2_Create.md) command creates a ordinary
|
|
objects.
|
|
|
|
The [`TPM2_CreateLoaded()`](TPM2_CreateLoaded.md) command can also
|
|
create primary key objects deterministically from the hierarchy's seed
|
|
and the "template" used to create the key (which includes a "unique"
|
|
area that provides "entropy" to the key derivation function).
|
|
|
|
## Key Wrapping and Resource Management
|
|
|
|
Key wrapping is encrypting a secret or private key (key encryotion key,
|
|
or KEK) such that a specific entity may recover the plain key.
|
|
|
|
A decrypt-only asymmetric private key can be used to encrypt secrets to
|
|
the TPM on which that private key resides.
|
|
|
|
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.
|
|
|
|
With a resource manager and access broker, a TPM can appear to have
|
|
infinite resources.
|
|
|
|
### 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 moved from one part of a key
|
|
hierarchy to another -- it 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.
|
|
|
|
> Key hierarchies are an important TPM topic that we're not really
|
|
> addresing in this intro.
|
|
|
|
## Persistence
|
|
|
|
In a TPM, key objects are, by default, transient, meaning the TPM will
|
|
forget them if restarted. Still, they can be saved (encrypted in a
|
|
secret key only the TPM knows) and later reloaded.
|
|
|
|
Transient objects can be made persistent, but because hardware TPMs have
|
|
very little non-volatile memory, few keys should be made persistent.
|
|
Instead you can save them (wrapped to a TPM-only KEK) and reload them as
|
|
needed.
|
|
|
|
Because primary keys (for any hierarchy other than the null hierarchy)
|
|
are derived deterministically from a built-in and protected seed, and
|
|
from a template, they are persistent even when not moved to NV storage
|
|
and even when not saved as long as the hierarchy's seed is not reset.
|
|
|
|
(Resetting the endorsement hierarchy seed is a very dramatic action, as
|
|
it changes the EK/EKpub and renders any provisioned EKcert useless.
|
|
Resetting the storage hierarchy seed is much less dramatic. The NULL
|
|
hierarchy is reset every time the TPM resets.)
|
|
|
|
PCRs always persist, but they get reset on restart.
|
|
|
|
NV indexes always persist. (But in disorderly resets/shutdowns a
|
|
hybrid NV index may not be sync'ed to NV.)
|
|
|
|
## Non-Volatile (NV) Indexes
|
|
|
|
TPMs also have a special kind of non-volatile object: NV indexes.
|
|
|
|
> NOTE: NV indexes are not "objects" in the sense that the TCG's
|
|
> specifications mean. TCG's definition of "object" is
|
|
>
|
|
> > key or data that has a public portion and, optionally, a
|
|
> > sensitive portion; and which is a member of a hierarchy
|
|
|
|
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 (bitfields) (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. The
|
|
TPM will evaluate the policy and, at the end, check that its digest
|
|
matches that of the policy-protected resource. Thus, and because policy
|
|
digests are small and fixed-sized, 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. And that entity 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.
|
|
|
|
This can be done entirely in software, but the TPM supports a notion of
|
|
"trial sessions" where the application can issue policy commands to
|
|
build up a policy digest without the application having to know how to
|
|
do that in software. Trial sessions have every policy command succeed,
|
|
but they authorize nothing -- the point of a trial session is only to
|
|
compute and extract a `policyDigest` at the end of the policy.
|
|
|
|
### Policy Evaluation
|
|
|
|
Evaluation of a policy consists of issuing those same commands to the
|
|
TPM in a [non-trial] session, with those commands either evaluated
|
|
either 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 issued have been evaluated and
|
|
have succeeded, the resulting hash extension value is compared to the
|
|
policy that protects the resource used by the to-be-authorized command,
|
|
and if and only if the digest matches, then the command is allowed,
|
|
otherwise it is not.
|
|
|
|
For example, one might construct a policy like so:
|
|
|
|
```bash
|
|
$ tpm2 flushcontext -t
|
|
$ tpm2 flushcontext -s
|
|
$ tpm2 startauthsession --session session.ctx --policy-session
|
|
$ tpm2 policysecret --session session.ctx --object-context endorsement
|
|
$ tpm2 policycommandcode -S session.ctx -L activate.ctx TPM2_CC_ActivateCredential
|
|
```
|
|
|
|
which saves the digest of the policy in a file named `activate.ctx`.
|
|
|
|
### 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 a policy
|
|
to change over time without having to recreate the authorized object.
|
|
|
|
### 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
|
|
- require multi-factor authentication (password, biometric, smartcard)
|
|
- enforce bank vault-like time of day restrictions
|
|
- check revocation (using NV index bit-field objects)
|
|
- check system RTM state (PCRs)
|
|
- distinguish user roles
|
|
|
|
## Sessions
|
|
|
|
A session is an object (meaning, among other things, that it can be
|
|
loaded and unloaded as needed) that represents the current state used
|
|
for authorization of actions or for encryption of traffic between the
|
|
application and the TPM.
|
|
|
|
There are two types of sessions then: those used for authorization, and
|
|
those used for encryption of application `<->` TPM communication.
|
|
|
|
Authorization sessions contain state such as a `policyDigest`
|
|
representing authorization policy that has been satisfied, and various
|
|
other state. TPM commands may check that an authorization session's
|
|
state satisfies the requirements for use of the argument objects passed
|
|
to the commands.
|
|
|
|
> NOTE: Every command input parameter that is a handle that requires
|
|
> authorization must have its own session associated with it.
|
|
|
|
### Authorization Session State
|
|
|
|
Authorization sessions have a number of state attributes. Some of these
|
|
are set at the time of creation of the session. Some of these can be
|
|
set directly with `TPM2_Policy*()` commands. Others evolve in other
|
|
ways. These state attributes are:
|
|
|
|
- `policyDigest`
|
|
|
|
A hash extension digest of all the policy commands sent by the
|
|
application in this session thus far. Every successful
|
|
`TPM2_Policy*()` command extends this.
|
|
|
|
Objects may have a policy digest set on them to refer to the policy
|
|
that an application must meet in order to use them. The application
|
|
has to issue the `TPM2_Policy*()` commands, in order, that produce
|
|
that digest, the commands must all succeed, and the `policyDigest`
|
|
must equal that of the object.
|
|
|
|
- `isTrialPolicy`
|
|
|
|
When this is set then the session will not authorize anything at all
|
|
and all policy commands will be assumed to be met and will not be
|
|
evaluated. This is useful for constructing and extracting from the
|
|
TPM the `policyDigest` of a policy to set on some future new
|
|
object(s).
|
|
|
|
Sessions that have this set are known as "trial sessions".
|
|
|
|
Applications can construct `policyDigest` values entirely in
|
|
software, but using the TPM with a trial session saves one the
|
|
bother.
|
|
|
|
- `commandCode`
|
|
|
|
Identifies a command that will be authorized by the policy referred
|
|
to by `policyDigest`.
|
|
|
|
If a policy requires this, then it authorizes the one command
|
|
identified by the command code.
|
|
|
|
- `cpHash`
|
|
|
|
A hash of some command's parameters. If a policy requires this, then
|
|
it authorizes the one command whose parameters match this hash.
|
|
|
|
- `commandLocality`
|
|
|
|
A locality that the application must be in.
|
|
|
|
- policy reuse / expiration state:
|
|
|
|
- `startTime`
|
|
|
|
The start time of the session.
|
|
|
|
- `timeout`
|
|
|
|
The lifetime of the session.
|
|
|
|
- `nonceTPM`
|
|
|
|
- Authentication requirements:
|
|
|
|
- `isAuthValueNeeded`
|
|
|
|
- `isPasswordNeeded`
|
|
|
|
- `isPPRequired`
|
|
|
|
PP == physical presence.
|
|
|
|
- `checkNvWritten`
|
|
|
|
- `nvWrittenState`
|
|
|
|
- `nameHash`
|
|
|
|
- `pcrUpdateCounter`
|
|
|
|
### Encryption Sessions
|
|
|
|
Sessions can also be used for encrypting TPM command arguments and
|
|
results. This can be useful when one does not trust the path to the
|
|
TPM, such as when the TPM is remote.
|
|
|
|
Only the first input parameter of a TPM command will be encrypted, and
|
|
only the first output parameter of a TPM command will be encrypted, and
|
|
that only if when that first parameter is of type `TPM2B`. Those first
|
|
`TPM2B` type command input and/or output parameters will be encrypted
|
|
with a symmetrict AES key derived from a secret key established via RSA
|
|
key transport or ECDH key agreement.
|
|
|
|
> Encryption sessions are useful for when the path to a TPM is not
|
|
> trused, such as when a TPM is a remote TPM, or when otherwise the path
|
|
> to the TPM is not trusted.
|
|
|
|
### Key Exchange for Encryption Sessions
|
|
|
|
> Encryption sessions are useful for when the path to a TPM is not
|
|
> trused, such as when a TPM is a remote TPM, or when otherwise the path
|
|
> to the TPM is not trusted. This section talks about key exchange for
|
|
> such situations.
|
|
|
|
The symmetric keys used for TPM command encryption are exchanged at
|
|
session creation time.
|
|
|
|
Keys can be provided by one of either RSA key transport or ECC key
|
|
agreement, and/or the secret `authValue` of a loaded entity.
|
|
|
|
Sessions are created with
|
|
[`TPM2_StartAuthSession()`](/TPM-Commands/TPM2_StartAuthSession.md),
|
|
which has serveral _optional_ input and output parameters related to
|
|
session encryption. In particular it provides ways to create a session
|
|
key for command parameter encryption:
|
|
|
|
- RSA key transport
|
|
|
|
The caller can encrypt a secret to a public key for which the TPM has
|
|
loaded the private key as identified by the `tpmKey` input parameter
|
|
of [`TPM2_StartAuthSession()`].
|
|
|
|
- ECDH key agreement
|
|
|
|
The caller can generate an ephemeral ECDH key and use it with the
|
|
public key of the ECDH key object identified by the `tpmKey` input
|
|
parameter of [`TPM2_StartAuthSession()`]. The TPM will use the
|
|
private key of the object identified by the `tpmKey` input parameter
|
|
and the ephemeral public key sent by the caller in the
|
|
`encryptedSalt` input parameter.
|
|
|
|
- use the `authHash` of the entity identified by the `bind` input
|
|
parameter
|
|
|
|
The caller computes the same session key as the TPM.
|
|
|
|
To authenticate the TPM and prevent active attacks, the caller of
|
|
`TPM2_StartAuthSession()` should use an `EK` as the `tpmKey` and its
|
|
`EKpub` to locally compute the session key. Alternatively the caller
|
|
can use a non-`EK` key object created over an earlier encrypted session
|
|
that authenticated the target TPM.
|
|
|
|
> A non-null `bind` parameter can be used to create a "bound" session
|
|
> that can be used to satisfy HMAC-based authorization for specific
|
|
> objects. We will not cover this in detail here.
|
|
|
|
### HMAC Sessions
|
|
|
|
An HMAC session proves the caller knows the `authValue` secret of some
|
|
entity. This functions a lot like a password, with the `authValue`
|
|
used to compute HMACs that prove possession, but with the `authValue`
|
|
generally being large and randomly generated, thus much stronger than a
|
|
password.
|
|
|
|
Typically the `authValue` of some entity should be sent encrypted to the
|
|
TPM when creating an entity, with [the encrypted session being keyed via
|
|
RSA key transport or ECDH](#Key-Exchange-for-Encryption-Sessions). This
|
|
way an `authValue`, though a simple, password-like binary string, can be
|
|
strong and secure due to being large, randomly chosen and sent over
|
|
an encrypted session.
|
|
|
|
### Password Sessions
|
|
|
|
> WIP [Say something about passwords and password sessions, besides
|
|
> "don't use them" and "support remains mostly for TPM 1.2 reasons".]
|
|
|
|
Alternatively a session can be for encryption of command inputs/outputs,
|
|
which is useful when the path to the TPM is not secure.
|
|
|
|
### Authorization Roles
|
|
|
|
How a TPM authorizes some particular command and its use of its input
|
|
handles varies by command and according to two attributes of the objects
|
|
identified by the command's input handles.
|
|
|
|
A "role" is really a set of rules that will be applied to authorization
|
|
for a given object/command.
|
|
|
|
There are three types of authorization roles that can apply in any case:
|
|
|
|
- `USER` role
|
|
|
|
This means that if the object in question has an `authValue` set, and
|
|
it has the `userWithAuth` attribute set, then the application can get
|
|
access by demonstrating knowledge of the corresponding password. And
|
|
anyways, if the object has a policy then the user can get access by
|
|
satisfying the policy even w/o knowing the password.
|
|
|
|
This is the most commonly applied authorization role.
|
|
|
|
- `ADMIN` role
|
|
|
|
This means that if the object in question has an `authValue` set, and
|
|
it has the `adminWithPolicy` attribute _not_ set, then the
|
|
application can get access by demonstrating knowledge of the
|
|
corresponding password or by satisfying its `authPolicy` if one is
|
|
set. But if the object has a policy and the `adminWithPolicy`
|
|
attribute set then the user _must_ satisfy the policy to get access.
|
|
|
|
In the `adminWithPolicy` attribute set case, the caller _must_ also
|
|
have called `TPM2_PolicyCommandCode()` with the code of the command
|
|
that the caller wishes to execute.
|
|
|
|
Only three commands apply `ADMIN` role to any of the objects
|
|
identified by their input handle parameters:
|
|
|
|
- `TPM2_Certify()` requires `ADMIN` role for its `objectHandle`
|
|
input parameter.
|
|
|
|
Whereas the `signHandle` input parameter requires `USER` role.
|
|
|
|
- `TPM2_ActivateCredential()` requires `ADMIN` role for its
|
|
`activateHandle` input parameter.
|
|
|
|
Whereas the `keyHandle` input parameter requires `USER` role.
|
|
|
|
- `TPM2_ObjectChangeAuth()` requires `ADMIN` role for its
|
|
`objectHandle` input parameter.
|
|
|
|
- `DUP` role
|
|
|
|
This is just for the
|
|
[`TPM2_Duplicate()`](/TPM-Commands/TPM2_Duplicate.md) command. The
|
|
caller of `TPM2_Duplicate()` must satisfy the key object's
|
|
`authPolicy`, and must have called `TPM2_PolicyCommandCode()` with
|
|
the code of the `TPM2_Duplicate()` command (`TPM_CC_Duplicate`).
|
|
|
|
> `DUP` is very similar to `ADMIN` when the `adminWithPolicy`
|
|
> attribute is set.
|
|
|
|
For example, the
|
|
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md)
|
|
command requires `USER` role for the `keyHandle` input and `ADMIN` role
|
|
for the `activateHandle`. If the `keyHandle` is the `EK`, then since
|
|
the `EK` has a default `authValue`, use will be allowed. If the
|
|
`activateHandle` is for an object with an `authPolicy` and the
|
|
`adminWithPolicy` attribute set, then the caller must execute that
|
|
policy's commands (yielding, on success, a session whose `policyDigest`
|
|
matches that object's `authPolicy`) and must have called
|
|
`TPM2_PolicyCommandCode(TPM_CC_ActivateCredential)` on that same
|
|
session.
|
|
|
|
> NOTE: Every handle argument to a TPM command can require its own
|
|
> authorization, therefore there can be zero, one, or two authorization
|
|
> sessions as inputs to any TPM command (some TPM commands have no input
|
|
> handle parameters, some have one, and some have two).
|
|
|
|
## Restricted Cryptographic Keys
|
|
|
|
Cryptographic keys can either be unrestricted or restricted.
|
|
|
|
An unrestricted signing key can be used to sign arbitrary content.
|
|
|
|
An unrestricted decryption key can be used to decrypt arbitrary
|
|
ciphertexts encrypted to that key's public key.
|
|
|
|
> NOTE WELL: The endorsement key (EK) is a restricted key.
|
|
|
|
### Restricted Signing Keys
|
|
|
|
A restricted signing key can be used to sign only TPM-generated content
|
|
as part of specific TPM restricted signing commands. Such content
|
|
always begins with a magic byte sequence. Conversely, the TPM refuses
|
|
to sign externally generated content that starts with that magic byte
|
|
sequence. See the [`TPM2_Certify()`](/TPM-Commands/TPM2_Certify.md),
|
|
[`TPM2_Quote()`](/TPM-Commands/TPM2_Quote.md), `TPM2_CertifyCreation()`,
|
|
`TPM2_GetSessionAuditDigest()`, and `TPM2_GetCommandAuditDigest()` TPM
|
|
commands.
|
|
|
|
There is also a notion of signing keys that can only be used to sign
|
|
PKIX certificates using `TPM2_CertifyX509()`.
|
|
|
|
### Restricted Decryption Keys
|
|
|
|
> NOTE WELL: The endorsement key (EK) is a restricted key.
|
|
|
|
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()`](/TPM-Commands/TPM2_MakeCredential.md) /
|
|
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md)
|
|
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 remotely communicate secrets
|
|
("credentials") to TPMs.
|
|
|
|
Another operation that a restricted decryption key can perform is
|
|
[`TPM2_Import()`](/TPM-Commands/TPM2_Import.md), which decrypts a key
|
|
wrapped to the given decrypt-only key and outputs a file that can be
|
|
loaded with [`TPM2_Load()`](/TPM-Commands/TPM2_Load.md). The wrapped
|
|
key payload given to [`TPM2_Import()`](/TPM-Commands/TPM2_Import.md) too
|
|
has a particular structure and is produced by a remote peer using
|
|
[`TPM2_Duplicate()`](/TPM-Commands/TPM2_Duplicate.md).
|
|
|
|
To recap, a restricted decryption key can only be used to:
|
|
|
|
- "activate credentials" (made with
|
|
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md))
|
|
|
|
- receive wrapped keys sent by a peer (made with
|
|
[`TPM2_Duplicate()`](/TPM-Commands/TPM2_Duplicate.md))
|
|
|
|
## Attestation
|
|
|
|
Attestation is the process of demonstrating that a system's current
|
|
state is "trusted", or the truthfulness of some set of assertions.
|
|
|
|
Often a system gets something in exchange for attesting to its current
|
|
state. E.g., keys for unlocking filesystems, or device credentials.
|
|
|
|
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 and cryptographic object naming 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.
|
|
|
|
## Use Cases (reprise)
|
|
|
|
### Off-line RTM / TOTP
|
|
|
|
Use a TPM to generate a time-based one-time (TOTP) password based on
|
|
current time and a seed derived from selected PCR values, then display
|
|
this TOTP. A user can then check that the TOTP presented by the device
|
|
matches the TOTP on a separate authenticator.
|
|
|
|
Links:
|
|
|
|
- https://github.com/tpm2-software/tpm2-totp
|
|
- https://github.com/mjg59/tpmtotp
|
|
- https://trmm.net/Tpmtotp/
|
|
|
|
### Online RTM (aka Attestation)
|
|
|
|
See [our tutorial on attestation](/Attestation/README.md).
|
|
|
|
### Encrypted Storage
|
|
|
|
- [Safeboot](https://safeboot.dev/)
|
|
- [Hacking with a TPM](https://c3media.vsos.ethz.ch/congress/2019/slides-pdf/36c3-10564-hacking_with_a_tpm.pdf)
|
|
|
|
### HSM / CA / Smartcard
|
|
|
|
Use `TPM2_Sign()` or `TPM2_CertifyX509()` to sign certificates with a
|
|
TPM-resident key that is fixedTPM and fixedParent.
|
|
|
|
Use `TPM2_GetCommandAuditDigest()` to implement an audit trail for the
|
|
CA.
|
|
|
|
### Authentication and Authorization of Console and/or Remote User Logins
|
|
|
|
Use [TPM policies](#Authentication-and-Authorization).
|
|
|
|
### Entropy Source
|
|
|
|
See our tutorial on [TPM-based RNGs](/Random_Number_Generator/README.md).
|
|
|
|
### Cryptographic Co-Processor
|
|
|
|
Use cryptographic primitives provided by the TPM using unrestricted key
|
|
objects:
|
|
|
|
- use TPM cryptographic primitives commands directly -- see
|
|
[TCG TPM 2.0 Library part 3: Commands, sections 14 and 15](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
|
|
|
- use PKCS#11 with a TPM-backed token provider:
|
|
- https://github.com/tpm2-software/tpm2-pkcs11
|
|
- https://docs.oracle.com/cd/E36784_01/html/E37121/gmsch.html
|
|
- https://incenp.org/notes/2020/tpm-based-ssh-key.html
|
|
- http://trousers.sourceforge.net/pkcs11.html
|
|
- https://www.lorier.net/docs/tpm
|
|
|
|
- use OpenSSL with a PKCS#11 `ENGINE` (see above)
|
|
|
|
- use OpenSSL with a TPM `ENGINE`
|
|
- https://github.com/tpm2-software/tpm2-tss-engine
|
|
|
|
# Other Resources
|
|
|
|
- [A Practical Guide to TPM 2.0](https://trustedcomputinggroup.org/resource/a-practical-guide-to-tpm-2-0/)
|
|
is an excellent book that informed much of this tutorial.
|
|
|
|
- Of course, there is the [TPM.dev community](https://developers.tpm.dev/),
|
|
which has many resources, posts, a chat room, and knowledgeable
|
|
participants.
|
|
|
|
- Nokia has a [TPM course](https://github.com/nokia/TPMCourse/tree/master/docs).
|
|
|
|
- [Hacking with a TPM](https://c3media.vsos.ethz.ch/congress/2019/slides-pdf/36c3-10564-hacking_with_a_tpm.pdf).
|
|
|
|
- [Microsoft has solid TPM resources](https://docs.microsoft.com/en-us/windows/security/information-protection/tpm/trusted-platform-module-top-node).
|
|
|
|
- The TCG has a number of members-only tutorials, but it seems that it
|
|
is possible to be invited to be a non-fee paying member.
|
|
|
|
- Core TCG TPM specs:
|
|
|
|
- [TCG TPM 2.0 Library part 1: Architecture](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf).
|
|
- [TCG TPM 2.0 Library part 2: Structures](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part2_Structures_pub.pdf).
|
|
- [TCG TPM 2.0 Library part 3: Commands](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf).
|
|
- [TCG TPM 2.0 Library part 3: Commands Code](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_code_pub.pdf).
|