登录

Android N 指纹框架

2017-10-26  本文已影响205人  xiabodan

1. 指纹框架UML

image.png

2. Fingerprint

2.1 Fingerprint数据流图

图片.png

2.2 HAL层的初始化工作

2.2.1 HAL初始化

每个Hal层库文件有一个入口,即HAL_MODULE_INFO_SYM,上层在调用hal层库文件时会在/system/lib/hw/下面寻找对应库文件,找到对应库文件后便从入口HAL_MODULE_INFO_SYM调用Hal层里面的open, init, write, read等接口,Hal层再通过这个接口去读写设备节点。

static struct hw_module_methods_t fingerprint_module_methods = {
    .open = fingerprint_open,
};
Fingerprintd 调用hw_get_module函数获取了一个fingerprint_module_t类型的数据结构。 这个就是在fingerprint.default.so中,由指纹芯片厂商填充实现的。
static int fingerprint_open(const hw_module_t* module, const char __unused *id,
hw_device_t** device) {
  if (fpc_init() < 0) {
ALOGE("Could not init FPC device");
return -EINVAL;
}
fingerprint_device_t *dev = malloc(sizeof(fingerprint_device_t));
memset(dev, 0, sizeof(fingerprint_device_t));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = FINGERPRINT_MODULE_API_VERSION_2_0;
dev->common.module = (struct hw_module_t*) module;
dev->common.close = fingerprint_close;
dev->pre_enroll = fingerprint_pre_enroll;
dev->enroll = fingerprint_enroll;
dev->get_authenticator_id = fingerprint_get_auth_id;
dev->cancel = fingerprint_cancel;
dev->remove = fingerprint_remove;
dev->set_active_group = fingerprint_set_active_group;
dev->enumerate = fingerprint_enumerate;
dev->authenticate = fingerprint_authenticate;
dev->set_notify = set_notify_callback;
dev->notify = NULL;
*device = (hw_device_t*) dev;
return 0;
}

fingerprint_open就是填充实现Android 在fingerprint.h定义fingerprint_device_t需要实现的这些接口。然后赋给指针device。上层,也就是fingerprintd,就能用这个device来操作hal层的指纹模块了。
fpc_init() 应该是初始化指纹驱动,并与Trusted Execution Environment (TEE)建立安全链接,TEE提供的一个安全的硬件运行环境。指纹就是运行在这样一个硬件安全环境下的程序。它保证了指纹敏感数据的安全性。

2.2.2 HAL主要接口

HAL主要接口函数都会在/hardware/libhardware/include/hardware/fingerprint.h 中,主要的接口主要是enroll和authenticate,以及相应的回调函数


图片.png

其他的函数还有以下:

Enroll流程

2.3.1 preEnroll点击设置中的添加指纹,setting就会调到fingerprintd的preEnroll接口。

2.3.2 enroll

int (*enroll)(struct fingerprint_device *dev, const hw_auth_token_t *hat,uint32_t gid, uint32_t timeout_sec);
void *enroll_thread_loop() {
fingerprint_msg_t msg;
msg.type = FINGERPRINT_TEMPLATE_ENROLLING;
msg.data.enroll.finger.fid = print_id;
msg.data.enroll.finger.gid = fpc_gid;
msg.data.enroll.samples_remaining = 0;
msg.data.enroll.msg = 0;
callback(&msg);
}

最终会在FingerprintService保存一份Fingerprint,Fingerprint包含以下数据,主要用于FingerprintService判断是否有指纹template存在。

2.3.3 postEnroll

postEnroll主要工作是更新一下指纹设备中保存的Challenge。

2.4 Authenticate流程

当按下power键锁屏时,APP会调用FingerprintManager api,进入到authenticate流程。和enroll一样,框架层工作工作很少,基本就是一个简单的接口调用。其中CryptoObject是加密对象,这是由于验证结果有可能被第三方软件篡改,这个加密对象会随着验证结果返回并验证。
void authenticate (FingerprintManager.CryptoObject crypto,CancellationSignal cancel,int flags,FingerprintManager.AuthenticationCallback callback,Handler handler)

parameter
crypto FingerprintManager.CryptoObject: object associated with the call or null if none required.
cancel CancellationSignal: an object that can be used to cancel authentication
flags int: optional flags; should be 0
callback FingerprintManager.AuthenticationCallback: an object to receive authentication events
handler Handler: an optional handler to handle callback events

主要工作还是在hal层以下完成。重点看hal层之下的部分。authenticate一直调用到指纹服务进程fingerprintd。在有fingerprintd根据加载的fingerprint module调用hal层的接口。我们看看HAl怎样定义authenticate接口的,在fingerprint.h中
int (*authenticate)(struct fingerprint_device *dev, uint64_t operation_id, uint32_t gid);

2.4.1 加载用户模板、切换采图模式

2.4.2 采图与识别

之后的主要工作流程如下图

图片.png
void *enroll_thread_loop() {
fingerprint_msg_t msg;
msg.type = FINGERPRINT_AUTHENTICATED;
msg.data.authenticated.finger.gid = fpc_gid;
msg.data.authenticated.finger.fid = print_id;
msg.data.authenticated.hat = hat;
callback(&msg);
}

其中auth_token会在fingerprintd中同步到keystore service中。

void FingerprintDaemonProxy::hal_notify_callback(const fingerprint_msg_t *msg) {
switch (msg->type) {
case FINGERPRINT_AUTHENTICATED:
if (msg->data.authenticated.finger.fid != 0) {
const uint8_t* hat = reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
instance->notifyKeystore(hat, sizeof(msg->data.authenticated.hat));
}
callback->onAuthenticated(device,
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid);
break;
}
}

void FingerprintDaemonProxy::notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length) {
if (auth_token != NULL && auth_token_length > 0) {
// TODO: cache service?
sp < IServiceManager > sm = defaultServiceManager();
sp < IBinder > binder = sm->getService(String16("android.security.keystore"));
sp < IKeystoreService > service = interface_cast < IKeystoreService > (binder);
if (service != NULL) {
          status_t ret = service->addAuthToken(auth_token, auth_token_length);
}
}
}

2.4.3 AuthToken数据流

图片.png

安全框架

指纹安全框架一般有两种方案,一种是Fingerprint without TrustZone 和Fingerprint with TrustZone。在root情况下without TrustZone是非常危险的,所有的数据都可以轻松获取到。但是在有了TrustZone的情况下,hacker在获取了root以后依然无法读取TrustZone中的指纹信息。如果想要获取指纹信息,理论上还需要破解TrustZone才行。TrustZone是arm支持的一种安全运行环境空间,有自己运行操作系统。

Fingerprint可能存在的安全漏洞

参考

安卓指纹验证官方指南
Keystore
指纹验证APP Demo

上一篇下一篇

猜你喜欢

热点阅读