Gatekeeper 子系统在可信执行环境 (TEE) 中执行设备图案/密码身份验证。Gatekeeper 通过带有硬件支持的密钥的 HMAC 注册和验证密码。此外,Gatekeeper 会限制连续失败的验证尝试次数,并且必须根据给定的超时时间和给定的连续失败尝试次数拒绝为请求提供服务。
当用户验证其密码时,Gatekeeper 会使用 TEE 派生的共享密钥签署身份验证证明,以发送到硬件支持的密钥库 (Keystore)。也就是说,Gatekeeper 证明会通知密钥库 (Keystore),可以发布身份验证绑定的密钥(例如,应用创建的密钥),以供应用使用。
架构
Gatekeeper 包含三个主要组件
gatekeeperd
(Gatekeeper 守护进程)。一个 C++ Binder 服务,包含独立于平台的逻辑,并且对应于GateKeeperService
Java 接口。- Gatekeeper 硬件抽象层 (HAL)。
hardware/libhardware/include/hardware/gatekeeper.h
中的 HAL 接口以及实现模块。 - Gatekeeper (TEE)。
gatekeeperd
的 TEE 对等组件。Gatekeeper 的基于 TEE 的实现。
Gatekeeper 需要实现 Gatekeeper HAL(特别是 hardware/libhardware/include/hardware/gatekeeper.h
中的函数)和 TEE 专属 Gatekeeper 组件(部分基于 system/gatekeeper/include/gatekeeper/gatekeeper.h
头文件,该文件包含用于创建/访问密钥和计算签名的纯虚拟函数)。
LockSettingsService
发出请求(通过 Binder),该请求到达 Android 操作系统中的 gatekeeperd
守护进程。gatekeeperd
守护进程随后发出请求,该请求到达 TEE 中的对等组件 (Gatekeeper)

gatekeeperd
守护进程使 Android 框架 API 能够访问 HAL,并参与向密钥库 (Keystore) 报告设备身份验证。gatekeeperd
守护进程在其自己的进程中运行,并且与系统服务器分离。
HAL 实现
gatekeeperd
守护进程使用 HAL 与 gatekeeperd
守护进程的 TEE 对等组件交互,以进行密码身份验证。HAL 实现必须能够签名(注册)和验证 Blob。所有实现都应遵循每次密码验证成功时生成的身份验证令牌 (AuthToken) 的标准格式。如需详细了解 AuthToken 的内容和语义,请参阅AuthToken 格式。
hardware/libhardware/include/hardware/gatekeeper.h
头文件的实现必须实现 enroll
和 verify
函数
enroll
函数接受密码 Blob,对其进行签名,并将签名作为句柄返回。返回的 Blob(来自对enroll
的调用)必须具有system/gatekeeper/include/gatekeeper/password_handle.h
中所示的结构。verify
函数必须比较提供的密码生成的签名,并确保其与注册的密码句柄匹配。
用于注册和验证的密钥绝不能更改,并且应在每次设备启动时重新派生。
Trusty 和其他实现
Trusty 操作系统是 Google 针对 TEE 环境的开源可信操作系统,其中包含 GateKeeper 的已批准实现。但是,您可以使用任何 TEE 操作系统来实现 Gatekeeper,只要 TEE 可以访问硬件支持的密钥和安全单调时钟(在暂停状态下也会计时)。
Trusty 使用内部 IPC 系统在 Keymaster 和 Gatekeeper 的 Trusty 实现(Trusty Gatekeeper)之间直接通信共享密钥。此共享密钥用于签署发送到密钥库 (Keystore) 的 AuthToken,以提供密码验证的证明。Trusty Gatekeeper 每次使用时都从 Keymaster 请求密钥,并且不会持久保存或缓存该值。各种实现可以自由地以任何不损害安全性的方式共享此密钥。
用于注册和验证密码的 HMAC 密钥仅在 GateKeeper 中派生和保存。
Android 提供了一个 GateKeeper 的通用 C++ 实现,只需要添加设备专属例程即可完成。要使用设备专属代码为您的 TEE 实现 TEE Gatekeeper,请参阅 system/gatekeeper/include/gatekeeper/gatekeeper.h
中的函数和注释。对于 TEE GateKeeper,合规实现的主要职责包括:
- 遵守 Gatekeeper HAL。
- 返回的 AuthToken 必须按照 AuthToken 规范(在身份验证中描述)进行格式化。
- TEE Gatekeeper 必须能够与 Keymaster 共享 HMAC 密钥,可以通过按需通过 TEE IPC 请求密钥,也可以始终维护该值的有效缓存。
用户安全 ID (SID)
用户 SID 是用户的 TEE 表示形式(与 Android 用户 ID 没有强关联)。每当用户在未提供先前密码的情况下注册新密码时,都会使用加密伪随机数生成器 (PRNG) 生成 SID。这称为不受信任的重新注册,在正常情况下 Android 框架不允许这样做。当用户提供有效的先前密码时,会发生受信任的重新注册;在这种情况下,用户 SID 会迁移到新的密码句柄,从而保留绑定到该句柄的密钥。
注册密码时,用户 SID 会与密码句柄中的密码一起进行 HMAC 运算。
用户 SID 会写入 verify
函数返回的 AuthToken 中,并与所有身份验证绑定的密钥库 (Keystore) 密钥关联(如需详细了解 AuthToken 格式和密钥库 (Keystore),请参阅身份验证)。由于对 enroll
函数的不受信任调用会更改用户 SID,因此该调用会使绑定到该密码的密钥失效。攻击者如果控制了 Android 操作系统,则可以更改设备的密码,但在此过程中,他们会销毁受 root 保护的敏感密钥。
请求限制
GateKeeper 必须能够安全地限制用户凭据的暴力破解尝试。如 hardware/libhardware/include/hardware/gatekeeper.h
中所示,HAL 提供了以毫秒为单位返回超时时间的功能。超时时间会通知客户端在超时时间过去之前不要再次调用 GateKeeper;如果有待处理的超时,GateKeeper 不应为请求提供服务。
GateKeeper 必须在验证用户密码之前写入失败计数器。如果密码验证成功,则应清除失败计数器。这可以防止通过在发出 verify
调用后禁用嵌入式 MMC (eMMC) 来阻止限制的攻击。enroll
函数还会验证用户密码(如果提供),并且必须以相同的方式进行限制。
如果设备支持,强烈建议将失败计数器写入安全存储空间。如果设备不支持基于文件的加密,或者安全存储空间速度太慢,则实现可以直接使用重放保护内存块 (RPMB)。