375 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Markdown
		
	
	
	
			
		
		
	
	
			375 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Markdown
		
	
	
	
| # 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)
 | |
| 
 |