快速链接:
.
???????????? 个人博客笔记导读目录(全部) ????????????
相关推荐:
Android Gatekeeper流程深度解剖
Android手机使用命令行增加/删除/修改密码(password/pin/pattern)
android密码解锁/指纹解锁返回的authToken深度解剖
说明: 在无特别的说明下,本文讲述得是android10.0 !
本文旨在讲解LockSettingsService的应用,先上一张系统框图,看下LockSettingsService处于什么有样子的位置
在android系统中的设置密码、清除密码、修改密码,都是调用到LockSettingsService.java的setLockCredential函数进行的,而setLockCredential又调用了setLockCredentialInternal,接下来我们来分析这个函数的流程
setLockCredentialInternal完成的功能有:
- 1、如果是清除密码,即credential.isNone()==true, 则走另外一套流程;
- 2、根据userId,读取存储的密码(其实是个hash): currentHandle = mStorage.readCredentialHash(userId)
- 3、调用底层的enroll,将密码转换成enrolledHandle,如果enrolledHandle则说明底层出错了,则返回失败;
- 4、将enrolledHandle转换成hash,并保存起来
- 5、验证verifyChallenge
- 6、setUserKeyProtection:添加一个userkey,vold使用d
- 7、fixateNewestUserKeyAuth,也是调用到vold,fscrypt_fixate_newest_user_key_auth
- 8、doVerifyCredential 做一次verify验证
- 9、synchronizeUnifiedWorkChallengeForProfiles
- 10、sendCredentialsOnChangeIfRequired
private boolean setLockCredentialInternal(LockscreenCredential credential,
LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) {
Objects.requireNonNull(credential);
Objects.requireNonNull(savedCredential);
synchronized (mSpManager) { --------------------------------------------------//暂不介绍mSpManager机制
if (isSyntheticPasswordBasedCredentialLocked(userId)) {
return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
isLockTiedToParent);
}
}
if (credential.isNone()) { --------------------------------------------------//,其实就是密码类型选择了None,可以理解为,这是清除密码的流程
clearUserKeyProtection(userId, null);
gateKeeperClearSecureUserId(userId);
mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
// Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path,
// since it forms part of the state that determines the credential type
// @see getCredentialTypeInternal
setKeyguardStoredQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
setKeystorePassword(null, userId);
fixateNewestUserKeyAuth(userId);
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
setUserPasswordMetrics(LockscreenCredential.createNone(), userId);
sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
return true;
}
CredentialHash currentHandle = mStorage.readCredentialHash(userId);--------------------// 读取原来的密码
if (isManagedProfileWithUnifiedLock(userId)) {
// get credential from keystore when managed profile has unified lock
if (savedCredential.isNone()) {
try {
//TODO: remove as part of b/80170828
savedCredential = getDecryptedPasswordForTiedProfile(userId);
} catch (FileNotFoundException e) {
Slog.i(TAG, "Child profile key not found");
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
| NoSuchAlgorithmException | NoSuchPaddingException
| InvalidAlgorithmParameterException | IllegalBlockSizeException
| BadPaddingException | CertificateException | IOException e) {
Slog.e(TAG, "Failed to decrypt child profile key", e);
}
}
} else {
if (currentHandle.hash == null) {
if (!savedCredential.isNone()) {
Slog.w(TAG, "Saved credential provided, but none stored");
}
savedCredential.close();
savedCredential = LockscreenCredential.createNone();
}
}
synchronized (mSpManager) {
if (shouldMigrateToSyntheticPasswordLocked(userId)) {
initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, userId);
return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
isLockTiedToParent);
}
}
if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
byte[] enrolledHandle = enrollCredential(currentHandle.hash, --------------------------------// 调用底层,完成enroll
savedCredential.getCredential(), credential.getCredential(), userId);
if (enrolledHandle == null) {
Slog.w(TAG, String.format("Failed to enroll %s: incorrect credential",-------------------------------// 如果底层enroll错误了,则返回failed
credential.isPattern() ? "pattern" : "password"));
return false;
}
CredentialHash willStore = CredentialHash.create(enrolledHandle, credential.getType());-----------------------------//创建hash
mStorage.writeCredentialHash(willStore, userId); -----------------------------//保存hash
// Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path,
// since it forms part of the state that determines the credential type
// @see getCredentialTypeInternal
setKeyguardStoredQuality(
LockPatternUtils.credentialTypeToPasswordQuality(credential.getType()), userId);
// push new secret and auth token to vold
GateKeeperResponse gkResponse;
try {
gkResponse = getGateKeeperService().verifyChallenge(userId, 0, willStore.hash, -----------------------------//验证challenge
credential.getCredential());
} catch (RemoteException e) {
throw new IllegalStateException("Failed to verify current credential", e);
}
setUserKeyProtection(userId, credential, convertResponse(gkResponse));
fixateNewestUserKeyAuth(userId);
// Refresh the auth token
doVerifyCredential(credential, CHALLENGE_FROM_CALLER, 0, userId, -----------------------------//再做一次verify
null /* progressCallback */);
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
return true;
}
流程图