Fingerprint HIDL

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

如需实现 Fingerprint HIDL,您必须在某个供应商专用库中实现 IBiometricsFingerprint.hal

指纹匹配

设备的指纹传感器通常处于闲置状态。不过,为了响应对 authenticate 或 enroll 的调用,指纹传感器会监听触摸操作(并且屏幕可能会在用户触摸指纹传感器时被唤醒)。指纹匹配的概要流程包括以下步骤:

  1. 用户将手指放在指纹传感器上。
  2. 供应商专用库会根据当前的已注册指纹模板集判断是否匹配。
  3. 匹配结果会传递到 FingerprintService

该流程假设设备上已经注册了一个指纹,即供应商专用库已为该指纹注册了一个模板。如需了解详情,请参阅身份验证

注意:设备上存储的指纹模板越多,进行指纹匹配所需的时间就越长。

架构

Fingerprint HAL 会与以下组件交互。

  • BiometricManager 会在应用进程中与应用直接交互。每个应用都有一个 IBiometricsFingerprint.hal 实例。
  • FingerprintService 在系统进程中运行,可处理与 Fingerprint HAL 之间的通信。
  • Fingerprint HAL 是 IBiometricsFingerprint HIDL 接口的 C/C++ 实现。它包含可与设备专有硬件进行通信的供应商专用库。
  • Keystore API 和 Keymaster 组件提供由硬件支持的加密功能,以便在安全环境(例如可信执行环境 (TEE))中安全地存储密钥。

Android 使用指纹demo_android

图 1. 指纹身份验证的概要数据流程

供应商专用 HAL 实现必须使用 TEE 所要求的通信协议。不得将原始图像和处理后的指纹特征传递到不可信内存中。所有此类生物识别数据都需要存储在安全硬件(例如 TEE)中。请确保即使具备 Root 权限,也不能取得生物识别数据。

FingerprintService 和 fingerprintd 会通过 Fingerprint HAL 调用供应商专用库,以便注册指纹以及执行其他操作。

Android 使用指纹demo_android_02

图 2. Fingerprint 守护程序与 Fingerprint 供应商专用库之间的交互

实现准则

以下 Fingerprint HAL 准则旨在确保指纹数据不会被泄露,并可以在从设备中移除用户时一并移除相应指纹数据:

  • 必须要确保在任何情况下都无法从传感器驱动程序或 TEE 以外访问原始指纹数据或衍生内容(例如模板)。如果硬件支持 TEE,则只能将硬件访问权限授予 TEE,并且必须通过 SELinux 政策对硬件访问权限加以保护。串行外设接口 (SPI) 通道必须只能供 TEE 访问,并且必须有针对所有设备文件的明确 SELinux 政策。
  • 指纹采集、注册和识别必须在 TEE 内部进行。
  • 只有加密的指纹数据才能存储在文件系统中(即使文件系统本身已加密)。
  • 指纹模板必须采用设备专用私钥进行签名。对于高级加密标准 (AES),模板必须至少通过绝对文件系统路径、群组和指纹 ID 进行签名,这样一来,相应模板文件便无法在其他设备上使用,并且无法用于在同一设备上注册的任何其他用户。例如,您将无法复制同一设备上其他用户的指纹数据,也无法从其他设备复制指纹数据。
  • 实现必须使用 setActiveGroup() 函数提供的文件系统路径,或提供一种能够在移除用户时一并清空该用户所有模板数据的方法。强烈建议将指纹模板文件以加密形式存储在提供的路径中。如果因 TEE 存储要求而导致这种做法不可行,实现人员必须添加一些钩子,以确保在移除用户时一并移除相关数据。

Fingerprint 方法

Fingerprint HIDL 接口在 IBiometricsFingerprint.hal 中包含以下主要方法。

方法

说明

enroll()

将 HAL 状态机切换到开始收集和存储指纹模板的状态。注册完成后或超时后,HAL 状态机会返回到闲置状态。

preEnroll()

生成一个独一无二的令牌,以指明指纹注册已开始。为 enroll 函数提供令牌,以确保事先已经过身份验证(例如使用密码)。为了防止被篡改,确认设备凭据后,便会封装令牌。在注册期间必须检查令牌,以确认令牌仍然有效。

getAuthenticatorId()

返回与当前指纹集关联的令牌。

cancel()

取消待处理的注册或身份验证操作。HAL 状态机会返回到闲置状态。

enumerate()

同步调用,用于枚举所有已知指纹模板。

remove()

删除指纹模板。

setActiveGroup()

限定只能对属于指定群组(通过群组标识符 (GID) 来标识)的指纹集执行某项 HAL 操作。

authenticate()

验证与指纹相关的操作(通过操作 ID 来标识)。

setNotify()

注册一个从 HAL 接收通知的用户函数。如果 HAL 状态机处于繁忙状态,该函数会阻塞,直到 HAL 不再处于繁忙状态为止。

postEnroll()

结束注册操作并使 preEnroll() 生成的质询代码无效。必须在多指纹注册会话结束时调用该函数,以表明不会再添加指纹。

如需详细了解这些函数,请参阅 IBiometricsFingerprint.hal 中的备注。