Merge changes from topic "face-challenge-bug" into qt-r1-dev
* changes: Make recalibration notification VISIBILITY_SECRET Unlocking children profile must pass on existing challenge LSS must check canAuthenticate(userId) for correct user/profile Add much needed logging for face auth challenge / lockout path
This commit is contained in:
@@ -104,9 +104,17 @@ public class BiometricManager {
|
||||
*/
|
||||
@RequiresPermission(USE_BIOMETRIC)
|
||||
public @BiometricError int canAuthenticate() {
|
||||
return canAuthenticate(mContext.getUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||
public @BiometricError int canAuthenticate(int userId) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.canAuthenticate(mContext.getOpPackageName());
|
||||
return mService.canAuthenticate(mContext.getOpPackageName(), userId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ interface IBiometricService {
|
||||
void cancelAuthentication(IBinder token, String opPackageName);
|
||||
|
||||
// Checks if biometrics can be used.
|
||||
int canAuthenticate(String opPackageName);
|
||||
int canAuthenticate(String opPackageName, int userId);
|
||||
|
||||
// Register callback for when keyguard biometric eligibility changes.
|
||||
void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback);
|
||||
|
||||
@@ -766,10 +766,16 @@ public class BiometricService extends SystemService {
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public int canAuthenticate(String opPackageName) {
|
||||
checkPermission();
|
||||
public int canAuthenticate(String opPackageName, int userId) {
|
||||
Slog.d(TAG, "canAuthenticate: User=" + userId
|
||||
+ ", Caller=" + UserHandle.getCallingUserId());
|
||||
|
||||
if (userId != UserHandle.getCallingUserId()) {
|
||||
checkInternalPermission();
|
||||
} else {
|
||||
checkPermission();
|
||||
}
|
||||
|
||||
final int userId = UserHandle.getCallingUserId();
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
int error;
|
||||
try {
|
||||
@@ -965,6 +971,11 @@ public class BiometricService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
Slog.d(TAG, "checkAndGetBiometricModality: user=" + userId
|
||||
+ " isHardwareDetected=" + isHardwareDetected
|
||||
+ " hasTemplatesEnrolled=" + hasTemplatesEnrolled
|
||||
+ " enabledForApps=" + enabledForApps);
|
||||
|
||||
// Check error conditions
|
||||
if (!isHardwareDetected) {
|
||||
return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
|
||||
@@ -1090,6 +1090,8 @@ public abstract class BiometricServiceBase extends SystemService
|
||||
if (DEBUG) Slog.v(getTag(), "starting client "
|
||||
+ mCurrentClient.getClass().getSuperclass().getSimpleName()
|
||||
+ "(" + mCurrentClient.getOwnerString() + ")"
|
||||
+ " targetUserId: " + mCurrentClient.getTargetUserId()
|
||||
+ " currentUserId: " + mCurrentUserId
|
||||
+ " cookie: " + cookie + "/" + mCurrentClient.getCookie());
|
||||
if (cookie != mCurrentClient.getCookie()) {
|
||||
Slog.e(getTag(), "Mismatched cookie");
|
||||
|
||||
@@ -193,6 +193,7 @@ public class FaceService extends BiometricServiceBase {
|
||||
.setAutoCancel(true)
|
||||
.setCategory(Notification.CATEGORY_SYSTEM)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setVisibility(Notification.VISIBILITY_SECRET)
|
||||
.build();
|
||||
|
||||
nm.createNotificationChannel(channel);
|
||||
@@ -480,6 +481,8 @@ public class FaceService extends BiometricServiceBase {
|
||||
return;
|
||||
}
|
||||
|
||||
Slog.d(TAG, "Resetting lockout for user: " + mCurrentUserId);
|
||||
|
||||
try {
|
||||
mDaemonWrapper.resetLockout(token);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -420,9 +420,9 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
new PasswordSlotManager());
|
||||
}
|
||||
|
||||
public boolean hasEnrolledBiometrics() {
|
||||
public boolean hasEnrolledBiometrics(int userId) {
|
||||
BiometricManager bm = mContext.getSystemService(BiometricManager.class);
|
||||
return bm.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS;
|
||||
return bm.canAuthenticate(userId) == BiometricManager.BIOMETRIC_SUCCESS;
|
||||
}
|
||||
|
||||
public int binderGetCallingUid() {
|
||||
@@ -584,7 +584,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
// If boot took too long and the password in vold got expired, parent keystore will
|
||||
// be still locked, we ignore this case since the user will be prompted to unlock
|
||||
// the device after boot.
|
||||
unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */);
|
||||
unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */,
|
||||
false /* hasChallenge */, 0 /* challenge */);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to unlock child profile");
|
||||
}
|
||||
@@ -1160,12 +1161,13 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
return decryptionResult;
|
||||
}
|
||||
|
||||
private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated)
|
||||
private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated,
|
||||
boolean hasChallenge, long challenge)
|
||||
throws RemoteException {
|
||||
try {
|
||||
doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
|
||||
CREDENTIAL_TYPE_PASSWORD,
|
||||
false, 0 /* no challenge */, profileHandle, null /* progressCallback */);
|
||||
hasChallenge, challenge, profileHandle, null /* progressCallback */);
|
||||
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
|
||||
| NoSuchAlgorithmException | NoSuchPaddingException
|
||||
| InvalidAlgorithmParameterException | IllegalBlockSizeException
|
||||
@@ -1180,6 +1182,10 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void unlockUser(int userId, byte[] token, byte[] secret) {
|
||||
unlockUser(userId, token, secret, false /* hasChallenge */, 0 /* challenge */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock the user (both storage and user state) and its associated managed profiles
|
||||
* synchronously.
|
||||
@@ -1188,7 +1194,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
* can end up calling into other system services to process user unlock request (via
|
||||
* {@link com.android.server.SystemServiceManager#unlockUser} </em>
|
||||
*/
|
||||
private void unlockUser(int userId, byte[] token, byte[] secret) {
|
||||
private void unlockUser(int userId, byte[] token, byte[] secret,
|
||||
boolean hasChallenge, long challenge) {
|
||||
// TODO: make this method fully async so we can update UI with progress strings
|
||||
final boolean alreadyUnlocked = mUserManager.isUserUnlockingOrUnlocked(userId);
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
@@ -1230,7 +1237,10 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
// Unlock managed profile with unified lock
|
||||
if (tiedManagedProfileReadyToUnlock(profile)) {
|
||||
try {
|
||||
unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */);
|
||||
// Must pass the challenge on for resetLockout, so it's not over-written, which
|
||||
// causes LockSettingsService to revokeChallenge inappropriately.
|
||||
unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */,
|
||||
hasChallenge, challenge);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Failed to unlock child profile", e);
|
||||
}
|
||||
@@ -2493,7 +2503,11 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
private VerifyCredentialResponse spBasedDoVerifyCredential(byte[] userCredential,
|
||||
@CredentialType int credentialType, boolean hasChallenge, long challenge, int userId,
|
||||
ICheckCredentialProgressCallback progressCallback) throws RemoteException {
|
||||
if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId);
|
||||
|
||||
final boolean hasEnrolledBiometrics = mInjector.hasEnrolledBiometrics(userId);
|
||||
|
||||
Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId + " hasChallenge=" + hasChallenge
|
||||
+ " hasEnrolledBiometrics=" + hasEnrolledBiometrics);
|
||||
if (credentialType == CREDENTIAL_TYPE_NONE) {
|
||||
userCredential = null;
|
||||
}
|
||||
@@ -2503,7 +2517,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
// we need to generate challenge for each one, have it signed by GK and reset lockout
|
||||
// for each modality.
|
||||
if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE)
|
||||
&& mInjector.hasEnrolledBiometrics()) {
|
||||
&& hasEnrolledBiometrics) {
|
||||
challenge = mContext.getSystemService(FaceManager.class).generateChallenge();
|
||||
}
|
||||
|
||||
@@ -2546,9 +2560,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
notifyActivePasswordMetricsAvailable(credentialType, userCredential, userId);
|
||||
unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
|
||||
// Reset lockout only if user has enrolled templates
|
||||
if (mInjector.hasEnrolledBiometrics()) {
|
||||
if (hasEnrolledBiometrics) {
|
||||
BiometricManager bm = mContext.getSystemService(BiometricManager.class);
|
||||
Slog.i(TAG, "Resetting lockout, length: " + response.getPayload().length);
|
||||
bm.resetLockout(response.getPayload());
|
||||
|
||||
if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
|
||||
@@ -2558,7 +2571,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
|
||||
final byte[] secret = authResult.authToken.deriveDiskEncryptionKey();
|
||||
Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length);
|
||||
unlockUser(userId, null, secret);
|
||||
unlockUser(userId, null, secret, hasChallenge, challenge);
|
||||
|
||||
activateEscrowTokens(authResult.authToken, userId);
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ public class LockSettingsServiceTestable extends LockSettingsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrolledBiometrics() {
|
||||
public boolean hasEnrolledBiometrics(int userId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user