Authentication

Android uses the concept of user-authentication-gated cryptographic keys that requires the following components:

  • Cryptographic key storage and service provider. Stores cryptographic keys and provides standard crypto routines on top of those keys. Android supports a hardware-backed Keystore and Keymaster for cryptographic services, including hardware-backed cryptography for key storage that might include a Trusted Execution Environment (TEE) or Secure Element (SE), such as Strongbox.
  • User authenticators. Attest to the user's presence and/or successful authentication. Android supports Gatekeeper for PIN/pattern/password authentication and Fingerprint for fingerprint authentication. Devices that ship with Android 9 and higher can use BiometricPrompt as a single integration point for fingerprint and additional biometrics. These components communicate their authentication state with the keystore service via an authenticated channel. (The Android Keystore system at the framework level is also backed by the keystore service.)

Gatekeeper, Fingerprint, and Biometric components work with Keystore and other components to support the use of hardware-backed authentication tokens (AuthTokens).

Enrollment

On first boot of the device after a factory reset, all authenticators are prepared to receive credential enrollments from the user. A user must initially enroll a PIN/pattern/password with Gatekeeper. This initial enrollment creates a randomly generated, 64-bit User SID (user secure identifier) that serves as an identifier for the user and as a binding token for the user's cryptographic material. This User SID is cryptographically bound to the user's password; successful authentications to Gatekeeper result in AuthTokens that contain the User SID for that password.

A user who wants to change a credential must present an existing credential. If an existing credential is verified successfully, the User SID associated with the existing credential is transferred to the new credential, enabling the user to keep accessing keys after changing a credential. If a user does not present an existing credential, the new credential is enrolled with a fully random User SID. The user can access the device, but keys created under the old User SID are permanently lost. This is known as an untrusted enroll.

Under normal circumstances, the Android framework does not allow an untrusted enroll, so most users won't ever see this functionality. However, forcible password resets, either by a device administrator or an attacker, may cause this to occur.

Authentication

After a user has set up a credential and received a User SID, they may proceed to start authentication, which begins when a user provides a PIN, pattern, password, or fingerprint. All TEE components share a secret key which they use to authenticate each other's messages.

Authentication flow
Figure 1. Authentication flow.
  1. A user provides an authentication method and the associated service makes a request to the the associated daemon.
    • For PIN, pattern, or password, the LockSettingsService makes a request to gatekeeperd.
    • Biometrics-based authentication flows depend on the Android version. On devices running Android 8.x and lower, FingerprintService makes a request to fingerprintd). On devices running Android 9 and higher, BiometricPrompt makes a request to the appropriate biometric daemon (for example, fingerprintd for fingerprints or faced for face) using the appropriate BiometricManager class, such as FingerprintManager or FaceManager. Regardless of version, biometric authentication occurs asynchronously after the request is sent.
  2. The daemon sends data to its counterpart, which generates an AuthToken:
    • For PIN/pattern/password authentication, gatekeeperd sends the PIN, pattern, or password hash to Gatekeeper in the TEE. If authentication in the TEE is successful, Gatekeeper in the TEE sends an AuthToken containing the corresponding User SID (signed with the AuthToken HMAC key) to its counterpart in the Android OS.
    • For fingerprint authentication, fingerprintd listens for fingerprint events and sends the data to Fingerprint in the TEE. If authentication in the TEE is successful, Fingerprint in the TEE sends an AuthToken (signed with the AuthToken HMAC key) to its counterpart in the Android OS.
    • For other biometric authentication, the appropriate biometric daemon listens for the biometric event and sends it to the appropriate biometric TEE component.
  3. The daemon receives a signed AuthToken and passes it to the keystore service via an extension to the keystore service's Binder interface. (gatekeeperd also notifies the keystore service when the device is re-locked and when the device password changes.)
  4. The keystore service passes the AuthTokens to Keymaster and verifies them using the key shared with the Gatekeeper and supported biometric TEE component. Keymaster trusts the timestamp in the token as the last authentication time and bases a key release decision (to allow an app to use the key) on the timestamp.

AuthToken format

To ensure token sharing and compatibility across languages and components, the AuthToken format is described in hw_auth_token.h. The format is a simple serialization protocol with fixed size fields:

Field Type Required Description
AuthToken Version 1 byte Yes Group tag for all fields below.
Challenge 64-bit unsigned integer No A random integer to prevent replay attacks. Usually the ID of a requested crypto operation. Currently used by transactional fingerprint authorizations. If present, the AuthToken is valid only for crypto operations containing the same challenge.
User SID 64-bit unsigned integer Yes Non-repeating user identifier tied cryptographically to all keys associated with device authentication. For details, see Gatekeeper.
Authenticator ID (ASID) 64-bit unsigned integer in network order No Identifier used to bind to a specific authenticator policy. All authenticators have their own value of ASID that they can change according to their own requirements.
Authenticator type 32-bit unsigned integer in network order Yes
  • 0x00 is Gatekeeper.
  • 0x01 is Fingerprint.
Timestamp 64-bit unsigned integer in network order Yes Time (in milliseconds) since the most recent system boot.
AuthToken HMAC (SHA-256) 256-bit blob Yes Keyed SHA-256 MAC of all fields except the HMAC field.

Device boot flow

On every boot of a device, the AuthToken HMAC key must be generated and shared with all TEE components (Gatekeeper, Keymaster, and supported biometrics trustlets). Thus, for added protection against replay attacks, the HMAC key must be randomly generated every time the device reboots.

The protocol for sharing this HMAC key with all components is a platform-dependent implementation feature. The key must never be made available outside the TEE. If a TEE OS lacks an internal inter-process communication (IPC) mechanism and needs to transfer the data through the untrusted OS, the transfer must be done via a secure key exchange protocol.

The Trusty operating system, which runs next to Android, is an example of a TEE, but other TEEs can be used instead. Trusty uses an internal IPC system to communicate directly between Keymaster and Gatekeeper or the appropriate biometric trustlet. The HMAC key is kept solely in Keymaster; Fingerprint and Gatekeeper request the key from Keymaster for each use and do not persist or cache the value.

As some TEEs lack an IPC infrastructure, no communication occurs between applets in the TEE. This also permits the keystore service to quickly deny requests that are bound to fail as it has knowledge of the authentication table in the system, saving a potentially costly IPC into the TEE.