Merge "Update KeyStore for new biometric modalities"
This commit is contained in:
committed by
Android (Google) Code Review
commit
278913ae62
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
args.addUnsignedLong(
|
||||
KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid));
|
||||
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
|
||||
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);
|
||||
|
||||
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()) {
|
||||
|
||||
Reference in New Issue
Block a user