概述
如果设备配有指纹传感器,用户就可以注册一个或多个指纹,然后使用自己的指纹来解锁设备以及执行其他任务。
Android 会利用 Fingerprint 硬件抽象层 (HAL) 连接到供应商专用库和指纹硬件,例如指纹传感器。
要实现 Fingerprint HAL,您必须在某个供应商专用库中实现 fingerprint.h
(/hardware/libhardware/include/hardware/fingerprint.h
) 中的函数;请参阅 fingerprint.h
文件中的备注。
指纹匹配流程
下文概要介绍了指纹匹配流程。该流程假设设备上已经注册了一个指纹,即供应商专用库已为该指纹注册了一个模板。另请参阅身份验证。
设备的指纹传感器通常处于闲置状态。但为了响应对 authenticate
或 enroll
函数的调用,指纹传感器会监听触摸操作(并且屏幕可能会在用户触摸指纹传感器时被唤醒)。
- 当用户将手指放在指纹传感器上时,供应商专用库会根据当前的已注册模板集判断是否匹配。
- 第 1 步的结果会传递到 Fingerprint HAL,后者会将指纹身份验证结果通知给
fingerprintd
(Fingerprint 守护进程)。
请注意,单个设备上存储的模板越多,进行匹配所需的时间就越长。
架构
Fingerprint HAL 会与以下组件交互:
- FingerprintManager API:会在应用进程中与应用直接交互。
- 每个应用都有一个 FingerprintManager 实例。
- FingerprintManager 是与 FingerprintService 进行通信的封装容器。
- FingerprintService:在系统进程中运行的单例服务,可处理与
fingerprintd
之间的通信。
- fingerprintd(Fingerprint 守护进程):FingerprintService 中 Binder 界面的 C/C++ 实现。
fingerprintd
守护进程在自己的进程中运行,并会封装 Fingerprint HAL 供应商专用库。
- Fingerprint HAL 供应商专用库:硬件供应商的 Fingerprint HAL 实现。供应商专用库能够与设备专用硬件进行通信。
- Keystore API 和 Keymaster:这两种组件可以提供由硬件支持的加密功能,以便在可信执行环境 (TEE) 中安全地存储密钥。
如下图所示,供应商专用 HAL 实现需要使用 TEE 要求的通信协议。
图 1. 指纹身份验证的概要数据流程
因此,不得将原始图片和处理后的指纹特征传递到不可信内存中。所有此类生物识别数据都需要安全地存储在传感器硬件或可信内存中。(TEE 中的内存被视为可信内存,TEE 之外的内存则被视为不可信内存。)
获取 Root 权限不得损坏生物识别数据。
如下图所示,fingerprintd
会通过 Fingerprint HAL 调用供应商专用库,以便注册指纹以及执行其他操作。
图 2. Fingerprint 守护进程 (fingerprintd
) 与 Fingerprint 供应商专用库之间的交互
Fingerprint 实现准则
本部分中的准则旨在确保:
- 指纹数据不会被泄露
- 从设备中移除用户时,一并移除指纹数据
以下是具体准则:
- 必须要确保在任何情况下都无法从传感器驱动程序或可信执行环境 (TEE) 以外访问原始指纹数据或衍生内容(例如模板)。只能将硬件访问权限授予 TEE(如果硬件支持它的话),并且必须通过 SELinux 政策对硬件访问权限加以保护。也就是说,串行外设接口 (SPI) 渠道必须只能供 TEE 访问,并且必须有针对所有设备文件的明确 SELinux 政策。
- 指纹采集、注册和识别必须在 TEE 内部进行。
- 只有加密形式的指纹数据可以存储在文件系统中(即使文件系统本身已加密)。
- 指纹模板必须已通过设备专用私钥(例如 AES 密钥)签名,并且必须至少包含绝对文件系统路径、群组和指纹 ID,这样一来,相应模板文件便无法在其他设备上使用,并且无法用于在同一设备上注册的任何其他用户。例如,您将无法复制同一设备上其他用户的指纹数据,也无法从其他设备复制指纹数据。
- 实现必须使用
set_active_group()
函数提供的文件系统路径,或提供一种能够在移除用户时一并清空所有用户模板数据的方法。强烈建议将指纹模板文件以加密形式存储在提供的路径中。如果因 TEE 存储要求导致这种做法不可行,实现人员必须添加一些钩子,以确保在移除用户时一并移除相关数据。
Fingerprint HAL 中的主要函数
以下是 /hardware/libhardware/include/hardware/fingerprint.h
文件中的主要函数。您可以查看该文件中的详细说明。
- enroll: 将 HAL 状态机切换到开始收集和存储指纹模板的状态。注册完成后或超时后,HAL 状态机会立即返回到闲置状态。
- pre_enroll: 生成一个独一无二的令牌,以指明指纹注册已开始。为
enroll
函数提供令牌,以确保事先已经过身份验证(例如使用密码)。一旦确认了设备凭据,便会开始封装令牌并对其进行相应的处理(例如,进行 HMAC 处理),以防被篡改。在注册期间必须检查令牌,以确认令牌仍然有效。
- get_authenticator_id: 返回与当前指纹集关联的令牌。
- cancel: 取消所有待处理的注册或验证操作。HAL 状态机会返回到闲置状态。
- enumerate: 同步调用,用于枚举所有已知指纹模板。
- remove: 删除指纹模板。
- set_active_group: 限定只能对属于指定群组(通过群组标识符 (GID) 来标识)的指纹集执行某项 HAL 操作。
- authenticate: 验证与指纹相关的操作(通过操作 ID 来标识)。
- set_notify: 注册将从 HAL 获得通知的用户函数。如果 HAL 状态机处于繁忙状态,该函数会被屏蔽,直到 HAL 不再处于繁忙状态为止。