diff options
| author | 2018-11-16 22:52:30 +0000 | |
|---|---|---|
| committer | 2018-11-16 22:52:30 +0000 | |
| commit | 278913ae620c06f1bbdf70e8d52c0a6eae33ce29 (patch) | |
| tree | 078be8d2624cd984f0a82ec7161c5eb7220ee1af | |
| parent | 992cd354fcebfd78ff7dc0eb2acf362d14497eef (diff) | |
| parent | 057b743fe90ff6b9d19db297e12d9f6055439276 (diff) | |
Merge "Update KeyStore for new biometric modalities"
4 files changed, 54 insertions, 19 deletions
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index f4dcce1e7e58..15ded8d1b7b1 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -154,7 +154,7 @@ public final class KeymasterDefs { // User authenticators. public static final int HW_AUTH_PASSWORD = 1 << 0; - public static final int HW_AUTH_FINGERPRINT = 1 << 1; + public static final int HW_AUTH_BIOMETRIC = 1 << 1; // Error codes. public static final int KM_ERROR_OK = 0; diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 835b735ad55f..fec800dcb306 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -23,6 +23,7 @@ import android.app.Application; import android.app.KeyguardManager; import android.content.Context; import android.content.pm.PackageManager; +import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.os.Binder; import android.os.IBinder; @@ -1254,7 +1255,7 @@ public class KeyStore { return new UserNotAuthenticatedException(); } - long fingerprintOnlySid = getFingerprintOnlySid(); + final long fingerprintOnlySid = getFingerprintOnlySid(); if ((fingerprintOnlySid != 0) && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) { // One of the key's SIDs is the current fingerprint SID -- user can be @@ -1262,6 +1263,14 @@ public class KeyStore { return new UserNotAuthenticatedException(); } + final long faceOnlySid = getFaceOnlySid(); + if ((faceOnlySid != 0) + && (keySids.contains(KeymasterArguments.toUint64(faceOnlySid)))) { + // One of the key's SIDs is the current face SID -- user can be + // authenticated against that SID. + return new UserNotAuthenticatedException(); + } + // None of the key's SIDs can ever be authenticated return new KeyPermanentlyInvalidatedException(); } @@ -1272,6 +1281,21 @@ public class KeyStore { } } + private long getFaceOnlySid() { + final PackageManager packageManager = mContext.getPackageManager(); + if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) { + return 0; + } + FaceManager faceManager = mContext.getSystemService(FaceManager.class); + if (faceManager == null) { + return 0; + } + + // TODO: Restore USE_BIOMETRIC or USE_BIOMETRIC_INTERNAL permission check in + // FaceManager.getAuthenticatorId once the ID is no longer needed here. + return faceManager.getAuthenticatorId(); + } + private long getFingerprintOnlySid() { final PackageManager packageManager = mContext.getPackageManager(); if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java index 7bbc09964584..a2d23558616b 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java @@ -182,8 +182,8 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED); boolean invalidatedByBiometricEnrollment = false; - if (keymasterSwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT - || keymasterHwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT) { + if (keymasterSwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_BIOMETRIC + || keymasterHwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_BIOMETRIC) { // Fingerprint-only key; will be invalidated if the root SID isn't in the SID list. invalidatedByBiometricEnrollment = keymasterSecureUserIds != null && !keymasterSecureUserIds.isEmpty() diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java index f829bb7cfeed..52896b59ddaf 100644 --- a/keystore/java/android/security/keystore/KeymasterUtils.java +++ b/keystore/java/android/security/keystore/KeymasterUtils.java @@ -16,7 +16,7 @@ package android.security.keystore; -import android.app.ActivityManager; +import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.security.GateKeeper; import android.security.KeyStore; @@ -24,6 +24,8 @@ import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterDefs; import java.security.ProviderException; +import java.util.ArrayList; +import java.util.List; /** * @hide @@ -121,35 +123,44 @@ public abstract class KeymasterUtils { if (spec.getUserAuthenticationValidityDurationSeconds() == -1) { // Every use of this key needs to be authorized by the user. This currently means - // fingerprint-only auth. + // fingerprint or face auth. FingerprintManager fingerprintManager = KeyStore.getApplicationContext().getSystemService(FingerprintManager.class); + FaceManager faceManager = + KeyStore.getApplicationContext().getSystemService(FaceManager.class); // TODO: Restore USE_FINGERPRINT permission check in // FingerprintManager.getAuthenticatorId once the ID is no longer needed here. - long fingerprintOnlySid = + final long fingerprintOnlySid = (fingerprintManager != null) ? fingerprintManager.getAuthenticatorId() : 0; - if (fingerprintOnlySid == 0) { + final long faceOnlySid = + (faceManager != null) ? faceManager.getAuthenticatorId() : 0; + + if (fingerprintOnlySid == 0 && faceOnlySid == 0) { throw new IllegalStateException( - "At least one fingerprint must be enrolled to create keys requiring user" + "At least one biometric must be enrolled to create keys requiring user" + " authentication for every use"); } - long sid; + List<Long> sids = new ArrayList<>(); if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) { - sid = spec.getBoundToSpecificSecureUserId(); + sids.add(spec.getBoundToSpecificSecureUserId()); } else if (spec.isInvalidatedByBiometricEnrollment()) { - // The fingerprint-only SID will change on fingerprint enrollment or removal of all, - // enrolled fingerprints, invalidating the key. - sid = fingerprintOnlySid; + // The biometric-only SIDs will change on biometric enrollment or removal of all + // enrolled templates, invalidating the key. + sids.add(fingerprintOnlySid); + sids.add(faceOnlySid); } else { // The root SID will *not* change on fingerprint enrollment, or removal of all // enrolled fingerprints, allowing the key to remain valid. - sid = getRootSid(); + sids.add(getRootSid()); + } + + for (int i = 0; i < sids.size(); i++) { + args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, + KeymasterArguments.toUint64(sids.get(i))); } + args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_BIOMETRIC); - args.addUnsignedLong( - KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid)); - args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT); if (spec.isUserAuthenticationValidWhileOnBody()) { throw new ProviderException("Key validity extension while device is on-body is not " + "supported for keys requiring fingerprint authentication"); @@ -166,7 +177,7 @@ public abstract class KeymasterUtils { args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid)); args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, - KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT); + KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_BIOMETRIC); args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, spec.getUserAuthenticationValidityDurationSeconds()); if (spec.isUserAuthenticationValidWhileOnBody()) { |