身份验证

Android 使用用户身份验证门控加密密钥的概念,这需要以下组件

  • 加密密钥存储和服务提供商。 存储加密密钥,并在这些密钥之上提供标准加密例程。Android 支持硬件支持的 Keystore 和 Keymaster,用于提供加密服务,包括用于密钥存储的硬件支持加密,其中可能包括可信执行环境 (TEE) 或安全元件 (SE),例如 Strongbox。
  • 用户身份验证器。 证明用户在场和/或身份验证成功。Android 支持 Gatekeeper 用于 PIN 码/图案/密码身份验证,以及 指纹 用于指纹身份验证。搭载 Android 9 及更高版本的设备可以使用 BiometricPrompt 作为指纹和其他生物识别技术的单一集成点。这些组件通过经过身份验证的通道将其身份验证状态与密钥库服务通信。(框架级别的 Android Keystore 系统 也由密钥库服务提供支持。)

Gatekeeper、指纹和生物识别组件与 Keystore 及其他组件协同工作,以支持使用硬件支持的 身份验证令牌 (AuthToken)。

注册

在设备恢复出厂设置后首次启动时,所有身份验证器都已准备好接收用户的凭据注册。用户必须首先使用 Gatekeeper 注册 PIN 码/图案/密码。初始注册会创建一个随机生成的 64 位用户安全标识符 (SID),该标识符用作用户的标识符以及用户加密材料的绑定令牌。此用户 SID 以加密方式绑定到用户的密码;对 Gatekeeper 的成功身份验证会生成包含该密码的用户 SID 的 AuthToken。

想要更改凭据的用户必须出示现有凭据。如果现有凭据验证成功,则与现有凭据关联的用户 SID 将转移到新凭据,从而使用户在更改凭据后仍可访问密钥。如果用户未出示现有凭据,则新凭据将使用完全随机的用户 SID 进行注册。用户可以访问设备,但旧用户 SID 下创建的密钥将永久丢失。这称为不受信任的注册

在正常情况下,Android 框架不允许不受信任的注册,因此大多数用户永远不会看到此功能。但是,设备管理员或攻击者强制重置密码可能会导致这种情况发生。

身份验证

用户设置凭据并收到用户 SID 后,即可开始身份验证,身份验证在用户提供 PIN 码、图案、密码或指纹时开始。所有 TEE 组件共享一个密钥,他们使用该密钥对彼此的消息进行身份验证。

Authentication flow
图 1. 身份验证流程
  1. 用户提供一种身份验证方法,关联服务向关联的守护进程发出请求。
    • 对于 PIN 码、图案或密码,LockSettingsServicegatekeeperd 发出请求。
    • 基于生物识别技术的身份验证流程取决于 Android 版本。在运行 Android 8.x 及更低版本的设备上,FingerprintServicefingerprintd 发出请求。在运行 Android 9 及更高版本的设备上,BiometricPrompt 使用相应的 BiometricManager 类(例如,FingerprintManager 用于指纹或 FaceManager 用于面部)向相应的生物识别守护进程(例如,fingerprintd 用于指纹或 faced 用于面部)发出请求。无论版本如何,生物识别身份验证都在发送请求后异步发生。
  2. 守护进程将数据发送到其对应方,后者生成 AuthToken
    • 对于 PIN 码/图案/密码身份验证,gatekeeperd 将 PIN 码、图案或密码哈希发送到 TEE 中的 Gatekeeper。如果 TEE 中的身份验证成功,TEE 中的 Gatekeeper 会向 Android 操作系统中的对应方发送一个 AuthToken,其中包含相应的用户 SID(使用 AuthToken HMAC 密钥签名)。
    • 对于指纹身份验证,fingerprintd 侦听指纹事件并将数据发送到 TEE 中的指纹。如果 TEE 中的身份验证成功,TEE 中的指纹会向 Android 操作系统中的对应方发送 AuthToken(使用 AuthToken HMAC 密钥签名)。
    • 对于其他生物识别身份验证,相应的生物识别守护进程侦听生物识别事件并将其发送到相应的生物识别 TEE 组件。
  3. 守护进程接收签名的 AuthToken,并通过密钥库服务 Binder 接口的扩展将其传递给密钥库服务。(gatekeeperd 还在设备重新锁定和设备密码更改时通知密钥库服务。)
  4. 密钥库服务将 AuthToken 传递给 Keymaster,并使用与 Gatekeeper 和受支持的生物识别 TEE 组件共享的密钥对其进行验证。Keymaster 信任令牌中的时间戳作为上次身份验证时间,并根据时间戳做出密钥发布决策(允许应用使用密钥)。

AuthToken 格式

为确保令牌共享以及跨语言和组件的兼容性,AuthToken 格式在 hw_auth_token.h 中进行了描述。该格式是一个简单的序列化协议,具有固定大小的字段。

字段 类型 必需 说明
AuthToken 版本 1 字节 以下所有字段的组标记。
质询 64 位无符号整数 一个随机整数,用于防止重放攻击。通常是请求的加密操作的 ID。当前由事务性指纹授权使用。如果存在,则 AuthToken 仅对包含相同质询的加密操作有效。
用户 SID 64 位无符号整数 非重复用户标识符,以加密方式绑定到与设备身份验证关联的所有密钥。有关详细信息,请参阅 Gatekeeper
身份验证器 ID (ASID) 网络字节序中的 64 位无符号整数 用于绑定到特定身份验证器策略的标识符。所有身份验证器都有自己的 ASID 值,他们可以根据自己的要求更改该值。
身份验证器类型 网络字节序中的 32 位无符号整数
  • 0x00 是 Gatekeeper。
  • 0x01 是指纹。
时间戳 网络字节序中的 64 位无符号整数 自最近一次系统启动以来的时间(以毫秒为单位)。
AuthToken HMAC (SHA-256) 256 位 Blob 除 HMAC 字段外的所有字段的密钥 SHA-256 MAC。

设备启动流程

在设备每次启动时,都必须生成 AuthToken HMAC 密钥并与所有 TEE 组件(Gatekeeper、Keymaster 和受支持的生物识别信任应用)共享。因此,为了更好地防止重放攻击,HMAC 密钥必须在设备每次重启时随机生成。

与所有组件共享此 HMAC 密钥的协议是平台相关的实现功能。密钥绝不能在 TEE 外部提供。如果 TEE 操作系统缺少内部进程间通信 (IPC) 机制,并且需要通过不受信任的操作系统传输数据,则传输必须通过安全密钥交换协议完成。

Trusty 操作系统与 Android 并行运行,是 TEE 的一个示例,但也可以使用其他 TEE。Trusty 使用内部 IPC 系统在 Keymaster 和 Gatekeeper 或相应的生物识别信任应用之间直接通信。HMAC 密钥仅保留在 Keymaster 中;指纹和 Gatekeeper 在每次使用时都从 Keymaster 请求密钥,并且不持久化或缓存该值。

由于某些 TEE 缺少 IPC 基础架构,因此 TEE 中的小程序之间不会发生通信。这也允许密钥库服务快速拒绝绑定到失败的请求,因为它了解系统中的身份验证表,从而节省了可能代价高昂的 IPC 进入 TEE 的开销。