From 9e0c1fe534334e1c2af863b4f101ab998185b1c2 Mon Sep 17 00:00:00 2001 From: Shawn Willden Date: Mon, 30 Oct 2017 17:57:42 -0600 Subject: [PATCH] Add support for StrongBox implementations to Keymaster HAL Also adds secure key import. Bug: 63931634 Test: not yet Change-Id: I54f38a8787e2fcb51e01f378228e4a0c576fdfbe --- keymaster/4.0/IKeymasterDevice.hal | 236 ++++++++++++++++-- .../keymasterV4_0/attestation_record.h | 3 - .../include/keymasterV4_0/key_param_output.h | 8 +- .../include/keymasterV4_0/keymaster_tags.h | 2 +- keymaster/4.0/types.hal | 169 ++++++++++++- .../functional/keymaster_hidl_hal_test.cpp | 16 +- 6 files changed, 399 insertions(+), 35 deletions(-) diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal index 06b4b7345e..84354bfc4e 100644 --- a/keymaster/4.0/IKeymasterDevice.hal +++ b/keymaster/4.0/IKeymasterDevice.hal @@ -26,22 +26,147 @@ import android.hardware.keymaster@3.0::KeyFormat; interface IKeymasterDevice { /** - * Returns information about the underlying keymaster hardware. + * Returns information about the underlying Keymaster hardware. * - * @return isSecure Indicates whether this keymaster implementation is in some sort of secure - * hardware. + * @return security level of the Keymaster implementation accessed through this HAL. * - * @return keymasterName is the name of the keymaster implementation. + * @return keymasterName is the name of the Keymaster implementation. * - * @return keymasterAuthorName is the name of the author of the keymaster implementation + * @return keymasterAuthorName is the name of the author of the Keymaster implementation * (organization name, not individual). */ - getHardwareInfo() generates (bool isSecure, string keymasterName, string keymasterAuthorName); + getHardwareInfo() + generates (SecurityLevel securityLevel, string keymasterName, string keymasterAuthorName); /** - * Adds entropy to the RNG used by keymaster. Entropy added through this method must not be the - * only source of entropy used. The keymaster implementation must securely mix entropy provided - * through this method with internally-generated entropy. + * Start the creation of an HMAC key, shared with another Keymaster implementation. Any device + * with a StrongBox Keymaster has two Keymaster instances, because there must be a TEE Keymaster + * as well. The HMAC key used to MAC and verify authentication tokens must be shared between + * TEE and StrongBox so they can each validate tokens produced by the other. This method is the + * first step in the process for for agreeing on a shared key. It is called by Keystore during + * startup if and only if Keystore loads multiple Keymaster HALs. Keystore calls it on each of + * the HAL instances and collects the results in preparation for the second step. + */ + getHmacSharingParameters() generates (ErrorCode error, HmacSharingParameters params); + + /** + * Complete the creation of an HMAC key, shared with another Keymaster implementation. Any + * device with a StrongBox Keymaster has two Keymasters instances, because there must be a TEE + * Keymaster as well. The HMAC key used to MAC and verify authentication tokens must be shared + * between TEE and StrongBox so they can each validate tokens produced by the other. This + * method is the second and final step in the process for for agreeing on a shared key. It is + * called by Keystore during startup if and only if Keystore loads multiple Keymaster HALs. + * Keystore calls it on each of the HAL instances, and sends to it all of the + * HmacSharingParameters returned by all HALs. + * + * This method computes the shared 32-byte HMAC ``H'' as follows (all Keymaster instances + * perform the same computation to arrive at the same result): + * + * H = CKDF(key = K, + * context = P1 || P2 || ... || Pn, + * label = "KeymasterSharedMac") + * + * where: + * + * ``CKDF'' is the standard AES-CMAC KDF from NIST SP 800-108 in counter mode (see Section + * 5.1 of the referenced publication). ``key'', ``context'', and ``label'' are + * defined in the standard. The counter is prefixed, as shown in the construction on + * page 12 of the standard. The label string is UTF-8 encoded. + * + * ``K'' is a pre-established shared secret, set up during factory reset. The mechanism for + * establishing this shared secret is implementation-defined, but see below for a + * recommended approach, which assumes that the TEE Keymaster does not have storage + * available to it, but the StrongBox Keymaster does. + * + * CRITICAL SECURITY REQUIREMENT: All keys created by a Keymaster instance must + * be cryptographically bound to the value of K, such that establishing a new K + * permanently destroys them. + * + * ``||'' represents concatenation. + * + * ``Pi'' is the i'th HmacSharingParameters value in the params vector. Note that at + * present only two Keymaster implementations are supported, but this mechanism + * extends without modification to any number of implementations. Encoding of an + * HmacSharingParameters is the concatenation of its two fields, i.e. seed || nonce. + * + * Process for establishing K: + * + * Any method of securely establishing K that ensures that an attacker cannot obtain or + * derive its value is acceptable. What follows is a recommended approach, to be executed + * during each factory reset. It relies on use of the factory-installed attestation keys to + * mitigate man-in-the-middle attacks. This protocol requires that one of the instancess + * have secure persistent storage. This model was chosen because StrongBox has secure + * persistent storage (by definition), but the TEE may not. The instance without storage is + * assumed to be able to derive a unique hardware-bound key (HBK) which is used only for + * this purpose, and is not derivable outside of the secure environment.. + * + * In what follows, T is the Keymaster instance without storage, S is the Keymaster instance + * with storage: + * + * 1. T generates an ephemeral EC P-256 key pair K1 + * 2. T sends K1_pub to S, signed with T's attestation key. + * 3. S validates the signature on K1_pub. + * 4. S generates an ephemeral EC P-256 key pair K2. + * 5. S sends {K1_pub, K2_pub}, to T, signed with S's attestation key. + * 6. T validates the signature on {K1_pub, K2_pub} + * 7. T uses {K1_priv, K2_pub} with ECDH to compute session secret Q. + * 8. T generates a random seed S + * 9. T computes K = KDF(HBK, S), where KDF is some secure key derivation function. + * 10. T sends M = AES-GCM-ENCRYPT(Q, {S || K}) to S. + * 10. S uses {K2_priv, K1_pub} with ECDH to compute session secret Q. + * 11. S computes S || K = AES-GCM-DECRYPT(Q, M) and stores S and K. + * + * When S receives the getHmacSharingParameters call, it returns the stored S as the seed + * and a nonce. When T receives the same call, it returns an empty seed and a nonce. When + * T receives the computeSharedHmac call, it uses the seed provided by S to compute K. S, + * of course, has K stored. + * + * @param params The HmacSharingParameters data returned by all Keymaster instances when + * getHmacSharingParameters was called. + * + * @return sharingCheck A 32-byte value used to verify that all Keymaster instances have + * computed the same shared HMAC key. The sharingCheck value is computed as follows: + * + * sharingCheck = HMAC(H, "Keymaster HMAC Verification") + * + * The string is UTF-8 encoded. If the returned values of all Keymaster instances don't + * match, Keystore will assume that HMAC agreement failed. + */ + computeSharedHmac(vec params) + generates (ErrorCode error, vec sharingCheck); + + /** + * Verify authorizations for another Keymaster instance. + * + * On systems with both a StrongBox and a TEE Keymaster instance it is sometimes useful to ask + * the TEE Keymaster to verify authorizations for a key hosted in StrongBox. + * + * For every StrongBox operation, Keystore is required to call this method on the TEE Keymaster, + * passing in the StrongBox key's hardwareEnforced authorization list and the operation handle + * returned by StrongBox begin(). The TEE Keymaster must validate all of the authorizations it + * can and return those it validated in the VerificationToken. If it cannot verify any, the + * parametersVerified field of the VerificationToken must be empty. Keystore must then pass the + * VerificationToken to the subsequent invocations of StrongBox update() and finish(). + * + * StrongBox implementations must return ErrorCode::UNIMPLEMENTED. + * + * @param operationHandle the operation handle returned by StrongBox Keymaster's begin(). + * + * @param parametersToVerify Set of authorizations to verify. + * + * @param authToken A HardwareAuthToken if needed to authorize key usage. + */ + verifyAuthorization(uint64_t operationHandle, vec parametersToVerify, + HardwareAuthToken authToken) + generates (ErrorCode error, VerificationToken token); + + + /** + * Adds entropy to the RNG used by Keymaster. Entropy added through this method is guaranteed + * not to be the only source of entropy used, and the mixing function is required to be secure, + * in the sense that if the RNG is seeded (from any source) with any data the attacker cannot + * predict (or control), then the RNG output is indistinguishable from random. Thus, if the + * entropy from any source is good, the output must be good. * * @param data Bytes to be mixed into the RNG. * @@ -52,7 +177,7 @@ interface IKeymasterDevice { /** * Generates a key, or key pair, returning a key blob and a description of the key. * - * @param keyParams Key generation parameters are defined as keymaster tag/value pairs, provided + * @param keyParams Key generation parameters are defined as Keymaster tag/value pairs, provided * in params. See Tag in types.hal for the full list. * * @return error See the ErrorCode enum in types.hal. @@ -70,7 +195,7 @@ interface IKeymasterDevice { /** * Imports a key, or key pair, returning a key blob and/or a description of the key. * - * @param keyParams Key generation parameters are defined as keymaster tag/value pairs, provided + * @param keyParams Key generation parameters are defined as Keymaster tag/value pairs, provided * in params. See Tag for the full list. * * @param keyFormat The format of the key material to import. @@ -88,6 +213,77 @@ interface IKeymasterDevice { importKey(vec keyParams, KeyFormat keyFormat, vec keyData) generates (ErrorCode error, vec keyBlob, KeyCharacteristics keyCharacteristics); + /** + * Securely imports a key, or key pair, returning a key blob and a description of the imported + * key. + * + * @param wrappedKeyData The wrapped key material to import. The wrapped key is in DER-encoded + * ASN.1 format, specified by the following schema: + * + * KeyDescription ::= SEQUENCE( + * keyFormat INTEGER, # Values from KeyFormat enum. + * keyParams AuthorizationList, + * ) + * + * SecureKeyWrapper ::= SEQUENCE( + * version INTEGER, # Contains value 0 + * encryptedTransportKey OCTET_STRING, + * initializationVector OCTET_STRING, + * keyDescription KeyDescription, + * encryptedKey OCTET_STRING, + * tag OCTET_STRING + * ) + * + * Where: + * + * o keyFormat is an integer from the KeyFormat enum, defining the format of the plaintext + * key material. + * o keyParams is the characteristics of the key to be imported (as with generateKey or + * importKey). If the secure import is successful, these characteristics must be + * associated with the key exactly as if the key material had been insecurely imported + * with the @3.0::IKeymasterDevice::importKey. + * o encryptedTransportKey is a 256-bit AES key, XORed with a masking key and then encrypted + * in RSA-OAEP mode (SHA-256 digest, SHA-1 MGF1 digest) with the wrapping key specified by + * wrappingKeyBlob. + * o keyDescription is a KeyDescription, above. + * o encryptedKey is the key material of the key to be imported, in format keyFormat, and + * encrypted with encryptedEphemeralKey in AES-GCM mode, with the DER-encoded + * representation of keyDescription provided as additional authenticated data. + * o tag is the tag produced by the AES-GCM encryption of encryptedKey. + * + * So, importWrappedKey does the following: + * + * 1. Get the private key material for wrappingKeyBlob, verifying that the wrapping key has + * purpose KEY_WRAP, padding mode RSA_OAEP, and digest SHA_2_256, returning the + * appropriate error if any of those requirements fail. + * 2. Extract the encryptedTransportKey field from the SecureKeyWrapper, and decrypt + * it with the wrapping key. + * 3. XOR the result of step 2 with maskingKey. + * 4. Use the result of step 3 as an AES-GCM key to decrypt encryptedKey, using the encoded + * value of keyDescription as the additional authenticated data. Call the result + * "keyData" for the next step. + * 5. Perform the equivalent of calling importKey(keyParams, keyFormat, keyData), except + * that the origin tag should be set to SECURELY_IMPORTED. + * + * @param wrappingKeyBlob The opaque key descriptor returned by generateKey() or importKey(). + * This key must have been created with Purpose::WRAP_KEY, and must be a key algorithm + * that supports encryption and must be at least as strong (in key size) as the key to be + * imported (per NIST key length recommendations: 112 bits symmetric is equivalent to + * 2048-bit RSA or 224-bit EC, 128 bits symmetric ~ 3072-bit RSA or 256-bit EC, etc.). + * + * @param maskingKey The 32-byte value XOR'd with the transport key in the SecureWrappedKey + * structure. + * + * @return error See the ErrorCode enum. + * + * @return keyBlob Opaque descriptor of the imported key. It is recommended that the keyBlob + * contain a copy of the key material, wrapped in a key unavailable outside secure + * hardware. + */ + importWrappedKey(vec wrappedKeyData, vec wrappingKeyBlob, + vec maskingKey) + generates (ErrorCode error, vec keyBlob, KeyCharacteristics keyCharacteristics); + /** * Returns the characteristics of the specified key, if the keyBlob is valid (implementations * must fully validate the integrity of the key). @@ -139,7 +335,7 @@ interface IKeymasterDevice { /** * Generates a signed X.509 certificate chain attesting to the presence of keyToAttest in - * keymaster. The certificate must contain an extension with OID 1.3.6.1.4.1.11129.2.1.17 and + * Keymaster. The certificate must contain an extension with OID 1.3.6.1.4.1.11129.2.1.17 and * value defined in: * * https://developer.android.com/training/articles/security-key-attestation.html. @@ -161,7 +357,7 @@ interface IKeymasterDevice { * Upgrades an old key blob. Keys can become "old" in two ways: Keymaster can be upgraded to a * new version with an incompatible key blob format, or the system can be updated to invalidate * the OS version and/or patch level. In either case, attempts to use an old key blob with - * getKeyCharacteristics(), exportKey(), attestKey() or begin() must result in keymaster + * getKeyCharacteristics(), exportKey(), attestKey() or begin() must result in Keymaster * returning ErrorCode::KEY_REQUIRES_UPGRADE. The caller must use this method to upgrade the * key blob. * @@ -221,7 +417,7 @@ interface IKeymasterDevice { * to update(), finish() or abort(). * * It is critical that each call to begin() be paired with a subsequent call to finish() or - * abort(), to allow the keymaster implementation to clean up any internal operation state. The + * abort(), to allow the Keymaster implementation to clean up any internal operation state. The * caller's failure to do this may leak internal state space or other internal resources and may * eventually cause begin() to return ErrorCode::TOO_MANY_OPERATIONS when it runs out of space * for operations. Any result other than ErrorCode::OK from begin(), update() or finish() @@ -282,6 +478,10 @@ interface IKeymasterDevice { * @param authToken Authentication token. Callers that provide no token must set all numeric * fields to zero and the MAC must be an empty vector. * + * @param verificationToken Verification token, used to prove that another Keymaster HAL has + * verified some parameters, and to deliver the other HAL's current timestamp, if needed. + * If not provided, all fields must be initialized to zero and vectors empty. + * * @return error See the ErrorCode enum in types.hal. * * @return inputConsumed Amount of data that was consumed by update(). If this is less than the @@ -294,7 +494,7 @@ interface IKeymasterDevice { * @return output The output data, if any. */ update(OperationHandle operationHandle, vec inParams, vec input, - HardwareAuthToken authToken) + HardwareAuthToken authToken, VerificationToken verificationToken) generates (ErrorCode error, uint32_t inputConsumed, vec outParams, vec output); @@ -316,6 +516,10 @@ interface IKeymasterDevice { * @param authToken Authentication token. Callers that provide no token must set all numeric * fields to zero and the MAC must be an empty vector. * + * @param verificationToken Verification token, used to prove that another Keymaster HAL has + * verified some parameters, and to deliver the other HAL's current timestamp, if needed. + * If not provided, all fields must be initialized to zero and vectors empty. + * * @return error See the ErrorCode enum in types.hal. * * @return outParams Any output parameters generated by finish(). @@ -323,7 +527,7 @@ interface IKeymasterDevice { * @return output The output data, if any. */ finish(OperationHandle operationHandle, vec inParams, vec input, - vec signature, HardwareAuthToken authToken) + vec signature, HardwareAuthToken authToken, VerificationToken verificationToken) generates (ErrorCode error, vec outParams, vec output); /** diff --git a/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h b/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h index 203b349d37..fae403a7c5 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h +++ b/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h @@ -24,9 +24,6 @@ namespace hardware { namespace keymaster { namespace V4_0 { -using V3_0::ErrorCode; -using V3_0::SecurityLevel; - class AuthorizationSet; /** diff --git a/keymaster/4.0/support/include/keymasterV4_0/key_param_output.h b/keymaster/4.0/support/include/keymasterV4_0/key_param_output.h index 04ba3a4abc..9736da0140 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/key_param_output.h +++ b/keymaster/4.0/support/include/keymasterV4_0/key_param_output.h @@ -50,14 +50,14 @@ inline ::std::ostream& operator<<(::std::ostream& os, PaddingMode value) { return os << toString(value); } -inline ::std::ostream& operator<<(::std::ostream& os, KeyOrigin value) { - return os << toString(value); -} - } // namespace V3_0 namespace V4_0 { +inline ::std::ostream& operator<<(::std::ostream& os, KeyOrigin value) { + return os << toString(value); +} + template ::std::ostream& operator<<(::std::ostream& os, const NullOr& value) { if (!value.isOk()) { diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h index a3aae8bc2d..e5187df870 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h +++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h @@ -72,8 +72,8 @@ using ::android::hardware::keymaster::V3_0::Algorithm; using ::android::hardware::keymaster::V3_0::BlockMode; using ::android::hardware::keymaster::V3_0::Digest; using ::android::hardware::keymaster::V3_0::EcCurve; +using ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType; using ::android::hardware::keymaster::V3_0::KeyFormat; -using ::android::hardware::keymaster::V3_0::KeyOrigin; using ::android::hardware::keymaster::V3_0::PaddingMode; using ::android::hardware::keymaster::V3_0::TagType; diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal index b82848b6dd..8ca2274dfa 100644 --- a/keymaster/4.0/types.hal +++ b/keymaster/4.0/types.hal @@ -27,8 +27,24 @@ import android.hardware.keymaster@3.0::KeyDerivationFunction; import android.hardware.keymaster@3.0::KeyFormat; import android.hardware.keymaster@3.0::KeyOrigin; import android.hardware.keymaster@3.0::PaddingMode; +import android.hardware.keymaster@3.0::SecurityLevel; import android.hardware.keymaster@3.0::TagType; +/** + * Time in milliseconds since some arbitrary point in time. Time must be monotonically increasing, + * and a secure environment's notion of "current time" must not repeat until the Android device + * reboots, or until at least 50 million years have elapsed (note that this requirement is satisfied + * by setting the clock to zero during each boot, and then counting time accurately). + */ +typedef uint64_t Timestamp; + +/** + * A place to define any needed constants. + */ +enum Constants : uint32_t { + AUTH_TOKEN_MAC_LENGTH = 32, +}; + enum Tag : uint32_t { INVALID = TagType:INVALID | 0, @@ -66,6 +82,14 @@ enum Tag : uint32_t { * resistance, it must return * ROLLBACK_RESISTANCE_UNAVAILABLE. */ + /* HARDWARE_TYPE specifies the type of the secure hardware that is requested for the key + * generation / import. See the SecurityLevel enum. In the absence of this tag, keystore must + * use TRUSTED_ENVIRONMENT. If this tag is present and the requested hardware type is not + * available, Keymaster returns HARDWARE_TYPE_UNAVAILABLE. This tag is not included in + * attestations, but hardware type must be reflected in the Keymaster SecurityLevel of the + * attestation header. */ + HARDWARE_TYPE = TagType:ENUM | 304, + /** * Tags that should be semantically enforced by hardware if possible and will otherwise be * enforced by software (keystore). @@ -150,6 +174,15 @@ enum Tag : uint32_t { * key attestation. */ }; +/** + * The origin of a key, i.e. where it was generated. + */ +enum KeyOrigin : @3.0::KeyOrigin { + /** Securely imported into Keymaster. Was created elsewhere, and passed securely through + * Android to secure hardware. */ + SECURELY_IMPORTED = 4, +}; + /** * Possible purposes of a key (or pair). */ @@ -162,6 +195,54 @@ enum KeyPurpose : uint32_t { WRAP_KEY = 5, /* Usable with wrapping keys. */ }; +/** + * Keymaster error codes. + */ +enum ErrorCode : @3.0::ErrorCode { + ROLLBACK_RESISTANCE_UNAVAILABLE = -67, + HARDWARE_TYPE_UNAVAILABLE = -68, +}; + +/** + * Device security levels. + */ +enum SecurityLevel : @3.0::SecurityLevel { + /** + * STRONGBOX specifies that the secure hardware satisfies the following requirements: + * + * a) Has a discrete CPU. The StrongBox device must not be the same CPU that is used to run + * the Android non-secure world, or any other untrusted code. The StrongBox CPU must not + * share cache, RAM or any other critical resources with any device that runs untrusted + * code. + * + * b) Has integral secure storage. The StrongBox device must have its own non-volatile + * storage that is not accessible by any other hardware component. + * + * c) Has a high-quality True Random Number Generator. The StrongBox device must have sole + * control of and access to a high-quality TRNG which it uses for generating necessary + * random bits. It must combine the output of this TRNG with caller-provided entropy in a + * strong CPRNG, as do non-Strongbox Keymaster implementations. + * + * d) Is enclosed in tamper-resistant packaging. The StrongBox device must have + * tamper-resistant packaging which provides obstacles to physical penetration which are + * higher than those provided by normal integrated circuit packages. + * + * e) Provides side-channel resistance. The StrongBox device must implement resistance + * against common side-channel attacks, including power analysis, timing analysis, EM + * snooping, etc. + * + * Devices with StrongBox Keymasters must also have a non-StrongBox Keymaster, which lives in + * the higher-performance TEE. Keystore must load both StrongBox (if available) and + * non-StrongBox HALs and route key generation/import requests appropriately. Callers that want + * StrongBox keys must add Tag::HARDWARE_TYPE with value SecurityLevel::STRONGBOX to the key + * description provided to generateKey or importKey. Keytore must route the request to a + * StrongBox HAL (a HAL whose isStrongBox method returns true). Keymaster implementations that + * receive a request for a Tag::HARDWARE_TYPE that is inappropriate must fail with + * ErrorCode::HARDWARE_TYPE_UNAVAILABLE. + */ + STRONGBOX = 2, /* See IKeymaster::isStrongBox */ +}; + struct KeyParameter { /** * Discriminates the uinon/blob field used. The blob cannot be coincided with the union, but @@ -179,6 +260,7 @@ struct KeyParameter { KeyPurpose purpose; KeyDerivationFunction keyDerivationFunction; HardwareAuthenticatorType hardwareAuthenticatorType; + SecurityLevel hardwareType; /** Other types */ bool boolValue; // Always true, if a boolean tag is present. @@ -203,21 +285,100 @@ struct HardwareAuthToken { uint64_t userId; // Secure User ID, not Android user ID. uint64_t authenticatorId; // Secure authenticator ID. HardwareAuthenticatorType authenticatorType; - uint64_t timestamp; + Timestamp timestamp; /** * MACs are computed with a backward-compatible method, used by Keymaster 3.0, Gatekeeper 1.0 * and Fingerprint 1.0, as well as pre-treble HALs. * - * The MAC is 32 bytes in length and is computed as follows: + * The MAC is Constants::AUTH_TOKEN_MAC_LENGTH bytes in length and is computed as follows: * - * HMAC(H, 0 || challenge || user_id || authenticator_id || authenticator_type || timestamp) + * HMAC_SHA256( + * H, 0 || challenge || user_id || authenticator_id || authenticator_type || timestamp) * * where ``||'' represents concatenation, the leading zero is a single byte, and all integers * are represented as unsigned values, the full width of the type. The challenge, userId and * authenticatorId values are in machine order, but authenticatorType and timestamp are in * network order. This odd construction is compatible with the hw_auth_token_t structure, + * + * Note that mac is a vec rather than an array, not because it's actually variable-length but + * because it could be empty. As documented in the IKeymasterDevice::begin, + * IKeymasterDevice::update and IKeymasterDevice::finish doc comments, an empty mac indicates + * that this auth token is empty. */ - uint8_t[32] mac; + vec mac; }; typedef uint64_t OperationHandle; + +/** + * HmacSharingParameters holds the data used in the process of establishing a shared HMAC key + * between multiple Keymaster instances. Sharing parameters are returned in this struct by + * getHmacSharingParameters() and send to computeSharedHmac(). See the named methods in IKeymaster + * for details of usage. + */ +struct HmacSharingParameters { + /** + * Either empty or contains a persistent value that is associated with the pre-shared HMAC + * agreement key (see documentation of computeSharedHmac in @4.0::IKeymaster). It is either + * empty or 32 bytes in length. + */ + vec seed; + + /** + * A 32-byte value which is guaranteed to be different each time + * getHmacSharingParameters() is called. Probabilistic uniqueness (i.e. random) is acceptable, + * though a stronger uniqueness guarantee (e.g. counter) is recommended where possible. + */ + uint8_t[32] nonce; +}; + +/** + * VerificationToken enables one Keymaster instance to validate authorizations for another. See + * verifyAuthorizations() in IKeymaster for details. + */ +struct VerificationToken { + /** + * The operation handle, used to ensure freshness. + */ + uint64_t challenge; + + /** + * The current time of the secure environment that generates the VerificationToken. This can be + * checked against auth tokens generated by the same secure environment, which avoids needing to + * synchronize clocks. + */ + Timestamp timestamp; + + /** + * A list of the parameters verified. Empty if the only parameters verified are time-related. + * In that case the timestamp is the payload. + */ + vec parametersVerified; + + /** + * SecurityLevel of the secure environment that generated the token. + */ + SecurityLevel securityLevel; + + /** + * 32-byte HMAC of the above values, computed as: + * + * HMAC(H, + * "Auth Verification" || challenge || timestamp || securityLevel || parametersVerified) + * + * where: + * + * ``HMAC'' is the shared HMAC key (see computeSharedHmac() in IKeymaster). + * + * ``||'' represents concatenation + * + * The representation of challenge and timestamp is as 64-bit unsigned integers in big-endian + * order. securityLevel is represented as a 32-bit unsigned integer in big-endian order. + * + * If parametersVerified is non-empty, the representation of parametersVerified is an ASN.1 DER + * encoded representation of the values. The ASN.1 schema used is the AuthorizationList schema + * from the Keystore attestation documentation. If parametersVerified is empty, it is simply + * omitted from the HMAC computation. + */ + vec mac; +}; diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index 38dd3023bf..c8858de39e 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -138,6 +138,8 @@ bool operator==(const KeyParameter& a, const KeyParameter& b) { return a.f.integer == b.f.integer; case Tag::ORIGIN: return a.f.origin == b.f.origin; + case Tag::HARDWARE_TYPE: + return a.f.hardwareType == b.f.hardwareType; } return false; @@ -435,9 +437,9 @@ class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase { ASSERT_NE(keymaster_, nullptr); ASSERT_TRUE(keymaster_ - ->getHardwareInfo([&](bool is_secure, const hidl_string& name, + ->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name, const hidl_string& author) { - is_secure_ = is_secure; + securityLevel_ = securityLevel; name_ = name; author_ = author; }) @@ -617,7 +619,7 @@ class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase { ErrorCode error; EXPECT_TRUE(keymaster_ ->update(op_handle, in_params.hidl_data(), HidlBuf(input), - HardwareAuthToken(), + HardwareAuthToken(), VerificationToken(), [&](ErrorCode hidl_error, uint32_t hidl_input_consumed, const hidl_vec& hidl_out_params, const HidlBuf& hidl_output) { @@ -647,7 +649,7 @@ class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase { EXPECT_TRUE( keymaster_ ->finish(op_handle, in_params.hidl_data(), HidlBuf(input), HidlBuf(signature), - HardwareAuthToken(), + HardwareAuthToken(), VerificationToken(), [&](ErrorCode hidl_error, const hidl_vec& hidl_out_params, const HidlBuf& hidl_output) { error = hidl_error; @@ -869,7 +871,7 @@ class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase { return retval; } - static bool IsSecure() { return is_secure_; } + static bool IsSecure() { return securityLevel_ != SecurityLevel::SOFTWARE; } HidlBuf key_blob_; KeyCharacteristics key_characteristics_; @@ -880,7 +882,7 @@ class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase { static uint32_t os_version_; static uint32_t os_patch_level_; - static bool is_secure_; + static SecurityLevel securityLevel_; static hidl_string name_; static hidl_string author_; }; @@ -947,7 +949,7 @@ bool verify_attestation_record(const string& challenge, const string& app_id, sp KeymasterHidlTest::keymaster_; uint32_t KeymasterHidlTest::os_version_; uint32_t KeymasterHidlTest::os_patch_level_; -bool KeymasterHidlTest::is_secure_; +SecurityLevel KeymasterHidlTest::securityLevel_; hidl_string KeymasterHidlTest::name_; hidl_string KeymasterHidlTest::author_;