Hardware-backed Keystore

The availability of a trusted execution environment in a system on a chip (SoC) offers an opportunity for Android devices to provide hardware-backed, strong security services to the Android OS, to platform services, and even to third-party apps (in the form of Android-specific extensions to the standard Java Cryptography Architecture, see KeyGenParameterSpec).

Glossary

Here is a quick overview of Keystore components and their relationships.

AndroidKeyStore
The Android Framework API and component used by apps to access Keystore functionality. It is an implementation of the standard Java Cryptography Architecture APIs, but also adds Android-specific extensions and consists of Java code that runs in the app's own process space. AndroidKeyStore fulfills app requests for Keystore behavior by forwarding them to the keystore daemon.
keystore daemon
An Android system daemon that provides access to all Keystore functionality through a Binder API. This daemon is responsible for storing keyblobs created by the underlying KeyMint (or Keymaster) implementation, which contain the secret key material, encrypted so Keystore can store them but not use or reveal them.
KeyMint HAL service
An AIDL server that implements the IKeyMintDevice HAL, providing access to the underlying KeyMint TA.
KeyMint trusted app (TA)
Software running in a secure context, most often in TrustZone on an ARM SoC, that provides all of the secure cryptographic operations. This app has access to the raw key material, and validates all of the access control conditions on keys before allowing their use.
LockSettingsService
The Android system component responsible for user authentication, both password and fingerprint. It's not part of Keystore, but is relevant because Keystore supports the concept of authentication bound keys: keys that can be used only if the user has authenticated. LockSettingsService interacts with the Gatekeeper TA and Fingerprint TA to obtain authentication tokens, which it provides to the keystore daemon, and which are consumed by the KeyMint TA.
Gatekeeper TA
The component running in the secure environment that's responsible for authenticating user passwords and generating authentication tokens used to prove to the KeyMint TA that an authentication was done for a particular user at a particular point in time.
Fingerprint TA
The component running in the secure environment that's responsible for authenticating user fingerprints and generating authentication tokens used to prove to the KeyMint TA that an authentication was done for a particular user at a particular point in time.

Architecture

The Android Keystore API and the underlying KeyMint HAL provide a basic but adequate set of cryptographic primitives to allow the implementation of protocols using access-controlled, hardware-backed keys.

The KeyMint HAL is an OEM-provided service used by the Keystore service to provide hardware-backed cryptographic services. To keep private key material secure, HAL implementations don't perform any sensitive operations in user space, or even in kernel space. Instead, the KeyMint HAL service running in Android delegates sensitive operations to a TA running in some kind of secure environment, typically by marshalling and unmarshalling requests in some implementation-defined wire format.

The resulting architecture looks like this:

Access to KeyMint

Figure 1. Access to KeyMint.

The KeyMint HAL API is low level, used by platform-internal components, and not exposed to app developers. The higher-level Java API that is available to apps is described on the Android Developer site.

Access control

Android Keystore provides a central component for the storage and use of hardware-backed cryptographic keys, both for apps and for other system components. As such, access to any individual key is normally limited to the app or system component that created the key.

Keystore domains

To support this access control, keys are identified to Keystore with a key descriptor. This key descriptor indicates a domain that the descriptor belongs to, together with an identity within that domain.

Android apps access Keystore using the standard Java Cryptography Architecture, which identifies keys with a string alias. This method of identification maps to the Keystore APP domain internally; the UID of the caller is also included to disambiguate keys from different apps, preventing one app from accessing another's keys.

Internally, the frameworks code also receives a unique numeric key ID after a key has been loaded. This numeric ID is used as the identifier for key descriptors within the KEY_ID domain. However, access control is still performed: even if one app discovers a key ID for another app's key, it can't use it in normal circumstances.

However, it is possible for an app to grant use of a key to a different app (as identified by UID). This grant operation returns a unique grant identifier, which is used as the identifier for key descriptors within the GRANT domain. Again, access control is still performed: even if a third app discovers the grant ID for a grantee's key, it can't use it.

Keystore also supports two other domains for key descriptors, which are used for other system components and aren't available for app-created keys:

  • The BLOB domain indicates that there is no identifier for the key in the key descriptor; instead, the key descriptor holds the keyblob itself and the client handles keyblob storage. This is used by clients (for example, vold) that need to access Keystore before the data partition is mounted.
  • The SELINUX domain allows system components to share keys, with access governed by a numeric identifier that corresponds to an SELinux label (see SELinux policy for keystore_key).

SELinux policy for keystore_key

The identifier values used for Domain::SELINUX key descriptors are configured in the keystore2_key_context SELinux policy file. Each line in these files maps a numeric to an SELinux label, for example:

# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and
# Settings to share keystore keys.
102            u:object_r:wifi_key:s0

A component that needs access to the key with ID 102 in the SELINUX domain must have the corresponding SELinux policy. For example, to allow wpa_supplicant to get and use these keys, add the following line to hal_wifi_supplicant.te:

allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };

The numeric identifiers for Domain::SELINUX keys are divided into ranges to support different partitions without collisions:

Partition Range Config files
System 0 ... 9,999 /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
Extended System 10,000 ... 19,999 /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
Product 20,000 ... 29,999 /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
Vendor 30,000 ... 39,999 /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts

The following specific values have been defined for the system partition:

Namespace ID SEPolicy label UID Description
0 su_key N/A Super user key. Only used for testing on userdebug and eng builds. Not relevant on user builds.
1 shell_key N/A Namespace available to shell. Mostly used for testing, but can be used on user builds as well from the command line.
100 vold_key N/A Intended for use by vold.
101 odsign_key N/A Used by the on-device signing daemon.
102 wifi_key AID_WIFI(1010) Used by Android's Wifi subsystem including wpa_supplicant.
103 locksettings_key N/A Used by LockSettingsService
120 resume_on_reboot_key AID_SYSTEM(1000) Used by Android's system server to support resume on reboot.

Access vectors

Keystore allows control over which operations can be performed on a key, in addition to controlling overall access to a key. The keystore2_key permissions are described in the KeyPermission.aidl file.

System permissions

In addition to the per-key access controls described in SELinux policy for keystore_key, the following table describes other SELinux permissions that are required to perform various system and maintenance operations:

Permission Meaning
add_auth Required for adding auth tokens to Keystore; used by authentication providers such as Gatekeeper or BiometricManager.
clear_ns Required for deleting all keys in a specific namespace; used as a maintenance operation when apps are uninstalled.
list Required by the system for enumerating keys by various properties, such as ownership or whether they are authentication bound. This permission isn't required by callers enumerating their own namespaces (covered by the get_info permission).
lock Required for notifying keystore that the device was locked, which in turn evicts super-keys to ensure that authentication bound keys are unavailable.
unlock Required to notifying keystore that the device was unlocked, restoring access to the super-keys that protect authentication bound keys.
reset Required for resetting Keystore to factory default, deleting all keys that aren't vital to the functioning of the Android OS.

History

In Android 5 and lower, Android had a simple, hardware-backed cryptographic services API, provided by versions 0.2 and 0.3 of the Keymaster hardware abstraction layer (HAL). Keystore provided digital signing and verification operations, plus generation and import of asymmetric signing key pairs. This is already implemented on many devices, but there are many security goals that can't easily be achieved with only a signature API. Android 6.0 extended the Keystore API to provide a broader range of capabilities.

Android 6.0

In Android 6.0, Keymaster 1.0 added symmetric cryptographic primitives, AES and HMAC, and an access control system for hardware-backed keys. Access controls are specified during key generation and enforced for the lifetime of the key. Keys can be restricted to be usable only after the user has been authenticated, and only for specified purposes or with specified cryptographic parameters.

In addition to expanding the range of cryptographic primitives, Keystore in Android 6.0 added the following:

  • A usage control scheme to allow key usage to be limited, to mitigate the risk of security compromise due to misuse of keys
  • An access control scheme to enable restriction of keys to specified users, clients, and a defined time range

Android 7.0

In Android 7.0, Keymaster 2 added support for key attestation and version binding.

Key attestation provides public key certificates that contain a detailed description of the key and its access controls, to make the key's existence in secure hardware and its configuration remotely verifiable.

Version binding binds keys to the operating system and patch level version. This ensures that an attacker who discovers a weakness in an old version of the system or the TEE software can't roll a device back to the vulnerable version and use keys created with the newer version. In addition, when a key with a given version and patch level is used on a device that has been upgraded to a newer version or patch level, the key is upgraded before it can be used, and the previous version of the key invalidated. As the device is upgraded, the keys ratchet forward along with the device, but any reversion of the device to a previous release causes the keys to be unusable.

Android 8.0

In Android 8.0, Keymaster 3 transitioned from the old-style C-structure HAL to the C++ HAL interface generated from a definition in the new hardware interface definition language (HIDL). As part of the change, many of the argument types changed, though types and methods have a one-to-one correspondence with the old types and the HAL struct methods.

In addition to this interface revision, Android 8.0 extended the attestation feature of Keymaster 2 to support ID attestation. ID attestation provides a limited and optional mechanism for strongly attesting to hardware identifiers, such as device serial number, product name, and phone ID (IMEI or MEID). To implement this addition, Android 8.0 changed the ASN.1 attestation schema to add ID attestation. Keymaster implementations need to find some secure way to retrieve the relevant data items, as well as to define a mechanism for securely and permanently disabling the feature.

Android 9

In Android 9, updates included:

  • Update to Keymaster 4
  • Support for embedded Secure Elements
  • Support for secure key import
  • Support for 3DES encryption
  • Changes to version binding so that boot.img and system.img have separately set versions to allow for independent updates

Android 10

Android 10 introduced version 4.1 of the Keymaster HAL, which added:

  • Support for keys that are only usable when the device is unlocked
  • Support for keys that can only be used in early boot stages
  • Optional support for hardware-wrapped storage keys
  • Optional support for device-unique attestation in StrongBox

Android 12

Android 12 introduced the new KeyMint HAL, which replaces the Keymaster HAL but provides similar functionality. In addition to all of the features above, the KeyMint HAL also includes:

  • Support for ECDH key agreement
  • Support for user-specified attestation keys
  • Supoprt for keys with a limited number of uses

Android 12 also includes a new version of the keystore system daemon, rewritten in Rust and known as keystore2

Android 13

Android 13 added v2 of the KeyMint HAL, which adds support for Curve25519 for both signing and key agreement.