在Android里面,Gaterkeeper用于做密码锁屏或者图案锁屏的验证。比如你拿起手机输入密码解锁手机,这个密码验证就是gatekeepr做的,只有验证通过后,你的手机锁屏才能解开。
gatekeeper包括3部分
1)gatekeeperd,是native层的一个守护进程,与上层的锁屏服务locksettingservice交互
2)gatekeeper HAL 层,gatekeered通过hal层的接口访问gatekeeper TA
3)gatekeeper TA(Trust App ),是一个跑在安全os中的gatekeeper服务,真正的密码验证就是在里面做的
locksettingservice是上层的锁屏服务,负责接收用户输入的数字密码或者图案密码,经过一定的处理后将密码数据传给gatekeeper验证, 因为本人搞的是native层及以下,locksettingservice是应用层的,这里就不说了
gatekeeperd和 gatekeeper HAL 可以理解成中间件,真正的密码校验是在gatekeeper TA里面做的。
gatekeeper提供给locksetting 设置密码的binder接口
/system/core/gatekeeperd/IGateKeeperService.h
//存储密码数据
int enroll(uint32_t uid,
const uin8_t *current_password_handle, uin32_t current_password_handle_length,
const uint8_t *current_password, uint32_t current_password_length,
const uint8_t *desired_password, uint32_t desired_password_length,
uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length);
这里我们直接分析首次设置密码的情况,也就是当前没有密码,current_password_handle和current_password都为空,用户输入要设置的数字密码或者图案密码,locksettingservice经过一定的处理后得到密码数据desired_password传给enroll接口,gatekeeper经过一系列的操作生成enrolled_password_handle,返回给locksettingservice。
身份认证系统都不会直接存储用户的密码,而是对密码用某些算法做hash摘要,然后将摘要保存起来用于验证。Android也一样,locksetting传给gatekeeper的密码数据,gatekeeper也是先做hash摘要处理,生成password_handle_t结构的数据。这里注意下,gatekeeper并不存储password_handle_t数据,只是返回给locksettingservice,由locksettingservice负责存储。
password_handle_t 结构体定义如下:
//system/gatekeeper/include/gatekeeper/password_handle.h
struct __attribute__ ((__packed__)) password_handle_t {
//handle版本号
uint8_t version;
//设置密码时,teeos里面生成的一个随机数
secure_id_t user_id;
uint64_t flags;
//随机生成的盐值,用于HMAC生成摘要
salt_t salt;
//存储HMAC生成的摘要
uint8_t signature[32];
//是硬实现还是软实现,如果手机硬件不支持安全os,就走软实现
bool hardware_backed;
};
在安全os里面的gatekeer TA 中,随机生成盐值salt和suid,生成HMAC摘要,就是password_handle_t中的signature。最终password_handle生成了,返回给locksetting存储,设置密码完成。
gatekeeper提供给locksetting 验证密码的binder接口
int verifyChallenge(uint32_t uid, uint64_t challenge,
const uint8_t *enrolled_password_handle, uin32_t enrolled_password_handle_length,
const uint8_t *provided_password, uint32_t provided_password_length,
uint8_t **auth_token, uint32_t *auto_token_length, bool *request_reenroll);
验证密码时,locksetting会把已经存储的password_handle数据和用户现在输入的密码数据传给gatekeeper验证。gatekeeper TA拿到当前的密码数据后再重新做一次HMAC摘要,salt和HMAC key等都一样,生成新的password_handle数据,如果和存储的password_handle数据完全一样,说明密码验证通过。
验证通过后会生成auth_token数据给keystore使用,包括challenge也是用于生成auth_token的,这里就不讲了。