深入理解Android M 锁屏密码存储方式
AndroidM之前锁屏密码的存储
在AndroidM之前,锁屏密码的存储格式很简单,其使用了64位随机数作为salt值,此salt值被存储在SQLite数据库/data/system/locksettings.db中。密码在存储的时候,会将输入的密码加上此随机数组成新的字符串。然后对新的字符串分别进行SHA-1和MD5加密,将加密后的密文通过MD5+SHA-1的方式进行字符串拼接,组成新的密文存储在/data/system/password.key中,共有72位。其加密后的形式如下:
/data/system#catpassword.keyB40C2F6FE4E89F3386D4E689B135304410D64951914FB35770FDAC58B694177B29297A80
而密码的详细信息,存储在/data/system/device_policies.xml中,内容类似如下:
/data/system#catdevice_policies.xml
其中主要用到的两个字段quality是密码的类型,简单密码和复杂密码的值不同,length是密码的长度,其他字段存储密码中各种字符的数量。
AndroidM中锁屏密码的存储
在AndroidM中,锁屏密码的存储格式发生了变化,其默认的存储格式在/system/gatekeeper/include/gatekeeper/password_handle.h中描述如下:
typedefuint64_tsecure_id_t;typedefuint64_tsalt_t;/***structureforeasyserialization*anddeserializationofpasswordhandles.*/staticconstuint8_tHANDLE_VERSION=2;struct__attribute__((__packed__))password_handle_t{//fieldsincludedinsignatureuint8_tversion;secure_id_tuser_id;uint64_tflags;//fieldsnotincludedinsignaturesalt_tsalt;uint8_tsignature[32];boolhardware_backed;};
其中version默认是2,user_id是Android用户id,signature存储的便是密文,hardware_backed存储的是加密方式,0表示密文是软件加密,而1表示密文是通过TEE环境进行加密得到的。
密码加密后默认以password_handle_t格式存储在/data/system/gatekeeper.password.key中。密码的生成和校验,在HAL层是通过system/core/gatekeeperd/gatekeeperd.cpp中的函数实现的。其在系统启动时被注册为gatekeeperd服务,服务在启动的时候会调用GateKeeperProxy()对象,此类的构造函数会去查找TEEmodule,如果找到,则通过TEE设备进行加解密,如果没有找到,则通过一个软件设备进行加解密。
这里主要分析下通过软甲设备解密的逻辑。解密时,会调用到system/core/gatekeeperd/gatekeeperd.cpp中的以下函数:
intverify(uint32_tuid,constuint8_t*enrolled_password_handle, uint32_tenrolled_password_handle_length, constuint8_t*provided_password,uint32_tprovided_password_length, bool*request_reenroll)
在此函数中,由于没有使用TEE,所以会调用到软件设备验证system/core/gatekeeperd/SoftGateKeeperDevice.cpp中的:
intSoftGateKeeperDevice::verify(uint32_tuid, uint64_tchallenge,constuint8_t*enrolled_password_handle, uint32_tenrolled_password_handle_length,constuint8_t*provided_password, uint32_tprovided_password_length,uint8_t**auth_token,uint32_t*auth_token_length, bool*request_reenroll)
函数进行校验,此函数对传进来的信息进行处理后交到system/gatekeeper/gatekeeper.cpp中的
voidGateKeeper::Verify(constVerifyRequest&request,VerifyResponse*response)
进行处理,在这里对参数进行一系列处理和重新组织后再交给
boolGateKeeper::DoVerify(constpassword_handle_t*expected_handle,constSizedBuffer&password)
进行校验,在此函数中,再调用
boolGateKeeper::CreatePasswordHandle(SizedBuffer*password_handle_buffer,salt_tsalt, secure_id_tuser_id,uint64_tflags,uint8_thandle_version,constuint8_t*password, uint32_tpassword_length)
将上面提到的/data/system/gatekeeper.password.key
文件中存储的信息进行解析,然后调用
ComputePasswordSignature(password_handle->signature,sizeof(password_handle->signature), password_key,password_key_length,to_sign,sizeof(to_sign),salt);
函数将输入的密码进行加密,从这里可以看到,输入的密码要加密成密文只需要用到存储的密码中的salt值,此函数在system/core/gatekeeperd/SoftGateKeeper.h中,其调用crypto库中的
crypto_scrypt(password,password_length,reinterpret_cast(&salt), sizeof(salt),N,r,p,signature,signature_length);
将输入的密码存储在signature中并返回。此函数最终会通过SHA256进行加密,参数中的N,r,p默认为如下值:
staticconstuint64_tN=16384;staticconstuint32_tr=8;staticconstuint32_tp=1;
通过以上处理后对输入的密码加密后得到的密文与手机中存储的密文进行比较后返回校验结果,从而判断输入的密码的正确与否。
在AndroidM中,改变了之前直接在Java层进行密码校验的方式,将密码的校验通过HAL层的服务进行处理,同时加入对TEE的支持,使得锁屏密码的安全性大大提升,同时也可以方便的支持其他的安全特性,提升了整个系统的安全性。
以上这篇深入理解AndroidM锁屏密码存储方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。