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:
Ricky Wai
2016-04-05 15:29:24 +01:00
parent f5c0a55d1e
commit 53940d4c7f
5 changed files with 101 additions and 10 deletions

View File

@@ -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);

View File

@@ -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.
*

View File

@@ -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.

View File

@@ -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);

View File

@@ -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);
}
});