Gatekeeper

The Gatekeeper subsystem performs device pattern/password authentication in a Trusted Execution Environment (TEE). Gatekeeper enrolls and verifies passwords via an HMAC with 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 uses the TEE-derived shared secret to sign an authentication attestation to send to the hardware-backed Keystore. That is, a Gatekeeper attestation notifies Keystore that authentication-bound keys (for example, keys that apps have created) can be released for use by apps.

Architecture

Gatekeeper involves three main components:

  • gatekeeperd (Gatekeeper daemon). A C++ binder service containing platform-independent logic and corresponding to the GateKeeperService Java interface.
  • Gatekeeper Hardware Abstraction Layer (HAL). The HAL interface in hardware/libhardware/include/hardware/gatekeeper.h, and the implementing module.
  • Gatekeeper (TEE). The TEE counterpart of gatekeeperd. A TEE-based implementation of Gatekeeper.

Gatekeeper requires implementation of the Gatekeeper HAL (specifically the functions in hardware/libhardware/include/hardware/gatekeeper.h) and the TEE-specific Gatekeeper component (based in part on the system/gatekeeper/include/gatekeeper/gatekeeper.h header file that includes pure virtual functions for creating/accessing keys and computing signatures).

The LockSettingsService makes a request (via Binder) that reaches the gatekeeperd daemon in the Android OS. The gatekeeperd daemon then makes a request that reaches its counterpart (Gatekeeper) 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 HAL to interact with the gatekeeperd daemon's TEE counterpart for password authentication. The HAL implementation must be able to sign (enroll) and verify blobs. All implementations are expected to adhere to the standard format for the authentication token (AuthToken) generated on each successful password verification. For details on the content and semantic of the AuthToken, see AuthToken format.

Implementations of the hardware/libhardware/include/hardware/gatekeeper.h header file must implement the enroll and verify functions:

  • The enroll function 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, you can use any TEE OS to implement Gatekeeper as long as the TEE has access to a 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 Keymaster and the Trusty implementation of Gatekeeper (the Trusty Gatekeeper). This shared secret is used for signing AuthTokens sent to Keystore to provide attestations of password verification. Trusty Gatekeeper requests the key from Keymaster 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++ implementation of GateKeeper that requires only the addition of device-specific routines to be complete. 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. For the TEE GateKeeper, the primary responsibilities of a compliant implementation include:

  • Adherence to the Gatekeeper HAL.
  • Returned AuthTokens must be formatted according to the AuthToken specification (described in Authentication).
  • The TEE Gatekeeper must be able to share an HMAC key with Keymaster, either by requesting the key through a TEE IPC on demand or maintaining a valid cache of the value at all times.

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 is not allowed by the Android framework in normal circumstances. A trusted re-enroll occurs when a user provides a valid, previous 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 HMAC'ed along with the password in the password handle when the password is enrolled.

User SIDs are written into the AuthToken returned by the verify function and associated to all authentication-bound Keystore keys (for details on the AuthToken format and Keystore, see Authentication). As an untrusted call to the enroll function will change the User SID, the call will render the keys bound to that password useless. Attackers can change the password for the device if they control the Android OS, but they will 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 hardware/libhardware/include/hardware/gatekeeper.h, 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.