Merge "Add a README for Remote Key Provisioning." into tm-dev am: 8c1586bc4f
am: 0d4ab8520d
Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/interfaces/+/18635577 Change-Id: Ie85c89dcfbcfb1bef313631d24c912f7e3dff1f7 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
949b6bbb96
1 changed files with 374 additions and 0 deletions
374
security/keymint/RKP_README.md
Normal file
374
security/keymint/RKP_README.md
Normal file
|
@ -0,0 +1,374 @@
|
|||
# Remote Provisioning HAL
|
||||
|
||||
## Objective
|
||||
|
||||
Design a HAL to support over-the-air provisioning of certificates for asymmetric
|
||||
keys. The HAL must interact effectively with Keystore (and other daemons) and
|
||||
protect device privacy and security.
|
||||
|
||||
Note that this API is designed for KeyMint, but with the intention that it
|
||||
should be usable for other HALs that require certificate provisioning.
|
||||
Throughout this document we'll refer to the Keystore and KeyMint (formerly
|
||||
called Keymaster) components, but only for concreteness and convenience; those
|
||||
labels could be replaced with the names of any system and secure area
|
||||
components, respectively, that need certificates provisioned.
|
||||
|
||||
## Key design decisions
|
||||
|
||||
### General approach
|
||||
|
||||
To more securely and reliably get keys and certificates to Android devices, we
|
||||
need to create a system where no party outside of the device's secure components
|
||||
is responsible for managing private keys. The strategy we've chosen is to
|
||||
deliver certificates over the air, using an asymmetric key pair created
|
||||
on-device in the factory as a root of trust to create an authenticated, secure
|
||||
channel. In this document we refer to this device-unique asymmetric key pair as
|
||||
Device Key (DK), its public half DK\_pub, its private half DK\_priv and a Device
|
||||
Key Certificate containing DK\_pub is denoted DKC.
|
||||
|
||||
In order for the provisioning service to use DK (or a key authenticated by DK),
|
||||
it must know whether a given DK\_pub is known and trusted. To prove trust, we
|
||||
ask device OEMs to use one of two mechanisms:
|
||||
|
||||
1. (Preferred, recommended) The device OEM extracts DK\_pub from each device it
|
||||
manufactures and uploads the public keys to a backend server.
|
||||
|
||||
1. The device OEM signs the DK\_pub to produce DKC and stores it on the device.
|
||||
This has the advantage that they don't need to upload a DK\_pub for every
|
||||
device immediately, but the disadvantage that they have to manage their
|
||||
private signing keys, which means they have to have HSMs, configure and
|
||||
secure them correctly, etc. Some backend providers may also require that the
|
||||
OEM passes a factory security audit, and additionally promises to upload the
|
||||
keys eventually as well.
|
||||
|
||||
Note that in the full elaboration of this plan, DK\_pub is not the key used to
|
||||
establish a secure channel. Instead, DK\_pub is just the first public key in a
|
||||
chain of public keys which ends with the KeyMint public key, KM\_pub. All keys
|
||||
in the chain are device-unique and are joined in a certificate chain called the
|
||||
_Boot Certificate Chain_ (BCC), because in phases 2 and 3 of the remote
|
||||
provisioning project it is a chain of certificates corresponding to boot phases.
|
||||
We speak of the BCC even for phase 1, though in phase 1 it contains only a
|
||||
single self-signed DKC. This is described in more depth in the Phases section
|
||||
below.
|
||||
|
||||
The BCC is authenticated by DK\_pub. To authenticate DK\_pub, we may have
|
||||
additional DKCs, from the SoC vendor, the device OEM, or both. Those are not
|
||||
part of the BCC but included as optional fields in the certificate request
|
||||
structure.
|
||||
|
||||
The format of the the DK and BCC is specified within [Open Profile for DICE]
|
||||
(https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md). To
|
||||
map phrases within this document to their equivalent terminology in the DICE
|
||||
specification, read the terms as follows: the DK corresponds to the UDS-derived
|
||||
key pair, DKC corresponds to the UDS certificate, and the BCC entries between
|
||||
DK\_pub and KM\_pub correspond to a chain of CDI certificates.
|
||||
|
||||
Note: In addition to allowing 32 byte hash values for fields in the BCC payload,
|
||||
this spec additionally constrains some of the choices allowed in open-DICE.
|
||||
Specifically, these include which entries are required and which are optional in
|
||||
the BCC payload, and which algorithms are acceptable for use.
|
||||
|
||||
### Phases
|
||||
|
||||
RKP will be deployed in three phases, in terms of managing the root of trust
|
||||
binding between the device and the backend. To briefly describe them:
|
||||
|
||||
* Phase 1: In phase 1 there is only one entry in the BCC; DK_pub and KM_pub are
|
||||
the same key and the certificate is self-signed.
|
||||
* Phase 2: This is identical to phase 1, except it leverages the hardware root
|
||||
of trust process described by DICE. Instead of trust being rooted in the TEE,
|
||||
it is now rooted in the ROM by key material blown into fuses which are only
|
||||
accessible to the ROM code.
|
||||
* Phase 3: This is identical to Phase 2, except the SoC vendor also does the
|
||||
public key extraction or certification in their facilities, along with the OEM
|
||||
doing it in the factory. This tightens up the "supply chain" and aims to make
|
||||
key upload management more secure.
|
||||
|
||||
### Privacy considerations
|
||||
|
||||
Because DK and the DKCs are unique, immutable, unspoofable hardware-bound
|
||||
identifiers for the device, we must limit access to them to the absolute minimum
|
||||
possible. We do this in two ways:
|
||||
|
||||
1. We require KeyMint (which knows the BCC and either knows or at least has the
|
||||
ability to use KM\_priv) to refuse to ever divulge the BCC or additional
|
||||
signatures in plaintext. Instead, KeyMint requires the caller to provide an
|
||||
_Endpoint Encryption Key_ (EEK), with which it will encrypt the data before
|
||||
returning it. When provisioning production keys, the EEK must be signed by an
|
||||
approved authority whose public key is embedded in KeyMint. When certifying test
|
||||
keys, KeyMint will accept any EEK without checking the signature, but will
|
||||
encrypt and return a test BCC, rather than the real one. The result is that
|
||||
only an entity in possession of an Trusted EEK (TEEK) private key can discover
|
||||
the plaintext of the production BCC.
|
||||
1. Having thus limited access to the public keys to the trusted party only, we
|
||||
need to prevent the entity from abusing this unique device identifier. The
|
||||
approach and mechanisms for doing that are beyond the scope of this document
|
||||
(they must be addressed in the server design), but generally involve taking care
|
||||
to ensure that we do not create any links between user IDs, IP addresses or
|
||||
issued certificates and the device pubkey.
|
||||
|
||||
Although the details of the mechanisms for preventing the entity from abusing
|
||||
the BCC are, as stated, beyond the scope of this document, there is a subtle
|
||||
design decision here made specifically to enable abuse prevention. Specifically
|
||||
the `CertificateRequest` message sent to the server is (in
|
||||
[CDDL](https://tools.ietf.org/html/rfc8610)):
|
||||
|
||||
```
|
||||
cddl
|
||||
CertificateRequest = [
|
||||
DeviceInfo,
|
||||
challenge : bstr,
|
||||
ProtectedData,
|
||||
MacedKeysToSign
|
||||
]
|
||||
```
|
||||
|
||||
The public keys to be attested by the server are in `MacedKeysToSign`, which is
|
||||
a COSE\_Mac0 structure, MACed with a key that is found in `ProtectedData`. The
|
||||
MAC key is signed by DK\_pub.
|
||||
|
||||
This structure allows the backend component that has access to EEK\_priv to
|
||||
decrypt `ProtectedData`, validate that the request is from an authorized device,
|
||||
check that the request is fresh and verify and extract the MAC key. That backend
|
||||
component never sees any data related to the keys to be signed, but can provide
|
||||
the MAC key to another backend component that can verify `MacedKeysToSign` and
|
||||
proceed to generate the certificates.
|
||||
|
||||
In this way, we can partition the provisioning server into one component that
|
||||
knows the device identity, as represented by DK\_pub, but never sees the keys to
|
||||
be certified or certificates generated, and another component that sees the keys
|
||||
to be certified and certificates generated but does not know the device
|
||||
identity.
|
||||
|
||||
### Key and cryptographic message formatting
|
||||
|
||||
For simplicity of generation and parsing, compactness of wire representation,
|
||||
and flexibility and standardization, we've settled on using the CBOR Object
|
||||
Signing and Encryption (COSE) standard, defined in [RFC
|
||||
8152](https://tools.ietf.org/html/rfc8152). COSE provides compact and reasonably
|
||||
simple, yet easily-extensible, wire formats for:
|
||||
|
||||
* Keys,
|
||||
* MACed messages,
|
||||
* Signed messages, and
|
||||
* Encrypted messages
|
||||
|
||||
COSE enables easy layering of these message formats, such as using a COSE\_Sign
|
||||
structure to contain a COSE\_Key with a public key in it. We call this a
|
||||
"certificate".
|
||||
|
||||
Due to the complexity of the standard, we'll spell out the COSE structures
|
||||
completely in this document and in the HAL and other documentation, so that
|
||||
although implementors will need to understand CBOR and the CBOR Data Definition
|
||||
Language ([CDDL, defined in RFC 8610](https://tools.ietf.org/html/rfc8610)),
|
||||
they shouldn't need to understand COSE.
|
||||
|
||||
Note, however, that the certificate chains returned from the provisioning server
|
||||
are standard X.509 certificates.
|
||||
|
||||
### Algorithm choices
|
||||
|
||||
This document uses:
|
||||
|
||||
* ECDSA P-256 for attestation signing keys;
|
||||
* Remote provisioning protocol signing keys:
|
||||
* Ed25519 / P-256
|
||||
* ECDH keys:
|
||||
* X25519 / P-256
|
||||
* AES-GCM for all encryption;
|
||||
* SHA-256 for all message digesting;
|
||||
* HMAC-SHA-256 for all MACing; and
|
||||
* HKDF-SHA-256 for all key derivation.
|
||||
|
||||
We believe that Curve25519 offers the best tradeoff in terms of security,
|
||||
efficiency and global trustworthiness, and that it is now sufficiently
|
||||
widely-used and widely-implemented to make it a practical choice.
|
||||
|
||||
However, since Secure Elements (SE) do not currently offer support for curve
|
||||
25519, we are allowing implementations to instead make use of EC P-256 for
|
||||
signing and ECDH. To put it simply, the device unique key pair will be a P-256
|
||||
key pair for ECDSA instead of Ed25519, and the ProtectedData COSE\_Encrypt
|
||||
message will have its payload encrypted with P-256 ECDH key exchange instead of
|
||||
X25519.
|
||||
|
||||
The CDDL in the rest of the document will use the '/' operator to show areas
|
||||
where either curve 25519 or P-256 may be used. Since there is no easy way to
|
||||
bind choices across different CDDL groups, it is important that the implementor
|
||||
stays consistent in which type is chosen. E.g. taking ES256 as the choice for
|
||||
algorithm implies the implementor should also choose the P256 public key group
|
||||
further down in the COSE structure.
|
||||
|
||||
### Testability
|
||||
|
||||
It's critical that the remote provisioning implementation be testable, to
|
||||
minimize the probability that broken devices are sold to end users. To support
|
||||
testing, the remote provisioning HAL methods take a `testMode` argument. Keys
|
||||
created in test mode are tagged to indicate this. The provisioning server will
|
||||
check for the test mode tag and issue test certificates that do not chain back
|
||||
to a trusted public key. In test mode, any EEK will be accepted, enabling
|
||||
testing tools to use EEKs for which they have the private key so they can
|
||||
validate the content of certificate requests. The BCC included in the
|
||||
`CertificateRequest` must contain freshly-generated keys, not the real BCC keys.
|
||||
|
||||
Keystore (or similar) will need to be able to handle both testMode keys and
|
||||
production keys and keep them distinct, generating test certificate requests
|
||||
when asked with a test EEK and production certificate requests when asked with a
|
||||
production EEK. Likewise, the interface used to instruct Keystore to create keys
|
||||
will need to be able to specify whether test or production keys are desired.
|
||||
|
||||
## Design
|
||||
|
||||
### Certificate provisioning flow
|
||||
|
||||
TODO(jbires): Replace this with a `.png` containing a sequence diagram. The
|
||||
provisioning flow looks something like this:
|
||||
|
||||
Provisioner -> Keystore: Prepare N keys
|
||||
Keystore -> KeyMint: generateKeyPair
|
||||
KeyMint -> KeyMint: Generate key pair
|
||||
KeyMint --> Keystore: key\_blob,pubkey
|
||||
Keystore -> Keystore: Store key\_blob,pubkey
|
||||
Provisioner -> Server: Get TEEK
|
||||
Server --> Provisioner: TEEK
|
||||
Provisioner -> Keystore: genCertReq(N, TEEK)
|
||||
Keystore -> KeyMint: genCertReq(pubkeys, TEEK)
|
||||
KeyMint -> KeyMint: Sign pubkeys & encrypt BCC
|
||||
KeyMint --> Keystore: signature, encrypted BCC
|
||||
Keystore -> Keystore: Construct cert\_request
|
||||
Keystore --> Provisioner: cert\_request
|
||||
Provisioner --> Server: cert\_request
|
||||
Server -> Server: Validate cert\_request
|
||||
Server -> Server: Generate certificates
|
||||
Server --> Provisioner: certificates
|
||||
Provisioner -> Keystore: certificates
|
||||
Keystore -> Keystore: Store certificates
|
||||
|
||||
The actors in the above diagram are:
|
||||
|
||||
* **Server** is the backend certificate provisioning server. It has access to
|
||||
the uploaded device public keys and is responsible for providing encryption
|
||||
keys, decrypting and validating requests, and generating certificates in
|
||||
response to requests.
|
||||
* **Provisioner** is an application that is responsible for communicating with
|
||||
the server and all of the system components that require key certificates
|
||||
from the server. It also implements the policy that defines how many key
|
||||
pairs each client should keep in their pool.
|
||||
* **Keystore** is the [Android keystore
|
||||
daemon](https://developer.android.com/training/articles/keystore) (or, more
|
||||
generally, whatever system component manages communications with a
|
||||
particular secure aread component).
|
||||
* **KeyMint** is the secure area component that manages cryptographic keys and
|
||||
performs attestations (or perhaps some other secure area component).
|
||||
|
||||
### `BCC`
|
||||
|
||||
The _Boot Certificate Chain_ (BCC) is the chain of certificates that contains
|
||||
DK\_pub as well as other often device-unique certificates. The BCC is
|
||||
represented as a COSE\_Key containing DK\_pub followed by an array of
|
||||
COSE\_Sign1 "certificates" containing public keys and optional additional
|
||||
information, ordered from root to leaf, with each certificate signing the next.
|
||||
The first certificate in the array is signed by DK\_pub, the last certificate
|
||||
has the KeyMint (or whatever) signing key's public key, KM\_pub. In phase 1
|
||||
there is only one entry; DK\_pub and KM\_pub are the same key and the
|
||||
certificate is self-signed.
|
||||
|
||||
Each COSE\_Sign1 certificate is a CBOR Web Token (CWT) as described in [RFC
|
||||
8392](https://tools.ietf.org/html/rfc8392) with additional fields as described
|
||||
in the Open Profile for DICE. Of these additional fields, only the
|
||||
_subjectPublicKey_ and _keyUsage_ fields are expected to be present for the
|
||||
KM\_pub entry (that is, the last entry) in a BCC, but all fields required by the
|
||||
Open Profile for DICE are expected for other entries (each of which corresponds
|
||||
to a particular firmware component or boot stage). The CWT fields _iss_ and
|
||||
_sub_ identify the issuer and subject of the certificate and are consistent
|
||||
along the BCC entries; the issuer of a given entry matches the subject of the
|
||||
previous entry.
|
||||
|
||||
The BCC is designed to be constructed using the Open Profile for DICE. In this
|
||||
case the DK key pair is derived from the UDS as described by that profile and
|
||||
all BCC entries before the leaf are CBOR CDI certificates chained from DK\_pub.
|
||||
The KM key pair is not part of the derived DICE chain. It is generated (not
|
||||
derived) by the KeyMint module, certified by the last key in the DICE chain, and
|
||||
added as the leaf BCC entry. The key usage field in this leaf certificate must
|
||||
indicate the key is not used to sign certificates. If a UDS certificate is
|
||||
available on the device it should appear in the certificate request as the leaf
|
||||
of a DKCertChain in AdditionalDKSignatures (see
|
||||
[CertificateRequest](#certificaterequest)).
|
||||
|
||||
The Open Profile for DICE allows for an arbitrary configuration descriptor. For
|
||||
BCC entries, this configuration descriptor is a CBOR map with the following
|
||||
optional fields. If no fields are relevant, an empty map should be encoded.
|
||||
Additional implementation-specific fields may be added using key values not in
|
||||
the range \[-70000, -70999\] (these are reserved for future additions here).
|
||||
|
||||
```
|
||||
| Name | Key | Value type | Meaning |
|
||||
| ----------------- | ------ | ---------- | ----------------------------------|
|
||||
| Component name | -70002 | tstr | Name of firmware component / boot |
|
||||
: : : : stage :
|
||||
| Component version | -70003 | int | Version of firmware component / |
|
||||
: : : : boot stage :
|
||||
| Resettable | -70004 | null | If present, key changes on factory|
|
||||
: : : : reset :
|
||||
```
|
||||
|
||||
Please see
|
||||
[ProtectedData.aidl](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl)
|
||||
for a full CDDL definition of the BCC.
|
||||
|
||||
### `CertificateRequest`
|
||||
|
||||
The full CBOR message that will be sent to the server to request certificates
|
||||
is:
|
||||
|
||||
```cddl
|
||||
CertificateRequest = [
|
||||
DeviceInfo,
|
||||
challenge : bstr, // Provided by the server
|
||||
ProtectedData, // See ProtectedData.aidl
|
||||
MacedKeysToSign // See IRemotelyProvisionedComponent.aidl
|
||||
]
|
||||
|
||||
DeviceInfo = [
|
||||
VerifiedDeviceInfo, // See DeviceInfo.aidl
|
||||
UnverifiedDeviceInfo
|
||||
]
|
||||
|
||||
// Unverified info is anything provided by the HLOS. Subject to change out of
|
||||
// step with the HAL.
|
||||
UnverifiedDeviceInfo = {
|
||||
? "fingerprint" : tstr,
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
It will be the responsibility of Keystore and the Provisioner to construct the
|
||||
`CertificateRequest`. The HAL provides a method to generate the elements that
|
||||
need to be constructed on the secure side, which are the tag field of
|
||||
`MacedKeysToSign`, `VerifiedDeviceInfo`, and the ciphertext field of
|
||||
`ProtectedData`.
|
||||
|
||||
### HAL
|
||||
|
||||
The remote provisioning HAL provides a simple interface that can be implemented
|
||||
by multiple secure components that require remote provisioning. It would be
|
||||
slightly simpler to extend the KeyMint API, but that approach would only serve
|
||||
the needs of KeyMint, this is more general.
|
||||
|
||||
NOTE the data structures defined in this HAL may look a little bloated and
|
||||
complex. This is because the COSE data structures are fully spelled-out; we
|
||||
could make it much more compact by not re-specifying the standardized elements
|
||||
and instead just referencing the standard, but it seems better to fully specify
|
||||
them. If the apparent complexity seems daunting, consider what the same would
|
||||
look like if traditional ASN.1 DER-based structures from X.509 and related
|
||||
standards were used and also fully elaborated.
|
||||
|
||||
Please see the related HAL documentation directly in the source code at the
|
||||
following links:
|
||||
|
||||
* [IRemotelyProvisionedComponent
|
||||
HAL](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl)
|
||||
* [ProtectedData](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl)
|
||||
* [MacedPublicKey](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl)
|
||||
* [RpcHardwareInfo](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl)
|
||||
* [DeviceInfo](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl)
|
||||
|
Loading…
Reference in a new issue