Merge "Align AndroidKeyStore API with user auth API." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 61f907e..1117623 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28535,10 +28535,9 @@
     method public java.lang.String getKeystoreAlias();
     method public int getPurposes();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public int getUserAuthenticators();
     method public boolean isEncryptionRequired();
-    method public boolean isInvalidatedOnNewFingerprintEnrolled();
     method public boolean isRandomizedEncryptionRequired();
+    method public boolean isUserAuthenticationRequired();
   }
 
   public static class KeyGeneratorSpec.Builder {
@@ -28548,7 +28547,6 @@
     method public android.security.KeyGeneratorSpec.Builder setBlockModes(java.lang.String...);
     method public android.security.KeyGeneratorSpec.Builder setEncryptionPaddings(java.lang.String...);
     method public android.security.KeyGeneratorSpec.Builder setEncryptionRequired(boolean);
-    method public android.security.KeyGeneratorSpec.Builder setInvalidatedOnNewFingerprintEnrolled(boolean);
     method public android.security.KeyGeneratorSpec.Builder setKeySize(int);
     method public android.security.KeyGeneratorSpec.Builder setKeyValidityEnd(java.util.Date);
     method public android.security.KeyGeneratorSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date);
@@ -28556,8 +28554,8 @@
     method public android.security.KeyGeneratorSpec.Builder setKeyValidityStart(java.util.Date);
     method public android.security.KeyGeneratorSpec.Builder setPurposes(int);
     method public android.security.KeyGeneratorSpec.Builder setRandomizedEncryptionRequired(boolean);
+    method public android.security.KeyGeneratorSpec.Builder setUserAuthenticationRequired(boolean);
     method public android.security.KeyGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
-    method public android.security.KeyGeneratorSpec.Builder setUserAuthenticators(int);
   }
 
   public class KeyNotYetValidException extends java.security.InvalidKeyException {
@@ -28585,10 +28583,9 @@
     method public java.util.Date getStartDate();
     method public javax.security.auth.x500.X500Principal getSubjectDN();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public int getUserAuthenticators();
     method public boolean isEncryptionRequired();
-    method public boolean isInvalidatedOnNewFingerprintEnrolled();
     method public boolean isRandomizedEncryptionRequired();
+    method public boolean isUserAuthenticationRequired();
   }
 
   public static final class KeyPairGeneratorSpec.Builder {
@@ -28601,7 +28598,6 @@
     method public android.security.KeyPairGeneratorSpec.Builder setEncryptionPaddings(java.lang.String...);
     method public android.security.KeyPairGeneratorSpec.Builder setEncryptionRequired();
     method public android.security.KeyPairGeneratorSpec.Builder setEndDate(java.util.Date);
-    method public android.security.KeyPairGeneratorSpec.Builder setInvalidatedOnNewFingerprintEnrolled(boolean);
     method public android.security.KeyPairGeneratorSpec.Builder setKeySize(int);
     method public android.security.KeyPairGeneratorSpec.Builder setKeyType(java.lang.String) throws java.security.NoSuchAlgorithmException;
     method public android.security.KeyPairGeneratorSpec.Builder setKeyValidityEnd(java.util.Date);
@@ -28614,8 +28610,8 @@
     method public android.security.KeyPairGeneratorSpec.Builder setSignaturePaddings(java.lang.String...);
     method public android.security.KeyPairGeneratorSpec.Builder setStartDate(java.util.Date);
     method public android.security.KeyPairGeneratorSpec.Builder setSubject(javax.security.auth.x500.X500Principal);
+    method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationRequired(boolean);
     method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
-    method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticators(int);
   }
 
   public abstract class KeyStoreKeyProperties {
@@ -28640,14 +28636,6 @@
   public static abstract class KeyStoreKeyProperties.PurposeEnum implements java.lang.annotation.Annotation {
   }
 
-  public static abstract class KeyStoreKeyProperties.UserAuthenticator {
-    field public static final int FINGERPRINT_READER = 2; // 0x2
-    field public static final int LOCK_SCREEN = 1; // 0x1
-  }
-
-  public static abstract class KeyStoreKeyProperties.UserAuthenticatorEnum implements java.lang.annotation.Annotation {
-  }
-
   public class KeyStoreKeySpec implements java.security.spec.KeySpec {
     method public java.lang.String[] getBlockModes();
     method public java.lang.String[] getDigests();
@@ -28660,15 +28648,15 @@
     method public int getOrigin();
     method public int getPurposes();
     method public java.lang.String[] getSignaturePaddings();
-    method public int getTeeEnforcedUserAuthenticators();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public int getUserAuthenticators();
-    method public boolean isInvalidatedOnNewFingerprintEnrolled();
     method public boolean isTeeBacked();
+    method public boolean isUserAuthenticationRequired();
+    method public boolean isUserAuthenticationRequirementTeeEnforced();
   }
 
   public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
     method public java.lang.String[] getBlockModes();
+    method public android.content.Context getContext();
     method public java.lang.String[] getDigests();
     method public java.lang.String[] getEncryptionPaddings();
     method public java.util.Date getKeyValidityForConsumptionEnd();
@@ -28677,11 +28665,10 @@
     method public int getPurposes();
     method public java.lang.String[] getSignaturePaddings();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public int getUserAuthenticators();
     method public boolean isDigestsSpecified();
     method public boolean isEncryptionRequired();
-    method public boolean isInvalidatedOnNewFingerprintEnrolled();
     method public boolean isRandomizedEncryptionRequired();
+    method public boolean isUserAuthenticationRequired();
   }
 
   public static final class KeyStoreParameter.Builder {
@@ -28691,7 +28678,6 @@
     method public android.security.KeyStoreParameter.Builder setDigests(java.lang.String...);
     method public android.security.KeyStoreParameter.Builder setEncryptionPaddings(java.lang.String...);
     method public android.security.KeyStoreParameter.Builder setEncryptionRequired(boolean);
-    method public android.security.KeyStoreParameter.Builder setInvalidatedOnNewFingerprintEnrolled(boolean);
     method public android.security.KeyStoreParameter.Builder setKeyValidityEnd(java.util.Date);
     method public android.security.KeyStoreParameter.Builder setKeyValidityForConsumptionEnd(java.util.Date);
     method public android.security.KeyStoreParameter.Builder setKeyValidityForOriginationEnd(java.util.Date);
@@ -28699,8 +28685,8 @@
     method public android.security.KeyStoreParameter.Builder setPurposes(int);
     method public android.security.KeyStoreParameter.Builder setRandomizedEncryptionRequired(boolean);
     method public android.security.KeyStoreParameter.Builder setSignaturePaddings(java.lang.String...);
+    method public android.security.KeyStoreParameter.Builder setUserAuthenticationRequired(boolean);
     method public android.security.KeyStoreParameter.Builder setUserAuthenticationValidityDurationSeconds(int);
-    method public android.security.KeyStoreParameter.Builder setUserAuthenticators(int);
   }
 
   public class NetworkSecurityPolicy {
diff --git a/api/system-current.txt b/api/system-current.txt
index 3bbfb8a..7210666 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -30540,10 +30540,9 @@
     method public java.lang.String getKeystoreAlias();
     method public int getPurposes();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public int getUserAuthenticators();
     method public boolean isEncryptionRequired();
-    method public boolean isInvalidatedOnNewFingerprintEnrolled();
     method public boolean isRandomizedEncryptionRequired();
+    method public boolean isUserAuthenticationRequired();
   }
 
   public static class KeyGeneratorSpec.Builder {
@@ -30553,7 +30552,6 @@
     method public android.security.KeyGeneratorSpec.Builder setBlockModes(java.lang.String...);
     method public android.security.KeyGeneratorSpec.Builder setEncryptionPaddings(java.lang.String...);
     method public android.security.KeyGeneratorSpec.Builder setEncryptionRequired(boolean);
-    method public android.security.KeyGeneratorSpec.Builder setInvalidatedOnNewFingerprintEnrolled(boolean);
     method public android.security.KeyGeneratorSpec.Builder setKeySize(int);
     method public android.security.KeyGeneratorSpec.Builder setKeyValidityEnd(java.util.Date);
     method public android.security.KeyGeneratorSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date);
@@ -30561,8 +30559,8 @@
     method public android.security.KeyGeneratorSpec.Builder setKeyValidityStart(java.util.Date);
     method public android.security.KeyGeneratorSpec.Builder setPurposes(int);
     method public android.security.KeyGeneratorSpec.Builder setRandomizedEncryptionRequired(boolean);
+    method public android.security.KeyGeneratorSpec.Builder setUserAuthenticationRequired(boolean);
     method public android.security.KeyGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
-    method public android.security.KeyGeneratorSpec.Builder setUserAuthenticators(int);
   }
 
   public class KeyNotYetValidException extends java.security.InvalidKeyException {
@@ -30590,10 +30588,9 @@
     method public java.util.Date getStartDate();
     method public javax.security.auth.x500.X500Principal getSubjectDN();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public int getUserAuthenticators();
     method public boolean isEncryptionRequired();
-    method public boolean isInvalidatedOnNewFingerprintEnrolled();
     method public boolean isRandomizedEncryptionRequired();
+    method public boolean isUserAuthenticationRequired();
   }
 
   public static final class KeyPairGeneratorSpec.Builder {
@@ -30606,7 +30603,6 @@
     method public android.security.KeyPairGeneratorSpec.Builder setEncryptionPaddings(java.lang.String...);
     method public android.security.KeyPairGeneratorSpec.Builder setEncryptionRequired();
     method public android.security.KeyPairGeneratorSpec.Builder setEndDate(java.util.Date);
-    method public android.security.KeyPairGeneratorSpec.Builder setInvalidatedOnNewFingerprintEnrolled(boolean);
     method public android.security.KeyPairGeneratorSpec.Builder setKeySize(int);
     method public android.security.KeyPairGeneratorSpec.Builder setKeyType(java.lang.String) throws java.security.NoSuchAlgorithmException;
     method public android.security.KeyPairGeneratorSpec.Builder setKeyValidityEnd(java.util.Date);
@@ -30619,8 +30615,8 @@
     method public android.security.KeyPairGeneratorSpec.Builder setSignaturePaddings(java.lang.String...);
     method public android.security.KeyPairGeneratorSpec.Builder setStartDate(java.util.Date);
     method public android.security.KeyPairGeneratorSpec.Builder setSubject(javax.security.auth.x500.X500Principal);
+    method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationRequired(boolean);
     method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
-    method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticators(int);
   }
 
   public abstract class KeyStoreKeyProperties {
@@ -30645,14 +30641,6 @@
   public static abstract class KeyStoreKeyProperties.PurposeEnum implements java.lang.annotation.Annotation {
   }
 
-  public static abstract class KeyStoreKeyProperties.UserAuthenticator {
-    field public static final int FINGERPRINT_READER = 2; // 0x2
-    field public static final int LOCK_SCREEN = 1; // 0x1
-  }
-
-  public static abstract class KeyStoreKeyProperties.UserAuthenticatorEnum implements java.lang.annotation.Annotation {
-  }
-
   public class KeyStoreKeySpec implements java.security.spec.KeySpec {
     method public java.lang.String[] getBlockModes();
     method public java.lang.String[] getDigests();
@@ -30665,15 +30653,15 @@
     method public int getOrigin();
     method public int getPurposes();
     method public java.lang.String[] getSignaturePaddings();
-    method public int getTeeEnforcedUserAuthenticators();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public int getUserAuthenticators();
-    method public boolean isInvalidatedOnNewFingerprintEnrolled();
     method public boolean isTeeBacked();
+    method public boolean isUserAuthenticationRequired();
+    method public boolean isUserAuthenticationRequirementTeeEnforced();
   }
 
   public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
     method public java.lang.String[] getBlockModes();
+    method public android.content.Context getContext();
     method public java.lang.String[] getDigests();
     method public java.lang.String[] getEncryptionPaddings();
     method public java.util.Date getKeyValidityForConsumptionEnd();
@@ -30682,11 +30670,10 @@
     method public int getPurposes();
     method public java.lang.String[] getSignaturePaddings();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public int getUserAuthenticators();
     method public boolean isDigestsSpecified();
     method public boolean isEncryptionRequired();
-    method public boolean isInvalidatedOnNewFingerprintEnrolled();
     method public boolean isRandomizedEncryptionRequired();
+    method public boolean isUserAuthenticationRequired();
   }
 
   public static final class KeyStoreParameter.Builder {
@@ -30696,7 +30683,6 @@
     method public android.security.KeyStoreParameter.Builder setDigests(java.lang.String...);
     method public android.security.KeyStoreParameter.Builder setEncryptionPaddings(java.lang.String...);
     method public android.security.KeyStoreParameter.Builder setEncryptionRequired(boolean);
-    method public android.security.KeyStoreParameter.Builder setInvalidatedOnNewFingerprintEnrolled(boolean);
     method public android.security.KeyStoreParameter.Builder setKeyValidityEnd(java.util.Date);
     method public android.security.KeyStoreParameter.Builder setKeyValidityForConsumptionEnd(java.util.Date);
     method public android.security.KeyStoreParameter.Builder setKeyValidityForOriginationEnd(java.util.Date);
@@ -30704,8 +30690,8 @@
     method public android.security.KeyStoreParameter.Builder setPurposes(int);
     method public android.security.KeyStoreParameter.Builder setRandomizedEncryptionRequired(boolean);
     method public android.security.KeyStoreParameter.Builder setSignaturePaddings(java.lang.String...);
+    method public android.security.KeyStoreParameter.Builder setUserAuthenticationRequired(boolean);
     method public android.security.KeyStoreParameter.Builder setUserAuthenticationValidityDurationSeconds(int);
-    method public android.security.KeyStoreParameter.Builder setUserAuthenticators(int);
   }
 
   public class NetworkSecurityPolicy {
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index b3a3aad..458f153 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -105,11 +105,11 @@
         }
     }
 
-    public boolean getBoolean(KeyCharacteristics keyCharacteristics, int tag) {
-        if (keyCharacteristics.hwEnforced.containsTag(tag)) {
-            return keyCharacteristics.hwEnforced.getBoolean(tag, false);
+    public boolean getBoolean(int tag) {
+        if (hwEnforced.containsTag(tag)) {
+            return hwEnforced.getBoolean(tag, false);
         } else {
-            return keyCharacteristics.swEnforced.getBoolean(tag, false);
+            return swEnforced.getBoolean(tag, false);
         }
     }
 }
diff --git a/docs/html/training/articles/keystore.jd b/docs/html/training/articles/keystore.jd
index a4fc2d2..217db81 100644
--- a/docs/html/training/articles/keystore.jd
+++ b/docs/html/training/articles/keystore.jd
@@ -29,7 +29,9 @@
 <p>The Android Keystore system lets you store cryptographic keys in a container
   to make it more difficult to extract from the device. Once keys are in the
   keystore, they can be used for cryptographic operations with the key material
-  remaining non-exportable.</p>
+  remaining non-exportable. Moreover, it offers facilities to restrict when and
+  how keys can be used, such as requiring user authentication for key use or
+  restricting encryption keys to be used only in certain block modes.</p>
 
 <p>The Keystore system is used by the {@link
   android.security.KeyChain} API as well as the Android
@@ -112,3 +114,27 @@
 <p>Similarly, verify data with the {@link java.security.Signature#verify(byte[])} method:</p>
 
 {@sample development/samples/ApiDemos/src/com/example/android/apis/security/KeyStoreUsage.java verify}
+
+<h3 id="UserAuthentication">Requiring User Authentication For Key Use</h3>
+
+<p>When generating or importing a key into the {@code AndroidKeyStore} you can specify that the key
+can only be used if user has been authenticated. The user is authenticated using a subset of their
+secure lock screen credentials. This is a security measure which makes it possible to generate
+cryptographic assertions about the user having been authenticated.
+
+<p>When a key is configured to require user authentication, it is also configured to operate in one
+of the two modes:
+<ul>
+<li>User authentication is valid for a duration of time. All keys in this mode are authorized
+  for use as soon as the user unlocks the secure lock screen or confirms their secure lock screen
+  credentials using the {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence) KeyguardManager.createConfirmDeviceCredentialIntent}
+  flow. Each key specifies for how long the authorization remains valid for that key. Such keys
+  can only be generated or imported if the secure lock screen is enabled (see {@link android.app.KeyguardManager#isKeyguardSecure Keyguard.isKeyguardSecure}).
+  These keys become permanently invalidated once the secure lock screen is disabled or forcibly
+  reset (e.g. by a Device Admin).</li>
+<li>User authentication is required for every use of the key. In this mode, a specific operation
+  involving a specific key is authorized by the user. Currently, the only means of such
+  authorization is fingerprint authentication: {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, int) FingerprintManager.authenticate}.
+  Such keys can only be generated or imported if at least one fingerprint is enrolled (see {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints() FingerprintManager.hasEnrolledFingerprints}).
+  These keys become permanently invalidated once all fingerprints are unenrolled.</li>
+</ul>
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 @@
                 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 @@
     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 @@
             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 @@
                 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 @@
     }
 
     /**
-     * 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 @@
     }
 
     /**
-     * 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 @@
         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 @@
         }
 
         /**
-         * 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 @@
         }
 
         /**
-         * 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 @@
                     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 @@
 
     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 @@
             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 @@
         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 @@
                 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 @@
     }
 
     /**
-     * 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 @@
 
         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 @@
         }
 
         /**
-         * 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 @@
          * @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 @@
         }
 
         /**
-         * 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 @@
                     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 @@
                 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 @@
     }
 
     @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 @@
     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 @@
             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 @@
                 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 @@
     }
 
     /**
-     * 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 @@
  * {@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 @@
     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 @@
             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 @@
         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 @@
     }
 
     /**
-     * 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 @@
     }
 
     /**
-     * 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 @@
      * </pre>
      */
     public final static class Builder {
+        private final Context mContext;
         private int mFlags;
         private Date mKeyValidityStart;
         private Date mKeyValidityForOriginationEnd;
@@ -257,9 +256,8 @@
         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 @@
             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 @@
         }
 
         /**
-         * 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 @@
         }
 
         /**
-         * 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 @@
                     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 @@
         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 @@
                     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 @@
                 && (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 @@
                 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 @@
         }
         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);
+        }
+    }
 }