From dd77d27c1342b01c428dbc152f2463dbaaa87937 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Mon, 15 Mar 2021 16:54:29 -0700 Subject: [PATCH 1/2] Update lockout-related properties for easier understandability 1) resetLockoutRequiresHardwareAuthToken is moved to the base SensorPropertiesinternal class, despite face always requiring it. This will be clearer, since we are further splitting resetLockout logic into "challenge-required" (IBiometricsFace@1.0) and "challenge-less" (IFace@1.0) It would be weird to have a "resetLockoutRequiresChallenge" property without a "resetLockoutRequiresHardwareAuthToken" property. 2) Will be adding a resetLockoutRequiresChallenge to SensorPropertiesInternal in the next CL. Bug: 182327296 Test: reset lockout on Pixel4 Change-Id: Ifa4b36dc42d91e967506a59d2880f47f61ec6cdf --- .../biometrics/SensorPropertiesInternal.java | 8 ++++++-- .../face/FaceSensorPropertiesInternal.java | 5 ++++- .../FingerprintSensorPropertiesInternal.java | 14 ++------------ .../sensors/fingerprint/hidl/Fingerprint21.java | 3 ++- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java index 0b81c6c8cc25a..32d8bb5e94f60 100644 --- a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java +++ b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java @@ -31,23 +31,26 @@ public class SensorPropertiesInternal implements Parcelable { public final int sensorId; @SensorProperties.Strength public final int sensorStrength; public final int maxEnrollmentsPerUser; + public final boolean resetLockoutRequiresHardwareAuthToken; public static SensorPropertiesInternal from(@NonNull SensorPropertiesInternal prop) { return new SensorPropertiesInternal(prop.sensorId, prop.sensorStrength, - prop.maxEnrollmentsPerUser); + prop.maxEnrollmentsPerUser, prop.resetLockoutRequiresHardwareAuthToken); } protected SensorPropertiesInternal(int sensorId, @SensorProperties.Strength int sensorStrength, - int maxEnrollmentsPerUser) { + int maxEnrollmentsPerUser, boolean resetLockoutRequiresHardwareAuthToken) { this.sensorId = sensorId; this.sensorStrength = sensorStrength; this.maxEnrollmentsPerUser = maxEnrollmentsPerUser; + this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; } protected SensorPropertiesInternal(Parcel in) { sensorId = in.readInt(); sensorStrength = in.readInt(); maxEnrollmentsPerUser = in.readInt(); + resetLockoutRequiresHardwareAuthToken = in.readBoolean(); } public static final Creator CREATOR = @@ -73,6 +76,7 @@ public class SensorPropertiesInternal implements Parcelable { dest.writeInt(sensorId); dest.writeInt(sensorStrength); dest.writeInt(maxEnrollmentsPerUser); + dest.writeBoolean(resetLockoutRequiresHardwareAuthToken); } @Override diff --git a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java index b9c0d12de22ba..504f90c43e57f 100644 --- a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java +++ b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java @@ -42,7 +42,10 @@ public class FaceSensorPropertiesInternal extends SensorPropertiesInternal { public FaceSensorPropertiesInternal(int sensorId, @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, boolean supportsFaceDetection, boolean supportsSelfIllumination) { - super(sensorId, strength, maxEnrollmentsPerUser); + // resetLockout is managed by the HAL and requires a HardwareAuthToken for all face + // HAL interfaces (IBiometricsFace@1.0 HIDL and IFace@1.0 AIDL). + super(sensorId, strength, maxEnrollmentsPerUser, + true /* resetLockoutRequiresHardwareAuthToken */); this.supportsFaceDetection = supportsFaceDetection; this.supportsSelfIllumination = supportsSelfIllumination; } diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java index 51addc95ac79c..536b5d779741b 100644 --- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java +++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java @@ -35,12 +35,6 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna */ public final @FingerprintSensorProperties.SensorType int sensorType; - /** - * IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT - * cannot be checked - */ - public final boolean resetLockoutRequiresHardwareAuthToken; - /** * The location of the center of the sensor if applicable. For example, sensors of type * {@link FingerprintSensorProperties#TYPE_UDFPS_OPTICAL} would report this value as the @@ -68,9 +62,8 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna @FingerprintSensorProperties.SensorType int sensorType, boolean resetLockoutRequiresHardwareAuthToken, int sensorLocationX, int sensorLocationY, int sensorRadius) { - super(sensorId, strength, maxEnrollmentsPerUser); + super(sensorId, strength, maxEnrollmentsPerUser, resetLockoutRequiresHardwareAuthToken); this.sensorType = sensorType; - this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; this.sensorLocationX = sensorLocationX; this.sensorLocationY = sensorLocationY; this.sensorRadius = sensorRadius; @@ -98,9 +91,8 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, @FingerprintSensorProperties.SensorType int sensorType, boolean resetLockoutRequiresHardwareAuthToken) { - super(sensorId, strength, maxEnrollmentsPerUser); + super(sensorId, strength, maxEnrollmentsPerUser, resetLockoutRequiresHardwareAuthToken); this.sensorType = sensorType; - this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; int[] props = context.getResources().getIntArray( com.android.internal.R.array.config_udfps_sensor_props); @@ -119,7 +111,6 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna protected FingerprintSensorPropertiesInternal(Parcel in) { super(in); sensorType = in.readInt(); - resetLockoutRequiresHardwareAuthToken = in.readBoolean(); sensorLocationX = in.readInt(); sensorLocationY = in.readInt(); sensorRadius = in.readInt(); @@ -147,7 +138,6 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(sensorType); - dest.writeBoolean(resetLockoutRequiresHardwareAuthToken); dest.writeInt(sensorLocationX); dest.writeInt(sensorLocationY); dest.writeInt(sensorRadius); 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 6e22a797b435b..cc3b569a73776 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 @@ -347,7 +347,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider final @FingerprintSensorProperties.SensorType int sensorType = mIsUdfps ? FingerprintSensorProperties.TYPE_UDFPS_OPTICAL : FingerprintSensorProperties.TYPE_REAR; - // resetLockout is controlled by the framework, so hardwareAuthToken is not required + // IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT + // cannot be checked final boolean resetLockoutRequiresHardwareAuthToken = false; final int maxEnrollmentsPerUser = mContext.getResources() .getInteger(R.integer.config_fingerprintMaxTemplatesPerUser); From a372cb1c84838890d7f557797179ec953b6aa3c7 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Mon, 15 Mar 2021 19:11:47 -0700 Subject: [PATCH 2/2] Add resetLockoutRequiresChallenge property IFace and IFingerprint AIDL interfaces do not require challenge for resetLockout. Rather, they are time-based. See the HAL interface for more details. Bug: 182327296 Test: reset lockout on Pixel4 Test: atest com.android.systemui Test: atest com.android.server.biometrics Change-Id: Ibf1130d77e714d15fb9eccd3175027a28de08f7b --- .../hardware/biometrics/SensorPropertiesInternal.java | 10 ++++++++-- .../hardware/face/FaceSensorPropertiesInternal.java | 4 ++-- .../FingerprintSensorPropertiesInternal.java | 10 ++++++++-- .../android/keyguard/KeyguardUpdateMonitorTest.java | 3 ++- .../biometrics/sensors/face/aidl/FaceProvider.java | 2 +- .../server/biometrics/sensors/face/hidl/Face10.java | 3 ++- 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java index 32d8bb5e94f60..909f456dd4331 100644 --- a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java +++ b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java @@ -32,18 +32,22 @@ public class SensorPropertiesInternal implements Parcelable { @SensorProperties.Strength public final int sensorStrength; public final int maxEnrollmentsPerUser; public final boolean resetLockoutRequiresHardwareAuthToken; + public final boolean resetLockoutRequiresChallenge; public static SensorPropertiesInternal from(@NonNull SensorPropertiesInternal prop) { return new SensorPropertiesInternal(prop.sensorId, prop.sensorStrength, - prop.maxEnrollmentsPerUser, prop.resetLockoutRequiresHardwareAuthToken); + prop.maxEnrollmentsPerUser, prop.resetLockoutRequiresHardwareAuthToken, + prop.resetLockoutRequiresChallenge); } protected SensorPropertiesInternal(int sensorId, @SensorProperties.Strength int sensorStrength, - int maxEnrollmentsPerUser, boolean resetLockoutRequiresHardwareAuthToken) { + int maxEnrollmentsPerUser, boolean resetLockoutRequiresHardwareAuthToken, + boolean resetLockoutRequiresChallenge) { this.sensorId = sensorId; this.sensorStrength = sensorStrength; this.maxEnrollmentsPerUser = maxEnrollmentsPerUser; this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; + this.resetLockoutRequiresChallenge = resetLockoutRequiresChallenge; } protected SensorPropertiesInternal(Parcel in) { @@ -51,6 +55,7 @@ public class SensorPropertiesInternal implements Parcelable { sensorStrength = in.readInt(); maxEnrollmentsPerUser = in.readInt(); resetLockoutRequiresHardwareAuthToken = in.readBoolean(); + resetLockoutRequiresChallenge = in.readBoolean(); } public static final Creator CREATOR = @@ -77,6 +82,7 @@ public class SensorPropertiesInternal implements Parcelable { dest.writeInt(sensorStrength); dest.writeInt(maxEnrollmentsPerUser); dest.writeBoolean(resetLockoutRequiresHardwareAuthToken); + dest.writeBoolean(resetLockoutRequiresChallenge); } @Override diff --git a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java index 504f90c43e57f..34cbcb417e1b1 100644 --- a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java +++ b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java @@ -41,11 +41,11 @@ public class FaceSensorPropertiesInternal extends SensorPropertiesInternal { */ public FaceSensorPropertiesInternal(int sensorId, @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, boolean supportsFaceDetection, - boolean supportsSelfIllumination) { + boolean supportsSelfIllumination, boolean resetLockoutRequiresChallenge) { // resetLockout is managed by the HAL and requires a HardwareAuthToken for all face // HAL interfaces (IBiometricsFace@1.0 HIDL and IFace@1.0 AIDL). super(sensorId, strength, maxEnrollmentsPerUser, - true /* resetLockoutRequiresHardwareAuthToken */); + true /* resetLockoutRequiresHardwareAuthToken */, resetLockoutRequiresChallenge); this.supportsFaceDetection = supportsFaceDetection; this.supportsSelfIllumination = supportsSelfIllumination; } diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java index 536b5d779741b..adc61a744f89b 100644 --- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java +++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java @@ -62,7 +62,12 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna @FingerprintSensorProperties.SensorType int sensorType, boolean resetLockoutRequiresHardwareAuthToken, int sensorLocationX, int sensorLocationY, int sensorRadius) { - super(sensorId, strength, maxEnrollmentsPerUser, resetLockoutRequiresHardwareAuthToken); + // IBiometricsFingerprint@2.1 handles lockout in the framework, so the challenge is not + // required as it can only be generated/attested/verified by TEE components. + // IFingerprint@1.0 handles lockout below the HAL, but does not require a challenge. See + // the HAL interface for more details. + super(sensorId, strength, maxEnrollmentsPerUser, resetLockoutRequiresHardwareAuthToken, + false /* resetLockoutRequiresChallenge */); this.sensorType = sensorType; this.sensorLocationX = sensorLocationX; this.sensorLocationY = sensorLocationY; @@ -91,7 +96,8 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, @FingerprintSensorProperties.SensorType int sensorType, boolean resetLockoutRequiresHardwareAuthToken) { - super(sensorId, strength, maxEnrollmentsPerUser, resetLockoutRequiresHardwareAuthToken); + super(sensorId, strength, maxEnrollmentsPerUser, resetLockoutRequiresHardwareAuthToken, + false /* resetLockoutRequiresChallenge */); this.sensorType = sensorType; int[] props = context.getResources().getIntArray( diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index b9d8d27b89718..e35e9877998c5 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -195,7 +195,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { when(mFaceSensorProperties.get(anyInt())).thenReturn(new FaceSensorPropertiesInternal( 0 /* id */, FaceSensorProperties.STRENGTH_STRONG, 1 /* maxTemplatesAllowed */, - false /* supportsFaceDetection */, true /* supportsSelfIllumination */)); + false /* supportsFaceDetection */, true /* supportsSelfIllumination */, + false /* resetLockoutRequiresChallenge */)); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java index 1d8f210b394e6..07a653fcfd3f7 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java @@ -137,7 +137,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { final FaceSensorPropertiesInternal internalProp = new FaceSensorPropertiesInternal( prop.commonProps.sensorId, prop.commonProps.sensorStrength, prop.commonProps.maxEnrollmentsPerUser, false /* supportsFaceDetection */, - prop.halControlsPreview); + prop.halControlsPreview, false /* resetLockoutRequiresChallenge */); final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler, internalProp); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java index 1b9bd7fd0cea6..afe7f24edeaf8 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java @@ -332,7 +332,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @NonNull BiometricScheduler scheduler) { mSensorProperties = new FaceSensorPropertiesInternal(sensorId, Utils.authenticatorStrengthToPropertyStrength(strength), - maxTemplatesAllowed, false /* supportsFaceDetect */, supportsSelfIllumination); + maxTemplatesAllowed, false /* supportsFaceDetect */, supportsSelfIllumination, + true /* resetLockoutRequiresChallenge */); mContext = context; mSensorId = sensorId; mScheduler = scheduler;