From 314b21f39a4cffeb811f98682b055d248edd41f8 Mon Sep 17 00:00:00 2001 From: Max Bires Date: Wed, 26 May 2021 18:07:27 -0700 Subject: [PATCH] Updating CDDL schemas to match the finalized spec. This primarily updates CDDL to allow for OEMs who wish to use P256 instead of Ed25519 to do so. One structural change of note that affects all implementors is that SignedMacAad now includes the tag from the COSE_Mac0 of MacedKeysToSign to prevent a potential vulnerability that would exist if an attacker compromised the server's EEK private key. Bug: 189018262 Test: Purely a comment change Change-Id: I043a19c6aba0f771315d45c04ab5263b610b5de8 Merged-In: I043a19c6aba0f771315d45c04ab5263b610b5de8 --- .../hardware/security/keymint/DeviceInfo.aidl | 3 + .../IRemotelyProvisionedComponent.aidl | 103 +++++++++------- .../security/keymint/ProtectedData.aidl | 110 ++++++++++++------ 3 files changed, 141 insertions(+), 75 deletions(-) diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl index 3ea14a1b97..32d69cd227 100644 --- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl +++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl @@ -37,10 +37,13 @@ parcelable DeviceInfo { * ? "board" : tstr, * ? "vb_state" : "green" / "yellow" / "orange", // Taken from the AVB values * ? "bootloader_state" : "locked" / "unlocked", // Taken from the AVB values + * ? "vbmeta_digest": bstr, // Taken from the AVB values * ? "os_version" : tstr, // Same as android.os.Build.VERSION.release * ? "system_patch_level" : uint, // YYYYMMDD * ? "boot_patch_level" : uint, // YYYYMMDD * ? "vendor_patch_level" : uint, // YYYYMMDD + * "version" : 1, // The CDDL schema version. + * "security_level" : "tee" / "strongbox" * } */ byte[] deviceInfo; diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl index 04d91d0373..a29fb08553 100644 --- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl +++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl @@ -33,8 +33,8 @@ import android.hardware.security.keymint.RpcHardwareInfo; * * The root of trust for secure provisioning is something called the "Boot Certificate Chain", or * BCC. The BCC is a chain of public key certificates, represented as COSE_Sign1 objects containing - * COSE_Key representations of the public keys. The "root" of the BCC is a self-signed certificate - * for a device-unique public key, denoted DK_pub. All public keys in the BCC are device-unique. The + * COSE_Key representations of the public keys. The "root" of the BCC is + * a device-unique public key, denoted DK_pub. All public keys in the BCC are device-unique. The * public key from each certificate in the chain is used to sign the next certificate in the * chain. The final, "leaf" certificate contains a public key, denoted KM_pub, whose corresponding * private key, denoted KM_priv, is available for use by the IRemotelyProvisionedComponent. @@ -58,12 +58,8 @@ import android.hardware.security.keymint.RpcHardwareInfo; * (given the necessary input), but no stage can compute the secret of any preceding stage. Updating * the firmware or configuration of any stage changes the key pair of that stage, and of all * subsequent stages, and no attacker who compromised the previous version of the updated firmware - * can know or predict the post-update key pairs. - * - * The first BCC certificate is special because its contained public key, DK_pub, will never change, - * making it a permanent, device-unique identifier. Although the remaining keys in the BCC are also - * device-unique, they are not necessarily permanent, since they can change when the device software - * is updated. + * can know or predict the post-update key pairs. It is recommended and expected that the BCC is + * constructed using the Open Profile for DICE. * * When the provisioning server receives a message signed by KM_priv and containing a BCC that * chains from DK_pub to KM_pub, it can be certain that (barring vulnerabilities in some boot @@ -78,7 +74,7 @@ import android.hardware.security.keymint.RpcHardwareInfo; * While a proper BCC, as described above, reflects the complete boot sequence from boot ROM to the * secure area image of the IRemotelyProvisionedComponent, it's also possible to use a "degenerate" * BCC which consists only of a single, self-signed certificate containing the public key of a - * hardware-bound key pair. This is an appropriate solution for devices which haven't implemented + * hardware-bound key pair. This is an appopriate solution for devices which haven't implemented * everything necessary to produce a proper BCC, but can derive a unique key pair in the secure * area. In this degenerate case, DK_pub is the same as KM_pub. * @@ -141,7 +137,7 @@ interface IRemotelyProvisionedComponent { * privateKeyHandle, that the contained public key is for remote certification. * * @return data representing a handle to the private key. The format is implementation-defined, - * but note that specific services may define a required format. + * but note that specific services may define a required format. KeyMint does. */ byte[] generateEcdsaP256KeyPair(in boolean testMode, out MacedPublicKey macedPublicKey); @@ -162,65 +158,90 @@ interface IRemotelyProvisionedComponent { * If testMode is false, the keysToCertify array must not contain any keys flagged as * test keys. Otherwise, the method must return STATUS_TEST_KEY_IN_PRODUCTION_REQUEST. * - * @param in endpointEncryptionKey contains an X25519 public key which will be used to encrypt + * @param in endpointEncryptionKey contains an X22519 public key which will be used to encrypt * the BCC. For flexibility, this is represented as a certificate chain, represented as a * CBOR array of COSE_Sign1 objects, ordered from root to leaf. The leaf contains the * X25519 encryption key, each other element is an Ed25519 key signing the next in the - * chain. The root is self-signed. + * chain. The root is self-signed. An implementor may also choose to use P256 as an + * alternative curve for signing and encryption instead of Curve 25519. * * EekChain = [ + SignedSignatureKey, SignedEek ] * * SignedSignatureKey = [ // COSE_Sign1 * protected: bstr .cbor { - * 1 : -8, // Algorithm : EdDSA + * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm * }, - * unprotected: { }, - * payload: bstr .cbor SignatureKey, - * signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) + * unprotected: {}, + * payload: bstr .cbor SignatureKeyEd25519 / + * bstr .cbor SignatureKeyP256, + * signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) / + * bstr ECDSA(.cbor SignatureKeySignatureInput) * ] * - * SignatureKey = { // COSE_Key + * SignatureKeyEd25519 = { // COSE_Key * 1 : 1, // Key type : Octet Key Pair - * 3 : -8, // Algorithm : EdDSA + * 3 : AlgorithmEdDSA, // Algorithm * -1 : 6, // Curve : Ed25519 * -2 : bstr // Ed25519 public key * } * + * SignatureKeyP256 = { + * 1 : 2, // Key type : EC2 + * 3 : AlgorithmES256, // Algorithm + * -1 : 1, // Curve: P256 + * -2 : bstr, // X coordinate + * -3 : bstr // Y coordinate + * } + * * SignatureKeySignatureInput = [ * context: "Signature1", * body_protected: bstr .cbor { - * 1 : -8, // Algorithm : EdDSA + * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm * }, * external_aad: bstr .size 0, - * payload: bstr .cbor SignatureKey + * payload: bstr .cbor SignatureKeyEd25519 / + * bstr .cbor SignatureKeyP256 * ] * * SignedEek = [ // COSE_Sign1 * protected: bstr .cbor { - * 1 : -8, // Algorithm : EdDSA + * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm * }, - * unprotected: { }, - * payload: bstr .cbor Eek, - * signature: bstr PureEd25519(.cbor EekSignatureInput) + * unprotected: {}, + * payload: bstr .cbor EekX25519 / .cbor EekP256, + * signature: bstr PureEd25519(.cbor EekSignatureInput) / + * bstr ECDSA(.cbor EekSignatureInput) * ] * - * Eek = { // COSE_Key - * 1 : 1, // Key type : Octet Key Pair - * 2 : bstr // KID : EEK ID - * 3 : -25, // Algorithm : ECDH-ES + HKDF-256 - * -1 : 4, // Curve : X25519 - * -2 : bstr // X25519 public key + * EekX25519 = { // COSE_Key + * 1 : 1, // Key type : Octet Key Pair + * 2 : bstr // KID : EEK ID + * 3 : -25, // Algorithm : ECDH-ES + HKDF-256 + * -1 : 4, // Curve : X25519 + * -2 : bstr // Ed25519 public key + * } + * + * EekP256 = { // COSE_Key + * 1 : 2, // Key type : EC2 + * 2 : bstr // KID : EEK ID + * 3 : -25, // Algorithm : ECDH-ES + HKDF-256 + * -1 : 1, // Curve : P256 + * -2 : bstr // Sender X coordinate + * -3 : bstr // Sender Y coordinate * } * * EekSignatureInput = [ * context: "Signature1", * body_protected: bstr .cbor { - * 1 : -8, // Algorithm : EdDSA + * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm * }, * external_aad: bstr .size 0, - * payload: bstr .cbor Eek + * payload: bstr .cbor EekX25519 / .cbor EekP256 * ] * + * AlgorithmES256 = -7 + * AlgorithmEdDSA = -8 + * * If the contents of endpointEncryptionKey do not match the SignedEek structure above, * the method must return STATUS_INVALID_EEK. * @@ -228,7 +249,7 @@ interface IRemotelyProvisionedComponent { * in the chain, which implies that it must not attempt to validate the signature. * * If testMode is false, the method must validate the chain signatures, and must verify - * that the public key in the root certificate is in its pre-configured set of + * that the public key in the root certifictate is in its pre-configured set of * authorized EEK root keys. If the public key is not in the database, or if signature * verification fails, the method must return STATUS_INVALID_EEK. * @@ -236,8 +257,13 @@ interface IRemotelyProvisionedComponent { * by the secure area. See the description of the 'signature' output parameter for * details. * - * @param out keysToSignMac contains the MAC of KeysToSign in the CertificateRequest - * structure. Specifically, it contains: + * @param out DeviceInfo contains the VerifiedDeviceInfo portion of the DeviceInfo array in + * CertificateRequest. The structure is described within the DeviceInfo.aidl file. + * + * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to + * authenticate the keysToSign (see keysToSignMac output argument). + * + * @return The of KeysToSign in the CertificateRequest structure. Specifically, it contains: * * HMAC-256(EK_mac, .cbor KeysToMacStructure) * @@ -248,11 +274,11 @@ interface IRemotelyProvisionedComponent { * protected : bstr .cbor { * 1 : 5, // Algorithm : HMAC-256 * }, - * unprotected : { }, + * unprotected : {}, * // Payload is PublicKeys from keysToSign argument, in provided order. * payload: bstr .cbor [ * PublicKey ], * tag: bstr - * ] + * ] * * KeysToMacStructure = [ * context : "MAC0", @@ -261,9 +287,6 @@ interface IRemotelyProvisionedComponent { * // Payload is PublicKeys from keysToSign argument, in provided order. * payload : bstr .cbor [ * PublicKey ] * ] - * - * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to - * authenticate the keysToSign (see keysToSignMac output argument). */ byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo, diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl index 519906203d..31dbb288ab 100644 --- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl +++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl @@ -40,11 +40,7 @@ parcelable ProtectedData { * 1 : -25 // Algorithm : ECDH-ES + HKDF-256 * }, * unprotected : { - * -1 : { // COSE_Key - * 1 : 1, // Key type : Octet Key Pair - * -1 : 4, // Curve : X25519 - * -2 : bstr // Sender X25519 public key - * } + * -1 : PubKeyX25519 / PubKeyEcdhP256 // Of the sender * 4 : bstr, // KID : EEK ID * }, * ciphertext : nil @@ -67,7 +63,7 @@ parcelable ProtectedData { * other : bstr // EEK pubkey * ], * SuppPubInfo : [ - * 128, // Output key length + * 256, // Output key length * protected : bstr .size 0 * ] * ] @@ -75,34 +71,51 @@ parcelable ProtectedData { * ProtectedDataPayload [ * SignedMac, * Bcc, + * ? AdditionalDKSignatures, + * ] + * AdditionalDKSignatures = { + * + SignerName => DKCertChain + * } + * + * SignerName = tstr + * + * DKCertChain = [ + * 2* Certificate // Root -> Leaf. Root is the vendor + * // self-signed cert, leaf contains DK_pub * ] * - * SignedMac = [ // COSE_Sign1 - * bstr .cbor { // Protected params - * 1 : -8, // Algorithm : EdDSA + * Certificate = COSE_Sign1 of a public key + * + * SignedMac = [ // COSE_Sign1 + * bstr .cbor { // Protected params + * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm * }, - * { }, // Unprotected params + * {}, // Unprotected params * bstr .size 32, // MAC key - * bstr PureEd25519(DK_priv, .cbor SignedMac_structure) + * bstr PureEd25519(KM_priv, .cbor SignedMac_structure) / + * ECDSA(KM_priv, bstr .cbor SignedMac_structure) * ] * * SignedMac_structure = [ * "Signature1", - * bstr .cbor { // Protected params - * 1 : -8, // Algorithm : EdDSA + * bstr .cbor { // Protected params + * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm * }, * bstr .cbor SignedMacAad - * bstr .size 32 // MAC key + * bstr .size 32 // MAC key * ] * * SignedMacAad = [ * challenge : bstr, - * DeviceInfo + * VerifiedDeviceInfo, + * tag: bstr // This is the tag from COSE_Mac0 of + * // KeysToCertify, to tie the key set to + * // the signature. * ] * * Bcc = [ - * PubKey, // DK_pub - * + BccEntry, // Root -> leaf (KM_pub) + * PubKeyEd25519 / PubKeyECDSA256, // DK_pub + * + BccEntry, // Root -> leaf (KM_pub) * ] * * BccPayload = { // CWT @@ -120,44 +133,38 @@ parcelable ProtectedData { * ? -4670549 : bstr, // Authority Hash * ? -4670550 : bstr, // Authority Descriptor * ? -4670551 : bstr, // Mode - * -4670552 : bstr .cbor PubKey // Subject Public Key + * -4670552 : bstr .cbor PubKeyEd25519 / + * bstr .cbor PubKeyECDSA256 // Subject Public Key * -4670553 : bstr // Key Usage * } * - * BccEntry = [ // COSE_Sign1 - * protected: bstr .cbor { - * 1 : -8, // Algorithm : EdDSA + * BccEntry = [ // COSE_Sign1 (untagged) + * protected : bstr .cbor { + * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm * }, - * unprotected: { }, + * unprotected: {}, * payload: bstr .cbor BccPayload, - * // First entry in the chain is signed by DK_pub, the others are each signed by their - * // immediate predecessor. See RFC 8032 for signature representation. - * signature: bstr .cbor PureEd25519(SigningKey, bstr .cbor BccEntryInput) + * signature: bstr .cbor PureEd25519(SigningKey, bstr .cbor BccEntryInput) / + * bstr .cbor ECDSA(SigningKey, bstr .cbor BccEntryInput) + * // See RFC 8032 for details of how to encode the signature value for Ed25519. * ] * - * PubKey = { // COSE_Key - * 1 : 1, // Key type : octet key pair - * 3 : -8, // Algorithm : EdDSA - * 4 : 2, // Ops: Verify - * -1 : 6, // Curve : Ed25519 - * -2 : bstr // X coordinate, little-endian - * } - * * BccEntryInput = [ * context: "Signature1", * protected: bstr .cbor { - * 1 : -8, // Algorithm : EdDSA + * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm * }, * external_aad: bstr .size 0, * payload: bstr .cbor BccPayload * ] * - * DeviceInfo = { + * VerifiedDeviceInfo = { * ? "brand" : tstr, * ? "manufacturer" : tstr, * ? "product" : tstr, * ? "model" : tstr, * ? "board" : tstr, + * ? "device" : tstr, * ? "vb_state" : "green" / "yellow" / "orange", * ? "bootloader_state" : "locked" / "unlocked", * ? "os_version" : tstr, @@ -165,6 +172,39 @@ parcelable ProtectedData { * ? "boot_patch_level" : uint, // YYYYMMDD * ? "vendor_patch_level" : uint, // YYYYMMDD * } + * + * PubKeyX25519 = { // COSE_Key + * 1 : 1, // Key type : Octet Key Pair + * -1 : 4, // Curve : X25519 + * -2 : bstr // Sender X25519 public key + * } + * + * PubKeyEd25519 = { // COSE_Key + * 1 : 1, // Key type : octet key pair + * 3 : AlgorithmEdDSA, // Algorithm : EdDSA + * 4 : 2, // Ops: Verify + * -1 : 6, // Curve : Ed25519 + * -2 : bstr // X coordinate, little-endian + * } + * + * PubKeyEcdhP256 = { // COSE_Key + * 1 : 2, // Key type : EC2 + * -1 : 1, // Curve : P256 + * -2 : bstr // Sender X coordinate + * -3 : bstr // Sender Y coordinate + * } + * + * PubKeyECDSA256 = { // COSE_Key + * 1 : 2, // Key type : EC2 + * 3 : AlgorithmES256, // Algorithm : ECDSA w/ SHA-256 + * 4 : 2, // Ops: Verify + * -1 : 1, // Curve: P256 + * -2 : bstr, // X coordinate + * -3 : bstr // Y coordinate + * } + * + * AlgorithmES256 = -7 + * AlgorithmEdDSA = -8 */ byte[] protectedData; }