Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04b682d3 authored by Max Bires's avatar Max Bires
Browse files

Changing op per auth keys to allow password

Previously, auth per operation keystore keys could only be authorized
with biometrics. There is no reason to restrict this functionality to
biometrics. This change slightly refactors the key parameter builder
interface to allow the caller to specify which authentication types
should be allowed for an auth per op key.

Bug: 147693375
Bug: 140256692
Test: atest keystore
Change-Id: I5cbf3d4e3f0e84d577dbf6b4cb356b1010100925
parent f96fed1d
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -42533,6 +42533,7 @@ package android.security.keystore {
    method @NonNull public String getKeystoreAlias();
    method public int getPurposes();
    method @NonNull public String[] getSignaturePaddings();
    method public int getUserAuthenticationType();
    method public int getUserAuthenticationValidityDurationSeconds();
    method @NonNull public boolean isDigestsSpecified();
    method public boolean isInvalidatedByBiometricEnrollment();
@@ -42567,9 +42568,10 @@ package android.security.keystore {
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationParameters(@IntRange(from=0xffffffff) int, int);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(@IntRange(from=0xffffffff) int);
    method @Deprecated @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(@IntRange(from=0xffffffff) int);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUserConfirmationRequired(boolean);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUserPresenceRequired(boolean);
  }
@@ -42586,6 +42588,7 @@ package android.security.keystore {
    method public int getOrigin();
    method public int getPurposes();
    method @NonNull public String[] getSignaturePaddings();
    method public int getUserAuthenticationType();
    method public int getUserAuthenticationValidityDurationSeconds();
    method public boolean isInsideSecureHardware();
    method public boolean isInvalidatedByBiometricEnrollment();
@@ -42609,6 +42612,8 @@ package android.security.keystore {
  }
  public abstract class KeyProperties {
    field public static final int AUTH_BIOMETRIC_STRONG = 2; // 0x2
    field public static final int AUTH_DEVICE_CREDENTIAL = 1; // 0x1
    field public static final String BLOCK_MODE_CBC = "CBC";
    field public static final String BLOCK_MODE_CTR = "CTR";
    field public static final String BLOCK_MODE_ECB = "ECB";
@@ -42655,6 +42660,7 @@ package android.security.keystore {
    method @Nullable public java.util.Date getKeyValidityStart();
    method public int getPurposes();
    method @NonNull public String[] getSignaturePaddings();
    method public int getUserAuthenticationType();
    method public int getUserAuthenticationValidityDurationSeconds();
    method public boolean isDigestsSpecified();
    method public boolean isInvalidatedByBiometricEnrollment();
@@ -42680,9 +42686,10 @@ package android.security.keystore {
    method @NonNull public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
    method @NonNull public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
    method @NonNull public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
    method @NonNull public android.security.keystore.KeyProtection.Builder setUserAuthenticationParameters(@IntRange(from=0xffffffff) int, int);
    method @NonNull public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
    method @NonNull public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
    method @NonNull public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(@IntRange(from=0xffffffff) int);
    method @Deprecated @NonNull public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(@IntRange(from=0xffffffff) int);
    method @NonNull public android.security.keystore.KeyProtection.Builder setUserConfirmationRequired(boolean);
    method @NonNull public android.security.keystore.KeyProtection.Builder setUserPresenceRequired(boolean);
  }
+1 −0
Original line number Diff line number Diff line
@@ -206,6 +206,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
                blockModes,
                userAuthenticationRequired,
                (int) userAuthenticationValidityDurationSeconds,
                keymasterHwEnforcedUserAuthenticators,
                userAuthenticationRequirementEnforcedBySecureHardware,
                userAuthenticationValidWhileOnBody,
                trustedUserPresenceRequred,
+71 −1
Original line number Diff line number Diff line
@@ -263,6 +263,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
    private final boolean mRandomizedEncryptionRequired;
    private final boolean mUserAuthenticationRequired;
    private final int mUserAuthenticationValidityDurationSeconds;
    private final @KeyProperties.AuthEnum int mUserAuthenticationType;
    private final boolean mUserPresenceRequired;
    private final byte[] mAttestationChallenge;
    private final boolean mUniqueIdIncluded;
@@ -301,6 +302,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            boolean randomizedEncryptionRequired,
            boolean userAuthenticationRequired,
            int userAuthenticationValidityDurationSeconds,
            @KeyProperties.AuthEnum int userAuthenticationType,
            boolean userPresenceRequired,
            byte[] attestationChallenge,
            boolean uniqueIdIncluded,
@@ -352,6 +354,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        mUserAuthenticationRequired = userAuthenticationRequired;
        mUserPresenceRequired = userPresenceRequired;
        mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
        mUserAuthenticationType = userAuthenticationType;
        mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge);
        mUniqueIdIncluded = uniqueIdIncluded;
        mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
@@ -604,6 +607,22 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        return mUserAuthenticationValidityDurationSeconds;
    }

    /**
     * Gets the modes of authentication that can authorize use of this key. This has effect only if
     * user authentication is required (see {@link #isUserAuthenticationRequired()}).
     *
     * <p>This authorization applies only to secret key and private key operations. Public key
     * operations are not restricted.
     *
     * @return integer representing the bitwse OR of all acceptable authentication types for the
     *         key.
     *
     * @see #isUserAuthenticationRequired()
     * @see Builder#setUserAuthenticationParameters(int, int)
     */
    public @KeyProperties.AuthEnum int getUserAuthenticationType() {
        return mUserAuthenticationType;
    }
    /**
     * Returns {@code true} if the key is authorized to be used only if a test of user presence has
     * been performed between the {@code Signature.initSign()} and {@code Signature.sign()} calls.
@@ -746,6 +765,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        private boolean mRandomizedEncryptionRequired = true;
        private boolean mUserAuthenticationRequired;
        private int mUserAuthenticationValidityDurationSeconds = -1;
        private @KeyProperties.AuthEnum int mUserAuthenticationType;
        private boolean mUserPresenceRequired = false;
        private byte[] mAttestationChallenge = null;
        private boolean mUniqueIdIncluded = false;
@@ -810,6 +830,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            mUserAuthenticationRequired = sourceSpec.isUserAuthenticationRequired();
            mUserAuthenticationValidityDurationSeconds =
                sourceSpec.getUserAuthenticationValidityDurationSeconds();
            mUserAuthenticationType = sourceSpec.getUserAuthenticationType();
            mUserPresenceRequired = sourceSpec.isUserPresenceRequired();
            mAttestationChallenge = sourceSpec.getAttestationChallenge();
            mUniqueIdIncluded = sourceSpec.isUniqueIdIncluded();
@@ -1207,14 +1228,62 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
         * @see BiometricPrompt
         * @see BiometricPrompt.CryptoObject
         * @see KeyguardManager
         * @deprecated See {@link #setUserAuthenticationParameters(int, int)}
         */
        @Deprecated
        @NonNull
        public Builder setUserAuthenticationValidityDurationSeconds(
                @IntRange(from = -1) int seconds) {
            if (seconds < -1) {
                throw new IllegalArgumentException("seconds must be -1 or larger");
            }
            mUserAuthenticationValidityDurationSeconds = seconds;
            if (seconds == -1) {
                return setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG);
            }
            return setUserAuthenticationParameters(seconds, KeyProperties.AUTH_BIOMETRIC_STRONG);
        }

        /**
         * Sets the duration of time (seconds) and authorization type for which this key is
         * authorized to be used after the user is successfully authenticated. This has effect if
         * the key requires user authentication for its use (see
         * {@link #setUserAuthenticationRequired(boolean)}).
         *
         * <p>By default, if user authentication is required, it must take place for every use of
         * the key.
         *
         * <p>These cryptographic operations will throw {@link UserNotAuthenticatedException} during
         * initialization if the user needs to be authenticated to proceed. This situation can be
         * resolved by the user authenticating with the appropriate biometric or credential as
         * required by the key. See {@link BiometricPrompt.Builder#setAllowedAuthenticators(int)}
         * and {@link BiometricManager.Authenticators}.
         *
         * <p>Once resolved, initializing a new cryptographic operation using this key (or any other
         * key which is authorized to be used for a fixed duration of time after user
         * authentication) should succeed provided the user authentication flow completed
         * successfully.
         *
         * @param timeout duration in seconds or {@code 0} if user authentication must take place
         *        for every use of the key. {@code -1} is also accepted for legacy purposes. It is
         *        functionally the same as {@code 0}.
         * @param type set of authentication types which can authorize use of the key. See
         *        {@link KeyProperties}.{@code AUTH} flags.
         *
         * @see #setUserAuthenticationRequired(boolean)
         * @see BiometricPrompt
         * @see BiometricPrompt.CryptoObject
         * @see KeyguardManager
         */
        @NonNull
        public Builder setUserAuthenticationParameters(@IntRange(from = -1) int timeout,
                                                       @KeyProperties.AuthEnum int type) {
            if (timeout < -1) {
                throw new IllegalArgumentException("timeout must be -1 or larger");
            } else if (timeout == -1) {
                timeout = 0;
            }
            mUserAuthenticationValidityDurationSeconds = timeout;
            mUserAuthenticationType = type;
            return this;
        }

@@ -1392,6 +1461,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
                    mRandomizedEncryptionRequired,
                    mUserAuthenticationRequired,
                    mUserAuthenticationValidityDurationSeconds,
                    mUserAuthenticationType,
                    mUserPresenceRequired,
                    mAttestationChallenge,
                    mUniqueIdIncluded,
+19 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ public class KeyInfo implements KeySpec {
    private final @KeyProperties.BlockModeEnum String[] mBlockModes;
    private final boolean mUserAuthenticationRequired;
    private final int mUserAuthenticationValidityDurationSeconds;
    private final @KeyProperties.AuthEnum int mUserAuthenticationType;
    private final boolean mUserAuthenticationRequirementEnforcedBySecureHardware;
    private final boolean mUserAuthenticationValidWhileOnBody;
    private final boolean mTrustedUserPresenceRequired;
@@ -101,6 +102,7 @@ public class KeyInfo implements KeySpec {
            @KeyProperties.BlockModeEnum String[] blockModes,
            boolean userAuthenticationRequired,
            int userAuthenticationValidityDurationSeconds,
            @KeyProperties.AuthEnum int userAuthenticationType,
            boolean userAuthenticationRequirementEnforcedBySecureHardware,
            boolean userAuthenticationValidWhileOnBody,
            boolean trustedUserPresenceRequired,
@@ -122,6 +124,7 @@ public class KeyInfo implements KeySpec {
        mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
        mUserAuthenticationRequired = userAuthenticationRequired;
        mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
        mUserAuthenticationType = userAuthenticationType;
        mUserAuthenticationRequirementEnforcedBySecureHardware =
                userAuthenticationRequirementEnforcedBySecureHardware;
        mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
@@ -300,6 +303,22 @@ public class KeyInfo implements KeySpec {
        return mUserAuthenticationValidityDurationSeconds;
    }

    /**
     * Gets the acceptable user authentication types for which this key can be authorized to be
     * used. This has effect only if user authentication is required (see
     * {@link #isUserAuthenticationRequired()}).
     *
     * <p>This authorization applies only to secret key and private key operations. Public key
     * operations are not restricted.
     *
     * @return integer representing the accepted forms of user authentication for this key
     *
     * @see #isUserAuthenticationRequired()
     */
    public @KeyProperties.AuthEnum int getUserAuthenticationType() {
        return mUserAuthenticationType;
    }

    /**
     * Returns {@code true} if the requirement that this key can only be used if the user has been
     * authenticated is enforced by secure hardware (e.g., Trusted Execution Environment (TEE) or
+21 −0
Original line number Diff line number Diff line
@@ -35,6 +35,27 @@ import java.util.Locale;
public abstract class KeyProperties {
    private KeyProperties() {}

    /**
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = { "AUTH_" }, value = {
            AUTH_BIOMETRIC_STRONG,
            AUTH_DEVICE_CREDENTIAL,
    })
    public @interface AuthEnum {}

    /**
     * The non-biometric credential used to secure the device (i.e., PIN, pattern, or password)
     */
    public static final int AUTH_DEVICE_CREDENTIAL = 1 << 0;

    /**
     * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
     * requirements for <strong>Strong</strong>, as defined by the Android CDD.
     */
    public static final int AUTH_BIOMETRIC_STRONG = 1 << 1;

    /**
     * @hide
     */
Loading