指纹 HIDL

在配备指纹传感器的设备上,用户可以注册一个或多个指纹,并使用这些指纹解锁设备并执行其他任务。Android 使用指纹硬件接口定义语言 (HIDL) 连接到供应商特定的库和指纹硬件(例如,指纹传感器)。

要实现指纹 HIDL,您必须在供应商特定的库中实现 IBiometricsFingerprint.hal

指纹匹配

设备的指纹传感器通常处于空闲状态。但是,为了响应对 authenticateenroll 的调用,指纹传感器会侦听触摸(当用户触摸指纹传感器时,屏幕也可能会唤醒)。指纹匹配的高级流程包括以下步骤:

  1. 用户将手指放在指纹传感器上。
  2. 供应商特定的库确定当前注册的指纹模板集中是否存在指纹匹配。
  3. 匹配结果会传递到 FingerprintService

此流程假定设备上已注册指纹,即供应商特定的库已注册指纹模板。如需了解详情,请参阅身份验证

架构

指纹 HAL 与以下组件交互。

  • BiometricManager 直接与应用进程中的应用互动。每个应用都有一个 IBiometricsFingerprint.hal 实例。
  • FingerprintService 在系统进程中运行,负责处理与指纹 HAL 的通信。
  • 指纹 HAL 是 IBiometricsFingerprint HIDL 接口的 C/C++ 实现。其中包含与设备特定硬件通信的供应商特定库。
  • 密钥库 API 和 Keymaster 组件为安全密钥存储在安全环境(例如,可信执行环境 (TEE))中提供硬件后盾的加密技术。
Data flow for fingerprint
authentication
图 1. 指纹身份验证的高级数据流

供应商特定的 HAL 实现必须使用 TEE 要求的通信协议。原始图像和经过处理的指纹特征绝不能在不受信任的内存中传递。所有此类生物识别数据都需要存储在安全硬件(例如 TEE)中。Root 绝不能能够泄露生物识别数据。

FingerprintServicefingerprintd 通过指纹 HAL 调用供应商特定的库来注册指纹并执行其他操作。

Interaction with fingerprintd
图 2. 指纹守护程序与指纹供应商特定库的互动

实现指南

以下指纹 HAL 指南旨在确保指纹数据不会泄露,并且在从设备中移除用户时会被移除

  • 原始指纹数据或衍生物(例如,模板)绝不能从传感器驱动程序或 TEE 外部访问。如果硬件支持 TEE,则硬件访问必须仅限于 TEE,并受 SELinux 策略保护。串行外围接口 (SPI) 通道必须仅对 TEE 可访问,并且所有设备文件上都必须有显式的 SELinux 策略。
  • 指纹采集、注册和识别必须在 TEE 内部进行。
  • 只有指纹数据的加密形式才能存储在文件系统中,即使文件系统本身已加密也是如此。
  • 指纹模板必须使用私有的设备特定密钥进行签名。对于高级加密标准 (AES),模板至少必须使用绝对文件系统路径、群组和手指 ID 进行签名,以使模板文件在另一台设备上或对于在同一设备上注册模板的用户以外的任何人均无法操作。例如,从同一设备上的不同用户或从另一台设备复制指纹数据必须不起作用。
  • 实现必须使用 setActiveGroup() 函数提供的文件系统路径,或提供一种在移除用户时擦除所有用户模板数据的方法。强烈建议将指纹模板文件加密存储在提供的路径中。如果由于 TEE 存储要求而无法实现这一点,则实施者必须添加钩子以确保在移除用户时删除数据。

指纹方法

指纹 HIDL 接口包含 IBiometricsFingerprint.hal 中的以下主要方法。

方法 说明
enroll() 切换 HAL 状态机以开始收集和存储指纹模板。注册完成或超时后,HAL 状态机返回到空闲状态。
preEnroll() 生成唯一令牌以指示指纹注册的开始。向 enroll 函数提供令牌,以确保之前已进行身份验证(例如,使用密码)。为了防止篡改,在设备凭据确认后,令牌会被封装。必须在注册期间检查令牌,以验证其是否仍然有效。
getAuthenticatorId() 返回与当前指纹集关联的令牌。
cancel() 取消待处理的注册或身份验证操作。HAL 状态机将返回到空闲状态。
enumerate() 用于枚举所有已知指纹模板的同步调用。
remove() 删除指纹模板。
setActiveGroup() 将 HAL 操作限制为属于指定群组(由群组标识符 (GID) 标识)的一组指纹。
authenticate() 验证与指纹相关的操作(由操作 ID 标识)。
setNotify() 注册接收来自 HAL 的通知的用户函数。如果 HAL 状态机处于繁忙状态,则该函数将被阻止,直到 HAL 离开繁忙状态。
postEnroll() 完成注册操作并使 preEnroll() 生成的质询失效。必须在多指注册会话结束时调用此方法,以指示可能不再添加其他手指。

如需详细了解这些方法,请参阅 IBiometricsFingerprint.hal 中的注释。