Gatekeeper

The Gatekeeper subsystem performs device pattern/password authentication in a Trusted Execution Environment (TEE). Gatekeeper enrolls and verifies passwords using a hardware-backed secret key. Additionally, Gatekeeper throttles consecutive failed verification attempts and must refuse to service requests based on a given timeout and a given number of consecutive failed attempts.

When users verify their passwords, Gatekeeper emits an authentication token that is signed with a per-boot HMAC key that is available only to secure components, and this token is sent to the hardware-backed Keystore. That is, a Gatekeeper authentication token notifies Keystore that authentication-bound keys (for example, keys that apps have created) can be used by apps.

Architecture

Gatekeeper involves three main components:

  • gatekeeperd (Gatekeeper daemon) — A C++ Binder service in Android that contains platform-independent logic implementing the IGateKeeperService AIDL interface, based on an underlying vendor-specific implementation of IGatekeeper.
  • Gatekeeper hardware abstraction layer (HAL) service — A vendor-specific implementation of the IGatekeeper AIDL interface. This HAL service runs in Android, but the core Gatekeeper functionality needs to run in a secure environment, so it typically communicates with the Gatekeeper TA.
  • Gatekeeper Trusted Application (TA) — A vendor-specific implementation that runs in the TEE, and performs the actual password or pattern verification.

The LockSettingsService makes a request (through Binder) that reaches the gatekeeperd daemon in the Android OS. The gatekeeperd daemon then makes a request of the IGatekeeper HAL service, and that in turn reaches its counterpart Gatekeeper TA in the TEE:

Gatekeeper flow

Figure 1. High-level data flow for authentication by GateKeeper.

The gatekeeperd daemon gives the Android framework APIs access to the HAL, and participates in reporting device authentications to Keystore. The gatekeeperd daemon runs in its own process and is separate from the system server.

HAL implementation

The gatekeeperd daemon uses the IGatekeeper HAL to interact with the underlying Gatekeeper TA for password authentication. The Gatekeeper TA implementation must be able to sign (enroll) and verify blobs. All implementations are expected to adhere to the standard format for the authentication token (HardwareAuthToken) generated on each successful password verification. For details on the content and semantic of the HardwareAuthToken, see the HardwareAuthToken.aidl definition.

Vendor implementations of the IGatekeeper HAL must implement the enroll and verify functions:

  • The enroll method takes a password blob, signs it, and returns the signature as a handle. The returned blob (from a call to enroll) must have the structure shown in system/gatekeeper/include/gatekeeper/password_handle.h.
  • The verify function must compare the signature produced by the provided password and ensure it matches the enrolled password handle.

The key used to enroll and verify must never change, and should be re-derivable at every device boot.

Trusty and other implementations

The Trusty operating system is Google's open source trusted OS for TEE environments and contains an approved implementation of Gatekeeper. However any TEE OS can implement Gatekeeper as long as the TEE has access to a persistent hardware-backed key and a secure, monotonic clock that ticks in suspend.

Trusty uses an internal IPC system to communicate a shared secret directly between KeyMint and the Trusty implementation of Gatekeeper (the Trusty Gatekeeper). This shared secret is used for signing authentication tokens sent to Keystore to provide attestations of password verification. Trusty Gatekeeper requests the key from KeyMint for each use and does not persist or cache the value. Implementations are free to share this secret in any way that does not compromise security.

The HMAC key used to enroll and verify passwords is derived and kept solely in Gatekeeper.

Android provides a generic C++ Gatekeeper implementation that requires only the addition of device-specific routines to be complete; the Trusty implementation is based on this. To implement a TEE Gatekeeper with device-specific code for your TEE, refer to the functions and comments in system/gatekeeper/include/gatekeeper/gatekeeper.h. The primary responsibilities of a compliant implementation include:

  • Adherence to the IGatekeeper HAL.
  • Returned authentication tokens must be formatted according to the HardwareAuthToken specification (described in HardwareAuthToken.aidl).
  • The TEE Gatekeeper must be able to share an HMAC key with KeyMint, using one of the following:
    • Shared secret agreement: Gatekeeper can take part in the per-boot negotiation of the HMAC key by implementing the ISharedSecret HAL. This requires that Gatekeeper and KeyMint both have access to a common preshared secret.
    • Direct access: Gatekeeper can retrieve the HMAC key from KeyMint using a TEE-internal interprocess communication mechanism, either on demand or on first use (cached thereafter).

User secure IDs (SIDs)

A user SID is the TEE representation of a user (with no strong connection to an Android user ID). The SID is generated with a cryptographic pseudorandom number generator (PRNG) whenever a user enrolls a new password without providing a previous one. This is known as an untrusted re-enroll and normally happens only when a user first sets a password or pattern.

A trusted re-enroll occurs when a user provides a valid, previous password, such as when changing password. In this case, the user SID is migrated to the new password handle, conserving the keys that were bound to it.

The user SID is included in the HMAC authentication along with the password in the password handle when the password is enrolled.

User SIDs are included in the HardwareAuthToken returned by the verify() function and associated to all authentication-bound Keystore keys (for details on the HardwareAuthToken format and Keystore, see Authentication).

Note that as an untrusted call to the enroll() function changes the user SID, the call renders the keys bound to that password useless. Attackers can change the password for the device if they control the Android OS, but they destroy root-protected, sensitive keys in the process.

Request throttling

Gatekeeper must be able to securely throttle brute-force attempts on a user credential. As shown in GatekeeperVerifyResponse.aidl, the HAL provides for returning a timeout in milliseconds. The timeout informs the client not to call Gatekeeper again until after the timeout has elapsed. Gatekeeper should not service requests if there is a pending timeout.

Gatekeeper must write a failure counter before verifying a user password. If the password verification succeeds, the failure counter should be cleared. This prevents attacks that prevent throttling by disabling the embedded MMC (eMMC) after issuing a verify call. The enroll function also verifies the user password (if provided) and must be throttled in the same way.

If supported by the device, it is highly recommended that the failure counter be written to secure storage. If the device does not support file-based encryption, or if secure storage is too slow, implementations may use Replay Protected Memory Block (RPMB) directly.