This page provides additional details and guidelines to assist implementers of the KeyMint hardware abstraction layer (HAL). The primary documentation for the HAL is the AIDL interface specification.
API misuse
Callers can create KeyMint keys with authorizations that are valid as API parameters, but that make the resulting keys insecure or unusable. KeyMint implementations aren't required to fail in such cases or issue a diagnostic. Use of too-small keys, specification of irrelevant input parameters, reuse of IVs or nonces, generation of keys with no purposes (hence useless), and the like shouldn't be diagnosed by implementations.
It's the responsibility of apps, the framework, and Android Keystore to ensure that the calls to KeyMint modules are sensible and useful.
addRngEntropy entry point
The addRngEntropy
entry point adds caller-provided entropy to the
pool used by the KeyMint implementation for generating random numbers, for keys
and IVs.
KeyMint implementations need to securely mix the provided entropy into their
pool, which also must contain internally generated entropy from a hardware
random number generator. Mixing should be handled so that an attacker who has
complete control of either the addRngEntropy
-provided bits or the
hardware-generated bits (but not both) doesn't have a significant advantage in
predicting the bits generated from the entropy pool.
Key characteristics
Each of the mechanisms (generateKey
, importKey
,
and importWrappedKey
) that create KeyMint keys returns the newly
created key's characteristics, divided appropriately into the security levels
that enforce each characteristic. The returned characteristics include all of
the parameters specified for key creation,
except Tag::APPLICATION_ID
and Tag::APPLICATION_DATA
.
If these tags are included in the key parameters, they're removed from the
returned characteristics so that it isn't possible to find their values by
examining the returned keyblob. However, they're cryptographically bound to
the keyblob, so that if the correct values aren't provided when the key is
used, usage fails. Similarly,
Tag::ROOT_OF_TRUST
is
cryptographically bound to the key, but it can't be specified during
key creation or import and is never returned.
In addition to the provided tags, the KeyMint implementation also
adds Tag::ORIGIN
, indicating the manner in which the key was
created (KeyOrigin::GENERATED
,
KeyOrigin::IMPORTED
, or KeyOrigin::SECURELY_IMPORTED
).
Rollback resistance
Rollback resistance is indicated by Tag::ROLLBACK_RESISTANCE
,
and means that once a key is deleted with deleteKey
or deleteAllKeys
, the secure hardware
ensures it's never usable again.
KeyMint implementations return generated or imported key material to the caller as a keyblob, an encrypted and authenticated form. When Keystore deletes the keyblob, the key is gone, but an attacker who has previously managed to retrieve the key material could potentially restore it to the device.
A key is rollback resistant if the secure hardware ensures that deleted keys can't be restored later. This is generally done by storing additional key metadata in a trusted location that can't be manipulated by an attacker. On mobile devices, the mechanism used for this is usually replay protected memory blocks (RPMB). Because the number of keys that can be created is essentially unbounded and the trusted storage used for rollback resistance might be limited in size, the implementation can fail requests to create rollback-resistant keys when the storage is full.
begin
The begin()
entry point begins a cryptographic operation using the
specified key, for the specified purpose, with the specified parameters (as
appropriate). It returns a new IKeyMintOperation
Binder object
that is used to complete the operation. In addition, a challenge value is
returned that is used as part of the authentication token in authenticated
operations.
A KeyMint implementation supports at least 16 concurrent
operations. Keystore uses up to 15, leaving one for vold
to use for password
encryption. When Keystore has 15 operations in progress (begin()
has
been called, but finish
or abort
haven't been
called) and it receives a request to begin a 16th, it calls
abort()
on the least-recently used operation to reduce the number of
active operations to 14 before calling begin()
to start the
newly requested operation.
If Tag::APPLICATION_ID
or Tag::APPLICATION_DATA
were specified during key generation or import, calls to begin()
must
include those tags with the originally specified values in
the params
argument to this method.
Error handling
If a method on a IKeyMintOperation
returns an error code other
than ErrorCode::OK
, the operation is aborted and the operation
Binder object is invalidated. Any future use of the object
returns ErrorCode::INVALID_OPERATION_HANDLE
.
Authorization enforcement
Key authorization enforcement is performed primarily
in begin()
. The one exception is the case where the key
has one or more Tag::USER_SECURE_ID
values, and
doesn't have a Tag::AUTH_TIMEOUT
value.
In this case, the key requires an authorization per operation, and the update()
or finish()
methods receive an auth token in the authToken
argument. To ensure that the token is valid, the KeyMint implementation:
- Verifies the HMAC signature on the auth token.
- Checks that the token contains a secure user ID matching one associated with the key.
- Checks that the token's auth type matches the key's
Tag::USER_AUTH_TYPE
. - Checks that the token contains the challenge value for the current operation in the challenge field.
If these conditions aren't met, KeyMint
returns ErrorCode::KEY_USER_NOT_AUTHENTICATED
.
The caller provides the authentication token to every call to update()
and
finish()
. The implementation can validate the token only once.