use of com.android.internal.widget.VerifyCredentialResponse in project android_frameworks_base by AOSPA.
the class LockSettingsService method verifyCredential.
private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash, String credential, boolean hasChallenge, long challenge, CredentialUtil credentialUtil, ICheckCredentialProgressCallback progressCallback) throws RemoteException {
if ((storedHash == null || storedHash.hash.length == 0) && TextUtils.isEmpty(credential)) {
// don't need to pass empty credentials to GateKeeper
return VerifyCredentialResponse.OK;
}
if (TextUtils.isEmpty(credential)) {
return VerifyCredentialResponse.ERROR;
}
if (storedHash.version == CredentialHash.VERSION_LEGACY) {
byte[] hash = credentialUtil.toHash(credential, userId);
if (Arrays.equals(hash, storedHash.hash)) {
unlockKeystore(credentialUtil.adjustForKeystore(credential), userId);
// Users with legacy credentials don't have credential-backed
// FBE keys, so just pass through a fake token/secret
Slog.i(TAG, "Unlocking user with fake token: " + userId);
final byte[] fakeToken = String.valueOf(userId).getBytes();
unlockUser(userId, fakeToken, fakeToken);
// migrate credential to GateKeeper
credentialUtil.setCredential(credential, null, userId);
if (!hasChallenge) {
notifyActivePasswordMetricsAvailable(credential, userId);
return VerifyCredentialResponse.OK;
}
// Fall through to get the auth token. Technically this should never happen,
// as a user that had a legacy credential would have to unlock their device
// before getting to a flow with a challenge, but supporting for consistency.
} else {
return VerifyCredentialResponse.ERROR;
}
}
VerifyCredentialResponse response;
boolean shouldReEnroll = false;
GateKeeperResponse gateKeeperResponse = getGateKeeperService().verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
int responseCode = gateKeeperResponse.getResponseCode();
if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
} else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
byte[] token = gateKeeperResponse.getPayload();
if (token == null) {
// something's wrong if there's no payload with a challenge
Slog.e(TAG, "verifyChallenge response had no associated payload");
response = VerifyCredentialResponse.ERROR;
} else {
shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
response = new VerifyCredentialResponse(token);
}
} else {
response = VerifyCredentialResponse.ERROR;
}
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
if (progressCallback != null) {
progressCallback.onCredentialVerified();
}
notifyActivePasswordMetricsAvailable(credential, userId);
unlockKeystore(credential, userId);
Slog.i(TAG, "Unlocking user " + userId + " with token length " + response.getPayload().length);
unlockUser(userId, response.getPayload(), secretFromCredential(credential));
if (isManagedProfileWithSeparatedLock(userId)) {
TrustManager trustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
trustManager.setDeviceLockedForUser(userId, false);
}
if (shouldReEnroll) {
credentialUtil.setCredential(credential, credential, userId);
}
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
if (response.getTimeout() > 0) {
requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
}
}
return response;
}
use of com.android.internal.widget.VerifyCredentialResponse in project android_frameworks_base by DirtyUnicorns.
the class LockSettingsService method doVerifyPattern.
private VerifyCredentialResponse doVerifyPattern(String pattern, CredentialHash storedHash, boolean hasChallenge, long challenge, int userId, ICheckCredentialProgressCallback progressCallback) throws RemoteException {
if (TextUtils.isEmpty(pattern)) {
throw new IllegalArgumentException("Pattern can't be null or empty");
}
boolean shouldReEnrollBaseZero = storedHash != null && storedHash.isBaseZeroPattern;
String patternToVerify;
if (shouldReEnrollBaseZero) {
patternToVerify = LockPatternUtils.patternStringToBaseZero(pattern);
} else {
patternToVerify = pattern;
}
VerifyCredentialResponse response = verifyCredential(userId, storedHash, patternToVerify, hasChallenge, challenge, new CredentialUtil() {
@Override
public void setCredential(String pattern, String oldPattern, int userId) throws RemoteException {
setLockPatternInternal(pattern, oldPattern, userId);
}
@Override
public byte[] toHash(String pattern, int userId) {
return LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(pattern));
}
@Override
public String adjustForKeystore(String pattern) {
return LockPatternUtils.patternStringToBaseZero(pattern);
}
}, progressCallback);
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK && shouldReEnrollBaseZero) {
setLockPatternInternal(pattern, patternToVerify, userId);
}
return response;
}
use of com.android.internal.widget.VerifyCredentialResponse in project android_frameworks_base by DirtyUnicorns.
the class LockSettingsService method verifyCredential.
private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash, String credential, boolean hasChallenge, long challenge, CredentialUtil credentialUtil, ICheckCredentialProgressCallback progressCallback) throws RemoteException {
if ((storedHash == null || storedHash.hash.length == 0) && TextUtils.isEmpty(credential)) {
// don't need to pass empty credentials to GateKeeper
return VerifyCredentialResponse.OK;
}
if (TextUtils.isEmpty(credential)) {
return VerifyCredentialResponse.ERROR;
}
if (storedHash.version == CredentialHash.VERSION_LEGACY) {
byte[] hash = credentialUtil.toHash(credential, userId);
if (Arrays.equals(hash, storedHash.hash)) {
unlockKeystore(credentialUtil.adjustForKeystore(credential), userId);
// Users with legacy credentials don't have credential-backed
// FBE keys, so just pass through a fake token/secret
Slog.i(TAG, "Unlocking user with fake token: " + userId);
final byte[] fakeToken = String.valueOf(userId).getBytes();
unlockUser(userId, fakeToken, fakeToken);
// migrate credential to GateKeeper
credentialUtil.setCredential(credential, null, userId);
if (!hasChallenge) {
notifyActivePasswordMetricsAvailable(credential, userId);
return VerifyCredentialResponse.OK;
}
// Fall through to get the auth token. Technically this should never happen,
// as a user that had a legacy credential would have to unlock their device
// before getting to a flow with a challenge, but supporting for consistency.
} else {
return VerifyCredentialResponse.ERROR;
}
}
VerifyCredentialResponse response;
boolean shouldReEnroll = false;
GateKeeperResponse gateKeeperResponse = getGateKeeperService().verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
int responseCode = gateKeeperResponse.getResponseCode();
if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
} else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
byte[] token = gateKeeperResponse.getPayload();
if (token == null) {
// something's wrong if there's no payload with a challenge
Slog.e(TAG, "verifyChallenge response had no associated payload");
response = VerifyCredentialResponse.ERROR;
} else {
shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
response = new VerifyCredentialResponse(token);
}
} else {
response = VerifyCredentialResponse.ERROR;
}
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
if (progressCallback != null) {
progressCallback.onCredentialVerified();
}
notifyActivePasswordMetricsAvailable(credential, userId);
unlockKeystore(credential, userId);
Slog.i(TAG, "Unlocking user " + userId + " with token length " + response.getPayload().length);
unlockUser(userId, response.getPayload(), secretFromCredential(credential));
if (isManagedProfileWithSeparatedLock(userId)) {
TrustManager trustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
trustManager.setDeviceLockedForUser(userId, false);
}
if (shouldReEnroll) {
credentialUtil.setCredential(credential, credential, userId);
}
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
if (response.getTimeout() > 0) {
requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
}
}
return response;
}
use of com.android.internal.widget.VerifyCredentialResponse in project android_frameworks_base by ResurrectionRemix.
the class LockSettingsService method verifyTiedProfileChallenge.
@Override
public VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId) throws RemoteException {
checkPasswordReadPermission(userId);
if (!isManagedProfileWithUnifiedLock(userId)) {
throw new RemoteException("User id must be managed profile with unified lock");
}
final int parentProfileId = mUserManager.getProfileParent(userId).id;
// Unlock parent by using parent's challenge
final VerifyCredentialResponse parentResponse = isPattern ? doVerifyPattern(password, true, challenge, parentProfileId, null) : doVerifyPassword(password, true, challenge, parentProfileId, null);
if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
// Failed, just return parent's response
return parentResponse;
}
try {
// Unlock work profile, and work profile with unified lock must use password only
return doVerifyPassword(getDecryptedPasswordForTiedProfile(userId), true, challenge, userId, null);
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | CertificateException | IOException e) {
Slog.e(TAG, "Failed to decrypt child profile key", e);
throw new RemoteException("Unable to get tied profile token");
}
}
use of com.android.internal.widget.VerifyCredentialResponse in project android_frameworks_base by crdroidandroid.
the class LockSettingsService method verifyTiedProfileChallenge.
@Override
public VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId) throws RemoteException {
checkPasswordReadPermission(userId);
if (!isManagedProfileWithUnifiedLock(userId)) {
throw new RemoteException("User id must be managed profile with unified lock");
}
final int parentProfileId = mUserManager.getProfileParent(userId).id;
// Unlock parent by using parent's challenge
final VerifyCredentialResponse parentResponse = isPattern ? doVerifyPattern(password, true, challenge, parentProfileId, null) : doVerifyPassword(password, true, challenge, parentProfileId, null);
if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
// Failed, just return parent's response
return parentResponse;
}
try {
// Unlock work profile, and work profile with unified lock must use password only
return doVerifyPassword(getDecryptedPasswordForTiedProfile(userId), true, challenge, userId, null);
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | CertificateException | IOException e) {
Slog.e(TAG, "Failed to decrypt child profile key", e);
throw new RemoteException("Unable to get tied profile token");
}
}
Aggregations