Merge pull request #7 from nicowilliams/master

Address comments by Trammell Hudson about attestation
This commit is contained in:
Dimitar Tomov 2021-05-10 11:52:41 +03:00 committed by GitHub
commit 8b064bcf4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 406 additions and 39 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View file

@ -0,0 +1,20 @@
@startuml
participant TPM as T
participant Client as C
participant Server as S
participant ServerSimTPM as ST
title Four-message (two round trips) attestation protocol
C -> C: timestamp = gettimeofday();
C --> T: TPM2_Quote(AK, set-of-all-PCRs, timestamp)
T --> C: quote=Signed_AK({hash-of-PCRs, misc, timestamp})
C -> S: [ID], EKpub, [EKcert], AKpub,\nPCRs, eventlog, timestamp, quote
S -> S: check that timestamp is recent;\ndata = Lookup(EKpub, [EKcert], [ID]);\n[Validate(EKcert)];\ncompute PCRs hash from eventlog and PCRs;\nvalidate quote;\nsession_key = genkey();\nAKcert = CA_Certify(AKpub, data.ID, AKtbscert);\nticket = {vno, Encrypt_server_secret_key({timestamp,\n\t\t\tgettimeofday(),\n\t\t\tsession_key})}
S --> ST: TPM2_MakeCredential(EKpub, AKpub, session_key)
ST --> S: credentialBlob, secret
S -> C: credentialBlob, secret, ticket
C --> T: TPM2_ActivateCredential(AKhandle, EKhandle,\n\t\t\t\t\tcredentialBlob, secret)
T --> C: certInfo = session_key
C -> C: PoP = HMAC_session_key(ticket)
S -> C: Encrypt_session_key(stuff =\n\t\t\t\t\t\t{AKcert, data.for_client})
C -> C: {AKcert, secrets} =\n\t\tDecrypt_session_key(stuff)
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View file

@ -0,0 +1,19 @@
@startuml
participant TPM as T
participant Client as C
participant Server as S
participant ServerSimTPM as ST
title Three-message (1.5 round trips) attestation protocol w/ Proof-of-Possession
C -> C: timestamp = gettimeofday();
C --> T: TPM2_Quote(AK, set-of-all-PCRs, timestamp)
T --> C: quote=Signed_AK({hash-of-PCRs, misc, timestamp})
C -> S: [ID], EKpub, [EKcert], AKpub,\nPCRs, eventlog, timestamp, quote
S -> S: check that timestamp is recent;\ndata = Lookup(EKpub, [EKcert], [ID]);\n[Validate(EKcert)];\ncompute PCRs hash from eventlog and PCRs;\nvalidate quote;\nsession_key = genkey();\nAKcert = CA_Certify(AKpub, data.ID, AKtbscert);\nstuff = Encrypt_session_key({AKcert,\n\t\t\t\t\tdata.for_client})
S --> ST: TPM2_MakeCredential(EKpub, AKpub, session_key)
ST --> S: credentialBlob, secret
S -> C: credentialBlob, secret, stuff
C --> T: TPM2_ActivateCredential(AKhandle, EKhandle,\n\t\t\t\t\tcredentialBlob, secret)
T --> C: certInfo = session_key
C -> C: {AKcert, secrets} =\n\t\tDecrypt_session_key(stuff);
C -> S: {AKcert, PoP = Digest(AKcert)}
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View file

@ -0,0 +1,18 @@
@startuml
participant TPM as T
participant Client as C
participant Server as S
participant ServerSimTPM as ST
title Two-message (one round trip) attestation protocol
C -> C: timestamp = gettimeofday();
C --> T: TPM2_Quote(AK, set-of-all-PCRs, timestamp)
T --> C: quote=Signed_AK({hash-of-PCRs, misc, timestamp})
C -> S: [ID], EKpub, [EKcert], AKpub,\nPCRs, eventlog, timestamp, quote
S -> S: check that timestamp is recent;\ndata = Lookup(EKpub, [EKcert], [ID]);\n[Validate(EKcert)];\ncompute PCRs hash from eventlog and PCRs;\nvalidate quote;\nsession_key = genkey();\nAKcert = CA_Certify(AKpub, data.ID, AKtbscert);\nstuff = Encrypt_session_key({AKcert,\n\t\t\t\t\tdata.for_client})
S --> ST: TPM2_MakeCredential(EKpub, AKpub, session_key)
ST --> S: credentialBlob, secret
S -> C: credentialBlob, secret, stuff
C --> T: TPM2_ActivateCredential(AKhandle, EKhandle,\n\t\t\t\t\tcredentialBlob, secret)
T --> C: certInfo = session_key
C -> C: {AKcert, secrets} =\n\t\tDecrypt_session_key(stuff);
@enduml

View file

@ -12,29 +12,55 @@ A computer can use a TPM to demonstrate:
Possible outputs of succesful attestation: Possible outputs of succesful attestation:
- encrypted filesystems getting unlocked with the help of an - authorize client to join its network
attestation server
- other secrets (e.g., credentials for various authentication systems) - delivery of configuration metadata to the client
- issuance of X.509 certificate(s) for TPM-resident public keys - unlocking of storage / filesystems on the client
For servers these certificates would have `dNSName` subject - delivery of various secrets, such credentials for various authentication systems:
alternative names (SANs).
For a user device such a certificate might have a subject name and/or - issuance of X.509 certificate(s) for TPM-resident attestaion
SANs identifying the user. public keys
For servers these certificates would have `dNSName` subject
alternative names (SANs).
For a user device such a certificate might have a subject name
and/or SANs identifying the user or device.
- issuance of non-PKIX certificates (e.g., OpenSSH-style certificates)
- issuance of Kerberos host-based service principal long-term keys
("keytabs")
- service account tokens
- etc.
- client state tracking
- etc.
Possible outputs of unsuccessful attestation: Possible outputs of unsuccessful attestation:
- alerting - alerting
- diagnostics (e.g., which PCR extensions in the PCR quote and eventlog - diagnostics (e.g., which PCR extensions in the PCR quote and eventlog
are not recognized) are not recognized, which then might be used to determine what
firmware / OS updates a client has installed, or that it has been
compromised)
In this tutorial we'll focus on attestion of servers in an enterprise
environment. However, the concepts described here are applicable to
other environments, such as IoTs and personal devices, where the
attestation database could be hosted on a user's personal devices for
use in joining new devices to the user's set of devices, or for joining
new IoTs to the user's SOHO network.
# Attestation Protocols # Attestation Protocols
Attestation is done by a computer with a TPM interacting with an Attestation is done by a client computer with a TPM interacting with an
attestation service over a network. This requires a network protocol attestation service over a network. This requires a network protocol
for attestation. for attestation.
@ -91,6 +117,27 @@ EKpub and AKpub will happen via
[`TPM2_MakeCredential()`](TPM2_MakeCredential.md) / [`TPM2_MakeCredential()`](TPM2_MakeCredential.md) /
[`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md). [`TPM2_ActivateCredential()`](TPM2_ActivateCredential.md).
Note that the [`TPM2_Quote()`](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
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
PCR digest signed in the quote). `TPM2_Quote()` signs more than just a
digest of the selected PCRs. `TPM2_Quote()` signs all of:
- digest of selected PCRs
- caller-provided extra data (e.g., a cookie/nonce/timestamp/...),
- the TPM's firmware version number,
- `clock` (the TPM's time since startup),
- `resetCount` (an indirect indicator of reboots),
- `restartCount` (an indirect indicator of suspend/resume events)
- and `safe` (a boolean indicating whether the `clock` might have ever
gone backwards).
## Binding of Other Keys to EKpub ## Binding of Other Keys to EKpub
The semantics of [`TPM2_MakeCredential()`](TPM2_MakeCredential.md) / The semantics of [`TPM2_MakeCredential()`](TPM2_MakeCredential.md) /
@ -143,7 +190,9 @@ Let's start with few observations and security considerations:
- Some replay protection or freshness indication for client requests is - Some replay protection or freshness indication for client requests is
needed. A stateful method of doing this is to use a server-generated needed. A stateful method of doing this is to use a server-generated
nonce. A stateless method is to use a timestamp. nonce (as an encrypted state cookie embedding a timestamp). A
stateless method is to use a timestamp and reject requests with old
timestamps.
- Replay protection of server to client responses is mostly either not - 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()`](TMP2_MakeCredential.md)
@ -176,6 +225,33 @@ Let's start with few observations and security considerations:
have to be sent may not fit on a URI local part or URI query have to be sent may not fit on a URI local part or URI query
parameters, therefore HTTP `POST` is the better option. parameters, therefore HTTP `POST` is the better option.
### Error Cases Not Shown
Note that error cases are not shown in the protocols described below.
Naturally, in case of error the attestation server will send a suitable
error message back to the client.
### Databases, Log Sinks, and Dashboarding / Alerting Systems Not Shown
In order to simplify the protocol diagrams below, interactions with
databases, log sinks, and alerting systems are not shown.
A typical attestation service will, however, have interactions with
those components, some or all of which might even be remote:
- attestation database
- log sinks
- dashboarding / alerting
If an attestation service must be on the critical path for booting an
entire datacenter, it may be desirable for the attestation service to be
able to run with no remote dependencies, at least for some time. This
means, for example, that the attestation database should be locally
available and replicated/synchronized only during normal operation. It
also means that there should be a local log sink that can be sent to
upstream collectors during normal operation.
### Single Round Trip Attestation Protocol Patterns ### Single Round Trip Attestation Protocol Patterns
An attestation protocol need not complete proof-of-possession An attestation protocol need not complete proof-of-possession
@ -195,11 +271,13 @@ protocol:
``` ```
<client knows a priori what PCRs to quote, possibly all, saving a round trip> <client knows a priori what PCRs to quote, possibly all, saving a round trip>
CS0: Signed_AK({timestamp, [ID], EKpub, [EKcert], CS0: [ID], EKpub, [EKcert], AKpub, PCRs, eventlog, timestamp,
AKpub, PCR_quote, eventlog}) TPM2_Quote(AK, PCRs, extra_data)=Signed_AK({hash-of-PCRs, misc, extra_data})
SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key), SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key),
Encrypt_session_key({AKcert, filesystem_keys, etc.})} Encrypt_session_key({AKcert, filesystem_keys, etc.})}
<extra_data includes timestamp>
<subsequent client use of AK w/ AKcert, or of credentials made <subsequent client use of AK w/ AKcert, or of credentials made
available by dint of being able to access filesystems unlocked by available by dint of being able to access filesystems unlocked by
SC0, demonstrate that the client has attested successfully> SC0, demonstrate that the client has attested successfully>
@ -207,6 +285,11 @@ protocol:
(`ID` might be, e.g., a hostname.) (`ID` might be, e.g., a hostname.)
![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).)
The server will validate that the `timestamp` is near the current time, The server will validate that the `timestamp` is near the current time,
the EKcert (if provided, else the EKpub), the signature using the the EKcert (if provided, else the EKpub), the signature using the
asserted (but not yet bound to the EKpub) AKpub, then it will validate asserted (but not yet bound to the EKpub) AKpub, then it will validate
@ -218,26 +301,67 @@ The client obtains those items IFF (if and only if) the AK is resident
in the same TPM as the EK, courtesy of `TPM2_ActivateCredential()`'s in the same TPM as the EK, courtesy of `TPM2_ActivateCredential()`'s
semantics. semantics.
NOTE well that in this example it is *essential* that the AKcert not be NOTE well that in single round trip attestation protocols using only
logged in any public place since otherwise an attacker can make and send decrypt-only EKs it is *essential* that the AKcert not be logged in any
`CS0` using a non-TPM-resident AK and any TPM's EKpub/EKcert known to public place since otherwise an attacker can make and send `CS0` using a
the attacker, and then it may recover the AK certificate from the log in non-TPM-resident AK and any TPM's EKpub/EKcert known to the attacker,
spite of being unable to recover the AK certificate from `SC1`! and then it may recover the AK certificate from the log in spite of
being unable to recover the AK certificate from `SC1`!
Alternatively, a single round trip attestation protocol can be Alternatively, a single round trip attestation protocol can be
implemented as an optimization to a two round trip protocol when the AK implemented as an optimization to a two round trip protocol when the AK
is persisted both, in the client TPM and in the attestation service's is persisted both, in the client TPM and in the attestation service's
database: database:
``` ```
<having previously successfully enrolled AKpub and bound it to EKpub...> <having previously successfully enrolled AKpub and bound it to EKpub...>
CS0: Signed_AK({timestamp, AKpub, PCR_quote, eventlog}) CS0: timestamp, AKpub, PCRs, eventlog,
TPM2_Quote(AK, PCRs, extra_data)=Signed_AK({hash-of-PCRs, misc, extra_data})
SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key), SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key),
Encrypt_session_key({AKcert, filesystem_keys, etc.})} Encrypt_session_key({AKcert, filesystem_keys, etc.})}
``` ```
### Three-Message Attestation Protocol Patterns
A single round trip protocol using encrypt-only EKpub will not
demonstrate proof of possession immediately, but later on when the
certified AK is used elsewhere. A proof-of-possession (PoP) may be
desirable anyways for monitoring and alerting purposes.
```
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),
Encrypt_session_key({AKcert, filesystem_keys, etc.})}
CS1: AKcert, Signed_AK(AKcert)
```
![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).)
NOTE well that in this protocol, like single round trip attestation
protocols using only decrypt-only EKs, it is *essential* that the AKcert
not be logged in any public place since otherwise an attacker can make
and send `CS0` using a non-TPM-resident AK and any TPM's EKpub/EKcert
known to the attacker, and then it may recover the AK certificate from
the log in spite of being unable to recover the AK certificate from
`SC1`!
If such a protocol is instantiated over HTTP or TCP, it will really be
more like a two round trip protocol:
```
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),
Encrypt_session_key({AKcert, filesystem_keys, etc.})}
CS1: AKcert, Signed_AK(AKcert)
SC1: <empty>
```
### Two Round Trip Stateless Attestation Protocol Patterns ### Two Round Trip Stateless Attestation Protocol Patterns
We can add a round trip to the protocol in the previous section to make We can add a round trip to the protocol in the previous section to make
@ -252,11 +376,13 @@ back to the server rather than a secret key possesion of which is proven
with symmetriclly-keyed cryptographic algorithms. with symmetriclly-keyed cryptographic algorithms.
``` ```
CS0: Signed_AK({timestamp, [ID], EKpub, [EKcert], CS0: [ID], EKpub, [EKcert], AKpub, PCRs, eventlog, timestamp,
AKpub, PCR_quote, eventlog}) TPM2_Quote(AK, PCRs, extra_data)=Signed_AK({hash-of-PCRs, misc, extra_data})
SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key), ticket} SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key), ticket}
CS1: {ticket, MAC_session_key(CS0), CS0} CS1: {ticket, MAC_session_key(CS0), CS0}
SC1: Encrypt_session_key({AKcert, filesystem_keys, etc.}) SC1: Encrypt_session_key({AKcert, filesystem_keys, etc.})
<extra_data includes timestamp>
``` ```
where `session_key` is an ephemeral secret symmetric authenticated where `session_key` is an ephemeral secret symmetric authenticated
@ -267,6 +393,8 @@ encryption key, and `ticket` is an authenticated encrypted state cookie:
MAC_session_key(CS0)})} MAC_session_key(CS0)})}
``` ```
![Protocol Diagram](Protocol-Four-Messages.png)
where `server_secret_key` is a key known only to the attestation service where `server_secret_key` is a key known only to the attestation service
and `vno` identifies that key (in order to support key rotation without and `vno` identifies that key (in order to support key rotation without
having to try authenticated decryption twice near key rotation events). having to try authenticated decryption twice near key rotation events).
@ -309,6 +437,10 @@ An HTTP API binding for this protocol could look like:
Response: SC1 Response: SC1
``` ```
Here the attestation happens in the first round trip, but the proof of
possession is completed in the second, and the delivery of secrets and
AKcert also happens in the second round trip.
### Actual Protocols: ibmacs ### Actual Protocols: ibmacs
The [`IBM TPM Attestation Client Server`](https://sourceforge.net/projects/ibmtpm20acs/) The [`IBM TPM Attestation Client Server`](https://sourceforge.net/projects/ibmtpm20acs/)
@ -358,7 +490,20 @@ to two round trips.
### Actual Protocols: safeboot.dev ### Actual Protocols: safeboot.dev
(TBD) ```
CS0: <empty>
SC0: nonce, PCR_list
CS1: [ID], EKpub, [EKcert], AKpub, PCRs, eventlog, nonce,
TPM2_Quote(AK, PCRs, extra_data)=Signed_AK({hash-of-PCRs, misc, extra_data})
SC1: {TPM2_MakeCredential(EKpub, AKpub, session_key),
Encrypt_session_key({filesystem_keys})}
```
Nonce validation is currently not well-developed in Safeboot.
If a timestamp is used instead of a nonce, and if the client assumes all
PCRs are desired, then this becomes a one round trip protocol.
An AKcert will be added to the Safeboot protocol soon.
### Actual Protocols: ... ### Actual Protocols: ...
@ -383,9 +528,8 @@ proof of possession non-interactively, whereas asymmetric encryption
requires interaction to prove possession: requires interaction to prove possession:
``` ```
CS0: Signed_AK({timestamp, [ID], EKpub, [EKcert], CS0: timestamp, [ID], EKpub, [EKcert], AKpub, PCRs, eventlog,
AKpub, TPM2_Certify(EKpub, AKpub), TPM2_Certify(EKpub, AKpub), TPM2_Quote()
PCR_quote, eventlog})
SC0: AKcert SC0: AKcert
``` ```
@ -393,11 +537,9 @@ If secrets need to be sent back, then a decrypt-only EK also neds to be
used: used:
``` ```
CS0: Signed_AK({timestamp, [ID], CS0: timestamp, [ID], EKpub_signing, EKpub_encrypt,
EKpub_signing, EKpub_encrypt, [EKcert_signing], [EKcert_encrypt], AKpub, PCRs, eventlog,
[EKcert_signing], [EKcert_encrypt], TPM2_Certify(EKpub, AKpub), TPM2_Quote()
AKpub, TPM2_Certify(EKpub, AKpub),
PCR_quote, eventlog})
SC0: {TPM2_MakeCredential(EKpub_encrypt, AKpub, session_key), SC0: {TPM2_MakeCredential(EKpub_encrypt, AKpub, session_key),
Encrypt_session_key({AKcert, filesystem_keys, etc.})} Encrypt_session_key({AKcert, filesystem_keys, etc.})}
``` ```
@ -408,6 +550,7 @@ Attestation servers need to keep some long-term state:
- binding of `EKpub` and `ID` - binding of `EKpub` and `ID`
- PCR validation profile(s) for each identified client - PCR validation profile(s) for each identified client
- resetCount (for reboot detection)
Log-like attestation state: Log-like attestation state:
@ -431,16 +574,138 @@ Things to log:
attestation protocols above -- do not log AKcerts in public places attestation protocols above -- do not log AKcerts in public places
when using single round trip attestation protocols!) when using single round trip attestation protocols!)
## Long-Term State Created by Attestation Services ## Long-Term State Created or Updated by Attestation Services
An attestation service might support creation of host&lt;-&gt;EKpub - An attestation service might support creation of host&lt;-&gt;EKpub
bindings on a first-come-first-served basis. bindings on a first-come-first-served basis. In this mode the
attestation server might validate an EKcert and that the desired
hostname has not been bound to an EK, then create the binding.
An attestation service might support deletion of host PCR validation - An attestation service might support deletion of host PCR validation
profiles that represent past states upon validation of PCR quotes using profiles that represent past states upon validation of PCR quotes
newer profiles. This could be used to permit firmware and/or operating using newer profiles. This could be used to permit firmware and/or
system upgrades and then disallow downgrades after evidence of operating system upgrades and then disallow downgrades after evidence
successful upgrade. of successful upgrade.
- An attestation service might keep track of client reboots so as to:
- revoke old AKcerts when the client reboots (but note that this is
really not necessary if we trust the client's TPM, since then the
previous AKs will never be usable again)
- alert if the reboot count ever goes backwards
## Schema for Attestation Server Database
A schema for the attestation server's database entries might look like:
```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>",
"secrets": "<secrets>",
"resetCount": "<resetCount value from last quote>"
}
```
The attestation server's database should have two lookup keys:
- EKpub
- hostname
The attestation server's database's entry for any client should provide,
de minimis:
- a way to validate the root of trust measurements in the client's
quoted PCRs, for which two methods are possible:
- save the PCRs quoted last as the ones expected next time
- or, name profiles for validating firmware RTM PCRs and profiles
for validating operating system RTM PCRs
A profile for validating PCRs should contain a set of expected extension
values for each of a set of PCRs. The attestation server can then check
that the eventlog submitted by the client lists exactly those extension
values and no others. PCR extension order in the eventlog probably
doesn't matter here. If multiple profiles are named, then one of those
must match -- this allows for upgrades and downgrades.
```JSON
{
"profile_name":"SomeProfile",
"values":[
{
"PCR":0,
"values":["aaaaaaa","bbbbbb","..."]
},
{
"PCR":1,
"values":["ccccccc","dddddd","..."]
}
]
}
```
Using the PCR values from the previous attestation makes upgrades
tricky, probably requiring an authenticated and authorized administrator
to bless new PCR values after an upgrade. A client that presents a PCR
quote that does not match the previous one would cause the
`proposed_PCRs` field to be updated but otherwise could not continue,
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
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.
For break-glass recover, the simplest thing to do is to store
`Encrypt_backupKey({EKpub, hostname, secrets})`, where `backupKey` is an
asymmetric key whose private key is stored offline (e.g., in a safe, or
in an offline HSM). To break the glass and recover the key, just bring
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:
- Store `TPM2_MakeCredential(EKpub, someObjectName, key0), Encrypt_key0(secrets)`.
In this mode the server sends the client the stored data, then client
gets to recreate `someObject` (possibly by loading a saved object) 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.
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.
- 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.
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.
- A hybrid of the previous two options, where the server stores a
secret PCR extension value wrapped with `TPM2_MakeCredential()`.
Other ideas?
# References # References

45
Attestation/TPM2_Quote.md Normal file
View file

@ -0,0 +1,45 @@
# `TPM2_Quote()`
`TPM2_Quote()` computes a hash of the PCRs selected by the caller, and
signs that hash, some additional metadata, and any extra data provided
by the caller, with a signing key named by the caller. The caller must
have access to that key, naturally.
The PCRs' values are NOT included in the quote produced by
`TPM2_Quote()`. Instead, an attestation service can review an unsigned
eventlog to ensure it leads to the same values as unsigned PCR values
also provided by the attestation client, and then the attestation
service can verify that the hash of the PCR values is indeed signed by
the quote supplied by the client.
## Inputs
- `TPMI_DH_OBJECT sigHandle` (handle for an AK)
- `TPM2B_DATA qualifyingData` (extra data)
- `TPMT_SIG_SCHEME inScheme` ("signing scheme to use if the schemefor signHandleis `TPM_ALG_NULL`")
- `TPML_PCR_SELECTION PCRselect` (set of PCRs to quote)
## Outputs (success case)
- `TPM2B_ATTEST quoted`
- `TPMT_SIGNATURE signature`
Where `TPM2B_ATTEST` is basically a `TPMS_ATTEST`, which contains the
following fields:
- `TPM_GENERATED magic`
- `TPMI_ST_ATTEST type`
- `TPM2B_NAME signer` (name of AK)
- `TPM2B_DATA extraData` ("external information supplied by caller")
- `TPMS_CLOCK_INFO clockInfo` ("Clock, resetCount, restartCount, and Safe")
- `UINT64 firmwareVersion`
- `TPMU_ATTEST attested`, a discriminated union with the
`TPMS_QUOTE_INFO` arm (indicated by the `TPM_ST_ATTEST_QUOTE`
discriminant value), which contains:
- `TPML_PCR_SELECTION pcrSelect` (the set of PCRs digested by `pcrDigest`)
- `TPM2B_DIGEST pcrDigest` (the digest of the PCRs indicated by `pcrSelect`)
## References
- [TCG TPM Library part 3: Commands, section 18.4](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)