人脸验证 HIDL

概述

人脸验证允许用户仅通过查看设备正面来解锁设备。Android 10 新增了对新人脸验证堆栈的支持,该堆栈可以安全地处理相机帧,在支持的硬件上进行人脸验证期间保持安全性和隐私。Android 10 还为符合安全要求的实现提供了一种简单的方法来启用应用程序集成以进行交易,例如网上银行或其他服务。

Android 人脸验证堆栈是 Android 10 中的一项新实现。新实现引入了 IBiometricsFace.halIBiometricsFaceClientCallback.haltypes.hal 接口。

架构

BiometricPrompt API 包括所有生物识别身份验证,包括人脸、指纹和虹膜。Face HAL 与以下组件交互。

Biometric stack

图 1. 生物识别堆栈。

FaceManager

FaceManager 是一个私有接口,用于维护与 FaceService 的连接。Keyguard 使用它来访问带有自定义 UI 的人脸验证。应用无权访问 FaceManager,必须改用 BiometricPrompt

FaceService

这是框架实现,用于管理对人脸验证硬件的访问。它包含基本的注册和身份验证状态机以及各种其他帮助程序(例如,枚举)。出于稳定性和安全方面的考虑,不允许在此进程中运行任何供应商代码。所有供应商代码都通过 Face 1.0 HIDL 接口 访问。

faced

这是一个 Linux 可执行文件,实现了 FaceService 使用的 Face 1.0 HIDL 接口。它将自身注册为 IBiometricsFace@1.0,以便 FaceService 可以找到它。

实现

Face HIDL

要实现 Face HIDL,您必须在供应商特定的库中实现 methodsIBiometricsFace.hal 的所有方法。

错误消息

错误消息通过回调发送,并在发送后将状态机返回到 idle 状态。大多数消息都有相应的面向用户的字符串来告知用户错误,但并非所有错误都具有此面向用户的字符串。有关错误消息的更多信息,请参阅 types.hal。所有错误消息都表示终端状态,这意味着框架假定 HAL 在发送错误消息后返回到空闲状态。

采集消息

采集消息在注册或身份验证期间传递,旨在指导用户成功完成注册或身份验证。每个序数都有来自 FaceAuthenticationManager.java 文件的关联消息。可以添加供应商特定的消息,前提是提供了相应的帮助字符串。采集消息本身不是终端状态;HAL 预计会发送尽可能多的消息以完成当前的注册或身份验证。如果采集消息导致无法取得进展的终端状态,则 HAL 应在采集消息之后发送错误消息,例如,图像太暗且持续太暗而无法取得进展。在这种情况下,在进行了多次尝试但无法取得进一步进展后,发送 UNABLE_TO_PROCESS 是合理的。

硬件

为了使设备符合 Android 10 的强生物识别要求,它们必须具有安全的硬件,以确保人脸数据的完整性和最终的身份验证比较。Android 兼容性定义文档 (CDD) 概述了所需的安全级别和可接受的欺骗接受率 (SAR)。安全处理和识别需要可信执行环境 (TEE)。此外,还需要安全的相机硬件,以防止对人脸验证进行注入攻击。例如,图像数据的关联内存页可以是特权的,并标记为只读,以便只有相机硬件可以更新它们。理想情况下,除了 TEE 和硬件之外,任何进程都不应具有访问权限。

由于人脸验证硬件差异很大,因此有必要开发特定于硬件的驱动程序来启用人脸验证,具体取决于特定的设备架构。因此,faced 没有参考实现。

方法

以下方法都是异步的,必须立即返回到框架。否则会导致系统运行缓慢并可能导致看门狗重置。建议使用带有多个线程的消息队列,以避免阻塞调用方。所有 GET 请求都应尽可能缓存信息,以便尽可能缩短阻塞调用方的时间。

方法 描述
setCallback() FaceService 调用,以将所有消息管道回自身。
setActiveUser() 设置活动用户,所有后续 HAL 操作都将应用于该用户。身份验证始终针对此用户,直到再次调用此方法。
revokeChallenge() 通过使 generateChallenge() 生成的质询失效来完成安全事务。
enroll() 注册用户的人脸。
cancel() 取消当前操作(例如,注册、身份验证、移除或枚举)并将 faced 返回到空闲状态。
enumerate() 枚举与活动用户关联的所有人脸模板。
remove() 移除人脸模板或与活动用户关联的所有人脸模板。
authenticate() 验证活动用户的身份。
userActivity() 此方法应仅在 HAL 处于身份验证或待机状态时使用。当 HAL 不处于这些状态之一时使用此方法会返回 OPERATION_NOT_SUPPORTED。在 HAL 已经进行身份验证时调用此方法可能会延长系统查找人脸的时间。
resetLockout() 当拒绝的人脸过多时,faced 需要进入锁定状态(LOCKOUTLOCKOUT_PERMANENT)。当它进入锁定状态时,需要将剩余时间发送到框架,以便框架可以将其显示给用户。与 setFeature() 一样,此方法需要活动的硬件身份验证令牌 (HAT) 才能安全地重置内部状态。仅为当前用户重置锁定。

其余三种方法都是同步的,应尽可能缩短阻塞时间,以避免框架停顿。

方法 描述
generateChallenge() 生成唯一的、加密安全的随机令牌,用于指示安全事务的开始。
setFeature() 为当前用户启用或禁用某项功能。出于安全原因,这需要 HAT 来根据上述质询检查用户的 PIN 码/图案/密码
getFeature() 检索功能的当前启用状态,如默认状态或上述对 setFeature() 的调用所指示的状态。如果人脸 ID 无效,则实现必须返回 ILLEGAL_ARGUMENT
getAuthenticatorId() 返回与当前人脸集关联的标识符。每当添加人脸时,此标识符必须更改

状态图

框架希望 faced 遵循以下状态图。

State Diagram

图 2. 人脸验证状态流程。