Merge pull request #6 from nicowilliams/master

Update attestation tutorial: add links and details
This commit is contained in:
Dimitar Tomov 2021-05-04 12:44:46 +03:00 committed by GitHub
commit fd056d8ca2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 270 additions and 15 deletions

View file

@ -4,26 +4,39 @@ A computer can use a TPM to demonstrate:
- possession of a valid TPM
- it being in a trusted state by dint of having executed (possibly
only) trusted code to get to that state
- it being in a trusted state by dint of having executed trusted code
to get to that state
- possession of objects such as asymmetric keypairs being resident on
the TPM (objects that might be used in the attestation protocol)
Possible results of succesful attestation:
Possible outputs of succesful attestation:
- encrypted filesystems getting unlocked with the help of an
attestation server
- other secrets (e.g., credentials for various authentication systems)
- issuance of X.509 certificate(s) for TPM-resident public keys
- other secrets (e.g., credentials for various authentication systems)
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.
Possible outputs of unsuccessful attestation:
- alerting
- diagnostics (e.g., which PCR extensions in the PCR quote and eventlog
are not recognized)
# Attestation Protocols
Attestation is done by a computer with a TPM interacting with an
attestation service over a network. This requires an attestation
protocol.
attestation service over a network. This requires a network protocol
for attestation.
## Notation
@ -36,6 +49,9 @@ protocol.
- `CSn` == client-to-server message number `n`
- `SCn` == server-to-client message number `n`
- `{stuff, more_stuff}` == a sequence of data, a "struct"
- `{"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
## Proof of Possession of TPM
@ -63,7 +79,7 @@ plain asymmetric decryption.
Trusted state is attested by sending a quote of Platform Configuration
Registers (PCRs) and the `eventlog` describing the evolution of the
system's state from power-up to the current state. The attestation
service vallidates the digests used to extend the various PCRs,
service validates the digests used to extend the various PCRs,
and perhaps the sequence in which they appear in the eventlog, typically
by checking a list of known-trusted digests (these are, for example,
checksums of firmware images).
@ -104,25 +120,89 @@ knowledge of the secret sent by the server. Proof of possession can
also be delayed to an eventual use of that secret, allowing for single
round trip attestation.
## Attestation Protocol Patterns
## Binding hosts to TPMs
### Single Round Trip Attestation Protocols
(TBD. Talk about IDevID or similar certificates binding hosts to their
factory-installed TPMs, and how to obtain those from vendors.)
## Attestation Protocol Patterns and Actual Protocols (decrypt-only EKs)
Note: all the protocols described below are based on decrypt-only TPM
endorsement keys.
Let's start with few observations and security considerations:
- Clients need to know which PCRs to quote. E.g., the [Safe Boot](https://safeboot.dev/)
project and the [IBM sample attestation client and server](https://sourceforge.net/projects/ibmtpm20acs/)
have the client ask for a list of PCRs and then the client quotes
just those.
But clients could just quote all PCRs. It's more data to send, but
probably not a big deal, and it saves a round trip if there's no need
to ask what PCRs to send.
- Some replay protection or freshness indication for client requests is
needed. A stateful method of doing this is to use a server-generated
nonce. A stateless method is to use a timestamp.
- Replay protection of server to client responses is mostly either not
needed or implicitly provided by [`TPM2_MakeCredential()`](TMP2_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
authenticate a TPM-running host via its TPM's EKpub.
- Privacy protection of client identifiers may be needed, in which case
TLS may be desired.
- Even if a single round trip attestation protocol is adequate, a
return routability check may be needed to avoid denial of service
attacks. I.e., do not run a single round trip attestation protocol
over UDP without first requiring the client to echo a nonce/cookie.
- Statelessness on the server side is highly desirable, as that should
permit having multiple servers and each of a client's messages can go
to different servers. Conversely, keeping state on the server across
multiple round trips can cause resource exhaustion / denial of
service attack considerations.
- Statelessness maps well onto HTTP / REST. Indeed, attestation
protocol messages could all be idempotent and therefore map well onto
HTTP `GET` requests but for the fact that all the things that may be
have to be sent may not fit on a URI local part or URI query
parameters, therefore HTTP `POST` is the better option.
### Single Round Trip Attestation Protocol Patterns
An attestation protocol need not complete proof-of-possession
immediately if the successful outcome of the protocol has the client
demonstrate possession to other services/peers.
subsequently demonstrate possession to other services/peers. This is a
matter of taste and policy. However, one may want to have
cryptographically secure "client attested successfully" state on the
server without delay, in which case two round trips are the minimum for
an attestation protocol.
In the following example the client obtains a certificate (`AKcert`) for
its AK, filesystem decryption keys, and possibly other things, and
its AKpub, filesystem decryption keys, and possibly other things, and
eventually it will use those items in ways that -by virtue of having
thus been used- demonstrate that it possesses the EK used in the
protocol:
```
<client knows a priori what PCRs to quote, possibly all, saving a round trip>
CS0: Signed_AK({timestamp, [ID], EKpub, [EKcert],
AKpub, PCR_quote, eventlog})
SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key),
Encrypt_session_key({AKcert, filesystem_keys, etc.})}
<subsequent client use of AK w/ AKcert, or of credentials made
available by dint of being able to access filesystems unlocked by
SC0, demonstrate that the client has attested successfully>
```
(`ID` might be, e.g., a hostname.)
@ -144,7 +224,21 @@ logged in any public place since otherwise an attacker can make and send
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`!
### Two Round Trip Attestation Protocols
Alternatively, a single round trip attestation protocol can be
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
database:
```
<having previously successfully enrolled AKpub and bound it to EKpub...>
CS0: Signed_AK({timestamp, AKpub, PCR_quote, eventlog})
SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key),
Encrypt_session_key({AKcert, filesystem_keys, etc.})}
```
### Two Round Trip Stateless Attestation Protocol Patterns
We can add a round trip to the protocol in the previous section to make
the client prove possession of the EK and binding of the AK to the EK
@ -169,13 +263,19 @@ where `session_key` is an ephemeral secret symmetric authenticated
encryption key, and `ticket` is an authenticated encrypted state cookie:
```
ticket = {vno, Encrypt_server_secret_key({session_key, timestamp, MAC_session_key(CS0)})}
ticket = {vno, Encrypt_server_secret_key({session_key, timestamp,
MAC_session_key(CS0)})}
```
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
having to try authenticated decryption twice near key rotation events).
[Note: `ticket` here is not in the sense used by TPM specifications, but
in the sense of "TLS session resumption ticket" or "Kerberos ticket",
and, really, it's just an encrypted state cookie so that the server can
be stateless.]
The attestation server could validate that the `timestamp` is recent
upon receipt of `CS0`. But the attestation server can delay validation
of EKcert, signatures, and PCR quote and eventlog until receipt of
@ -192,9 +292,69 @@ proves possession of in `CS1`, and only then does the server send the
the cost of asymmetric encryption by using the `session_key` to key a
symmetric authenticated cipher.
(The `server_secret_key`, `ticket`, `session_key`, and proof of
possession used in `CS1` could even conform to Kerberos or encrypted JWT
and be used for authentication, possibly with an off-the-shelf HTTP
stack.)
An HTTP API binding for this protocol could look like:
```
POST /get-attestation-ticket
Body: CS0
Response: SC0
POST /attest
Body: CS1
Response: SC1
```
### Actual Protocols: ibmacs
(TBD)
The [`IBM TPM Attestation Client Server`](https://sourceforge.net/projects/ibmtpm20acs/)
(`ibmacs`) open source project has sample code for a "TCG attestation
application".
It implements a stateful (state is kept in a database) attestation and
enrollment protocol over TCP sockets that consists of JSON texts of the
following form, sent prefixed with a 32-bit message length in host byte
order:
```
CS0: {"command":"nonce","hostname":"somehostname",
"userid":"someusername","boottime":"2021-04-29 16:37:06"}
SC0: {"response":"nonce","nonce":"<hex>", "pcrselect":"<hex>", ...}
<nonce is used in production of signed PCR quote>
CS1: {"command":"quote","hostname":"somehostname",
"quoted":"<hex>","signature":"<hex>",
"event1":"<hex>","imaevent0":"<hex>"}
SC1: {"response":"quote"}
CS2: {"command":"enrollrequest","hostname":"somehost",
"tpmvendor":"...","ekcert":"<PEM>","akpub":"<hex(DER)>"}
SC2: {"response":"enrollrequest",
"credentialblob":"<hex of credentialBlob output of TPM2_MakeCredential()>",
"secret":"<hex of secret output of TPM2_MakeCredential()>"}
CS3: {"command":"enrollcert","hostname":"somecert","challenge":"<hex>"}
SC3: {"response":"enrollcert","akcert":"<hex>"}
```
The server keeps state across round trips.
Note that this protocol has *up to* four (4) round trips. Because the
`ibmacs` server keeps state in a database, it should be possible to
elide some of these round trips in attestations subsequent to
enrollment.
The messages of the second and third round trips could be combined since
there should be no need to wait for PCR quote validation before sending
the EKcert and AKpub. The messages of the first round trip too could be
combined with the messages of the second and third round trip by using a
timestamp as a nonce -- with those changes this protocol would get down
to two round trips.
### Actual Protocols: safeboot.dev
@ -204,12 +364,55 @@ symmetric authenticated cipher.
(TBD)
## Attestation Protocol Patterns and Actual Protocols (signing-only EKs)
Some TPMs come provisioned with signing-only endorsement keys in
addition to decrypt-only EKs. For example, vTPMs in Google cloud
provides both, decrypt-only and signing-only EKs.
Signing-only EKs can be used for attestation as well.
[Ideally signing-only EKs can be restricted to force the use of
`TPM2_Certify()`? Restricted signing keys can only sign payloads that
start with a magic value, whereas unrestricted signing keys can sign any
payload.]
Signing-only EKs make single round trip attestation protocols possible
that also provide immediate attestation status because signing provides
proof of possession non-interactively, whereas asymmetric encryption
requires interaction to prove possession:
```
CS0: Signed_AK({timestamp, [ID], EKpub, [EKcert],
AKpub, TPM2_Certify(EKpub, AKpub),
PCR_quote, eventlog})
SC0: AKcert
```
If secrets need to be sent back, then a decrypt-only EK also neds to be
used:
```
CS0: Signed_AK({timestamp, [ID],
EKpub_signing, EKpub_encrypt,
[EKcert_signing], [EKcert_encrypt],
AKpub, TPM2_Certify(EKpub, AKpub),
PCR_quote, eventlog})
SC0: {TPM2_MakeCredential(EKpub_encrypt, AKpub, session_key),
Encrypt_session_key({AKcert, filesystem_keys, etc.})}
```
# Long-Term State Kept by Attestation Services
Attestation servers need to keep some long-term state:
- binding of `EKpub` and `ID`
- PCR validation profile for each identified client
- PCR validation profile(s) for each identified client
Log-like attestation state:
- client attestation status (last time successfully attested, last time
unsuccessfully attested)
The PCR validation profile for a client consists of a set of required
and/or acceptable digests that must appear in each PCR's extension log.
@ -221,6 +424,13 @@ Grub), operating system kernels, `initrd` images, filesystem root hashes
Some of these are obtained by administrators on a trust-on-first-use
(TOFU) basis.
Things to log:
- client attestation attempts and outcomes
- AK certificates issued (WARNING: see note about single round trip
attestation protocols above -- do not log AKcerts in public places
when using single round trip attestation protocols!)
## Long-Term State Created by Attestation Services
An attestation service might support creation of host&lt;-&gt;EKpub
@ -231,3 +441,10 @@ profiles that represent past states upon validation of PCR quotes using
newer profiles. This could be used to permit firmware and/or operating
system upgrades and then disallow downgrades after evidence of
successful upgrade.
# References
- [TCG TPM Library part 1: Architecture, sections 23 and 24](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture_pub.pdf)
- https://sourceforge.net/projects/ibmtpm20acs/
- https://safeboot.dev/
- https://github.com/osresearch/safeboot/

View file

@ -10,3 +10,22 @@ 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)

View file

@ -10,3 +10,22 @@ semantics are on the
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)