Add hidden KeyProtection API to specify SID
Allows the caller to specify which SID the given key should be bound to, overriding the default rule of binding to the current root/fingerprint SID. This is a prerequsite for introducing synthetic password based authentication flow. Test: cts-tradefed run cts -m CtsKeystoreTestCases Bug: 33126414 Change-Id: Ide03c0f4fd33ecca7a169ea763c3d4d0b173d1dd
This commit is contained in:
@@ -29,6 +29,8 @@ import android.service.gatekeeper.IGateKeeperService;
|
||||
*/
|
||||
public abstract class GateKeeper {
|
||||
|
||||
public static final long INVALID_SECURE_USER_ID = 0;
|
||||
|
||||
private GateKeeper() {}
|
||||
|
||||
public static IGateKeeperService getService() {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.security.keystore;
|
||||
|
||||
import android.security.Credentials;
|
||||
import android.security.GateKeeper;
|
||||
import android.security.KeyStore;
|
||||
import android.security.keymaster.KeyCharacteristics;
|
||||
import android.security.keymaster.KeymasterArguments;
|
||||
@@ -235,7 +236,8 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
||||
spec.isUserAuthenticationRequired(),
|
||||
spec.getUserAuthenticationValidityDurationSeconds(),
|
||||
spec.isUserAuthenticationValidWhileOnBody(),
|
||||
spec.isInvalidatedByBiometricEnrollment());
|
||||
spec.isInvalidatedByBiometricEnrollment(),
|
||||
GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
|
||||
} catch (IllegalStateException | IllegalArgumentException e) {
|
||||
throw new InvalidAlgorithmParameterException(e);
|
||||
}
|
||||
@@ -275,7 +277,8 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
||||
spec.isUserAuthenticationRequired(),
|
||||
spec.getUserAuthenticationValidityDurationSeconds(),
|
||||
spec.isUserAuthenticationValidWhileOnBody(),
|
||||
spec.isInvalidatedByBiometricEnrollment());
|
||||
spec.isInvalidatedByBiometricEnrollment(),
|
||||
GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
|
||||
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
|
||||
args,
|
||||
mKeymasterAlgorithm,
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.security.keystore;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.security.Credentials;
|
||||
import android.security.GateKeeper;
|
||||
import android.security.KeyPairGeneratorSpec;
|
||||
import android.security.KeyStore;
|
||||
import android.security.keymaster.KeyCharacteristics;
|
||||
@@ -346,7 +347,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
||||
mSpec.isUserAuthenticationRequired(),
|
||||
mSpec.getUserAuthenticationValidityDurationSeconds(),
|
||||
mSpec.isUserAuthenticationValidWhileOnBody(),
|
||||
mSpec.isInvalidatedByBiometricEnrollment());
|
||||
mSpec.isInvalidatedByBiometricEnrollment(),
|
||||
GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
throw new InvalidAlgorithmParameterException(e);
|
||||
}
|
||||
@@ -533,7 +535,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
||||
mSpec.isUserAuthenticationRequired(),
|
||||
mSpec.getUserAuthenticationValidityDurationSeconds(),
|
||||
mSpec.isUserAuthenticationValidWhileOnBody(),
|
||||
mSpec.isInvalidatedByBiometricEnrollment());
|
||||
mSpec.isInvalidatedByBiometricEnrollment(),
|
||||
GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
|
||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
|
||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
|
||||
mSpec.getKeyValidityForOriginationEnd());
|
||||
|
||||
@@ -500,7 +500,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
spec.isUserAuthenticationRequired(),
|
||||
spec.getUserAuthenticationValidityDurationSeconds(),
|
||||
spec.isUserAuthenticationValidWhileOnBody(),
|
||||
spec.isInvalidatedByBiometricEnrollment());
|
||||
spec.isInvalidatedByBiometricEnrollment(),
|
||||
spec.getBoundToSpecificSecureUserId());
|
||||
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
|
||||
spec.getKeyValidityStart());
|
||||
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
|
||||
@@ -696,7 +697,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
params.isUserAuthenticationRequired(),
|
||||
params.getUserAuthenticationValidityDurationSeconds(),
|
||||
params.isUserAuthenticationValidWhileOnBody(),
|
||||
params.isInvalidatedByBiometricEnrollment());
|
||||
params.isInvalidatedByBiometricEnrollment(),
|
||||
params.getBoundToSpecificSecureUserId());
|
||||
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
|
||||
args,
|
||||
keymasterAlgorithm,
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.KeyguardManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.security.GateKeeper;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.Signature;
|
||||
@@ -225,6 +226,7 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
private final int mUserAuthenticationValidityDurationSeconds;
|
||||
private final boolean mUserAuthenticationValidWhileOnBody;
|
||||
private final boolean mInvalidatedByBiometricEnrollment;
|
||||
private final long mBoundToSecureUserId;
|
||||
|
||||
private KeyProtection(
|
||||
Date keyValidityStart,
|
||||
@@ -239,7 +241,8 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
boolean userAuthenticationRequired,
|
||||
int userAuthenticationValidityDurationSeconds,
|
||||
boolean userAuthenticationValidWhileOnBody,
|
||||
boolean invalidatedByBiometricEnrollment) {
|
||||
boolean invalidatedByBiometricEnrollment,
|
||||
long boundToSecureUserId) {
|
||||
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
|
||||
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
|
||||
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
|
||||
@@ -255,6 +258,7 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
|
||||
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
|
||||
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
|
||||
mBoundToSecureUserId = boundToSecureUserId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,6 +439,24 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
return mInvalidatedByBiometricEnrollment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the secure user id that this key should be bound to.
|
||||
*
|
||||
* Normally an authentication-bound key is tied to the secure user id of the current user
|
||||
* (either the root SID from GateKeeper for auth-bound keys with a timeout, or the authenticator
|
||||
* id of the current fingerprint set for keys requiring explicit fingerprint authorization).
|
||||
* If this parameter is set (this method returning non-zero value), the key should be tied to
|
||||
* the specified secure user id, overriding the logic above.
|
||||
*
|
||||
* This is only applicable when {@link #isUserAuthenticationRequired} is {@code true}
|
||||
*
|
||||
* @see KeymasterUtils#addUserAuthArgs
|
||||
* @hide
|
||||
*/
|
||||
public long getBoundToSpecificSecureUserId() {
|
||||
return mBoundToSecureUserId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder of {@link KeyProtection} instances.
|
||||
*/
|
||||
@@ -454,6 +476,7 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
private boolean mUserAuthenticationValidWhileOnBody;
|
||||
private boolean mInvalidatedByBiometricEnrollment = true;
|
||||
|
||||
private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
|
||||
/**
|
||||
* Creates a new instance of the {@code Builder}.
|
||||
*
|
||||
@@ -773,6 +796,26 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the secure user id that this key should be bound to.
|
||||
*
|
||||
* Normally an authentication-bound key is tied to the secure user id of the current user
|
||||
* (either the root SID from GateKeeper for auth-bound keys with a timeout, or the
|
||||
* authenticator id of the current fingerprint set for keys requiring explicit fingerprint
|
||||
* authorization). If this parameter is set (this method returning non-zero value), the key
|
||||
* should be tied to the specified secure user id, overriding the logic above.
|
||||
*
|
||||
* This is only applicable when {@link #setUserAuthenticationRequired} is set to
|
||||
* {@code true}
|
||||
*
|
||||
* @see KeyProtection#getBoundToSpecificSecureUserId()
|
||||
* @hide
|
||||
*/
|
||||
public Builder setBoundToSpecificSecureUserId(long secureUserId) {
|
||||
mBoundToSecureUserId = secureUserId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an instance of {@link KeyProtection}.
|
||||
*
|
||||
@@ -793,7 +836,8 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
mUserAuthenticationRequired,
|
||||
mUserAuthenticationValidityDurationSeconds,
|
||||
mUserAuthenticationValidWhileOnBody,
|
||||
mInvalidatedByBiometricEnrollment);
|
||||
mInvalidatedByBiometricEnrollment,
|
||||
mBoundToSecureUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,10 @@ public abstract class KeymasterUtils {
|
||||
* @param userAuthenticationValidityDurationSeconds duration of time (seconds) for which user
|
||||
* authentication is valid as authorization for using the key or {@code -1} if every
|
||||
* use of the key needs authorization.
|
||||
*
|
||||
* @param boundToSpecificSecureUserId if non-zero, specify which SID the key will be bound to,
|
||||
* overriding the default logic in this method where the key is bound to either the root
|
||||
* SID of the current user, or the fingerprint SID if explicit fingerprint authorization
|
||||
* is requested.
|
||||
* @throws IllegalStateException if user authentication is required but the system is in a wrong
|
||||
* state (e.g., secure lock screen not set up) for generating or importing keys that
|
||||
* require user authentication.
|
||||
@@ -98,7 +101,8 @@ public abstract class KeymasterUtils {
|
||||
boolean userAuthenticationRequired,
|
||||
int userAuthenticationValidityDurationSeconds,
|
||||
boolean userAuthenticationValidWhileOnBody,
|
||||
boolean invalidatedByBiometricEnrollment) {
|
||||
boolean invalidatedByBiometricEnrollment,
|
||||
long boundToSpecificSecureUserId) {
|
||||
if (!userAuthenticationRequired) {
|
||||
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
|
||||
return;
|
||||
@@ -120,7 +124,9 @@ public abstract class KeymasterUtils {
|
||||
}
|
||||
|
||||
long sid;
|
||||
if (invalidatedByBiometricEnrollment) {
|
||||
if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
|
||||
sid = boundToSpecificSecureUserId;
|
||||
} else if (invalidatedByBiometricEnrollment) {
|
||||
// The fingerprint-only SID will change on fingerprint enrollment or removal of all,
|
||||
// enrolled fingerprints, invalidating the key.
|
||||
sid = fingerprintOnlySid;
|
||||
@@ -138,11 +144,16 @@ public abstract class KeymasterUtils {
|
||||
+ "supported for keys requiring fingerprint authentication");
|
||||
}
|
||||
} else {
|
||||
// The key is authorized for use for the specified amount of time after the user has
|
||||
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
|
||||
long rootSid = getRootSid();
|
||||
long sid;
|
||||
if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
|
||||
sid = boundToSpecificSecureUserId;
|
||||
} else {
|
||||
// The key is authorized for use for the specified amount of time after the user has
|
||||
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
|
||||
sid = getRootSid();
|
||||
}
|
||||
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
|
||||
KeymasterArguments.toUint64(rootSid));
|
||||
KeymasterArguments.toUint64(sid));
|
||||
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
|
||||
KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
|
||||
|
||||
Reference in New Issue
Block a user