mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
Merge "Add support for StrongBox implementations to Keymaster HAL"
This commit is contained in:
committed by
Android (Google) Code Review
commit
4f7dabb1a9
@@ -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.
|
||||
*
|
||||
* <b>CRITICAL SECURITY REQUIREMENT</b>: 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<HmacSharingParameters> params)
|
||||
generates (ErrorCode error, vec<uint8_t> 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<KeyParameter> 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<KeyParameter> keyParams, KeyFormat keyFormat, vec<uint8_t> keyData)
|
||||
generates (ErrorCode error, vec<uint8_t> 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<uint8_t> wrappedKeyData, vec<uint8_t> wrappingKeyBlob,
|
||||
vec<uint8_t> maskingKey)
|
||||
generates (ErrorCode error, vec<uint8_t> 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<KeyParameter> inParams, vec<uint8_t> input,
|
||||
HardwareAuthToken authToken)
|
||||
HardwareAuthToken authToken, VerificationToken verificationToken)
|
||||
generates (ErrorCode error, uint32_t inputConsumed, vec<KeyParameter> outParams,
|
||||
vec<uint8_t> 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<KeyParameter> inParams, vec<uint8_t> input,
|
||||
vec<uint8_t> signature, HardwareAuthToken authToken)
|
||||
vec<uint8_t> signature, HardwareAuthToken authToken, VerificationToken verificationToken)
|
||||
generates (ErrorCode error, vec<KeyParameter> outParams, vec<uint8_t> output);
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,9 +24,6 @@ namespace hardware {
|
||||
namespace keymaster {
|
||||
namespace V4_0 {
|
||||
|
||||
using V3_0::ErrorCode;
|
||||
using V3_0::SecurityLevel;
|
||||
|
||||
class AuthorizationSet;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 <typename ValueT>
|
||||
::std::ostream& operator<<(::std::ostream& os, const NullOr<ValueT>& value) {
|
||||
if (!value.isOk()) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<uint8_t> 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<uint8_t> 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<KeyParameter> 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<uint8_t> mac;
|
||||
};
|
||||
|
||||
@@ -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<KeyParameter>& 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<KeyParameter>& 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<IKeymasterDevice> 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_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user