Merge "Add support for extending key validity while on body." into nyc-dev
am: 0f900c02d9
* commit '0f900c02d9aafa9a98ff39ea7d661c1cdfbddcdb':
Add support for extending key validity while on body.
This commit is contained in:
@@ -34094,6 +34094,7 @@ package android.security.keystore {
|
||||
method public boolean isDigestsSpecified();
|
||||
method public boolean isRandomizedEncryptionRequired();
|
||||
method public boolean isUserAuthenticationRequired();
|
||||
method public boolean isUserAuthenticationValidWhileOnBody();
|
||||
}
|
||||
|
||||
public static final class KeyGenParameterSpec.Builder {
|
||||
@@ -34116,6 +34117,7 @@ package android.security.keystore {
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
|
||||
}
|
||||
|
||||
@@ -34135,6 +34137,7 @@ package android.security.keystore {
|
||||
method public boolean isInsideSecureHardware();
|
||||
method public boolean isUserAuthenticationRequired();
|
||||
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
|
||||
method public boolean isUserAuthenticationValidWhileOnBody();
|
||||
}
|
||||
|
||||
public class KeyNotYetValidException extends java.security.InvalidKeyException {
|
||||
@@ -34197,6 +34200,7 @@ package android.security.keystore {
|
||||
method public boolean isDigestsSpecified();
|
||||
method public boolean isRandomizedEncryptionRequired();
|
||||
method public boolean isUserAuthenticationRequired();
|
||||
method public boolean isUserAuthenticationValidWhileOnBody();
|
||||
}
|
||||
|
||||
public static final class KeyProtection.Builder {
|
||||
@@ -34212,6 +34216,7 @@ package android.security.keystore {
|
||||
method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
|
||||
method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
|
||||
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
|
||||
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
|
||||
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
|
||||
}
|
||||
|
||||
|
||||
@@ -36583,6 +36583,7 @@ package android.security.keystore {
|
||||
method public boolean isDigestsSpecified();
|
||||
method public boolean isRandomizedEncryptionRequired();
|
||||
method public boolean isUserAuthenticationRequired();
|
||||
method public boolean isUserAuthenticationValidWhileOnBody();
|
||||
}
|
||||
|
||||
public static final class KeyGenParameterSpec.Builder {
|
||||
@@ -36605,6 +36606,7 @@ package android.security.keystore {
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
|
||||
}
|
||||
|
||||
@@ -36624,6 +36626,7 @@ package android.security.keystore {
|
||||
method public boolean isInsideSecureHardware();
|
||||
method public boolean isUserAuthenticationRequired();
|
||||
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
|
||||
method public boolean isUserAuthenticationValidWhileOnBody();
|
||||
}
|
||||
|
||||
public class KeyNotYetValidException extends java.security.InvalidKeyException {
|
||||
@@ -36686,6 +36689,7 @@ package android.security.keystore {
|
||||
method public boolean isDigestsSpecified();
|
||||
method public boolean isRandomizedEncryptionRequired();
|
||||
method public boolean isUserAuthenticationRequired();
|
||||
method public boolean isUserAuthenticationValidWhileOnBody();
|
||||
}
|
||||
|
||||
public static final class KeyProtection.Builder {
|
||||
@@ -36701,6 +36705,7 @@ package android.security.keystore {
|
||||
method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
|
||||
method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
|
||||
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
|
||||
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
|
||||
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
|
||||
}
|
||||
|
||||
|
||||
@@ -34109,6 +34109,7 @@ package android.security.keystore {
|
||||
method public boolean isDigestsSpecified();
|
||||
method public boolean isRandomizedEncryptionRequired();
|
||||
method public boolean isUserAuthenticationRequired();
|
||||
method public boolean isUserAuthenticationValidWhileOnBody();
|
||||
}
|
||||
|
||||
public static final class KeyGenParameterSpec.Builder {
|
||||
@@ -34131,6 +34132,7 @@ package android.security.keystore {
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
|
||||
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
|
||||
}
|
||||
|
||||
@@ -34150,6 +34152,7 @@ package android.security.keystore {
|
||||
method public boolean isInsideSecureHardware();
|
||||
method public boolean isUserAuthenticationRequired();
|
||||
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
|
||||
method public boolean isUserAuthenticationValidWhileOnBody();
|
||||
}
|
||||
|
||||
public class KeyNotYetValidException extends java.security.InvalidKeyException {
|
||||
@@ -34212,6 +34215,7 @@ package android.security.keystore {
|
||||
method public boolean isDigestsSpecified();
|
||||
method public boolean isRandomizedEncryptionRequired();
|
||||
method public boolean isUserAuthenticationRequired();
|
||||
method public boolean isUserAuthenticationValidWhileOnBody();
|
||||
}
|
||||
|
||||
public static final class KeyProtection.Builder {
|
||||
@@ -34227,6 +34231,7 @@ package android.security.keystore {
|
||||
method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
|
||||
method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
|
||||
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
|
||||
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
|
||||
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ public final class KeymasterDefs {
|
||||
public static final int KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503;
|
||||
public static final int KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504;
|
||||
public static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505;
|
||||
public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
|
||||
|
||||
public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
|
||||
public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
|
||||
|
||||
@@ -233,7 +233,8 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
||||
// not set up).
|
||||
KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
|
||||
spec.isUserAuthenticationRequired(),
|
||||
spec.getUserAuthenticationValidityDurationSeconds());
|
||||
spec.getUserAuthenticationValidityDurationSeconds(),
|
||||
spec.isUserAuthenticationValidWhileOnBody());
|
||||
} catch (IllegalStateException | IllegalArgumentException e) {
|
||||
throw new InvalidAlgorithmParameterException(e);
|
||||
}
|
||||
@@ -271,7 +272,8 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
|
||||
KeymasterUtils.addUserAuthArgs(args,
|
||||
spec.isUserAuthenticationRequired(),
|
||||
spec.getUserAuthenticationValidityDurationSeconds());
|
||||
spec.getUserAuthenticationValidityDurationSeconds(),
|
||||
spec.isUserAuthenticationValidWhileOnBody());
|
||||
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
|
||||
args,
|
||||
mKeymasterAlgorithm,
|
||||
|
||||
@@ -344,7 +344,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
||||
// not set up).
|
||||
KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
|
||||
mSpec.isUserAuthenticationRequired(),
|
||||
mSpec.getUserAuthenticationValidityDurationSeconds());
|
||||
mSpec.getUserAuthenticationValidityDurationSeconds(),
|
||||
mSpec.isUserAuthenticationValidWhileOnBody());
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
throw new InvalidAlgorithmParameterException(e);
|
||||
}
|
||||
@@ -529,7 +530,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
||||
|
||||
KeymasterUtils.addUserAuthArgs(args,
|
||||
mSpec.isUserAuthenticationRequired(),
|
||||
mSpec.getUserAuthenticationValidityDurationSeconds());
|
||||
mSpec.getUserAuthenticationValidityDurationSeconds(),
|
||||
mSpec.isUserAuthenticationValidWhileOnBody());
|
||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
|
||||
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
|
||||
mSpec.getKeyValidityForOriginationEnd());
|
||||
|
||||
@@ -167,6 +167,8 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
|
||||
boolean userAuthenticationRequirementEnforcedBySecureHardware = (userAuthenticationRequired)
|
||||
&& (keymasterHwEnforcedUserAuthenticators != 0)
|
||||
&& (keymasterSwEnforcedUserAuthenticators == 0);
|
||||
boolean userAuthenticationValidWhileOnBody =
|
||||
keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
|
||||
|
||||
return new KeyInfo(entryAlias,
|
||||
insideSecureHardware,
|
||||
@@ -182,7 +184,8 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
|
||||
blockModes,
|
||||
userAuthenticationRequired,
|
||||
(int) userAuthenticationValidityDurationSeconds,
|
||||
userAuthenticationRequirementEnforcedBySecureHardware);
|
||||
userAuthenticationRequirementEnforcedBySecureHardware,
|
||||
userAuthenticationValidWhileOnBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -498,7 +498,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings()));
|
||||
KeymasterUtils.addUserAuthArgs(importArgs,
|
||||
spec.isUserAuthenticationRequired(),
|
||||
spec.getUserAuthenticationValidityDurationSeconds());
|
||||
spec.getUserAuthenticationValidityDurationSeconds(),
|
||||
spec.isUserAuthenticationValidWhileOnBody());
|
||||
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
|
||||
spec.getKeyValidityStart());
|
||||
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
|
||||
@@ -692,7 +693,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
|
||||
KeymasterUtils.addUserAuthArgs(args,
|
||||
params.isUserAuthenticationRequired(),
|
||||
params.getUserAuthenticationValidityDurationSeconds());
|
||||
params.getUserAuthenticationValidityDurationSeconds(),
|
||||
params.isUserAuthenticationValidWhileOnBody());
|
||||
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
|
||||
args,
|
||||
keymasterAlgorithm,
|
||||
|
||||
@@ -252,6 +252,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
|
||||
private final int mUserAuthenticationValidityDurationSeconds;
|
||||
private final byte[] mAttestationChallenge;
|
||||
private final boolean mUniqueIdIncluded;
|
||||
private final boolean mUserAuthenticationValidWhileOnBody;
|
||||
|
||||
/**
|
||||
* @hide should be built with Builder
|
||||
@@ -277,7 +278,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
|
||||
boolean userAuthenticationRequired,
|
||||
int userAuthenticationValidityDurationSeconds,
|
||||
byte[] attestationChallenge,
|
||||
boolean uniqueIdIncluded) {
|
||||
boolean uniqueIdIncluded,
|
||||
boolean userAuthenticationValidWhileOnBody) {
|
||||
if (TextUtils.isEmpty(keyStoreAlias)) {
|
||||
throw new IllegalArgumentException("keyStoreAlias must not be empty");
|
||||
}
|
||||
@@ -321,6 +323,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
|
||||
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
|
||||
mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge);
|
||||
mUniqueIdIncluded = uniqueIdIncluded;
|
||||
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -586,6 +589,23 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
|
||||
return mUniqueIdIncluded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the key will remain authorized while the device is on the user's
|
||||
* body, even after the validity duration has expired. This option has no effect on keys that
|
||||
* don't have an authentication validity duration, and has no effect if the device lacks a
|
||||
* secure on-body sensor.
|
||||
*
|
||||
* <p>Authorization applies only to secret key and private key operations. Public key operations
|
||||
* are not restricted.
|
||||
*
|
||||
* @see #isUserAuthenticationRequired()
|
||||
* @see #getUserAuthenticationValidityDurationSeconds()
|
||||
* @see Builder#setUserAuthenticationValidWhileOnBody(boolean)
|
||||
*/
|
||||
public boolean isUserAuthenticationValidWhileOnBody() {
|
||||
return mUserAuthenticationValidWhileOnBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder of {@link KeyGenParameterSpec} instances.
|
||||
*/
|
||||
@@ -612,6 +632,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
|
||||
private int mUserAuthenticationValidityDurationSeconds = -1;
|
||||
private byte[] mAttestationChallenge = null;
|
||||
private boolean mUniqueIdIncluded = false;
|
||||
private boolean mUserAuthenticationValidWhileOnBody;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@code Builder}.
|
||||
@@ -1060,6 +1081,34 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the key is authorized for use after the authentication validity period is
|
||||
* expired (see {@link #setUserAuthenticationValidityDurationSeconds} and {@link
|
||||
* #setUserAuthenticationRequired}) if the device has a secure on-body sensor and if the
|
||||
* device has not been removed from the user's body since the last successful
|
||||
* authentication.
|
||||
*
|
||||
* <p>On devices that do not have a secure on-body sensor, creating a key with this
|
||||
* parameter set to {@code true} will have no effect; the private or secret key will no
|
||||
* longer be authorized for use after the validity period ends, and a fresh authentication
|
||||
* will be required to use it again.
|
||||
*
|
||||
* <p>Note that "secure" on-body sensors are required by Android to have a secure path to
|
||||
* the secure hardware, but the sensors themselves may not be difficult to fool. It is
|
||||
* recommended that this feature be used to increase slightly the security of keys which
|
||||
* would otherwise have to allow unauthenticated access, or have a very long validity
|
||||
* period. Keys that require high assurance of user authorization should not use this
|
||||
* feature and should set a short validity period.
|
||||
*
|
||||
* @param remainsValid if {@code true}, and if the device supports secure on-body detection,
|
||||
* key will remain valid after authentication validity duration has expired.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setUserAuthenticationValidWhileOnBody(boolean remainsValid) {
|
||||
mUserAuthenticationValidWhileOnBody = remainsValid;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an instance of {@code KeyGenParameterSpec}.
|
||||
*/
|
||||
@@ -1086,7 +1135,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
|
||||
mUserAuthenticationRequired,
|
||||
mUserAuthenticationValidityDurationSeconds,
|
||||
mAttestationChallenge,
|
||||
mUniqueIdIncluded);
|
||||
mUniqueIdIncluded,
|
||||
mUserAuthenticationValidWhileOnBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ public class KeyInfo implements KeySpec {
|
||||
private final boolean mUserAuthenticationRequired;
|
||||
private final int mUserAuthenticationValidityDurationSeconds;
|
||||
private final boolean mUserAuthenticationRequirementEnforcedBySecureHardware;
|
||||
private final boolean mUserAuthenticationValidWhileOnBody;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
@@ -97,7 +98,8 @@ public class KeyInfo implements KeySpec {
|
||||
@KeyProperties.BlockModeEnum String[] blockModes,
|
||||
boolean userAuthenticationRequired,
|
||||
int userAuthenticationValidityDurationSeconds,
|
||||
boolean userAuthenticationRequirementEnforcedBySecureHardware) {
|
||||
boolean userAuthenticationRequirementEnforcedBySecureHardware,
|
||||
boolean userAuthenticationValidWhileOnBody) {
|
||||
mKeystoreAlias = keystoreKeyAlias;
|
||||
mInsideSecureHardware = insideSecureHardware;
|
||||
mOrigin = origin;
|
||||
@@ -116,6 +118,7 @@ public class KeyInfo implements KeySpec {
|
||||
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
|
||||
mUserAuthenticationRequirementEnforcedBySecureHardware =
|
||||
userAuthenticationRequirementEnforcedBySecureHardware;
|
||||
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,4 +280,14 @@ public class KeyInfo implements KeySpec {
|
||||
public boolean isUserAuthenticationRequirementEnforcedBySecureHardware() {
|
||||
return mUserAuthenticationRequirementEnforcedBySecureHardware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this key will remain usable after its specified validity duration
|
||||
* for as long as the device remains on the user's body. This is possible only for keys with
|
||||
* a specified validity duration. Always returns {@code false} on devices that lack a secure
|
||||
* on-body sensor.
|
||||
*/
|
||||
public boolean isUserAuthenticationValidWhileOnBody() {
|
||||
return mUserAuthenticationValidWhileOnBody;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +214,7 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
private final boolean mRandomizedEncryptionRequired;
|
||||
private final boolean mUserAuthenticationRequired;
|
||||
private final int mUserAuthenticationValidityDurationSeconds;
|
||||
private final boolean mUserAuthenticationValidWhileOnBody;
|
||||
|
||||
private KeyProtection(
|
||||
Date keyValidityStart,
|
||||
@@ -226,7 +227,8 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
@KeyProperties.BlockModeEnum String[] blockModes,
|
||||
boolean randomizedEncryptionRequired,
|
||||
boolean userAuthenticationRequired,
|
||||
int userAuthenticationValidityDurationSeconds) {
|
||||
int userAuthenticationValidityDurationSeconds,
|
||||
boolean userAuthenticationValidWhileOnBody) {
|
||||
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
|
||||
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
|
||||
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
|
||||
@@ -240,6 +242,7 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
|
||||
mUserAuthenticationRequired = userAuthenticationRequired;
|
||||
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
|
||||
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -391,6 +394,23 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
return mUserAuthenticationValidityDurationSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the key will remain authorized while the device is on the user's
|
||||
* body, even after the validity duration has expired. This option has no effect on keys that
|
||||
* don't have an authentication validity duration, and has no effect if the device lacks a
|
||||
* secure on-body sensor.
|
||||
*
|
||||
* <p>Authorization applies only to secret key and private key operations. Public key operations
|
||||
* are not restricted.
|
||||
*
|
||||
* @see #isUserAuthenticationRequired()
|
||||
* @see #getUserAuthenticationValidityDurationSeconds()
|
||||
* @see Builder#setUserAuthenticationValidWhileOnBody(boolean)
|
||||
*/
|
||||
public boolean isUserAuthenticationValidWhileOnBody() {
|
||||
return mUserAuthenticationValidWhileOnBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder of {@link KeyProtection} instances.
|
||||
*/
|
||||
@@ -407,6 +427,7 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
private boolean mRandomizedEncryptionRequired = true;
|
||||
private boolean mUserAuthenticationRequired;
|
||||
private int mUserAuthenticationValidityDurationSeconds = -1;
|
||||
private boolean mUserAuthenticationValidWhileOnBody;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@code Builder}.
|
||||
@@ -679,6 +700,34 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the key is authorized for use after the authentication validity period is
|
||||
* expired (see {@link #setUserAuthenticationValidityDurationSeconds} and {@link
|
||||
* #setUserAuthenticationRequired}) if the device has a secure on-body sensor and if the
|
||||
* device has not been removed from the user's body since the last successful
|
||||
* authentication.
|
||||
*
|
||||
* <p>On devices that do not have a secure on-body sensor, creating a key with this
|
||||
* parameter set to {@code true} will have no effect; the private or secret key will no
|
||||
* longer be authorized for use after the validity period ends, and a fresh authentication
|
||||
* will be required to use it again.
|
||||
*
|
||||
* <p>Note that "secure" on-body sensors are required by Android to have a secure path to
|
||||
* the secure hardware, but the sensors themselves may not be difficult to fool. It is
|
||||
* recommended that this feature be used to increase slightly the security of keys which
|
||||
* would otherwise have to allow unauthenticated access, or have a very long validity
|
||||
* period. Keys that require high assurance of user authorization should not use this
|
||||
* feature and should set a short validity period.
|
||||
*
|
||||
* @param remainsValid if {@code true}, and if the device supports secure on-body detection,
|
||||
* key will remain valid after authentication validity duration has expired.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setUserAuthenticationValidWhileOnBody(boolean remainsValid) {
|
||||
mUserAuthenticationValidWhileOnBody = remainsValid;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an instance of {@link KeyProtection}.
|
||||
*
|
||||
@@ -697,7 +746,8 @@ public final class KeyProtection implements ProtectionParameter {
|
||||
mBlockModes,
|
||||
mRandomizedEncryptionRequired,
|
||||
mUserAuthenticationRequired,
|
||||
mUserAuthenticationValidityDurationSeconds);
|
||||
mUserAuthenticationValidityDurationSeconds,
|
||||
mUserAuthenticationValidWhileOnBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,8 @@ public abstract class KeymasterUtils {
|
||||
*/
|
||||
public static void addUserAuthArgs(KeymasterArguments args,
|
||||
boolean userAuthenticationRequired,
|
||||
int userAuthenticationValidityDurationSeconds) {
|
||||
int userAuthenticationValidityDurationSeconds,
|
||||
boolean userAuthenticationValidWhileOnBody) {
|
||||
if (!userAuthenticationRequired) {
|
||||
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
|
||||
return;
|
||||
@@ -119,6 +120,10 @@ public abstract class KeymasterUtils {
|
||||
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
|
||||
KeymasterArguments.toUint64(fingerprintOnlySid));
|
||||
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
|
||||
if (userAuthenticationValidWhileOnBody) {
|
||||
throw new ProviderException("Key validity extension while device is on-body is not "
|
||||
+ "supported for keys requiring fingerprint authentication");
|
||||
}
|
||||
} else {
|
||||
// The key is authorized for use for the specified amount of time after the user has
|
||||
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
|
||||
@@ -133,6 +138,9 @@ public abstract class KeymasterUtils {
|
||||
KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
|
||||
userAuthenticationValidityDurationSeconds);
|
||||
if (userAuthenticationValidWhileOnBody) {
|
||||
args.addBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user