KeyMint functions

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.