am ecde0330: am 0838084a: Merge "Align AndroidKeyStore API with user auth API." into mnc-dev

* commit 'ecde03306541259d786aeac9a658f440a2e1b098':
  Align AndroidKeyStore API with user auth API.
This commit is contained in:
Alex Klyubin
2015-04-29 02:01:16 +00:00
committed by Android Git Automerger
13 changed files with 265 additions and 413 deletions

View File

@@ -28535,10 +28535,9 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 {

View File

@@ -30540,10 +30540,9 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 @@ package android.security {
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 {

View File

@@ -105,11 +105,11 @@ public class KeyCharacteristics implements Parcelable {
}
}
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);
}
}
}

View File

@@ -29,7 +29,9 @@ page.title=Android Keystore System
<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 @@ and {@link java.security.KeyPairGenerator} or
<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>

View File

@@ -529,27 +529,10 @@ public class AndroidKeyStore extends KeyStoreSpi {
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));

View File

@@ -51,9 +51,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
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 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
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 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
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 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
}
/**
* 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.
@@ -208,17 +204,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
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;
}
/**
* Returns {@code true} if the key must be encrypted in the {@link java.security.KeyStore}.
*/
@@ -238,9 +223,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
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,52 +400,41 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
}
/**
* 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;
return this;
}
/**
* 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}.
*
@@ -479,9 +452,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec {
mEncryptionPaddings,
mBlockModes,
mRandomizedEncryptionRequired,
mUserAuthenticators,
mUserAuthenticationValidityDurationSeconds,
mInvalidatedOnNewFingerprintEnrolled);
mUserAuthenticationRequired,
mUserAuthenticationValidityDurationSeconds);
}
}
}

View File

@@ -95,12 +95,10 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
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 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
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 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
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 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
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,43 +391,33 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
}
/**
* 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>
@@ -493,12 +478,10 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
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 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
}
/**
* 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,27 +791,13 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
* @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;
return this;
}
/**
* 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}.
*
@@ -852,9 +824,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
mSignaturePaddings,
mBlockModes,
mRandomizedEncryptionRequired,
mUserAuthenticators,
mUserAuthenticationValidityDurationSeconds,
mInvalidatedOnNewFingerprintEnrolled);
mUserAuthenticationRequired,
mUserAuthenticationValidityDurationSeconds);
}
}
}

View File

@@ -161,27 +161,10 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
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));

View File

@@ -121,101 +121,6 @@ public abstract class KeyStoreKeyProperties {
}
}
@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 {}

View File

@@ -36,10 +36,9 @@ public class KeyStoreKeySpec implements KeySpec {
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 @@ public class KeyStoreKeySpec implements KeySpec {
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 @@ public class KeyStoreKeySpec implements KeySpec {
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 @@ public class KeyStoreKeySpec implements KeySpec {
}
/**
* 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;
}
}

View File

@@ -39,7 +39,8 @@ import javax.crypto.Cipher;
* {@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 @@ public final class KeyStoreParameter implements ProtectionParameter {
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 @@ public final class KeyStoreParameter implements ProtectionParameter {
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 @@ public final class KeyStoreParameter implements ProtectionParameter {
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 @@ public final class KeyStoreParameter implements ProtectionParameter {
}
/**
* 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.
@@ -218,17 +227,6 @@ public final class KeyStoreParameter implements ProtectionParameter {
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 KeyStoreParameter} objects.
* <p>
@@ -247,6 +245,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
* </pre>
*/
public final static class Builder {
private final Context mContext;
private int mFlags;
private Date mKeyValidityStart;
private Date mKeyValidityForOriginationEnd;
@@ -257,9 +256,8 @@ public final class KeyStoreParameter implements ProtectionParameter {
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 @@ public final class KeyStoreParameter implements ProtectionParameter {
if (context == null) {
throw new NullPointerException("context == null");
}
// Context is currently not used, but will be in the future.
mContext = context;
}
/**
@@ -440,52 +437,41 @@ public final class KeyStoreParameter implements ProtectionParameter {
}
/**
* 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;
return this;
}
/**
* 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}.
*
@@ -493,7 +479,9 @@ public final class KeyStoreParameter implements ProtectionParameter {
* @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 @@ public final class KeyStoreParameter implements ProtectionParameter {
mDigests,
mBlockModes,
mRandomizedEncryptionRequired,
mUserAuthenticators,
mUserAuthenticationValidityDurationSeconds,
mInvalidatedOnNewFingerprintEnrolled);
mUserAuthenticationRequired,
mUserAuthenticationValidityDurationSeconds);
}
}
}

View File

@@ -81,8 +81,8 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
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 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
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 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
&& (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 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
EmptyArray.STRING, // no signature paddings -- this is symmetric crypto
digests,
blockModes,
userAuthenticators,
teeEnforcedUserAuthenticators,
userAuthenticationRequired,
userAuthenticationValidityDurationSeconds,
invalidatedOnNewFingerprintEnrolled);
userAuthenticationRequirementEnforcedInTee);
}
@Override

View File

@@ -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 @@ public abstract class KeymasterUtils {
}
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);
}
}
}