mirror of
https://github.com/tpm2dev/tpm.dev.tutorials.git
synced 2024-11-10 01:12:10 +00:00
Update attestation tutorial
This commit is contained in:
parent
79bbeeb759
commit
bccc445326
1 changed files with 104 additions and 41 deletions
|
@ -97,19 +97,21 @@ For more about enrollment see the tutorial specifically for
|
||||||
- `SCn` == server-to-client message number `n`
|
- `SCn` == server-to-client message number `n`
|
||||||
- `{stuff, more_stuff}` == a sequence of data, a "struct"
|
- `{stuff, more_stuff}` == a sequence of data, a "struct"
|
||||||
- `{"key":<value>,...}` == JSON text
|
- `{"key":<value>,...}` == JSON text
|
||||||
- `TPM2_MakeCredential(<args>)` == outputs of calling `TPM2_MakeCredential()` with `args` arguments
|
- `TPM2_Foo(<args>)` == outputs of calling some TPM 2.0 command 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)
|
- `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)
|
- `EK` == endorsement key (the TPM-resident object and its private key)
|
||||||
- `AK` == attestation 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)
|
- `TK` == transport key (the TPM-resident object and its private key)
|
||||||
|
- `WK` == well-known key used only as a `TPM2_ActivateCredential()` activation object, not used for any actual encryption or signing
|
||||||
- `XKpub` == `<X>`'s public key, for some `<X>` purpose
|
- `XKpub` == `<X>`'s public key, for some `<X>` purpose
|
||||||
- `EKpub` == endorsement public key
|
- `EKpub` == `EK` public key
|
||||||
- `AKpub` == attestation public key
|
- `AKpub` == `AK` public key
|
||||||
- `TKpub` == transport public key
|
- `TKpub` == `TK` public key
|
||||||
|
- `WKpub` == `WK` public key
|
||||||
- `XKname` == `<X>`'s cryptographic name, for some `<X>` purpose
|
- `XKname` == `<X>`'s cryptographic name, for some `<X>` purpose
|
||||||
- `EKname` == endorsement key's cryptographic name
|
- `EKname` == `EK`'s cryptographic name
|
||||||
- `AKname` == attestation key's cryptographic name
|
- `AKname` == `AK`'s cryptographic name
|
||||||
|
- `WKname` == `WK`'s cryptographic name
|
||||||
|
|
||||||
## Threat Models
|
## Threat Models
|
||||||
|
|
||||||
|
@ -118,6 +120,7 @@ address:
|
||||||
|
|
||||||
- attestation client impersonation
|
- attestation client impersonation
|
||||||
- attestation server impersonation
|
- attestation server impersonation
|
||||||
|
- replay attacks
|
||||||
- unauthorized firmware and/or OS updates
|
- unauthorized firmware and/or OS updates
|
||||||
- theft or compromise of of attestation servers
|
- theft or compromise of of attestation servers
|
||||||
- theft of client devices or their local storage (e.g., disks, JBODs)
|
- theft of client devices or their local storage (e.g., disks, JBODs)
|
||||||
|
@ -264,9 +267,9 @@ endorsement keys.
|
||||||
|
|
||||||
Let's start with few observations and security considerations:
|
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/)
|
- Clients need to know which PCRs to quote. E.g.,
|
||||||
project and the [IBM sample attestation client and server](https://sourceforge.net/projects/ibmtpm20acs/)
|
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
|
has the client ask for a list of PCRs and then the client quotes
|
||||||
just those.
|
just those.
|
||||||
|
|
||||||
But clients could just quote all PCRs. It's more data to send, but
|
But clients could just quote all PCRs. It's more data to send, but
|
||||||
|
@ -279,25 +282,53 @@ Let's start with few observations and security considerations:
|
||||||
stateless method is to use a timestamp and reject requests with old
|
stateless method is to use a timestamp and reject requests with old
|
||||||
timestamps.
|
timestamps.
|
||||||
|
|
||||||
- Replay protection of server to client responses is mostly either not
|
As well, one can use the `resetCount` from the quote to check if an
|
||||||
needed or implicitly provided by [`TPM2_MakeCredential()`](TPM2_MakeCredential.md)
|
attestation is the first after a reboot or not. Though this does
|
||||||
because `TPM2_MakeCredential()` generates a secret seed that
|
require that the attestation server maintain some writable state
|
||||||
randomizes its outputs even when all the inputs are the same across
|
(namely, the reset count.
|
||||||
multiple calls to it.
|
|
||||||
|
- Replay protection of server to client responses is provided by using
|
||||||
|
a different `AK` each time the client attests. This works because
|
||||||
|
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) binds
|
||||||
|
the `AK` such that
|
||||||
|
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md)
|
||||||
|
will not succeed unless the server used the same `AKname` as the name
|
||||||
|
of the `AK` used by the client.
|
||||||
|
|
||||||
- Ultimately the protocol *must* make use of
|
- Ultimately the protocol *must* make use of
|
||||||
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) and
|
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) and
|
||||||
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md) in order to
|
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md) in order to
|
||||||
authenticate a TPM-running host via its TPM's EKpub.
|
authenticate a TPM-running host via its TPM's EKpub.
|
||||||
|
|
||||||
|
> The same is not true of [`TPM2_Quote()`](/TPM-Commands/TPM2_Quote.md)
|
||||||
|
> because one can build an attestation protocol that does not depend
|
||||||
|
> on signing quotes. Essentially one can simply send an unsigned
|
||||||
|
> reading of the client's TPM's PCRs and clock information and use an
|
||||||
|
> activation object with `adminWithPolicy` set and a `policyDigest`
|
||||||
|
> of a policy that uses the `TPM2_PolicyCounterTimer() and
|
||||||
|
> `TPM2_PolicyPCR()` commands to enforce that the `resetCount` and
|
||||||
|
> the PCRs are as asserted in the protocol. The server can then
|
||||||
|
> construct the same policy to compute the name of the activation
|
||||||
|
> object for
|
||||||
|
> [`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md),
|
||||||
|
> knowing that
|
||||||
|
> [`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md)
|
||||||
|
> will enforce that policy.
|
||||||
|
|
||||||
- Privacy protection of client identifiers may be needed, in which case
|
- Privacy protection of client identifiers may be needed, in which case
|
||||||
TLS may be desired.
|
TLS may be desired. Alternatively, the client could encrypt a
|
||||||
|
session key to a public of the attestation server using
|
||||||
|
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md), and
|
||||||
|
then use the session key to encrypt confidential parameters, thus
|
||||||
|
building something of a TLS-like protocol.
|
||||||
|
|
||||||
- Even if a single round trip attestation protocol is adequate, a
|
- Even if a single round trip attestation protocol is adequate, a
|
||||||
return routability check may be needed to avoid denial of service
|
return routability check may be needed to avoid denial of service
|
||||||
attacks. I.e., do not run a single round trip attestation protocol
|
attacks. I.e., do not run a single round trip attestation protocol
|
||||||
over UDP without first requiring the client to echo a nonce/cookie.
|
over UDP without first requiring the client to echo a nonce/cookie.
|
||||||
|
|
||||||
|
Using TCP effectively provides a return routability check.
|
||||||
|
|
||||||
- Statelessness on the server side is highly desirable, as that should
|
- Statelessness on the server side is highly desirable, as that should
|
||||||
permit having multiple servers and each of a client's messages can go
|
permit having multiple servers and each of a client's messages can go
|
||||||
to different servers. Conversely, keeping state on the server across
|
to different servers. Conversely, keeping state on the server across
|
||||||
|
@ -308,14 +339,20 @@ Let's start with few observations and security considerations:
|
||||||
protocol messages could all be idempotent and therefore map well onto
|
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
|
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
|
have to be sent may not fit on a URI local part or URI query
|
||||||
parameters, therefore HTTP `POST` is the better option.
|
parameters (and `GET` has no request body), therefore HTTP `POST` is
|
||||||
|
needed for its ability to send a request body.
|
||||||
|
|
||||||
### Error Cases Not Shown
|
### Error Cases Not Shown
|
||||||
|
|
||||||
Note that error cases are not shown in the protocols described below.
|
Note that error cases are not shown in the protocols described below.
|
||||||
|
|
||||||
Naturally, in case of error the attestation server will send a suitable
|
Naturally, in case of error the attestation server will send a suitable
|
||||||
error message back to the client.
|
error message back to the client. Providing integrity protection for
|
||||||
|
error messages is tricky, as there will always be some kinds of errors
|
||||||
|
for which integrity protection cannot be provided, but also, there is no
|
||||||
|
natural key with which to sign errors. An actual attestation protocol
|
||||||
|
specification may require that clients know a public key that the server
|
||||||
|
can use to sign its errors with.
|
||||||
|
|
||||||
### Databases, Log Sinks, and Dashboarding / Alerting Systems Not Shown
|
### Databases, Log Sinks, and Dashboarding / Alerting Systems Not Shown
|
||||||
|
|
||||||
|
@ -386,12 +423,12 @@ 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 single round trip attestation protocols using only
|
> NOTE well that in single round trip attestation protocols using only
|
||||||
decrypt-only EKs it is *essential* that the AKcert not be logged in any
|
> decrypt-only EKs it is *essential* that the AKcert not be logged in
|
||||||
public place since otherwise an attacker can make and send `CS0` using a
|
> any public place since otherwise an attacker can make and send `CS0`
|
||||||
non-TPM-resident AK and any TPM's EKpub/EKcert known to the attacker,
|
> using a non-TPM-resident AK and any TPM's EKpub/EKcert known to the
|
||||||
and then it may recover the AK certificate from the log in spite of
|
> attacker, and then it may recover the AK certificate from the log in
|
||||||
being unable to recover the AK certificate from `SC1`!
|
> 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
|
||||||
|
@ -407,6 +444,13 @@ database:
|
||||||
Encrypt_session_key({AKcert, filesystem_keys, etc.})}
|
Encrypt_session_key({AKcert, filesystem_keys, etc.})}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> NOTE: persisting the `AK` means that the `AK` must not have `stClear`
|
||||||
|
> set, which in turn means that it can be used and reused across
|
||||||
|
> reboots, so detecting reboots requires more mutable, synchronized
|
||||||
|
> state on the server to keep track of clients' `resetCount`s. Mutable,
|
||||||
|
> synchronized state complicates distributed databases, so it may not be
|
||||||
|
> desirable.
|
||||||
|
|
||||||
### Three-Message Attestation Protocol Patterns
|
### Three-Message Attestation Protocol Patterns
|
||||||
|
|
||||||
A single round trip protocol using encrypt-only EKpub will not
|
A single round trip protocol using encrypt-only EKpub will not
|
||||||
|
@ -427,13 +471,13 @@ desirable anyways for monitoring and alerting purposes.
|
||||||
(In this diagram we show the use of a TPM simulator on the server side
|
(In this diagram we show the use of a TPM simulator on the server side
|
||||||
for implementing [`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md).)
|
for implementing [`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md).)
|
||||||
|
|
||||||
NOTE well that in this protocol, like single round trip attestation
|
> NOTE well that in this protocol, like single round trip attestation
|
||||||
protocols using only decrypt-only EKs, it is *essential* that the AKcert
|
> protocols using only decrypt-only EKs, it is *essential* that the
|
||||||
not be logged in any public place since otherwise an attacker can make
|
> AKcert not be logged in any public place since otherwise an attacker
|
||||||
and send `CS0` using a non-TPM-resident AK and any TPM's EKpub/EKcert
|
> can make and send `CS0` using a non-TPM-resident AK and any TPM's
|
||||||
known to the attacker, and then it may recover the AK certificate from
|
> EKpub/EKcert known to the attacker, and then it may recover the AK
|
||||||
the log in spite of being unable to recover the AK certificate from
|
> certificate from the log in spite of being unable to recover the AK
|
||||||
`SC1`!
|
> certificate from `SC1`!
|
||||||
|
|
||||||
If such a protocol is instantiated over HTTP or TCP, it will really be
|
If such a protocol is instantiated over HTTP or TCP, it will really be
|
||||||
more like a two round trip protocol:
|
more like a two round trip protocol:
|
||||||
|
@ -575,20 +619,39 @@ to two round trips.
|
||||||
|
|
||||||
### Actual Protocols: safeboot.dev
|
### Actual Protocols: safeboot.dev
|
||||||
|
|
||||||
|
[Safeboot.dev](https://safeboot.dev) uses a single round trip stateless
|
||||||
|
attestation protocol, with a separate, one-time enrollment protocol.
|
||||||
|
|
||||||
```
|
```
|
||||||
CS0: <empty>
|
CS0: [ID], EKpub, [EKcert], AKpub, PCRs, eventlog, timestamp,
|
||||||
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})
|
TPM2_Quote(AK, PCRs, extra_data)=Signed_AK({hash-of-PCRs, misc, extra_data})
|
||||||
SC1: {TPM2_MakeCredential(EKpub, AKpub, session_key),
|
SC0: {TPM2_MakeCredential(EKpub, AKpub, session_key),
|
||||||
Encrypt_session_key({filesystem_keys})}
|
Encrypt_session_key({long-term-secrets-encrypted-to-EKpub})}
|
||||||
|
|
||||||
|
with
|
||||||
|
|
||||||
|
long-term-secrets-encrypted-to-EKpub =
|
||||||
|
[{TPM2_MakeCredential(EKpub, WKname(policy), aes_key0),
|
||||||
|
Encrypt_aes_key0(secret0)},
|
||||||
|
{TPM2_MakeCredential(EKpub, WKname(policy), aes_key1),
|
||||||
|
Encrypt_aes_key1(secret1)},
|
||||||
|
..,
|
||||||
|
{TPM2_MakeCredential(EKpub, WKname(policy), aes_keyN),
|
||||||
|
Encrypt_aes_key1(secretN)}]
|
||||||
```
|
```
|
||||||
|
|
||||||
Nonce validation is currently not well-developed in Safeboot.
|
During an initial enrollment step, the enrollment server can create any
|
||||||
If a timestamp is used instead of a nonce, and if the client assumes all
|
number of secrets to deliver to the client later:
|
||||||
PCRs are desired, then this becomes a one round trip protocol.
|
|
||||||
|
|
||||||
An AKcert will be added to the Safeboot protocol soon.
|
- local storage / filesystem keys
|
||||||
|
|
||||||
|
- private keys and certificates (PKIX, OpenSSH)
|
||||||
|
|
||||||
|
- OpenSSH host keys
|
||||||
|
|
||||||
|
- Kerberos keys
|
||||||
|
|
||||||
|
- etc.
|
||||||
|
|
||||||
## Attestation Protocol Patterns and Actual Protocols (signing-only EKs)
|
## Attestation Protocol Patterns and Actual Protocols (signing-only EKs)
|
||||||
|
|
||||||
|
@ -762,7 +825,7 @@ would not be performant if, for example, those secrets are being used to
|
||||||
encrypt filesystems. We must inherently trust the client to keep those
|
encrypt filesystems. We must inherently trust the client to keep those
|
||||||
secrets safe when running.
|
secrets safe when running.
|
||||||
|
|
||||||
## Break-Glass Recovery
|
## Break-Glass Recovery and Escrow
|
||||||
|
|
||||||
For break-glass recovery, the simplest thing to do is to store
|
For break-glass recovery, the simplest thing to do is to store
|
||||||
`Encrypt_backupKey({EKpub, hostname, secrets})`, where `backupKey` is an
|
`Encrypt_backupKey({EKpub, hostname, secrets})`, where `backupKey` is an
|
||||||
|
|
Loading…
Reference in a new issue