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:
Shawn Willden
2016-02-18 18:30:59 +00:00
committed by android-build-merger
12 changed files with 159 additions and 13 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

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

View File

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

View File

@@ -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());

View File

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

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}