Merge "Changing op per auth keys to allow password"

This commit is contained in:
TreeHugger Robot
2020-02-11 00:30:30 +00:00
committed by Android (Google) Code Review
9 changed files with 189 additions and 17 deletions

View File

@@ -42600,6 +42600,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();
@@ -42634,9 +42635,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);
}
@@ -42653,6 +42655,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();
@@ -42676,6 +42679,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";
@@ -42722,6 +42727,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();
@@ -42747,9 +42753,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);
}

View File

@@ -206,6 +206,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
blockModes,
userAuthenticationRequired,
(int) userAuthenticationValidityDurationSeconds,
keymasterHwEnforcedUserAuthenticators,
userAuthenticationRequirementEnforcedBySecureHardware,
userAuthenticationValidWhileOnBody,
trustedUserPresenceRequred,

View File

@@ -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,

View File

@@ -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

View File

@@ -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
*/

View File

@@ -225,6 +225,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
private final @KeyProperties.BlockModeEnum String[] mBlockModes;
private final boolean mRandomizedEncryptionRequired;
private final boolean mUserAuthenticationRequired;
private final @KeyProperties.AuthEnum int mUserAuthenticationType;
private final int mUserAuthenticationValidityDurationSeconds;
private final boolean mUserPresenceRequred;
private final boolean mUserAuthenticationValidWhileOnBody;
@@ -246,6 +247,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
@KeyProperties.BlockModeEnum String[] blockModes,
boolean randomizedEncryptionRequired,
boolean userAuthenticationRequired,
@KeyProperties.AuthEnum int userAuthenticationType,
int userAuthenticationValidityDurationSeconds,
boolean userPresenceRequred,
boolean userAuthenticationValidWhileOnBody,
@@ -267,6 +269,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
mUserAuthenticationRequired = userAuthenticationRequired;
mUserAuthenticationType = userAuthenticationType;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
mUserPresenceRequred = userPresenceRequred;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
@@ -429,6 +432,10 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
return mUserConfirmationRequired;
}
public @KeyProperties.AuthEnum int getUserAuthenticationType() {
return mUserAuthenticationType;
}
/**
* Gets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect only if user authentication is required
@@ -555,6 +562,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
private @KeyProperties.BlockModeEnum String[] mBlockModes;
private boolean mRandomizedEncryptionRequired = true;
private boolean mUserAuthenticationRequired;
private @KeyProperties.AuthEnum int mUserAuthenticationType;
private int mUserAuthenticationValidityDurationSeconds = -1;
private boolean mUserPresenceRequired = false;
private boolean mUserAuthenticationValidWhileOnBody;
@@ -850,14 +858,62 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
* @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;
}
@@ -1002,6 +1058,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
mBlockModes,
mRandomizedEncryptionRequired,
mUserAuthenticationRequired,
mUserAuthenticationType,
mUserAuthenticationValidityDurationSeconds,
mUserPresenceRequired,
mUserAuthenticationValidWhileOnBody,

View File

@@ -88,17 +88,9 @@ public abstract class KeymasterUtils {
* 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.
* @param boundToSpecificSecureUserId if non-zero, specify which SID the key will be bound to,
* overriding the default logic in this method where the key is bound to either the root
* SID of the current user, or the fingerprint SID if explicit fingerprint authorization
* is requested.
* @param userConfirmationRequired whether user confirmation is required to authorize the use
* of the key.
* @param args The arguments sent to keymaster that need to be populated from the spec
* @param spec The user authentication relevant portions of the spec passed in from the caller.
* This spec will be translated into the relevant keymaster tags to be loaded into args.
* @throws IllegalStateException if user authentication is required but the system is in a wrong
* state (e.g., secure lock screen not set up) for generating or importing keys that
* require user authentication.
@@ -122,7 +114,7 @@ public abstract class KeymasterUtils {
return;
}
if (spec.getUserAuthenticationValidityDurationSeconds() == -1) {
if (spec.getUserAuthenticationValidityDurationSeconds() == 0) {
PackageManager pm = KeyStore.getApplicationContext().getPackageManager();
// Every use of this key needs to be authorized by the user. This currently means
// fingerprint or face auth.
@@ -168,7 +160,8 @@ public abstract class KeymasterUtils {
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
KeymasterArguments.toUint64(sids.get(i)));
}
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_BIOMETRIC);
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, spec.getUserAuthenticationType());
if (spec.isUserAuthenticationValidWhileOnBody()) {
throw new ProviderException("Key validity extension while device is on-body is not "

View File

@@ -97,6 +97,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
out.writeBoolean(mSpec.isRandomizedEncryptionRequired());
out.writeBoolean(mSpec.isUserAuthenticationRequired());
out.writeInt(mSpec.getUserAuthenticationValidityDurationSeconds());
out.writeInt(mSpec.getUserAuthenticationType());
out.writeBoolean(mSpec.isUserPresenceRequired());
out.writeByteArray(mSpec.getAttestationChallenge());
out.writeBoolean(mSpec.isUniqueIdIncluded());
@@ -153,6 +154,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
final boolean randomizedEncryptionRequired = in.readBoolean();
final boolean userAuthenticationRequired = in.readBoolean();
final int userAuthenticationValidityDurationSeconds = in.readInt();
final int userAuthenticationTypes = in.readInt();
final boolean userPresenceRequired = in.readBoolean();
final byte[] attestationChallenge = in.createByteArray();
final boolean uniqueIdIncluded = in.readBoolean();
@@ -185,6 +187,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
randomizedEncryptionRequired,
userAuthenticationRequired,
userAuthenticationValidityDurationSeconds,
userAuthenticationTypes,
userPresenceRequired,
attestationChallenge,
uniqueIdIncluded,

View File

@@ -28,6 +28,7 @@ public interface UserAuthArgs {
boolean isUserAuthenticationRequired();
int getUserAuthenticationValidityDurationSeconds();
@KeyProperties.AuthEnum int getUserAuthenticationType();
boolean isUserAuthenticationValidWhileOnBody();
boolean isInvalidatedByBiometricEnrollment();
boolean isUserConfirmationRequired();