mirror of
https://github.com/tpm2dev/tpm.dev.tutorials.git
synced 2024-11-05 15:12:10 +00:00
Merge pull request #13 from nicowilliams/master
Expand on restricted keys; describe more TPM commands
This commit is contained in:
commit
463d39f272
15 changed files with 1244 additions and 178 deletions
|
@ -64,6 +64,26 @@ Attestation is done by a client computer with a TPM interacting with an
|
|||
attestation service over a network. This requires a network protocol
|
||||
for attestation.
|
||||
|
||||
## Intended Audience
|
||||
|
||||
Readers should have read the [TPM introduction tutorial](/Intro/README.md).
|
||||
|
||||
## Enrollment
|
||||
|
||||
[Enrollment](/Enrollment/README.md) is the process and protocol for
|
||||
onboarding devices into a network / organization. For example, adding
|
||||
an IoT to a home network, a server to a data center, a smartphone or
|
||||
tablet or laptop to a persons set of personal devices, etc.
|
||||
|
||||
Generally attestation protocols apply to enrolled devices. Enrollment
|
||||
protocols _may_ be very similar to attestation protocols, or even
|
||||
actually be sub-protocols of attestation protocols. Enrollment
|
||||
protocols can also be separate from attestation altogether.
|
||||
|
||||
This tutorial mostly covers only attestation of/by enrolled devices.
|
||||
For more about enrollment see the tutorial specifically for
|
||||
[enrollment](/Enrollment/README.md).
|
||||
|
||||
## Notation
|
||||
|
||||
- `Encrypt_<name>` == encryption with the named private or secret key
|
||||
|
@ -78,6 +98,70 @@ for attestation.
|
|||
- `{"key":<value>,...}` == JSON text
|
||||
- `TPM2_MakeCredential(<args>)` == outputs of calling `TPM2_MakeCredential()` with `args` arguments
|
||||
- `TPM2_Certify(<args>)` == outputs of calling `TPM2_Certify()` with `args` arguments
|
||||
- `XK` == `<X>` key, for some `<X>` purpose (the TPM-resident object and its private key)
|
||||
- `EK` == endorsement key (the TPM-resident object and its private key)
|
||||
- `AK` == attestation key (the TPM-resident object and its private key)
|
||||
- `TK` == transport key (the TPM-resident object and its private key)
|
||||
- `XKpub` == `<X>`'s public key, for some `<X>` purpose
|
||||
- `EKpub` == endorsement public key
|
||||
- `AKpub` == attestation public key
|
||||
- `TKpub` == transport public key
|
||||
- `XKname` == `<X>`'s cryptographic name, for some `<X>` purpose
|
||||
- `EKname` == endorsement key's cryptographic name
|
||||
- `AKname` == attestation key's cryptographic name
|
||||
|
||||
## Threat Models
|
||||
|
||||
Some threats that an attestation protocol and implementation may want to
|
||||
address:
|
||||
|
||||
- attestation client impersonation
|
||||
- attestation server impersonation
|
||||
- unauthorized firmware and/or OS updates
|
||||
- theft or compromise of of attestation servers
|
||||
- theft of client devices or their local storage (e.g., disks, JBODs)
|
||||
- theft of client devices by adversaries capable of decapping and
|
||||
reading the client's TPM's NVRAM
|
||||
|
||||
The attestation protocols we discuss will provide at least partial
|
||||
protection against impersonation of attestation clients: once a TPM's
|
||||
EKpub/EKcert are bound to the device in the attestation server's
|
||||
database, that TPM can only be used for that device and no others.
|
||||
|
||||
All the attestation protocols we discuss will provide protection against
|
||||
unauthorized firmware and/or OS updates via attestation of root of trust
|
||||
measurements (RTM).
|
||||
|
||||
The attestation protocols we discuss will provide protection against
|
||||
impersonation of attestation servers without necessarily authenticating
|
||||
the servers to the clients in traditional ways (e.g., using TLS server
|
||||
certificates). The role of the attestation server will be to deliver to
|
||||
clients secrets and credentials they need that can only be correct and
|
||||
legitimate if the server is authentic. As well, an attestation server
|
||||
may unlock network access for a client, something only an authentic
|
||||
server could do.
|
||||
|
||||
We will show how an attestation server can avoid storing any cleartext
|
||||
secrets.
|
||||
|
||||
Theft of _running_ client devices cannot be fully protected against by
|
||||
an attestation protocol. The client must detect being taken from its
|
||||
normal environment and shutdown in such a way that no secrets are left
|
||||
in cleartext on any of its devices. Frequent attestations might be used
|
||||
to detect theft of a client, but other keepalive signalling options are
|
||||
possible.
|
||||
|
||||
Theft of non-running client devices can be protected against by having
|
||||
the client shutdown in such a way that no secrets are left in cleartext
|
||||
on any of its devices. Such client devices may be configured to need
|
||||
the help of an attestation server to recover the secrets it needs for
|
||||
normal operation.
|
||||
|
||||
Full protection against decapping of TPM chips is not possible, but
|
||||
protection against off-line use of secrets stolen from TPM chips is
|
||||
possible by requiring that the client be on-line and attest in order to
|
||||
obtain secrets that it needs to operate. This allows for revocation of
|
||||
stolen clients, which would result in attestation protocol failures.
|
||||
|
||||
## Proof of Possession of TPM
|
||||
|
||||
|
@ -95,10 +179,10 @@ key) encrypted to the EKpub and then the attestation client demonstrate
|
|||
that it was able to decrypt that with the EK. However, this is not
|
||||
_quite_ how attestation protocols work! Instead of plain asymmetric
|
||||
encryption the server will use
|
||||
[`TPM2_MakeCredential()`](TPM2_MakeCredential.md), while the attestation
|
||||
client will use
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md) instead of
|
||||
plain asymmetric decryption.
|
||||
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md), while
|
||||
the attestation client will use
|
||||
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md)
|
||||
instead of plain asymmetric decryption.
|
||||
|
||||
## Trusted State Attestation
|
||||
|
||||
|
@ -114,15 +198,15 @@ Typically the attestation protocol will have the client generate a
|
|||
signing-only asymmetric public key pair known as the attestation key
|
||||
(AK) with which to sign the PCR quote and eventlog. Binding of the
|
||||
EKpub and AKpub will happen via
|
||||
[`TPM2_MakeCredential()`](TPM2_MakeCredential.md) /
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md).
|
||||
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) /
|
||||
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md).
|
||||
|
||||
Note that the [`TPM2_Quote()`](TPM2_Quote.md) function produces a signed
|
||||
Note that the [`TPM2_Quote()`](/TPM-Commands/TPM2_Quote.md) function produces a signed
|
||||
message -- signed with a TPM-resident AK named by the caller (and to
|
||||
which they have access), which would be the AK used in the attestation
|
||||
protocol.
|
||||
|
||||
The output of [`TPM2_Quote()`](TPM2_Quote.md) might be the only part of
|
||||
The output of [`TPM2_Quote()`](/TPM-Commands/TPM2_Quote.md) might be the only part of
|
||||
a client's messages to the attestation service that include a signature
|
||||
made with the AK, but integrity protection of everything else can be
|
||||
implied (e.g., the eventlog and PCR values are used to reconstruct the
|
||||
|
@ -140,14 +224,14 @@ digest of the selected PCRs. `TPM2_Quote()` signs all of:
|
|||
|
||||
## Binding of Other Keys to EKpub
|
||||
|
||||
The semantics of [`TPM2_MakeCredential()`](TPM2_MakeCredential.md) /
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md) make it
|
||||
The semantics of [`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) /
|
||||
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md) make it
|
||||
possible to bind a TPM-resident object to the TPM's EKpub.
|
||||
|
||||
[`TPM2_MakeCredential()`](TPM2_MakeCredential.md) encrypts to the EKpub
|
||||
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) encrypts to the EKpub
|
||||
a small secret datum and the name (digest of public part) of the
|
||||
TPM-resident object being bound. The counter-part to this,
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md), will decrypt
|
||||
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md), will decrypt
|
||||
that and return the secret to the application IFF (if and only if) the
|
||||
caller has access to the named object.
|
||||
|
||||
|
@ -195,14 +279,14 @@ Let's start with few observations and security considerations:
|
|||
timestamps.
|
||||
|
||||
- Replay protection of server to client responses is mostly either not
|
||||
needed or implicitly provided by [`TPM2_MakeCredential()`](TMP2_MakeCredential.md)
|
||||
needed or implicitly provided by [`TPM2_MakeCredential()`](TPM2_MakeCredential.md)
|
||||
because `TPM2_MakeCredential()` generates a secret seed that
|
||||
randomizes its outputs even when all the inputs are the same across
|
||||
multiple calls to it.
|
||||
|
||||
- Ultimately the protocol *must* make use of
|
||||
[`TPM2_MakeCredential()`](TMP2_MakeCredential.md) and
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md) in order to
|
||||
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) and
|
||||
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md) in order to
|
||||
authenticate a TPM-running host via its TPM's EKpub.
|
||||
|
||||
- Privacy protection of client identifiers may be needed, in which case
|
||||
|
@ -288,7 +372,7 @@ protocol:
|
|||
![Protocol Diagram](Protocol-Two-Messages.png)
|
||||
|
||||
(In this diagram we show the use of a TPM simulator on the server side
|
||||
for implementing [`TPM2_MakeCredential()`](TPM2_MakeCredential.md).)
|
||||
for implementing [`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md).)
|
||||
|
||||
The server will validate that the `timestamp` is near the current time,
|
||||
the EKcert (if provided, else the EKpub), the signature using the
|
||||
|
@ -314,7 +398,7 @@ is persisted both, in the client TPM and in the attestation service's
|
|||
database:
|
||||
|
||||
```
|
||||
<having previously successfully enrolled AKpub and bound it to EKpub...>
|
||||
<having previously successfully enrolled>
|
||||
|
||||
CS0: timestamp, AKpub, PCRs, eventlog,
|
||||
TPM2_Quote(AK, PCRs, extra_data)=Signed_AK({hash-of-PCRs, misc, extra_data})
|
||||
|
@ -340,7 +424,7 @@ desirable anyways for monitoring and alerting purposes.
|
|||
![Protocol Diagram](Protocol-Three-Messages.png)
|
||||
|
||||
(In this diagram we show the use of a TPM simulator on the server side
|
||||
for implementing [`TPM2_MakeCredential()`](TPM2_MakeCredential.md).)
|
||||
for implementing [`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md).)
|
||||
|
||||
NOTE well that in this protocol, like single round trip attestation
|
||||
protocols using only decrypt-only EKs, it is *essential* that the AKcert
|
||||
|
@ -505,10 +589,6 @@ PCRs are desired, then this becomes a one round trip protocol.
|
|||
|
||||
An AKcert will be added to the Safeboot protocol soon.
|
||||
|
||||
### Actual Protocols: ...
|
||||
|
||||
(TBD)
|
||||
|
||||
## Attestation Protocol Patterns and Actual Protocols (signing-only EKs)
|
||||
|
||||
Some TPMs come provisioned with signing-only endorsement keys in
|
||||
|
@ -609,8 +689,8 @@ A schema for the attestation server's database entries might look like:
|
|||
"previous_PCRs": "<...>",
|
||||
"proposed_PCRs": "<...>",
|
||||
"ak_cert_template": "<AKCertTemplate>",
|
||||
"secrets": "<secrets>",
|
||||
"resetCount": "<resetCount value from last quote>"
|
||||
"resetCount": "<resetCount value from last quote>",
|
||||
"secrets": "<see below>"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -660,12 +740,28 @@ then an administrator would confirm that the client just did a
|
|||
firmware/OS upgrade and if so replace the `previous_PCRs` with the
|
||||
`proposed_PCRs`, then the client could attempt attestation again.
|
||||
|
||||
## Dealing with Secrets
|
||||
# Delivery of Secrets to Attestation Clients
|
||||
|
||||
An attestation server might want to return storage/filesystem decryption
|
||||
key-encryption-keys to a client. But one might not want to store those
|
||||
keys in the clear on the attestation server. As well, one might want a
|
||||
break-glass way to recover those secrets.
|
||||
An attestation server might have to return storage/filesystem decryption
|
||||
key-encryption-keys (KEKs) to a client. But one might not want to store
|
||||
those keys in the clear on the attestation server. As well, one might
|
||||
want a break-glass way to recover those secrets.
|
||||
|
||||
Possible goals:
|
||||
|
||||
- store secrets that clients need on the attestation server
|
||||
- do not store plaintext or plaintext-equivalent secrets on the
|
||||
attestation server
|
||||
- allow for adding more secrets to send to the client after enrollment
|
||||
- provide a break-glass recovery mechanism
|
||||
|
||||
Note that in all cases the client does get direct access to various
|
||||
secrets. Using a TPM to prevent direct software access to those secrets
|
||||
would not be performant if, for example, those secrets are being used to
|
||||
encrypt filesystems. We must inherently trust the client to keep those
|
||||
secrets safe when running.
|
||||
|
||||
## Break-Glass Recovery
|
||||
|
||||
For break-glass recovery, the simplest thing to do is to store
|
||||
`Encrypt_backupKey({EKpub, hostname, secrets})`, where `backupKey` is an
|
||||
|
@ -675,53 +771,299 @@ the ciphertext to the offline system where the private backup key is
|
|||
kept, decrypt it, and then use the secrets manually to recover the
|
||||
affected system.
|
||||
|
||||
Here are some ideas for how to make an attestation client depend on the
|
||||
attestation server giving it keys needed to continue booting after
|
||||
successful attestation:
|
||||
## Secret Transport Sub-Protocols
|
||||
|
||||
- Store `TPM2_MakeCredential(EKpub, someObjectName, key0), Encrypt_key0(secrets)`.
|
||||
Here we describe several possible sub-protocols of attestation protocols
|
||||
for secret transport. This list is almost certainly not exhaustive.
|
||||
|
||||
In this mode the server sends the client the stored data, then client
|
||||
gets to recreate `someObject` (possibly by loading a saved object or
|
||||
by re-creating it on the same non-NULL hierarchy from the same
|
||||
primary seed using the same template and extra entropy) on its TPM so
|
||||
that the corresponding call to `TPM2_ActivateCredential()` can
|
||||
succeed, then the client recovers `key0` and decrypts the encrypted
|
||||
secrets. Here `someObject` can be trivial and need only exist to
|
||||
make the `{Make,Activate}Credential` machinery work.
|
||||
### Store a `TPM2_MakeCredential()` Payload
|
||||
|
||||
TPM replacement and/or migration of a host from one physical system
|
||||
to another can be implemented by learning the new system's TPM's
|
||||
EKpub and using the offline `backupKey` to compute
|
||||
`TPM2_MakeCredential(EKpub_new, someObjectName, key0)` and update the
|
||||
host's entry.
|
||||
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) and
|
||||
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md)
|
||||
are a form of limited asymmetric encryption (`TPM2_MakeCredential()`)
|
||||
and asymmetric decryption (`TPM2_ActivateCredential()`) subject to the
|
||||
sender's choice of authorization. The details are explained
|
||||
[here](/TPM-Commands/TPM2_MakeCredential.md) and
|
||||
[here](/TPM-Commands/TPM2_ActivateCredential.md). Basically, there are
|
||||
two TPM key objects involved:
|
||||
|
||||
- Alternatively generate a non-restricted decryption private key using
|
||||
a set template and extra entropy, on the same non-NULL hierarchy
|
||||
(i.e., from the same seed), enroll the public key to this private key
|
||||
in an attestation protocol, and have the attestation server store
|
||||
secrets encrypted to that public key.
|
||||
- a transport key (typically the `EK`),
|
||||
- and an authorization key (typically an `AK`)
|
||||
|
||||
(The EK cannot be used this way because it is restricted.)
|
||||
and the caller of `TPM2_MakeCredential()` must specify the public part
|
||||
of the transport key and the
|
||||
[name](/Intro/README.md#Cryptographic-Object-Naming) of the
|
||||
authorization key, along with a small secret to transport. The caller
|
||||
of `TPM2_ActivateCredential()` must then provide the handles for those
|
||||
two key objects and the outputs of `TPM2_MakeCredential()` in order to
|
||||
extract the small secret. Typically the small secret is an AES key for
|
||||
encrypting larger secrets.
|
||||
|
||||
- Store a secret value that will be extended into an application PCR
|
||||
that is used as a policy PCR for unsealing a persistent object stored
|
||||
on the client's TPM.
|
||||
So if we can store the outputs of `TPM2_MakeCredential()` long-term so
|
||||
that the client can activate over multiple reboots, then we have a way
|
||||
to deliver secrets to the client.
|
||||
|
||||
In this mode the server sends the client the secret PCR extension
|
||||
value, and the client uses it to extend a PCR such that it can then
|
||||
unseal the real storage / filesystem decryption keys.
|
||||
We'll discuss two ways to do this:
|
||||
|
||||
Using a PCR and a policy on the key object allows for a clever
|
||||
break-glass secret recovery mechanism by using a compound extended
|
||||
authorization (EA) policy that allows either unsealing based on a
|
||||
PCR, or maybe based on an password-based HMAC (with machine passwords
|
||||
stored in a safe).
|
||||
- use a `WK` -- a universally well-known key (thus WK, for well-known)
|
||||
|
||||
- A hybrid of the previous options, where the server stores a secret
|
||||
PCR extension value wrapped with `TPM2_MakeCredential()`.
|
||||
Since the `WK`'s private area is not used for any cryptography in
|
||||
`TPM2_MakeCredential()`/`TPM2_ActivateCredential()`, it can be a key
|
||||
that everyone knows.
|
||||
|
||||
Other ideas?
|
||||
Note that the `WK`'s public area can name arbitrary an auth policy,
|
||||
and `TPM2_MakeCredential()` will enforce it.
|
||||
|
||||
E.g., the `WK` could be the all-zeros AES key. Its policy could be
|
||||
whatever is appropriate for the organization. For example, the
|
||||
policy could require that some non-resettable application PCR have
|
||||
the value zero so that extending it can disable use of
|
||||
`TPM2_MakeCredential()` post-boot.
|
||||
|
||||
- use an `LTAK` -- a long-term `AK`
|
||||
|
||||
I.e., an `AK` that lacks the `stClear` attribute, and _preferably_
|
||||
created deterministically with either
|
||||
[`TPM2_CreateLoaded()`](/TPM-Commands/TPM2_CreateLoaded.md) or
|
||||
[`TPM2_CreatePrimary()`](/TPM-Commands/TPM2_CreatePrimary.md).
|
||||
|
||||
> Note that the `LTAK` need not be a primary.
|
||||
|
||||
> If the `LTAK` were created with
|
||||
> [`TPM2_Create()`](/TPM-Commands/TPM2_Create.md) then the key's saved
|
||||
> context file would have to be stored somewhere so that it could be
|
||||
> loaded again on next boot with
|
||||
> [`TPM2_Load()`](/TPM-Commands/TPM2_Load.md). Whereas creating it
|
||||
> deterministically means that it can be re-created every time it's
|
||||
> needed using the same hiercarchy, template, and entropy as
|
||||
> arguments to `TPM2_CreatePrimary()` or `TPM2_CreateLoaded()`
|
||||
|
||||
Note that the `AK`'s public area can name arbitrary an auth policy,
|
||||
and `TPM2_MakeCredential()` will enforce it.
|
||||
|
||||
The best option here is to use a `WK` because using an `LTAK` would
|
||||
require recording its public key in the device's enrolled attestation
|
||||
state, which would complicate enrollment, whereas the `WK`, being
|
||||
well-known and the same for all cases, would not need to be recorded in
|
||||
server-side attestation state.
|
||||
|
||||
> One might like to use the `EK` as the `activateHandle`. Sadly, this
|
||||
> is not possible.
|
||||
> While `TPM2_MakeCredential(EKpub, EKname, input)` works,
|
||||
> `TPM2_ActivateCredential(EK, EK, credentialBlob, secret)` does not
|
||||
> and cannot.
|
||||
>
|
||||
> The reason for this is that `TPM2_ActivateCredential()` requires
|
||||
> `ADMIN` role for the `activateHandle`, and since the `EK` has
|
||||
> `adminWithPolicy` attribute set and its policy doesn't have the
|
||||
> `TPM_CC_ACTIVATECREDENTIAL` command permitted, the call must fail.
|
||||
>
|
||||
> Credit for the `WK` idea goes to [Erik > Larsson](https://developers.tpm.dev/chats/new?user_id=4336638).
|
||||
|
||||
Normally during attestation we want to use an `AK` with `stClear` set so
|
||||
that each boot forces the client to use a new one. However, for sending
|
||||
secrets to the client via `TPM2_MakeCredential()` /
|
||||
`TPM2_ActivateCredential()` we really need need the `activateHandle`
|
||||
object to not have `stClear` set.
|
||||
|
||||
For this approach then, the best solution is to use a `WK`.
|
||||
|
||||
```
|
||||
CS0: timestamp, AKpub, PCRs, eventlog,
|
||||
TPM2_Quote(AK, PCRs, extra_data)=Signed_AK({hash-of-PCRs, misc, extra_data})
|
||||
SC0: {TPM2_MakeCredential(EKpub, AKname, session_key),
|
||||
Encrypt_session_key(long_term_Credential)}
|
||||
|
||||
where
|
||||
|
||||
long_term_Credential = TPM2_MakeCredential(EKpub, WKname, secrets)
|
||||
```
|
||||
|
||||
New secrets can be added at any time without interaction with the
|
||||
client if the attestation server recalls the `LTAKname`.
|
||||
|
||||
The schema for storing secrets transported this way would be:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"EKpub": "<EKpub>",
|
||||
"hostname": "<hostname>",
|
||||
"EKcert": "<EKcert in PEM, if available>",
|
||||
"previous_firmware_profile": "FWProfile0",
|
||||
"current_firmware_profiles": ["FWProfile1", "FWProfile2", "..."],
|
||||
"previous_operating_system_profiles": "OSProfile0",
|
||||
"current_operating_system_profiles": ["OSProfile1", "OSProfile2", "..."],
|
||||
"previous_PCRs": "<...>",
|
||||
"proposed_PCRs": "<...>",
|
||||
"resetCount": "<resetCount value from last quote>",
|
||||
|
||||
"secret store and transport fields":"vvvvvvvvvvvvvvvvvv",
|
||||
|
||||
"secrets": ["<MakeCredential_0>", "<MakeCredential_1>", "..", "<MakeCredential_N>"]
|
||||
"secrets_backup": ["<RSA_Encrypt_to_backup_key(...)", "..."],
|
||||
}
|
||||
```
|
||||
|
||||
### Use an Unrestricted Decryption Transport Key (TK) for Secret Transport (client-side)
|
||||
|
||||
Another option is to generate an asymmetric key-pair at device
|
||||
enrollment time (we shall call this the "transport key", or `TK`), and
|
||||
store:
|
||||
|
||||
- the `TKpub`, and
|
||||
|
||||
- zero, one, or more secrets encrypted in the `EKpub`.
|
||||
|
||||
The client has to use
|
||||
[`TPM2_CreatePrimary()`](/TPM-Commands/TPM2_CreatePrimary.md) or
|
||||
[`TPM2_CreateLoaded()`](/TPM-Commands/TPM2_CreateLoaded.md) in order to
|
||||
deterministically create the same `TK` (without the `stClear`)
|
||||
attribute, else if it uses
|
||||
[`TPM2_Create()`](/TPM-Commands/TPM2_Create.md) then it must store the
|
||||
key save file somewhere (possibly in the attestation server!) or make
|
||||
the key object persistent.
|
||||
|
||||
New secrets can be added at any time without interaction with the
|
||||
client.
|
||||
|
||||
```JSON
|
||||
{
|
||||
"EKpub": "<EKpub>",
|
||||
"hostname": "<hostname>",
|
||||
"EKcert": "<EKcert in PEM, if available>",
|
||||
"previous_firmware_profile": "FWProfile0",
|
||||
"current_firmware_profiles": ["FWProfile1", "FWProfile2", "..."],
|
||||
"previous_operating_system_profiles": "OSProfile0",
|
||||
"current_operating_system_profiles": ["OSProfile1", "OSProfile2", "..."],
|
||||
"previous_PCRs": "<...>",
|
||||
"proposed_PCRs": "<...>",
|
||||
"ak_cert_template": "<AKCertTemplate>",
|
||||
"resetCount": "<resetCount value from last quote>",
|
||||
|
||||
"secret store and transport fields":"vvvvvvvvvvvvvvvvvv",
|
||||
|
||||
"TKpub": "<TKpub in PEM>",
|
||||
"secrets": ["<RSA_Encrypt_0>", "<RSA_Encrypt_1>", "..", "<RSA_Encrypt_N>"]
|
||||
"secrets_backup": ["<RSA_Encrypt_to_backup_key(...)", "..."],
|
||||
}
|
||||
```
|
||||
|
||||
### Use an Unrestricted Decryption Transport Key (TK) for Secret Transport (server-side)
|
||||
|
||||
Another option is to generate an asymmetric key-pair at device
|
||||
enrollment time (we shall call this the "transport key", or `TK`), and
|
||||
store:
|
||||
|
||||
- the TK exported to the client device's TPM (i.e., the output of
|
||||
`TPM2_Duplicate()` called on that private key to export it to the
|
||||
client's TPM's EKpub), and
|
||||
|
||||
- the ciphertext resulting from encrypting long-term secrets to that
|
||||
TK.
|
||||
|
||||
At attestation time the server can send back these two values to the
|
||||
client, and then the client can `TPM2_Import()` and then `TPM2_Load()`
|
||||
the duplicated (exported) TK, then use it to `TPM2_RSA_Decrypt()` the
|
||||
encrypted long-term secrets.
|
||||
|
||||
New secrets can be added at any time without interaction with the
|
||||
client.
|
||||
|
||||
```JSON
|
||||
{
|
||||
"EKpub": "<EKpub>",
|
||||
"hostname": "<hostname>",
|
||||
"EKcert": "<EKcert in PEM, if available>",
|
||||
"previous_firmware_profile": "FWProfile0",
|
||||
"current_firmware_profiles": ["FWProfile1", "FWProfile2", "..."],
|
||||
"previous_operating_system_profiles": "OSProfile0",
|
||||
"current_operating_system_profiles": ["OSProfile1", "OSProfile2", "..."],
|
||||
"previous_PCRs": "<...>",
|
||||
"proposed_PCRs": "<...>",
|
||||
"ak_cert_template": "<AKCertTemplate>",
|
||||
"resetCount": "<resetCount value from last quote>",
|
||||
|
||||
"secret store and transport fields":"vvvvvvvvvvvvvvvvvv",
|
||||
|
||||
"TKdup": "<output of TPM2_Duplicate(EKpub, TK)>",
|
||||
"TKpub": "<TKpub in PEM>",
|
||||
"secrets": ["<RSA_Encrypt_0>", "<RSA_Encrypt_1>", "..", "<RSA_Encrypt_N>"]
|
||||
"secrets_backup": ["<RSA_Encrypt_to_backup_key(...)", "..."],
|
||||
}
|
||||
```
|
||||
|
||||
### Store a Secret PCR Extension Value for Unsealing Data Objects
|
||||
|
||||
The attestation server could store in plaintext a secret that it will
|
||||
returned encrypted to the client's EKpub vias `TPM2_MakeCredential()`,
|
||||
and which the client must use to extend a PCR (e.g., the debug PCR) to
|
||||
get that PCR into the state needed to unseal a persistent data object on
|
||||
the TPM.
|
||||
|
||||
Because the sealed data object may itself be stored in cleartext in the
|
||||
TPM's NVRAM, and because an attacker might be able to decap a stolen
|
||||
client device's TPM and recover the TPM's NVRAM contents and seeds, the
|
||||
client might store an encrypted value in that sealed data object that
|
||||
the TPM does not have the keey to decrypt. The decryption key would be
|
||||
sent by the attestation server (possibly being the same secret as is
|
||||
extended into that PCR).
|
||||
|
||||
```JSON
|
||||
{
|
||||
"EKpub": "<EKpub>",
|
||||
"hostname": "<hostname>",
|
||||
"EKcert": "<EKcert in PEM, if available>",
|
||||
"previous_firmware_profile": "FWProfile0",
|
||||
"current_firmware_profiles": ["FWProfile1", "FWProfile2", "..."],
|
||||
"previous_operating_system_profiles": "OSProfile0",
|
||||
"current_operating_system_profiles": ["OSProfile1", "OSProfile2", "..."],
|
||||
"previous_PCRs": "<...>",
|
||||
"proposed_PCRs": "<...>",
|
||||
"ak_cert_template": "<AKCertTemplate>",
|
||||
"resetCount": "<resetCount value from last quote>",
|
||||
|
||||
"secret store and transport fields":"vvvvvvvvvvvvvvvvvv",
|
||||
|
||||
"unseal_key": "<key>",
|
||||
"secrets_backup": ["<RSA_Encrypt_to_backup_key(...)", "..."],
|
||||
}
|
||||
```
|
||||
|
||||
### Store Secrets in Plaintext, Encrypt to EKpub Using `TPM2_MakeCredential()`
|
||||
|
||||
As the title says, one option is to store the secrets in plaintext and
|
||||
send them encrypted to the EKpub via
|
||||
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md).
|
||||
Because [`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md)
|
||||
encrypts only a small secret, it goes without saying that that secret
|
||||
would be a one-time use symmetric encryption key that would be used to
|
||||
encrypt the actual secrets.
|
||||
|
||||
This is, naturally, the least desirable option.
|
||||
|
||||
```JSON
|
||||
{
|
||||
"EKpub": "<EKpub>",
|
||||
"hostname": "<hostname>",
|
||||
"EKcert": "<EKcert in PEM, if available>",
|
||||
"previous_firmware_profile": "FWProfile0",
|
||||
"current_firmware_profiles": ["FWProfile1", "FWProfile2", "..."],
|
||||
"previous_operating_system_profiles": "OSProfile0",
|
||||
"current_operating_system_profiles": ["OSProfile1", "OSProfile2", "..."],
|
||||
"previous_PCRs": "<...>",
|
||||
"proposed_PCRs": "<...>",
|
||||
"ak_cert_template": "<AKCertTemplate>",
|
||||
"resetCount": "<resetCount value from last quote>",
|
||||
|
||||
"secret store and transport fields":"vvvvvvvvvvvvvvvvvv",
|
||||
|
||||
"secrets": ["<secret_0>", "<secret_1>", "<secret_N>"]
|
||||
}
|
||||
```
|
||||
|
||||
# Security Considerations
|
||||
|
||||
TBD
|
||||
|
||||
# References
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
# `TPM2_ActivateCredential()`
|
||||
|
||||
`TPM2_ActivateCredential()` decrypts a ciphertext made by
|
||||
[`TPM2_MakeCredential()`](TPM2_MakeCredential.md) and checks that the
|
||||
caller has access to the object named by the caller of
|
||||
[`TPM2_MakeCredential()`](TPM2_MakeCredential.md), and if so then
|
||||
`TPM2_ActivateCredential()` outputs the small secret provided by the
|
||||
caller of [`TPM2_MakeCredential()`](TPM2_MakeCredential.md),
|
||||
otherwise `TPM2_ActivateCredential()` fails.
|
||||
|
||||
Together with [`TPM2_MakeCredential()`](TPM2_MakeCredential.md),
|
||||
this function can be used to implement attestation protocols.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_DH_OBJECT activateHandle` (e.g., handle for an AK)
|
||||
- `TPMI_DH_OBJECT keyHandle` (e.g., handle for an EK corresponding to the EKpub encrypted to by `TPM2_MakeCredential()`)
|
||||
- `TPM2B_ID_OBJECT credentialBlob` (output of `TPM2_MakeCredential()`)
|
||||
- `TPM2B_ENCRYPTED_SECRET secret` (output of `TPM2_MakeCredential()`)
|
||||
|
||||
## Outputs (success case)
|
||||
|
||||
- `TPM2B_DIGEST certInfo` (not necessarily a digest, but a small [digest-sized] secret that was input to `TPM2_MakeCredential()`)
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 1: Architecture, section 24](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf)
|
||||
- [TCG TPM Library part 2: Structures](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part2_Structures_pub.pdf)
|
||||
- [TCG TPM Library part 3: Commands, section 12](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
- [TCG TPM Library part 3: Commands Code, section 12](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_code_pub.pdf)
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
# `TPM2_MakeCredential()`
|
||||
|
||||
`TPM2_MakeCredential()` takes an EKpub, the name of an object in a TPM
|
||||
identified by that EKpub, and a small secret, and it encrypts `{name,
|
||||
secret}` to the EKpub.
|
||||
|
||||
Nothing terribly interesting happens here. All the interesting
|
||||
semantics are on the
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md) side.
|
||||
|
||||
Together with [`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md),
|
||||
this function can be used to implement attestation protocols.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_DH_OBJECT handle` (e.g., an EKpub to encrypt to)
|
||||
- `TPM2B_DIGEST credential` (not necessarily a digest, but a small [digest-sized] secret)
|
||||
- `TPM2B_NAME objectName` (name of object resident on the same TPM as `handle` that `TPM2_ActivateCredential()` will check)
|
||||
|
||||
## Outputs
|
||||
|
||||
- `TPM2B_ID_OBJECT credentialBlob` (ciphertext of encryption of `credential` with a secret "seed" [see below])
|
||||
- `TPM2B_ENCRYPTED_SECRET secret` (ciphertext of encryption of a "seed" to `handle`)
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 1: Architecture, section 24](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf)
|
||||
- [TCG TPM Library part 2: Structures](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part2_Structures_pub.pdf)
|
||||
- [TCG TPM Library part 3: Commands, section 13](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
- [TCG TPM Library part 3: Commands Code, section 13](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_code_pub.pdf)
|
||||
|
139
Enrollment/README.md
Normal file
139
Enrollment/README.md
Normal file
|
@ -0,0 +1,139 @@
|
|||
# Device Enrollment
|
||||
|
||||
Device Enrollment is the act of registering a device -anything from an
|
||||
IoT to a server- and creating the state that will be referenced in
|
||||
future [attestations](/Attestation/README.md) from that device.
|
||||
|
||||
This can be as simple as sending the device's endorsement key
|
||||
certificate (EKcert) to a registration server (possibly authenticating
|
||||
to that server using some administrator user's credentials), to a more
|
||||
complex protocol similar to [attestation](/Attestation/README.md).
|
||||
|
||||
## Online Enrollment
|
||||
|
||||
Online enrollment means that the device to be enrolled interacts with an
|
||||
enrollment service over a network.
|
||||
|
||||
## Off-line Enrollment
|
||||
|
||||
Off-line enrollment means that the device to be enrolled *does not*
|
||||
interact with an enrollment service.
|
||||
|
||||
For example, one might scan an endorsement key (EK) public key or
|
||||
certificate from a QR code on a shipment manifest and then enroll the
|
||||
device using only that information.
|
||||
|
||||
# Server-Side State to Create during Enrollment
|
||||
|
||||
- device name <-> EKpub binding
|
||||
- enrolling user/admin
|
||||
- that the device has a valid TPM (i.e., the EKcert validates to a
|
||||
trusted TPM vendor's trust anchor)
|
||||
- initial root of trust measurement (RTM)
|
||||
- backup, secret recovery keys
|
||||
- encrypted secrets to send to the device
|
||||
|
||||
# Client-side State to Create during Enrollment
|
||||
|
||||
- encrypted filesystems?
|
||||
- device credentials? (e.g., TLS server certificates, Kerberos keys ["keytabs"], etc.)
|
||||
|
||||
# Secrets Transport
|
||||
|
||||
Every time an enrolled device reboots, or possibly more often, it may
|
||||
have to connect to an attestation server to obtain secrets from it that
|
||||
the device needs in order to proceed. For example, filesystem
|
||||
decryption keys, general network access, device authentication
|
||||
credentials, etc.
|
||||
|
||||
See [attestation](/Attestation/README.md) for details of how to
|
||||
transport secrets onto an enrolled device post-enrollment.
|
||||
|
||||
# Enrollment Semantics
|
||||
|
||||
- online vs. off-line
|
||||
|
||||
- client device trust semantics:
|
||||
- bind device name and EKpub on first use ("BOFU")?
|
||||
- enroll into inventory and then allow authorized users to bind a
|
||||
device name to an EKpub on a first-come-first-served basis?
|
||||
|
||||
- enrollment server trust semantics:
|
||||
- trust on first use (TOFU) (i.e., trust the first enrollment server
|
||||
found)
|
||||
- pre-install a trust anchor on the client device
|
||||
- use a user/admin credential on the device to establish trust on
|
||||
the server (e.g., intrinsically to how user authentication works,
|
||||
or having the user review and approve the server's credentials)
|
||||
|
||||
# Threat Models
|
||||
|
||||
Threats:
|
||||
|
||||
- enrollment server impersonation
|
||||
- enrollment of rogue devices
|
||||
- eavesdroppers
|
||||
- DoS
|
||||
|
||||
A typical enrollment protocol for servers in datacenters may well not
|
||||
bother protecting against all of the above.
|
||||
|
||||
A typical enrollment protocol for IoTs in a home network also may well
|
||||
not bother protecting against any of the above.
|
||||
|
||||
Enrollment protocols for personal devices must protect against all the
|
||||
listed threats except DoS attacks.
|
||||
|
||||
# Enrollment Protocols
|
||||
|
||||
## Trivial Enrollment Protocols
|
||||
|
||||
The simplest enrollment protocols just have the client device send its
|
||||
EKcert to the enrollment server. The enrollment server may have a user
|
||||
associate enrolled devices with device IDs (e.g., hostnames), and the
|
||||
device's enrollment is complete.
|
||||
|
||||
## Enrollment Protocols with Proof of Possession and Attestation
|
||||
|
||||
A more complex enrollment protocol would have the device attest to
|
||||
possession of the EK whose EKpub is certified by its EKcert, and might
|
||||
as well also perform attestation of other things, such as RTM.
|
||||
|
||||
An enrollment protocol with proof of possession might look a lot like
|
||||
the [two round trip attestation
|
||||
protocol](/Attestation/README.md#two-round-trip-stateless-attestation-protocol-patterns),
|
||||
with the addition of `enrollment_data` in the last message from the
|
||||
client to the server (server authentication not shown):
|
||||
|
||||
```
|
||||
CS0: [ID], EKpub, [EKcert], AKpub, PCRs, eventlog, timestamp,
|
||||
TPM2_Quote(AK, PCRs, extra_data)=Signed_AK({hash-of-PCRs, misc, extra_data})
|
||||
SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key), ticket}
|
||||
CS1: {ticket, MAC_session_key(CS0), CS0, Encrypt_session_key(enrollment_data)}
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
(new)
|
||||
SC1: Encrypt_session_key({AKcert, filesystem_keys, etc.})
|
||||
|
||||
<extra_data includes timestamp>
|
||||
```
|
||||
|
||||
where
|
||||
|
||||
```
|
||||
enrollment_data = { Encrypt_TK(secrets), [TKpub], [HK_pub] }
|
||||
|
||||
secrets = any secrets generated on the client side
|
||||
TKpub = public part of transport key for encrypting secrets to the
|
||||
client
|
||||
HKpub = public part of a host key for host authentication
|
||||
```
|
||||
|
||||
## Enrollment Protocols for Personal Devices
|
||||
|
||||
Enrollment of personal devices in their owners' personal device groups
|
||||
can be a lot like Bluetooth device pairing. Where such devices have
|
||||
TPMs then perhaps there is a role for the TPM to play in enrollment.
|
||||
|
||||
# Security Considerations
|
||||
|
||||
TBD
|
362
Intro/README.md
362
Intro/README.md
|
@ -48,6 +48,39 @@ general, which include:
|
|||
> 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:
|
||||
|
@ -291,16 +324,18 @@ necessarily yields a new name.
|
|||
> 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()` and
|
||||
`TPM2_ActivateCredential()`, illustrate the use of cryptographic object
|
||||
naming as a binding or a sort of authorization function.
|
||||
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()` 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.
|
||||
[`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.
|
||||
|
@ -312,21 +347,21 @@ keys, each with zero, one, or more children keys:
|
|||
|
||||
```
|
||||
seed
|
||||
|
|
||||
|
|
||||
v
|
||||
/|\
|
||||
/ | \
|
||||
v v v
|
||||
primary key (asymmetric encryption)
|
||||
|
|
||||
|
|
||||
v
|
||||
/|\
|
||||
/ | \
|
||||
v v v
|
||||
secondary keys (of any kind)
|
||||
|
|
||||
|
|
||||
v
|
||||
/|\
|
||||
/ | \
|
||||
v v v
|
||||
...
|
||||
```
|
||||
|
||||
Note that every key has a parent or is a primary key.
|
||||
Keys that have no parent are primary keys.
|
||||
|
||||
There are four built-in hierarchies:
|
||||
|
||||
|
@ -346,10 +381,18 @@ 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()` and `TPM2_CreateLoaded()` commands create 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_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
|
||||
|
||||
|
@ -482,16 +525,36 @@ policy because the TPM knows only a digest of it.
|
|||
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 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.
|
||||
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
|
||||
|
||||
|
@ -530,9 +593,108 @@ indexes, policies can be used to:
|
|||
## 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.
|
||||
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.
|
||||
|
||||
### 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
|
||||
|
||||
> Work in progress.
|
||||
|
||||
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.
|
||||
|
||||
> TODO: Discuss key exchange options, etc.
|
||||
|
||||
## Restricted Cryptographic Keys
|
||||
|
||||
|
@ -540,21 +702,53 @@ 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.
|
||||
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()`/`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.
|
||||
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.
|
||||
|
||||
There is also a notion of signing keys that can only be used to sign
|
||||
PKIX certificates.
|
||||
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
|
||||
|
||||
|
@ -577,19 +771,87 @@ many TPM concepts can be used to great effect:
|
|||
- 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.
|
||||
- [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.
|
||||
|
||||
Nokia has a [TPM course](https://github.com/nokia/TPMCourse/tree/master/docs).
|
||||
- Of course, there is the [TPM.dev community](https://developers.tpm.dev/),
|
||||
which has many resources, posts, a chat room, and knowledgeable
|
||||
participants.
|
||||
|
||||
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.
|
||||
- Nokia has a [TPM course](https://github.com/nokia/TPMCourse/tree/master/docs).
|
||||
|
||||
Core TCG TPM specs:
|
||||
- [Hacking with a TPM](https://c3media.vsos.ethz.ch/congress/2019/slides-pdf/36c3-10564-hacking_with_a_tpm.pdf).
|
||||
|
||||
- [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, section 12](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf).
|
||||
- [TCG TPM 2.0 Library part 3: Commands Code, section 12](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_code_pub.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).
|
||||
|
|
76
TPM-Commands/TPM2_ActivateCredential.md
Normal file
76
TPM-Commands/TPM2_ActivateCredential.md
Normal file
|
@ -0,0 +1,76 @@
|
|||
# `TPM2_ActivateCredential()`
|
||||
|
||||
`TPM2_ActivateCredential()` is the flip side to
|
||||
[`TPM2_MakeCredential()`](TPM2_MakeCredential.md), decrypting a small
|
||||
ciphertext made by [`TPM2_MakeCredential()`](TPM2_MakeCredential.md).
|
||||
|
||||
The intersting things about `TPM2_ActivateCredential()` are that
|
||||
|
||||
- the decryption key used may be a restricted key (which
|
||||
`TPM2_RSA_Decrypt()` would refuse to use)
|
||||
- and that `TPM2_ActivateCredential()` evaluates an authorization
|
||||
policy of the sender's choice.
|
||||
|
||||
Together with [`TPM2_MakeCredential()`](TPM2_MakeCredential.md) an
|
||||
[`TPM2_Quote()`](TPM2_Quote.md) this function can be used to implement
|
||||
attestation protocols.
|
||||
|
||||
Two of the input parameters of `TPM2_ActivateCredential()`, `keyHandle`
|
||||
and `activateHandle`, correspond to the `handle` and `objectName` inputs
|
||||
of [`TPM2_MakeCredential()`](TPM2_MakeCredential.md), respectively. The
|
||||
other inputs are [`TPM2_MakeCredential()`](TPM2_MakeCredential.md)'s
|
||||
outputs. The output, `certInfo` is
|
||||
[`TPM2_MakeCredential()`](TPM2_MakeCredential.md)'s `credential` input.
|
||||
|
||||
## Authorization
|
||||
|
||||
`TPM2_ActivateCredential()` checks the authorization of the caller to
|
||||
perform this operation by enforcing the `keyHandle`'s policy in the
|
||||
`USER` role, and the `activateHandle`'s policy in the `ADMIN` role. See
|
||||
section 19.2 of [TCG TPM Library part 1:
|
||||
Architecture](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf).
|
||||
|
||||
What this means specifically depends on whether the `userWithAuth`
|
||||
attribute is set on the `keyHandle` and whether the `adminWithPolicy`
|
||||
attribute is set on the `activateHandle`.
|
||||
|
||||
In particular, if `adminWithPolicy` is set on the `activateHandle` then
|
||||
the authorization session's `policyDigest` must match the
|
||||
`activateHandle`'s policy _and_ the authorization session's
|
||||
`commandCode` must be set to `TPM_CC_ActivateCredential`, which means
|
||||
that the caller must have called `TPM2_PolicyCommandCode()` with
|
||||
`TPM_CC_ActivateCredential` as the command code argument.
|
||||
|
||||
Some possible authorization policies to enforce include:
|
||||
|
||||
- that some non-resettable PCR has not been extended since boot
|
||||
|
||||
This allows the recipient to extend that PCR immediately after
|
||||
activating the credential to prevent the attestation protocol from
|
||||
being used again without rebooting.
|
||||
|
||||
- user authentication / attended boot
|
||||
|
||||
The policy could require physical presence, authentication of a user
|
||||
with biometrics and/or a smartcard and/or a password.
|
||||
|
||||
- locality
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_DH_OBJECT keyHandle` (e.g., handle for an EK corresponding to the EKpub encrypted to by `TPM2_MakeCredential()`)
|
||||
- `TPMI_DH_OBJECT activateHandle` (e.g., handle for an AK)
|
||||
- `TPM2B_ID_OBJECT credentialBlob` (output of `TPM2_MakeCredential()`)
|
||||
- `TPM2B_ENCRYPTED_SECRET secret` (output of `TPM2_MakeCredential()`)
|
||||
|
||||
## Outputs (success case)
|
||||
|
||||
- `TPM2B_DIGEST certInfo` (not necessarily a digest, but a small [digest-sized] secret that was input to `TPM2_MakeCredential()`)
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 1: Architecture, section 24](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf)
|
||||
- [TCG TPM Library part 2: Structures](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part2_Structures_pub.pdf)
|
||||
- [TCG TPM Library part 3: Commands, section 12](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
- [TCG TPM Library part 3: Commands Code, section 12](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_code_pub.pdf)
|
||||
|
21
TPM-Commands/TPM2_Certify.md
Normal file
21
TPM-Commands/TPM2_Certify.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# `TPM2_Certify()`
|
||||
|
||||
`TPM2_Certify()` signs an assertion that some named object is loaded in
|
||||
the TPM.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_DH_OBJECT objectHandle` (object to be certified)
|
||||
- `TPMI_DH_OBJECT signHandle` (handle for a signing key)
|
||||
- `TPM2B_DATA qualifyingData` (extra data)
|
||||
- `TPMT_SIG_SCHEME inScheme` ("signing scheme to use if the schemefor signHandleis `TPM_ALG_NULL`")
|
||||
|
||||
## Outputs (success case)
|
||||
|
||||
- `TPM2B_ATTEST certifyInfo` (what was signed)
|
||||
- `TPMT_SIGNATURE signature` (signature)
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 3: Commands, section 18.2](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
|
49
TPM-Commands/TPM2_Create.md
Normal file
49
TPM-Commands/TPM2_Create.md
Normal file
|
@ -0,0 +1,49 @@
|
|||
# `TPM2_Create()`
|
||||
|
||||
This command creates an ordinary key object.
|
||||
|
||||
The created object can then be loaded with [`TPM2_Load()`](TPM2_Load.md).
|
||||
|
||||
To decide whether to use [`TPM2_CreateLoaded()`](TPM2_CreateLoaded.md),
|
||||
`TPM2_Create()`, or [`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md)
|
||||
refer to table 28 in section 2.7 of the [TCG TPM Library part 1:
|
||||
Architecture](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf).
|
||||
|
||||
If you need to `TPM2_CertifyCreation()` that a TPM created some object,
|
||||
you must use [`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) or
|
||||
`TPM2_Create()`.
|
||||
|
||||
If you need to seal the object to a PCR selection, you must use
|
||||
[`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) or
|
||||
`TPM2_Create()`.
|
||||
|
||||
If you need to create a derived object, you must use
|
||||
[`TPM2_CreateLoaded()`](TPM2_CreateLoaded.md).
|
||||
|
||||
If you need to create an ordinary object, use `TPM2_Create()` or
|
||||
[`TPM2_CreateLoaded()`](TPM2_CreateLoaded.md).
|
||||
|
||||
If you need to create a primary object, use
|
||||
[`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) or
|
||||
[`TPM2_CreateLoaded()`](TPM2_CreateLoaded.md).
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_DH_OBJECT parentHandle`
|
||||
- `TPM2B_PUBLIC inPublic`
|
||||
- `TPM2B_DATA outsideInfo`
|
||||
- `TPML_PCR_SELECTION creationPCR`
|
||||
|
||||
## Outputs (success case)
|
||||
|
||||
- `TPM_HANDLE objectHandle`
|
||||
- `TPM2B_PRIVATE outPrivate`
|
||||
- `TPM2B_PUBLIC outPublic`
|
||||
- `TPM2B_CREATION_DATA creationData`
|
||||
- `TPM2B_DIGEST creationHash`
|
||||
- `TPMT_TK_CREATION creationTicket`
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 3: Commands, section 12.1](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
|
43
TPM-Commands/TPM2_CreateLoaded.md
Normal file
43
TPM-Commands/TPM2_CreateLoaded.md
Normal file
|
@ -0,0 +1,43 @@
|
|||
# `TPM2_CreateLoaded()`
|
||||
|
||||
This command creates a key object and loads it. The object can be a
|
||||
primary key, in which case `TPM2_CreateLoaded()` behaves just like
|
||||
[`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md). Or the object can be
|
||||
`ordinary` or `derived`.
|
||||
|
||||
The created object can then be loaded with [`TPM2_Load()`](TPM2_Load.md).
|
||||
|
||||
To decide whether to use `TPM2_CreateLoaded()`,
|
||||
[`TPM2_Create()`](TPM2_Create.md), or
|
||||
[`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) refer to table 28 in
|
||||
section 2.7 of the [TCG TPM Library part 1:
|
||||
Architecture](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf).
|
||||
|
||||
If you need to `TPM2_CertifyCreation()` that a TPM created some object,
|
||||
you must use [`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) or
|
||||
[`TPM2_Create()`](TPM2_Create.md).
|
||||
|
||||
If you need to seal the object to a PCR selection, you must use
|
||||
[`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) or
|
||||
[`TPM2_Create()`](TPM2_Create.md).
|
||||
|
||||
If you need to create a derived object, you must use
|
||||
`TPM2_CreateLoaded()`.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_DH_PARENT+ parentHandle`
|
||||
- `TPM2B_SENSITIVE_CREATE inSensitive`
|
||||
- `TPM2B_TEMPLATE inPublic`
|
||||
|
||||
## Outputs (success case)
|
||||
|
||||
- `TPM_HANDLE objectHandle`
|
||||
- `TPM2B_PRIVATE outPrivate` (optional)
|
||||
- `TPM2B_PUBLIC outPublic`
|
||||
- `TPM2B_NAME name`
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 3: Commands, section 12.9](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
|
41
TPM-Commands/TPM2_CreatePrimary.md
Normal file
41
TPM-Commands/TPM2_CreatePrimary.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# `TPM2_CreatePrimary()`
|
||||
|
||||
This command creates a primary key object.
|
||||
|
||||
The created object can then be loaded with [`TPM2_Load()`](TPM2_Load.md).
|
||||
|
||||
To decide whether to use [`TPM2_CreateLoaded()`](TPM2_CreateLoaded.md),
|
||||
[`TPM2_Create()`](TPM2_Create.md), or
|
||||
[`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) refer to table 28 in
|
||||
section 2.7 of the [TCG TPM Library part 1:
|
||||
Architecture](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf).
|
||||
|
||||
If you need to `TPM2_CertifyCreation()` that a TPM created some object,
|
||||
you must use [`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) or
|
||||
[`TPM2_Create()`](TPM2_Create.md).
|
||||
|
||||
If you need to seal the object to a PCR selection, you must use
|
||||
[`TPM2_CreatePrimary()`](TPM2_CreatePrimary.md) or
|
||||
[`TPM2_Create()`](TPM2_Create.md).
|
||||
|
||||
If you need to create a derived object, you must use
|
||||
[`TPM2_CreateLoaded()`](TPM2_CreateLoaded.md).
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_RH_HIERARCHY+ primaryHandle`
|
||||
- `TPM2B_TEMPLATE inPublic`
|
||||
- `TPM2B_DATA outsideInfo`
|
||||
- `TPML_PCR_SELECTION creationPCR`
|
||||
|
||||
## Outputs (success case)
|
||||
|
||||
- `TPM_HANDLE objectHandle`
|
||||
- `TPM2B_CREATION_DATA creationData`
|
||||
- `TPM2B_DIGEST creationHash`
|
||||
- `TPMT_TK_CREATION creationTicket`
|
||||
- `TPM2B_NAME name`
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 3: Commands, section 24.1](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
25
TPM-Commands/TPM2_Duplicate.md
Normal file
25
TPM-Commands/TPM2_Duplicate.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# `TPM2_Duplicate()`
|
||||
|
||||
`TPM2_Duplicate()` wraps a key, typically encrypting it to a public key
|
||||
for a key on a remote TPM.
|
||||
|
||||
I.e., this is used to export a wrapped key for some target, typically a
|
||||
remote TPM.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_DH_OBJECT objectHandle` (handle for key to encrypt with)
|
||||
- `TPMI_DH_OBJECT newParentHandle` (optional; handle for key to wrap to -- "Only the public area of newParentHandle is required to be loaded")
|
||||
- `TPM2B_DATA encryptionKeyIn` (optional; symmetric key to encrypt with)
|
||||
- `TPMT_SYM_DEF_OBJECT+ symmetricAlg` ("definition for the symmetric algorithm to be used for the inner wrapper")
|
||||
|
||||
## Outputs (success case)
|
||||
|
||||
- `TPM2B_DATA encryptionKeyOut`
|
||||
- `TPM2B_PRIVATE duplicate`
|
||||
- `TPM2B_ENCRYPTED_SECRET outSymSeed`
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 3: Commands, section 18.4](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
|
22
TPM-Commands/TPM2_Import.md
Normal file
22
TPM-Commands/TPM2_Import.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# `TPM2_Import()`
|
||||
|
||||
`TPM2_Import()` reads a wrapped key produced by
|
||||
[`TPM2_Duplicate()`](TPM2_Duplicate.md) and outputs a blob that can be
|
||||
saved and later loaded with [`TPM2_Load()`](TPM2_Load.md).
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPM2B_DATA encryptionKey` (optional; symmetric key to decrypt with)
|
||||
- `TPM2B_PUBLIC objectPublic`
|
||||
- `TPM2B_PRIVATE duplicate`
|
||||
- `TPM2B_ENCRYPTED_SECRET inSymSeed`
|
||||
- `TPMT_SYM_DEF_OBJECT+ symmetricAlg`
|
||||
|
||||
## Outputs (success case)
|
||||
|
||||
- `TPM2B_PRIVATE outPrivate`
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 3: Commands, section 13.3](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
|
19
TPM-Commands/TPM2_Load.md
Normal file
19
TPM-Commands/TPM2_Load.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# `TPM2_Load()`
|
||||
|
||||
`TPM2_Load()` loads a saved key.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_DH_OBJECT parentHandle`
|
||||
- `TPM2B_PRIVATE inPrivate`
|
||||
- `TPM2B_PUBLIC inPublic`
|
||||
|
||||
## Outputs (success case)
|
||||
|
||||
- `TPM_HANDLE objectHandle`
|
||||
- `TPM2B_NAME name`
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 3: Commands, section 12.2.2](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
|
89
TPM-Commands/TPM2_MakeCredential.md
Normal file
89
TPM-Commands/TPM2_MakeCredential.md
Normal file
|
@ -0,0 +1,89 @@
|
|||
# `TPM2_MakeCredential()`
|
||||
|
||||
`TPM2_MakeCredential()` and
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md) provide a
|
||||
mechanism by which an application can send secrets to a TPM-using
|
||||
application. This mechanism is asymmetric encryption/decryption with
|
||||
support for an authorization policy of the sender's choice.
|
||||
|
||||
`TPM2_MakeCredential()` takes an a public key (typically the endorsement
|
||||
key's public key), the [cryptographic name of an
|
||||
object](/Intro/README.md#Cryptographic-Object-Naming) in a TPM
|
||||
identified by that the given public key, and a small secret called a
|
||||
`credential`, and it encrypts `{name, credential}` to the given public
|
||||
key.
|
||||
|
||||
The object name input parameter, being a name, binds an optional
|
||||
authorization policy that
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md) will enforce.
|
||||
|
||||
`TPM2_MakeCredential()` can be implemented entirely in software, as it
|
||||
uses no secret, TPM-resident key material. All the interesting
|
||||
semantics are on the
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md) side.
|
||||
|
||||
Together with [`TPM2_Quote()`](TPM2_Quote.md) and
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md), this function
|
||||
can be used to implement attestation protocols.
|
||||
|
||||
A typical use is to encrypt an AES key to an `EKpub`, then encrypt a
|
||||
large secret payload in the AES key, then sending the outputs of
|
||||
`TPM2_MakeCredential()` and the encrypted large secret payload. The
|
||||
peer receives these items and calls
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md) to recover the
|
||||
AES key, then decrypts the large ciphertext payload to recover the large
|
||||
cleartext secret.
|
||||
|
||||
> NOTE: The `objectName` input names a key object that must present on
|
||||
> the destination TPM, and the `objectName` is included in the plaintext
|
||||
> that is encrypted to the public key identified by `handle`, _but_ none
|
||||
> of the key material of `objectName` is used to key any cryptographic
|
||||
> operations in `TPM2_MakeCredential()`, and therefore neither is the
|
||||
> private area of `objectName` on the destination TPM used in any
|
||||
> cryptographic operations in
|
||||
> [`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md).
|
||||
>
|
||||
> This means that the key named by `objectName` can even be a
|
||||
> universally-well-known key. The only part of that key that truly
|
||||
> matters is the policy digest named in the public area of `objectName`.
|
||||
|
||||
## Authorization
|
||||
|
||||
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md) checks the
|
||||
authorization of the caller to perform this operation by enforcing the
|
||||
sender's policy named by the sender's `objectName`. See
|
||||
[here](TPM2_ActivateCredential.md) for details.
|
||||
|
||||
Some possible authorization policies to enforce include:
|
||||
|
||||
- that some non-resettable PCR has not been extended since boot
|
||||
|
||||
This allows the recipient to extend that PCR immediately after
|
||||
activating the credential to prevent the attestation protocol from
|
||||
being used again without rebooting.
|
||||
|
||||
- user authentication / attended boot
|
||||
|
||||
The policy could require physical presence, authentication of a user
|
||||
with biometrics and/or a smartcard and/or a password.
|
||||
|
||||
- locality
|
||||
|
||||
## Inputs
|
||||
|
||||
- `TPMI_DH_OBJECT handle` (public key to encrypt to, typically a remote TPM's EKpub)
|
||||
- `TPM2B_DIGEST credential` (not necessarily a digest, but a small [digest-sized] secret)
|
||||
- `TPM2B_NAME objectName` (name of object resident on the same TPM as `handle` that `TPM2_ActivateCredential()` will check)
|
||||
|
||||
## Outputs
|
||||
|
||||
- `TPM2B_ID_OBJECT credentialBlob` (ciphertext of encryption of `credential` with a secret "seed" [see below])
|
||||
- `TPM2B_ENCRYPTED_SECRET secret` (ciphertext of encryption of a "seed" to `handle`)
|
||||
|
||||
## References
|
||||
|
||||
- [TCG TPM Library part 1: Architecture, section 24](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf)
|
||||
- [TCG TPM Library part 2: Structures](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part2_Structures_pub.pdf)
|
||||
- [TCG TPM Library part 3: Commands, section 13](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)
|
||||
- [TCG TPM Library part 3: Commands Code, section 13](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_code_pub.pdf)
|
||||
|