summaryrefslogtreecommitdiffstats
path: root/keystore
diff options
context:
space:
mode:
authorAlex Klyubin <klyubin@google.com>2015-04-28 14:21:01 -0700
committerAlex Klyubin <klyubin@google.com>2015-04-28 17:39:30 -0700
commit1eda77ae2122e2b85084eb429fbeecec0b9962e5 (patch)
treea10b902dce083a2899ab2445b4c5047ee492b321 /keystore
parent2301174eb3598a3290b5c56aae36b19b2c6743ac (diff)
downloadframeworks_base-1eda77ae2122e2b85084eb429fbeecec0b9962e5.zip
frameworks_base-1eda77ae2122e2b85084eb429fbeecec0b9962e5.tar.gz
frameworks_base-1eda77ae2122e2b85084eb429fbeecec0b9962e5.tar.bz2
Align AndroidKeyStore API with user auth API.
This simplifies the AndroidKeyStore API around user authentication: no more explicit control over which user authenticators are bound to which keys. User-authenticated keys with timeout are unlocked by whatever unlocks the secure lock screen (currently, password/PIN/pattern or fingerprint). User-authenticated keys that need authentication for every use are unlocked by fingerprint only. Bug: 20526234 Bug: 20642549 Change-Id: I1e5e6c988f32657d820797ad5696797477a9ebe9
Diffstat (limited to 'keystore')
-rw-r--r--keystore/java/android/security/AndroidKeyStore.java25
-rw-r--r--keystore/java/android/security/KeyGeneratorSpec.java80
-rw-r--r--keystore/java/android/security/KeyPairGeneratorSpec.java89
-rw-r--r--keystore/java/android/security/KeyStoreKeyGeneratorSpi.java25
-rw-r--r--keystore/java/android/security/KeyStoreKeyProperties.java95
-rw-r--r--keystore/java/android/security/KeyStoreKeySpec.java50
-rw-r--r--keystore/java/android/security/KeyStoreParameter.java107
-rw-r--r--keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java32
-rw-r--r--keystore/java/android/security/KeymasterUtils.java75
9 files changed, 216 insertions, 362 deletions
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index c259c25..ed91d70 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -529,27 +529,10 @@ public class AndroidKeyStore extends KeyStoreSpi {
KeymasterUtils.getKeymasterPaddingsFromJcaSignaturePaddings(
params.getSignaturePaddings()));
args.addInts(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
- if (params.getUserAuthenticators() == 0) {
- args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
- } else {
- args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
- KeyStoreKeyProperties.UserAuthenticator.allToKeymaster(
- params.getUserAuthenticators()));
- long secureUserId = GateKeeper.getSecureUserId();
- if (secureUserId == 0) {
- throw new IllegalStateException("Secure lock screen must be enabled"
- + " to import keys requiring user authentication");
- }
- args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, secureUserId);
- }
- if (params.isInvalidatedOnNewFingerprintEnrolled()) {
- // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports
- // that.
- }
- if (params.getUserAuthenticationValidityDurationSeconds() != -1) {
- args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
- params.getUserAuthenticationValidityDurationSeconds());
- }
+ KeymasterUtils.addUserAuthArgs(args,
+ params.getContext(),
+ params.isUserAuthenticationRequired(),
+ params.getUserAuthenticationValidityDurationSeconds());
args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
(params.getKeyValidityStart() != null)
? params.getKeyValidityStart() : new Date(0));
diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java
index 7ecc47e..8f135a6 100644
--- a/keystore/java/android/security/KeyGeneratorSpec.java
+++ b/keystore/java/android/security/KeyGeneratorSpec.java
@@ -51,9 +51,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
private final String[] mEncryptionPaddings;
private final String[] mBlockModes;
private final boolean mRandomizedEncryptionRequired;
- private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators;
+ private final boolean mUserAuthenticationRequired;
private final int mUserAuthenticationValidityDurationSeconds;
- private final boolean mInvalidatedOnNewFingerprintEnrolled;
private KeyGeneratorSpec(
Context context,
@@ -67,9 +66,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
String[] encryptionPaddings,
String[] blockModes,
boolean randomizedEncryptionRequired,
- @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators,
- int userAuthenticationValidityDurationSeconds,
- boolean invalidatedOnNewFingerprintEnrolled) {
+ boolean userAuthenticationRequired,
+ int userAuthenticationValidityDurationSeconds) {
if (context == null) {
throw new IllegalArgumentException("context == null");
} else if (TextUtils.isEmpty(keyStoreAlias)) {
@@ -92,9 +90,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings));
mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
- mUserAuthenticators = userAuthenticators;
+ mUserAuthenticationRequired = userAuthenticationRequired;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
- mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
}
/**
@@ -188,18 +185,17 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Gets the set of user authenticators which protect access to this key. The key can only be
- * used iff the user has authenticated to at least one of these user authenticators.
+ * Returns {@code true} if user authentication is required for this key to be used.
*
- * @return user authenticators or {@code 0} if the key can be used without user authentication.
+ * @see #getUserAuthenticationValidityDurationSeconds()
*/
- public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() {
- return mUserAuthenticators;
+ public boolean isUserAuthenticationRequired() {
+ return mUserAuthenticationRequired;
}
/**
- * Gets the duration of time (seconds) for which this key can be used after the user
- * successfully authenticates to one of the associated user authenticators.
+ * Gets the duration of time (seconds) for which this key can be used after the user is
+ * successfully authenticated.
*
* @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
* is required for every use of the key.
@@ -209,17 +205,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Returns {@code true} if this key must be permanently invalidated once a new fingerprint is
- * enrolled. This constraint only has effect if fingerprint reader is one of the user
- * authenticators protecting access to this key.
- *
- * @see #getUserAuthenticators()
- */
- public boolean isInvalidatedOnNewFingerprintEnrolled() {
- return mInvalidatedOnNewFingerprintEnrolled;
- }
-
- /**
* Returns {@code true} if the key must be encrypted in the {@link java.security.KeyStore}.
*/
public boolean isEncryptionRequired() {
@@ -238,9 +223,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
private String[] mEncryptionPaddings;
private String[] mBlockModes;
private boolean mRandomizedEncryptionRequired = true;
- private @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators;
+ private boolean mUserAuthenticationRequired;
private int mUserAuthenticationValidityDurationSeconds = -1;
- private boolean mInvalidatedOnNewFingerprintEnrolled;
/**
* Creates a new instance of the {@code Builder} with the given {@code context}. The
@@ -416,32 +400,35 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Sets the user authenticators which protect access to this key. The key can only be used
- * iff the user has authenticated to at least one of these user authenticators.
+ * Sets whether user authentication is required to use this key.
*
* <p>By default, the key can be used without user authentication.
*
- * @param userAuthenticators user authenticators or empty list if this key can be accessed
- * without user authentication.
+ * <p>When user authentication is required, the user authorizes the use of the key by
+ * authenticating to this Android device using a subset of their secure lock screen
+ * credentials. Different authentication methods are used depending on whether the every
+ * use of the key must be authenticated (as specified by
+ * {@link #setUserAuthenticationValidityDurationSeconds(int)}).
+ * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More
+ * information</a>.
*
* @see #setUserAuthenticationValidityDurationSeconds(int)
*/
- public Builder setUserAuthenticators(
- @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators) {
- mUserAuthenticators = userAuthenticators;
+ public Builder setUserAuthenticationRequired(boolean required) {
+ mUserAuthenticationRequired = required;
return this;
}
/**
- * Sets the duration of time (seconds) for which this key can be used after the user
- * successfully authenticates to one of the associated user authenticators.
+ * Sets the duration of time (seconds) for which this key can be used after the user is
+ * successfully authenticated. This has effect only if user authentication is required.
*
* <p>By default, the user needs to authenticate for every use of the key.
*
* @param seconds duration in seconds or {@code 0} if the user needs to authenticate for
* every use of the key.
*
- * @see #setUserAuthenticators(int)
+ * @see #setUserAuthenticationRequired(boolean)
*/
public Builder setUserAuthenticationValidityDurationSeconds(int seconds) {
mUserAuthenticationValidityDurationSeconds = seconds;
@@ -449,20 +436,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Sets whether this key must be invalidated (permanently) once a new fingerprint is
- * enrolled. This only has effect if fingerprint reader is one of the user authenticators
- * protecting access to the key.
- *
- * <p>By default, enrolling a new fingerprint does not invalidate the key.
- *
- * @see #setUserAuthenticators(Set)
- */
- public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) {
- mInvalidatedOnNewFingerprintEnrolled = invalidated;
- return this;
- }
-
- /**
* Builds a new instance instance of {@code KeyGeneratorSpec}.
*
* @throws IllegalArgumentException if a required field is missing or violates a constraint.
@@ -479,9 +452,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
mEncryptionPaddings,
mBlockModes,
mRandomizedEncryptionRequired,
- mUserAuthenticators,
- mUserAuthenticationValidityDurationSeconds,
- mInvalidatedOnNewFingerprintEnrolled);
+ mUserAuthenticationRequired,
+ mUserAuthenticationValidityDurationSeconds);
}
}
}
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index 5e5cf37..d6d3789 100644
--- a/keystore/java/android/security/KeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -95,12 +95,10 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
private final boolean mRandomizedEncryptionRequired;
- private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators;
+ private final boolean mUserAuthenticationRequired;
private final int mUserAuthenticationValidityDurationSeconds;
- private final boolean mInvalidatedOnNewFingerprintEnrolled;
-
/**
* Parameter specification for the "{@code AndroidKeyPairGenerator}"
* instance of the {@link java.security.KeyPairGenerator} API. The
@@ -145,9 +143,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
String[] signaturePaddings,
String[] blockModes,
boolean randomizedEncryptionRequired,
- @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators,
- int userAuthenticationValidityDurationSeconds,
- boolean invalidatedOnNewFingerprintEnrolled) {
+ boolean userAuthenticationRequired,
+ int userAuthenticationValidityDurationSeconds) {
if (context == null) {
throw new IllegalArgumentException("context == null");
} else if (TextUtils.isEmpty(keyStoreAlias)) {
@@ -195,9 +192,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(signaturePaddings));
mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
- mUserAuthenticators = userAuthenticators;
+ mUserAuthenticationRequired = userAuthenticationRequired;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
- mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
}
/**
@@ -227,9 +223,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
null, // signature paddings
null, // block modes
false, // randomized encryption required
- 0, // user authenticators
- -1, // user authentication validity duration (seconds)
- false // invalidate on new fingerprint enrolled
+ false, // user authentication required
+ -1 // user authentication validity duration (seconds)
);
}
@@ -396,44 +391,34 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Gets the set of user authenticators which protect access to the private key. The key can only
- * be used iff the user has authenticated to at least one of these user authenticators.
+ * Returns {@code true} if user authentication is required for this key to be used.
*
* <p>This restriction applies only to private key operations. Public key operations are not
* restricted.
*
- * @return user authenticators or {@code 0} if the key can be used without user authentication.
+ * @see #getUserAuthenticationValidityDurationSeconds()
*/
- public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() {
- return mUserAuthenticators;
+ public boolean isUserAuthenticationRequired() {
+ return mUserAuthenticationRequired;
}
/**
* Gets the duration of time (seconds) for which the private key can be used after the user
- * successfully authenticates to one of the associated user authenticators.
+ * is successfully authenticated.
*
* <p>This restriction applies only to private key operations. Public key operations are not
* restricted.
*
* @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
* is required for every use of the key.
+ *
+ * @see #isUserAuthenticationRequired()
*/
public int getUserAuthenticationValidityDurationSeconds() {
return mUserAuthenticationValidityDurationSeconds;
}
/**
- * Returns {@code true} if this key must be permanently invalidated once a new fingerprint is
- * enrolled. This constraint only has effect if fingerprint reader is one of the user
- * authenticators protecting access to this key.
- *
- * @see #getUserAuthenticators()
- */
- public boolean isInvalidatedOnNewFingerprintEnrolled() {
- return mInvalidatedOnNewFingerprintEnrolled;
- }
-
- /**
* Builder class for {@link KeyPairGeneratorSpec} objects.
* <p>
* This will build a parameter spec for use with the <a href="{@docRoot}
@@ -493,12 +478,10 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
private boolean mRandomizedEncryptionRequired = true;
- private @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators;
+ private boolean mUserAuthenticationRequired;
private int mUserAuthenticationValidityDurationSeconds = -1;
- private boolean mInvalidatedOnNewFingerprintEnrolled;
-
/**
* Creates a new instance of the {@code Builder} with the given
* {@code context}. The {@code context} passed in may be used to pop up
@@ -774,28 +757,31 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Sets the user authenticators which protect access to this key. The key can only be used
- * iff the user has authenticated to at least one of these user authenticators.
+ * Sets whether user authentication is required to use this key.
*
* <p>By default, the key can be used without user authentication.
*
+ * <p>When user authentication is required, the user authorizes the use of the key by
+ * authenticating to this Android device using a subset of their secure lock screen
+ * credentials. Different authentication methods are used depending on whether the every
+ * use of the key must be authenticated (as specified by
+ * {@link #setUserAuthenticationValidityDurationSeconds(int)}).
+ * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More
+ * information</a>.
+ *
* <p>This restriction applies only to private key operations. Public key operations are not
* restricted.
*
- * @param userAuthenticators user authenticators or {@code 0} if this key can be accessed
- * without user authentication.
- *
* @see #setUserAuthenticationValidityDurationSeconds(int)
*/
- public Builder setUserAuthenticators(
- @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators) {
- mUserAuthenticators = userAuthenticators;
+ public Builder setUserAuthenticationRequired(boolean required) {
+ mUserAuthenticationRequired = required;
return this;
}
/**
- * Sets the duration of time (seconds) for which this key can be used after the user
- * successfully authenticates to one of the associated user authenticators.
+ * Sets the duration of time (seconds) for which this key can be used after the user is
+ * successfully authenticated. This has effect only if user authentication is required.
*
* <p>By default, the user needs to authenticate for every use of the key.
*
@@ -805,7 +791,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
* @param seconds duration in seconds or {@code 0} if the user needs to authenticate for
* every use of the key.
*
- * @see #setUserAuthenticators(int)
+ * @see #setUserAuthenticationRequired(boolean)
*/
public Builder setUserAuthenticationValidityDurationSeconds(int seconds) {
mUserAuthenticationValidityDurationSeconds = seconds;
@@ -813,20 +799,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Sets whether this key must be invalidated (permanently) once a new fingerprint is
- * enrolled. This only has effect if fingerprint reader is one of the user authenticators
- * protecting access to the key.
- *
- * <p>By default, enrolling a new fingerprint does not invalidate the key.
- *
- * @see #setUserAuthenticators(Set)
- */
- public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) {
- mInvalidatedOnNewFingerprintEnrolled = invalidated;
- return this;
- }
-
- /**
* Builds the instance of the {@code KeyPairGeneratorSpec}.
*
* @throws IllegalArgumentException if a required field is missing
@@ -852,9 +824,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
mSignaturePaddings,
mBlockModes,
mRandomizedEncryptionRequired,
- mUserAuthenticators,
- mUserAuthenticationValidityDurationSeconds,
- mInvalidatedOnNewFingerprintEnrolled);
+ mUserAuthenticationRequired,
+ mUserAuthenticationValidityDurationSeconds);
}
}
}
diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
index 293c4c9..20f6042 100644
--- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
@@ -161,27 +161,10 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
KeymasterDefs.KM_TAG_PADDING,
KeymasterUtils.getKeymasterPaddingsFromJcaEncryptionPaddings(
spec.getEncryptionPaddings()));
- if (spec.getUserAuthenticators() == 0) {
- args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
- } else {
- args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
- KeyStoreKeyProperties.UserAuthenticator.allToKeymaster(
- spec.getUserAuthenticators()));
- long secureUserId = GateKeeper.getSecureUserId();
- if (secureUserId == 0) {
- throw new IllegalStateException("Secure lock screen must be enabled"
- + " to generate keys requiring user authentication");
- }
- args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, secureUserId);
- }
- if (spec.isInvalidatedOnNewFingerprintEnrolled()) {
- // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports
- // that.
- }
- if (spec.getUserAuthenticationValidityDurationSeconds() != -1) {
- args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
- spec.getUserAuthenticationValidityDurationSeconds());
- }
+ KeymasterUtils.addUserAuthArgs(args,
+ spec.getContext(),
+ spec.isUserAuthenticationRequired(),
+ spec.getUserAuthenticationValidityDurationSeconds());
args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
(spec.getKeyValidityStart() != null)
? spec.getKeyValidityStart() : new Date(0));
diff --git a/keystore/java/android/security/KeyStoreKeyProperties.java b/keystore/java/android/security/KeyStoreKeyProperties.java
index 206103f..b85ec53 100644
--- a/keystore/java/android/security/KeyStoreKeyProperties.java
+++ b/keystore/java/android/security/KeyStoreKeyProperties.java
@@ -122,101 +122,6 @@ public abstract class KeyStoreKeyProperties {
}
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true,
- value = {UserAuthenticator.LOCK_SCREEN, UserAuthenticator.FINGERPRINT_READER})
- public @interface UserAuthenticatorEnum {}
-
- /**
- * User authenticators which can be used to restrict/protect access to keys.
- */
- public static abstract class UserAuthenticator {
- private UserAuthenticator() {}
-
- /** Lock screen. */
- public static final int LOCK_SCREEN = 1 << 0;
-
- /** Fingerprint reader/sensor. */
- public static final int FINGERPRINT_READER = 1 << 1;
-
- /**
- * @hide
- */
- public static int toKeymaster(@UserAuthenticatorEnum int userAuthenticator) {
- switch (userAuthenticator) {
- case LOCK_SCREEN:
- return KeymasterDefs.HW_AUTH_PASSWORD;
- case FINGERPRINT_READER:
- return KeymasterDefs.HW_AUTH_FINGERPRINT;
- default:
- throw new IllegalArgumentException(
- "Unknown user authenticator: " + userAuthenticator);
- }
- }
-
- /**
- * @hide
- */
- public static @UserAuthenticatorEnum int fromKeymaster(int userAuthenticator) {
- switch (userAuthenticator) {
- case KeymasterDefs.HW_AUTH_PASSWORD:
- return LOCK_SCREEN;
- case KeymasterDefs.HW_AUTH_FINGERPRINT:
- return FINGERPRINT_READER;
- default:
- throw new IllegalArgumentException(
- "Unknown user authenticator: " + userAuthenticator);
- }
- }
-
- /**
- * @hide
- */
- public static int allToKeymaster(@UserAuthenticatorEnum int userAuthenticators) {
- int result = 0;
- int userAuthenticator = 1;
- while (userAuthenticators != 0) {
- if ((userAuthenticators & 1) != 0) {
- result |= toKeymaster(userAuthenticator);
- }
- userAuthenticators >>>= 1;
- userAuthenticator <<= 1;
- }
- return result;
- }
-
- /**
- * @hide
- */
- public static @UserAuthenticatorEnum int allFromKeymaster(int userAuthenticators) {
- @UserAuthenticatorEnum int result = 0;
- int userAuthenticator = 1;
- while (userAuthenticators != 0) {
- if ((userAuthenticators & 1) != 0) {
- result |= fromKeymaster(userAuthenticator);
- }
- userAuthenticators >>>= 1;
- userAuthenticator <<= 1;
- }
- return result;
- }
-
- /**
- * @hide
- */
- public static String toString(@UserAuthenticatorEnum int userAuthenticator) {
- switch (userAuthenticator) {
- case LOCK_SCREEN:
- return "LOCK_SCREEN";
- case FINGERPRINT_READER:
- return "FINGERPRINT_READER";
- default:
- throw new IllegalArgumentException(
- "Unknown user authenticator: " + userAuthenticator);
- }
- }
- }
-
- @Retention(RetentionPolicy.SOURCE)
@IntDef({Origin.GENERATED, Origin.IMPORTED, Origin.UNKNOWN})
public @interface OriginEnum {}
diff --git a/keystore/java/android/security/KeyStoreKeySpec.java b/keystore/java/android/security/KeyStoreKeySpec.java
index a89e4dd..96d58d8 100644
--- a/keystore/java/android/security/KeyStoreKeySpec.java
+++ b/keystore/java/android/security/KeyStoreKeySpec.java
@@ -36,10 +36,9 @@ public class KeyStoreKeySpec implements KeySpec {
private final String[] mSignaturePaddings;
private final String[] mDigests;
private final String[] mBlockModes;
- private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators;
- private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mTeeEnforcedUserAuthenticators;
+ private final boolean mUserAuthenticationRequired;
private final int mUserAuthenticationValidityDurationSeconds;
- private final boolean mInvalidatedOnNewFingerprintEnrolled;
+ private final boolean mUserAuthenticationRequirementTeeEnforced;
/**
* @hide
@@ -56,10 +55,9 @@ public class KeyStoreKeySpec implements KeySpec {
String[] signaturePaddings,
String[] digests,
String[] blockModes,
- @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators,
- @KeyStoreKeyProperties.UserAuthenticatorEnum int teeEnforcedUserAuthenticators,
+ boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
- boolean invalidatedOnNewFingerprintEnrolled) {
+ boolean userAuthenticationRequirementTeeEnforced) {
mKeystoreAlias = keystoreKeyAlias;
mTeeBacked = teeBacked;
mOrigin = origin;
@@ -74,10 +72,9 @@ public class KeyStoreKeySpec implements KeySpec {
ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(signaturePaddings));
mDigests = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(digests));
mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
- mUserAuthenticators = userAuthenticators;
- mTeeEnforcedUserAuthenticators = teeEnforcedUserAuthenticators;
+ mUserAuthenticationRequired = userAuthenticationRequired;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
- mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
+ mUserAuthenticationRequirementTeeEnforced = userAuthenticationRequirementTeeEnforced;
}
/**
@@ -172,43 +169,34 @@ public class KeyStoreKeySpec implements KeySpec {
}
/**
- * Gets the set of user authenticators which protect access to the key. The key can only be used
- * iff the user has authenticated to at least one of these user authenticators.
+ * Returns {@code true} if user authentication is required for this key to be used.
*
- * @return user authenticators or {@code 0} if the key can be used without user authentication.
+ * @see #getUserAuthenticationValidityDurationSeconds()
*/
- public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() {
- return mUserAuthenticators;
+ public boolean isUserAuthenticationRequired() {
+ return mUserAuthenticationRequired;
}
/**
- * Gets the set of user authenticators for which the TEE enforces access restrictions for this
- * key. This is a subset of the user authentications returned by
- * {@link #getUserAuthenticators()}.
- */
- public @KeyStoreKeyProperties.UserAuthenticatorEnum int getTeeEnforcedUserAuthenticators() {
- return mTeeEnforcedUserAuthenticators;
- }
-
- /**
- * Gets the duration of time (seconds) for which the key can be used after the user
- * successfully authenticates to one of the associated user authenticators.
+ * Gets the duration of time (seconds) for which this key can be used after the user is
+ * successfully authenticated.
*
* @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
* is required for every use of the key.
+ *
+ * @see #isUserAuthenticationRequired()
*/
public int getUserAuthenticationValidityDurationSeconds() {
return mUserAuthenticationValidityDurationSeconds;
}
/**
- * Returns {@code true} if this key will be permanently invalidated once a new fingerprint is
- * enrolled. This constraint only has effect if fingerprint reader is one of the user
- * authenticators protecting access to this key.
+ * Returns {@code true} if the requirement that this key can only be used if the user has been
+ * authenticated if enforced by the TEE.
*
- * @see #getUserAuthenticators()
+ * @see #isUserAuthenticationRequired()
*/
- public boolean isInvalidatedOnNewFingerprintEnrolled() {
- return mInvalidatedOnNewFingerprintEnrolled;
+ public boolean isUserAuthenticationRequirementTeeEnforced() {
+ return mUserAuthenticationRequirementTeeEnforced;
}
}
diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java
index c24b74f..b4747e9 100644
--- a/keystore/java/android/security/KeyStoreParameter.java
+++ b/keystore/java/android/security/KeyStoreParameter.java
@@ -39,7 +39,8 @@ import javax.crypto.Cipher;
* {@code KeyStore}.
*/
public final class KeyStoreParameter implements ProtectionParameter {
- private int mFlags;
+ private final Context mContext;
+ private final int mFlags;
private final Date mKeyValidityStart;
private final Date mKeyValidityForOriginationEnd;
private final Date mKeyValidityForConsumptionEnd;
@@ -49,11 +50,12 @@ public final class KeyStoreParameter implements ProtectionParameter {
private final String[] mDigests;
private final String[] mBlockModes;
private final boolean mRandomizedEncryptionRequired;
- private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators;
+ private final boolean mUserAuthenticationRequired;
private final int mUserAuthenticationValidityDurationSeconds;
- private final boolean mInvalidatedOnNewFingerprintEnrolled;
- private KeyStoreParameter(int flags,
+ private KeyStoreParameter(
+ Context context,
+ int flags,
Date keyValidityStart,
Date keyValidityForOriginationEnd,
Date keyValidityForConsumptionEnd,
@@ -63,15 +65,17 @@ public final class KeyStoreParameter implements ProtectionParameter {
String[] digests,
String[] blockModes,
boolean randomizedEncryptionRequired,
- @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators,
- int userAuthenticationValidityDurationSeconds,
- boolean invalidatedOnNewFingerprintEnrolled) {
- if ((userAuthenticationValidityDurationSeconds < 0)
+ boolean userAuthenticationRequired,
+ int userAuthenticationValidityDurationSeconds) {
+ if (context == null) {
+ throw new IllegalArgumentException("context == null");
+ } else if ((userAuthenticationValidityDurationSeconds < 0)
&& (userAuthenticationValidityDurationSeconds != -1)) {
throw new IllegalArgumentException(
"userAuthenticationValidityDurationSeconds must not be negative");
}
+ mContext = context;
mFlags = flags;
mKeyValidityStart = keyValidityStart;
mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
@@ -84,9 +88,15 @@ public final class KeyStoreParameter implements ProtectionParameter {
mDigests = ArrayUtils.cloneIfNotEmpty(digests);
mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
- mUserAuthenticators = userAuthenticators;
+ mUserAuthenticationRequired = userAuthenticationRequired;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
- mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
+ }
+
+ /**
+ * Gets the Android context used for operations with this instance.
+ */
+ public Context getContext() {
+ return mContext;
}
/**
@@ -198,18 +208,17 @@ public final class KeyStoreParameter implements ProtectionParameter {
}
/**
- * Gets the set of user authenticators which protect access to this key. The key can only be
- * used iff the user has authenticated to at least one of these user authenticators.
+ * Returns {@code true} if user authentication is required for this key to be used.
*
- * @return user authenticators or {@code 0} if the key can be used without user authentication.
+ * @see #getUserAuthenticationValidityDurationSeconds()
*/
- public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() {
- return mUserAuthenticators;
+ public boolean isUserAuthenticationRequired() {
+ return mUserAuthenticationRequired;
}
/**
- * Gets the duration of time (seconds) for which this key can be used after the user
- * successfully authenticates to one of the associated user authenticators.
+ * Gets the duration of time (seconds) for which this key can be used after the user is
+ * successfully authenticated.
*
* @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
* is required for every use of the key.
@@ -219,17 +228,6 @@ public final class KeyStoreParameter implements ProtectionParameter {
}
/**
- * Returns {@code true} if this key must be permanently invalidated once a new fingerprint is
- * enrolled. This constraint only has effect if fingerprint reader is one of the user
- * authenticators protecting access to this key.
- *
- * @see #getUserAuthenticators()
- */
- public boolean isInvalidatedOnNewFingerprintEnrolled() {
- return mInvalidatedOnNewFingerprintEnrolled;
- }
-
- /**
* Builder class for {@link KeyStoreParameter} objects.
* <p>
* This will build protection parameters for use with the
@@ -247,6 +245,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
* </pre>
*/
public final static class Builder {
+ private final Context mContext;
private int mFlags;
private Date mKeyValidityStart;
private Date mKeyValidityForOriginationEnd;
@@ -257,9 +256,8 @@ public final class KeyStoreParameter implements ProtectionParameter {
private String[] mDigests;
private String[] mBlockModes;
private boolean mRandomizedEncryptionRequired = true;
- private @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators;
+ private boolean mUserAuthenticationRequired;
private int mUserAuthenticationValidityDurationSeconds = -1;
- private boolean mInvalidatedOnNewFingerprintEnrolled;
/**
* Creates a new instance of the {@code Builder} with the given
@@ -271,8 +269,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
if (context == null) {
throw new NullPointerException("context == null");
}
-
- // Context is currently not used, but will be in the future.
+ mContext = context;
}
/**
@@ -440,32 +437,35 @@ public final class KeyStoreParameter implements ProtectionParameter {
}
/**
- * Sets the user authenticators which protect access to this key. The key can only be used
- * iff the user has authenticated to at least one of these user authenticators.
+ * Sets whether user authentication is required to use this key.
*
* <p>By default, the key can be used without user authentication.
*
- * @param userAuthenticators user authenticators or {@code 0} if this key can be accessed
- * without user authentication.
+ * <p>When user authentication is required, the user authorizes the use of the key by
+ * authenticating to this Android device using a subset of their secure lock screen
+ * credentials. Different authentication methods are used depending on whether the every
+ * use of the key must be authenticated (as specified by
+ * {@link #setUserAuthenticationValidityDurationSeconds(int)}).
+ * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More
+ * information</a>.
*
* @see #setUserAuthenticationValidityDurationSeconds(int)
*/
- public Builder setUserAuthenticators(
- @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators) {
- mUserAuthenticators = userAuthenticators;
+ public Builder setUserAuthenticationRequired(boolean required) {
+ mUserAuthenticationRequired = required;
return this;
}
/**
- * Sets the duration of time (seconds) for which this key can be used after the user
- * successfully authenticates to one of the associated user authenticators.
+ * Sets the duration of time (seconds) for which this key can be used after the user is
+ * successfully authenticated. This has effect only if user authentication is required.
*
* <p>By default, the user needs to authenticate for every use of the key.
*
* @param seconds duration in seconds or {@code 0} if the user needs to authenticate for
* every use of the key.
*
- * @see #setUserAuthenticators(int)
+ * @see #setUserAuthenticationRequired(boolean)
*/
public Builder setUserAuthenticationValidityDurationSeconds(int seconds) {
mUserAuthenticationValidityDurationSeconds = seconds;
@@ -473,27 +473,15 @@ public final class KeyStoreParameter implements ProtectionParameter {
}
/**
- * Sets whether this key must be invalidated (permanently) whenever a new fingerprint is
- * enrolled. This only has effect if fingerprint reader is one of the user authenticators
- * protecting access to the key.
- *
- * <p>By default, enrolling a new fingerprint does not invalidate the key.
- *
- * @see #setUserAuthenticators(Set)
- */
- public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) {
- mInvalidatedOnNewFingerprintEnrolled = invalidated;
- return this;
- }
-
- /**
* Builds the instance of the {@code KeyStoreParameter}.
*
* @throws IllegalArgumentException if a required field is missing
* @return built instance of {@code KeyStoreParameter}
*/
public KeyStoreParameter build() {
- return new KeyStoreParameter(mFlags,
+ return new KeyStoreParameter(
+ mContext,
+ mFlags,
mKeyValidityStart,
mKeyValidityForOriginationEnd,
mKeyValidityForConsumptionEnd,
@@ -503,9 +491,8 @@ public final class KeyStoreParameter implements ProtectionParameter {
mDigests,
mBlockModes,
mRandomizedEncryptionRequired,
- mUserAuthenticators,
- mUserAuthenticationValidityDurationSeconds,
- mInvalidatedOnNewFingerprintEnrolled);
+ mUserAuthenticationRequired,
+ mUserAuthenticationValidityDurationSeconds);
}
}
}
diff --git a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
index 4be0638..bfe09e3 100644
--- a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
@@ -81,8 +81,8 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
String[] encryptionPaddings;
String[] digests;
String[] blockModes;
- @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators;
- @KeyStoreKeyProperties.UserAuthenticatorEnum int teeEnforcedUserAuthenticators;
+ int keymasterSwEnforcedUserAuthenticators;
+ int keymasterHwEnforcedUserAuthenticators;
try {
if (keyCharacteristics.hwEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
teeBacked = true;
@@ -122,21 +122,10 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
keyCharacteristics.getInts(KeymasterDefs.KM_TAG_DIGEST));
blockModes = KeymasterUtils.getJcaBlockModesFromKeymasterBlockModes(
keyCharacteristics.getInts(KeymasterDefs.KM_TAG_BLOCK_MODE));
-
- @KeyStoreKeyProperties.UserAuthenticatorEnum
- int swEnforcedKeymasterUserAuthenticators =
+ keymasterSwEnforcedUserAuthenticators =
keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
- @KeyStoreKeyProperties.UserAuthenticatorEnum
- int hwEnforcedKeymasterUserAuthenticators =
+ keymasterHwEnforcedUserAuthenticators =
keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
- @KeyStoreKeyProperties.UserAuthenticatorEnum
- int keymasterUserAuthenticators =
- swEnforcedKeymasterUserAuthenticators | hwEnforcedKeymasterUserAuthenticators;
- userAuthenticators = KeyStoreKeyProperties.UserAuthenticator.allFromKeymaster(
- keymasterUserAuthenticators);
- teeEnforcedUserAuthenticators =
- KeyStoreKeyProperties.UserAuthenticator.allFromKeymaster(
- hwEnforcedKeymasterUserAuthenticators);
} catch (IllegalArgumentException e) {
throw new InvalidKeySpecException("Unsupported key characteristic", e);
}
@@ -157,11 +146,13 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
&& (keyValidityForConsumptionEnd.getTime() == Long.MAX_VALUE)) {
keyValidityForConsumptionEnd = null;
}
+ boolean userAuthenticationRequired =
+ !keyCharacteristics.getBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
int userAuthenticationValidityDurationSeconds =
keyCharacteristics.getInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, -1);
-
- // TODO: Populate the value below from key characteristics once Keymaster is ready.
- boolean invalidatedOnNewFingerprintEnrolled = false;
+ boolean userAuthenticationRequirementEnforcedInTee = (userAuthenticationRequired)
+ && (keymasterHwEnforcedUserAuthenticators != 0)
+ && (keymasterSwEnforcedUserAuthenticators == 0);
return new KeyStoreKeySpec(entryAlias,
teeBacked,
@@ -175,10 +166,9 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
EmptyArray.STRING, // no signature paddings -- this is symmetric crypto
digests,
blockModes,
- userAuthenticators,
- teeEnforcedUserAuthenticators,
+ userAuthenticationRequired,
userAuthenticationValidityDurationSeconds,
- invalidatedOnNewFingerprintEnrolled);
+ userAuthenticationRequirementEnforcedInTee);
}
@Override
diff --git a/keystore/java/android/security/KeymasterUtils.java b/keystore/java/android/security/KeymasterUtils.java
index 67f75c2..7bf5475 100644
--- a/keystore/java/android/security/KeymasterUtils.java
+++ b/keystore/java/android/security/KeymasterUtils.java
@@ -16,7 +16,14 @@
package android.security;
+import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterDefs;
+import android.service.gatekeeper.IGateKeeperService;
import libcore.util.EmptyArray;
@@ -339,4 +346,72 @@ public abstract class KeymasterUtils {
}
return result;
}
+
+ private static long getRootSid() {
+ IGateKeeperService gatekeeperService = IGateKeeperService.Stub.asInterface(
+ ServiceManager.getService("android.service.gatekeeper.IGateKeeperService"));
+ if (gatekeeperService == null) {
+ throw new IllegalStateException("Gatekeeper service not available");
+ }
+
+ try {
+ return gatekeeperService.getSecureUserId(UserHandle.myUserId());
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to obtain root SID");
+ }
+ }
+
+ /**
+ * Adds keymaster arguments to express the key's authorization policy supported by user
+ * authentication.
+ *
+ * @param userAuthenticationRequired whether user authentication is required to authorize the
+ * use of the key.
+ * @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.
+ */
+ public static void addUserAuthArgs(KeymasterArguments args,
+ Context context,
+ boolean userAuthenticationRequired,
+ int userAuthenticationValidityDurationSeconds) {
+ if (!userAuthenticationRequired) {
+ args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
+ return;
+ }
+
+ if (userAuthenticationValidityDurationSeconds == -1) {
+ // Every use of this key needs to be authorized by the user. This currently means
+ // fingerprint-only auth.
+ FingerprintManager fingerprintManager =
+ context.getSystemService(FingerprintManager.class);
+ if ((fingerprintManager == null) || (!fingerprintManager.isHardwareDetected())) {
+ throw new IllegalStateException(
+ "This device does not support keys which require authentication for every"
+ + " use -- this requires fingerprint authentication which is not"
+ + " available on this device");
+ }
+ long fingerprintOnlySid = fingerprintManager.getAuthenticatorId();
+ if (fingerprintOnlySid == 0) {
+ throw new IllegalStateException(
+ "At least one fingerprint must be enrolled to create keys requiring user"
+ + " authentication for every use");
+ }
+ args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, fingerprintOnlySid);
+ args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
+ } 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();
+ if (rootSid == 0) {
+ throw new IllegalStateException("Secure lock screen must be enabled"
+ + " to create keys requiring user authentication");
+ }
+ args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, rootSid);
+ args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
+ KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
+ args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
+ userAuthenticationValidityDurationSeconds);
+ }
+ }
}