Fingerprint should confirm device lock when unified
When unified and adding a fingerprint, the user is prompted to set up a backup Bug:27419438 Change-Id: I3e857fa07c50ee0904f685b721595ef6cfe729f9
This commit is contained in:
@@ -33,6 +33,7 @@ interface ILockSettings {
|
||||
void setLockPassword(in String password, in String savedPassword, int userId);
|
||||
VerifyCredentialResponse checkPassword(in String password, int userId);
|
||||
VerifyCredentialResponse verifyPassword(in String password, long challenge, int userId);
|
||||
VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId);
|
||||
boolean checkVoldPassword(int userId);
|
||||
boolean havePattern(int userId);
|
||||
boolean havePassword(int userId);
|
||||
|
||||
@@ -144,6 +144,43 @@ public final class LockPatternChecker {
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a password asynchronously.
|
||||
*
|
||||
* @param utils The LockPatternUtils instance to use.
|
||||
* @param password The password to check.
|
||||
* @param challenge The challenge to verify against the pattern.
|
||||
* @param userId The user to check against the pattern.
|
||||
* @param callback The callback to be invoked with the verification result.
|
||||
*/
|
||||
public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils,
|
||||
final String password,
|
||||
final boolean isPattern,
|
||||
final long challenge,
|
||||
final int userId,
|
||||
final OnVerifyCallback callback) {
|
||||
AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
|
||||
private int mThrottleTimeout;
|
||||
|
||||
@Override
|
||||
protected byte[] doInBackground(Void... args) {
|
||||
try {
|
||||
return utils.verifyTiedProfileChallenge(password, isPattern, challenge, userId);
|
||||
} catch (RequestThrottledException ex) {
|
||||
mThrottleTimeout = ex.getTimeoutMs();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(byte[] result) {
|
||||
callback.onVerified(result, mThrottleTimeout);
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a password asynchronously.
|
||||
*
|
||||
|
||||
@@ -375,6 +375,36 @@ public class LockPatternUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check to see if a password matches the saved password.
|
||||
* If password matches, return an opaque attestation that the challenge
|
||||
* was verified.
|
||||
*
|
||||
* @param password The password to check.
|
||||
* @param challenge The challenge to verify against the password
|
||||
* @return the attestation that the challenge was verified, or null.
|
||||
*/
|
||||
public byte[] verifyTiedProfileChallenge(String password, boolean isPattern, long challenge,
|
||||
int userId) throws RequestThrottledException {
|
||||
throwIfCalledOnMainThread();
|
||||
try {
|
||||
VerifyCredentialResponse response =
|
||||
getLockSettings().verifyTiedProfileChallenge(password, isPattern, challenge,
|
||||
userId);
|
||||
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
return response.getPayload();
|
||||
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
|
||||
throw new RequestThrottledException(response.getTimeout());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a password matches the saved password. If no password exists,
|
||||
* always returns true.
|
||||
|
||||
@@ -1110,6 +1110,37 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
return doVerifyPassword(password, true, challenge, userId);
|
||||
}
|
||||
|
||||
@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)
|
||||
: doVerifyPassword(password, true, challenge, parentProfileId);
|
||||
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);
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
|
||||
private VerifyCredentialResponse doVerifyPassword(String password, boolean hasChallenge,
|
||||
long challenge, int userId) throws RemoteException {
|
||||
checkPasswordReadPermission(userId);
|
||||
|
||||
@@ -947,10 +947,6 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
||||
if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Group ID is arbitrarily set to parent profile user ID. It just represents
|
||||
// the default fingerprints for the user.
|
||||
final int effectiveGroupId = getEffectiveUserId(groupId);
|
||||
final int realUserId = Binder.getCallingUid();
|
||||
|
||||
final boolean restricted = isRestricted();
|
||||
@@ -958,7 +954,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
||||
@Override
|
||||
public void run() {
|
||||
MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
|
||||
startAuthentication(token, opId, realUserId, effectiveGroupId, receiver,
|
||||
startAuthentication(token, opId, realUserId, groupId, receiver,
|
||||
flags, restricted, opPackageName);
|
||||
}
|
||||
});
|
||||
@@ -993,14 +989,10 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
||||
final IFingerprintServiceReceiver receiver) {
|
||||
checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
|
||||
final boolean restricted = isRestricted();
|
||||
|
||||
// Group ID is arbitrarily set to parent profile user ID. It just represents
|
||||
// the default fingerprints for the user.
|
||||
final int effectiveGroupId = getEffectiveUserId(groupId);
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startRemove(token, fingerId, effectiveGroupId, receiver, restricted);
|
||||
startRemove(token, fingerId, groupId, receiver, restricted);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user