diff options
| author | 2021-03-18 03:24:08 +0000 | |
|---|---|---|
| committer | 2021-03-18 03:24:08 +0000 | |
| commit | 741663a30dc7b4a2fab9936b5b07c8c046672f06 (patch) | |
| tree | 93d860ec9be1f5e6400734bbc89e68494cba64a7 | |
| parent | 4e94266881e8d76b4e109c6fb40162f5fac9d717 (diff) | |
| parent | 7f59ef96d12de1ae36784a5e91702c0048c0a4d0 (diff) | |
Merge "Add challenge-less resetLockout for new AIDL interfaces" into sc-dev
7 files changed, 148 insertions, 49 deletions
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index 6dbd590df851..a74e2da30077 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -393,14 +393,13 @@ public class FaceService extends SystemService implements BiometricServiceCallba final IFaceServiceReceiver receiver, final String opPackageName) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); - final Pair<Integer, ServiceProvider> provider = getSingleProvider(); - if (provider == null) { - Slog.w(TAG, "Null provider for removeAll"); - return; + for (ServiceProvider provider : mServiceProviders) { + List<FaceSensorPropertiesInternal> props = provider.getSensorProperties(); + for (FaceSensorPropertiesInternal prop : props) { + provider.scheduleRemoveAll(prop.sensorId, token, userId, receiver, + opPackageName); + } } - - provider.second.scheduleRemoveAll(provider.first, token, userId, receiver, - opPackageName); } @Override // Binder call diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java index 4cdb68df70af..84aa6d9ad1f8 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java @@ -23,11 +23,11 @@ import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback; import android.hardware.biometrics.face.V1_0.OptionalBool; import android.hardware.biometrics.face.V1_0.OptionalUint64; import android.hardware.biometrics.face.V1_0.Status; -import android.os.NativeHandle; import android.os.RemoteException; import android.util.Slog; import java.util.ArrayList; +import java.util.Arrays; public class TestHal extends IBiometricsFace.Stub { private static final String TAG = "face.hidl.TestHal"; @@ -107,8 +107,12 @@ public class TestHal extends IBiometricsFace.Stub { } @Override - public int remove(int faceId) { + public int remove(int faceId) throws RemoteException { Slog.w(TAG, "remove"); + if (mCallback != null) { + mCallback.onRemoved(0 /* deviceId */, new ArrayList<Integer>(Arrays.asList(faceId)), + 0 /* userId */); + } return 0; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 396dd5f42d4d..3f489e98d5f1 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -506,13 +506,13 @@ public class FingerprintService extends SystemService implements BiometricServic final IFingerprintServiceReceiver receiver, final String opPackageName) { Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); - final Pair<Integer, ServiceProvider> provider = getSingleProvider(); - if (provider == null) { - Slog.w(TAG, "Null provider for removeAll"); - return; + for (ServiceProvider provider : mServiceProviders) { + List<FingerprintSensorPropertiesInternal> props = provider.getSensorProperties(); + for (FingerprintSensorPropertiesInternal prop : props) { + provider.scheduleRemoveAll(prop.sensorId, token, receiver, userId, + opPackageName); + } } - provider.second.scheduleRemoveAll(provider.first, token, receiver, userId, - opPackageName); } @Override // Binder call diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index 50fdc2e8a856..7ff5ec305b88 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -527,7 +527,9 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider // Fingerprint2.1 keeps track of lockout in the framework. Let's just do it on the handler // thread. mHandler.post(() -> { - mLockoutTracker.resetFailedAttemptsForUser(true /* clearAttemptCounter */, userId); + final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(mContext, + userId, mContext.getOpPackageName(), sensorId, mLockoutTracker); + mScheduler.scheduleClientMonitor(client); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java new file mode 100644 index 000000000000..a39f4f8c4d7e --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.biometrics.sensors.fingerprint.hidl; + +import android.annotation.NonNull; +import android.content.Context; +import android.hardware.biometrics.BiometricsProtoEnums; + +import com.android.server.biometrics.BiometricsProto; +import com.android.server.biometrics.sensors.BaseClientMonitor; + +/** + * Clears lockout, which is handled in the framework (and not the HAL) for the + * IBiometricsFingerprint@2.1 interface. + */ +public class FingerprintResetLockoutClient extends BaseClientMonitor { + + @NonNull final LockoutFrameworkImpl mLockoutTracker; + + public FingerprintResetLockoutClient(@NonNull Context context, int userId, + @NonNull String owner, int sensorId, @NonNull LockoutFrameworkImpl lockoutTracker) { + super(context, null /* token */, null /* listener */, userId, owner, 0 /* cookie */, + sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN, + BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN); + mLockoutTracker = lockoutTracker; + } + + @Override + public void start(@NonNull Callback callback) { + super.start(callback); + mLockoutTracker.resetFailedAttemptsForUser(true /* clearAttemptCounter */, + getTargetUserId()); + callback.onClientFinished(this, true /* success */); + } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_RESET_LOCKOUT; + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java index 14fdb507b0b1..129f6a61df04 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java @@ -93,8 +93,11 @@ public class TestHal extends IBiometricsFingerprint.Stub { } @Override - public int remove(int gid, int fid) { + public int remove(int gid, int fid) throws RemoteException { Slog.w(TAG, "Remove"); + if (mCallback != null) { + mCallback.onRemoved(0 /* deviceId */, fid, gid, 0 /* remaining */); + } return 0; } diff --git a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java index 6d250ecb9fa4..6201b9414aaf 100644 --- a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java +++ b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java @@ -119,19 +119,11 @@ public class BiometricDeferredQueue { for (UserAuthInfo userAuthInfo : pendingResetLockuts) { Slog.d(TAG, "Resetting face lockout for sensor: " + sensorId + ", user: " + userAuthInfo.userId); - final VerifyCredentialResponse response = spManager.verifyChallengeInternal( - getGatekeeperService(), userAuthInfo.gatekeeperPassword, challenge, - userAuthInfo.userId); - if (response == null) { - Slog.wtf(TAG, "VerifyChallenge failed, null response"); - continue; + final byte[] hat = requestHatFromGatekeeperPassword(spManager, userAuthInfo, + challenge); + if (hat != null) { + faceManager.resetLockout(sensorId, userAuthInfo.userId, hat); } - if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { - Slog.wtf(TAG, "VerifyChallenge failed, response: " - + response.getResponseCode()); - } - faceManager.resetLockout(sensorId, userAuthInfo.userId, - response.getGatekeeperHAT()); } sensorIds.remove(sensorId); @@ -146,15 +138,6 @@ public class BiometricDeferredQueue { finishCallback.onFinished(); } } - - synchronized IGateKeeperService getGatekeeperService() { - final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE); - if (service == null) { - Slog.e(TAG, "Unable to acquire GateKeeperService"); - return null; - } - return IGateKeeperService.Stub.asInterface(service); - } } @Nullable private FaceResetLockoutTask mFaceResetLockoutTask; @@ -214,10 +197,19 @@ public class BiometricDeferredQueue { mFingerprintManager.resetLockout(prop.sensorId, user.userId, null /* hardwareAuthToken */); } + } else if (!prop.resetLockoutRequiresChallenge) { + for (UserAuthInfo user : pendingResetLockouts) { + Slog.d(TAG, "Resetting fingerprint lockout for sensor: " + prop.sensorId + + ", user: " + user.userId); + final byte[] hat = requestHatFromGatekeeperPassword(mSpManager, user, + 0 /* challenge */); + if (hat != null) { + mFingerprintManager.resetLockout(prop.sensorId, user.userId, hat); + } + } } else { - Slog.e(TAG, "Fingerprint resetLockout with HAT not supported yet"); - // TODO(b/152414803): Implement this when resetLockout is implemented below - // the framework. + Slog.w(TAG, "No fingerprint HAL interface requires HAT with challenge" + + ", sensorId: " + prop.sensorId); } } } @@ -228,11 +220,6 @@ public class BiometricDeferredQueue { * in-flight challenge, we generate a single challenge to reset lockout for all profiles. This * hopefully reduces/eliminates issues such as overwritten challenge, incorrectly revoked * challenge, or other race conditions. - * - * TODO(b/162965646) This logic can be avoided if multiple in-flight challenges are supported. - * Though it will need to continue to exist to support existing HIDLs, each profile that - * requires resetLockout could have its own challenge, and the `mPendingResetLockouts` queue - * can be avoided. */ private void processPendingLockoutsForFace(List<UserAuthInfo> pendingResetLockouts) { if (mFaceManager != null) { @@ -251,10 +238,60 @@ public class BiometricDeferredQueue { mFaceResetLockoutTask = new FaceResetLockoutTask(mFaceFinishCallback, mFaceManager, mSpManager, sensorIds, pendingResetLockouts); for (final FaceSensorPropertiesInternal prop : faceSensorProperties) { - // Generate a challenge for each sensor. The challenge does not need to be - // per-user, since the HAT returned by gatekeeper contains userId. - mFaceManager.generateChallenge(prop.sensorId, mFaceResetLockoutTask); + if (prop.resetLockoutRequiresHardwareAuthToken) { + if (prop.resetLockoutRequiresChallenge) { + // Generate a challenge for each sensor. The challenge does not need to be + // per-user, since the HAT returned by gatekeeper contains userId. + mFaceManager.generateChallenge(prop.sensorId, mFaceResetLockoutTask); + } else { + for (UserAuthInfo user : pendingResetLockouts) { + Slog.d(TAG, "Resetting face lockout for sensor: " + prop.sensorId + + ", user: " + user.userId); + final byte[] hat = requestHatFromGatekeeperPassword(mSpManager, user, + 0 /* challenge */); + if (hat != null) { + mFaceManager.resetLockout(prop.sensorId, user.userId, hat); + } + } + } + } else { + Slog.w(TAG, "Lockout is below the HAL for all face authentication interfaces" + + ", sensorId: " + prop.sensorId); + } } } } + + @Nullable + private static byte[] requestHatFromGatekeeperPassword( + @NonNull SyntheticPasswordManager spManager, + @NonNull UserAuthInfo userAuthInfo, long challenge) { + final VerifyCredentialResponse response = spManager.verifyChallengeInternal( + getGatekeeperService(), userAuthInfo.gatekeeperPassword, challenge, + userAuthInfo.userId); + if (response == null) { + Slog.wtf(TAG, "VerifyChallenge failed, null response"); + return null; + } + if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { + Slog.wtf(TAG, "VerifyChallenge failed, response: " + + response.getResponseCode()); + return null; + } + if (response.getGatekeeperHAT() == null) { + Slog.e(TAG, "Null HAT received from spManager"); + } + + return response.getGatekeeperHAT(); + } + + @Nullable + private static synchronized IGateKeeperService getGatekeeperService() { + final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE); + if (service == null) { + Slog.e(TAG, "Unable to acquire GateKeeperService"); + return null; + } + return IGateKeeperService.Stub.asInterface(service); + } } |