diff options
Diffstat (limited to 'keystore/java/android')
16 files changed, 242 insertions, 127 deletions
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java index 964fb21..1c068be 100644 --- a/keystore/java/android/security/AndroidKeyStore.java +++ b/keystore/java/android/security/AndroidKeyStore.java @@ -536,6 +536,10 @@ public class AndroidKeyStore extends KeyStoreSpi { KeyStoreKeyProperties.UserAuthenticator.allToKeymaster( params.getUserAuthenticators())); } + 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()); diff --git a/keystore/java/android/security/CryptoOperationException.java b/keystore/java/android/security/CryptoOperationException.java index 00c142f..1c9d005 100644 --- a/keystore/java/android/security/CryptoOperationException.java +++ b/keystore/java/android/security/CryptoOperationException.java @@ -25,8 +25,6 @@ package android.security; * permitted to throw a checked exception during operation. Because crypto operations can fail * for a variety of reasons after initialization, this base class provides type-safety for unchecked * exceptions that may be thrown in those cases. - * - * @hide */ public class CryptoOperationException extends RuntimeException { diff --git a/keystore/java/android/security/EcIesParameterSpec.java b/keystore/java/android/security/EcIesParameterSpec.java index 3372da9..a3e5aec 100644 --- a/keystore/java/android/security/EcIesParameterSpec.java +++ b/keystore/java/android/security/EcIesParameterSpec.java @@ -46,8 +46,6 @@ import javax.crypto.Mac; * MAC algorithm specified by {@link #getDemMacAlgorithm()} (e.g., {@code HmacSHA1} for standard * DEM1).</li> * </ul> - * - * @hide */ public class EcIesParameterSpec implements AlgorithmParameterSpec { diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index dfa41e8..e9c24dd 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -127,6 +127,12 @@ public final class KeyChain { * Extra for use with {@link #ACTION_CHOOSER} * @hide Also used by KeyChainActivity implementation */ + public static final String EXTRA_URL = "url"; + + /** + * Extra for use with {@link #ACTION_CHOOSER} + * @hide Also used by KeyChainActivity implementation + */ public static final String EXTRA_ALIAS = "alias"; /** @@ -224,6 +230,51 @@ public final class KeyChain { * selected alias or null will be returned via the * KeyChainAliasCallback callback. * + * <p>The device or profile owner can intercept this before the activity + * is shown, to pick a specific private key alias. + * + * <p>{@code keyTypes} and {@code issuers} may be used to + * highlight suggested choices to the user, although to cope with + * sometimes erroneous values provided by servers, the user may be + * able to override these suggestions. + * + * <p>{@code host} and {@code port} may be used to give the user + * more context about the server requesting the credentials. + * + * <p>{@code alias} allows the chooser to preselect an existing + * alias which will still be subject to user confirmation. + * + * @param activity The {@link Activity} context to use for + * launching the new sub-Activity to prompt the user to select + * a private key; used only to call startActivity(); must not + * be null. + * @param response Callback to invoke when the request completes; + * must not be null + * @param keyTypes The acceptable types of asymmetric keys such as + * "RSA" or "DSA", or a null array. + * @param issuers The acceptable certificate issuers for the + * certificate matching the private key, or null. + * @param host The host name of the server requesting the + * certificate, or null if unavailable. + * @param port The port number of the server requesting the + * certificate, or -1 if unavailable. + * @param alias The alias to preselect if available, or null if + * unavailable. + */ + public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response, + String[] keyTypes, Principal[] issuers, String host, int port, String alias) { + choosePrivateKeyAlias(activity, response, keyTypes, issuers, host, port, null, alias); + } + + /** + * Launches an {@code Activity} for the user to select the alias + * for a private key and certificate pair for authentication. The + * selected alias or null will be returned via the + * KeyChainAliasCallback callback. + * + * <p>The device or profile owner can intercept this before the activity + * is shown, to pick a specific private key alias.</p> + * * <p>{@code keyTypes} and {@code issuers} may be used to * highlight suggested choices to the user, although to cope with * sometimes erroneous values provided by servers, the user may be @@ -249,12 +300,14 @@ public final class KeyChain { * certificate, or null if unavailable. * @param port The port number of the server requesting the * certificate, or -1 if unavailable. + * @param url The full url the server is requesting the certificate + * for, or null if unavailable. * @param alias The alias to preselect if available, or null if * unavailable. */ public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response, String[] keyTypes, Principal[] issuers, - String host, int port, + String host, int port, String url, String alias) { /* * TODO currently keyTypes, issuers are unused. They are meant @@ -283,6 +336,7 @@ public final class KeyChain { intent.putExtra(EXTRA_RESPONSE, new AliasResponse(response)); intent.putExtra(EXTRA_HOST, host); intent.putExtra(EXTRA_PORT, port); + intent.putExtra(EXTRA_URL, url); intent.putExtra(EXTRA_ALIAS, alias); // the PendingIntent is used to get calling package name intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(), 0)); diff --git a/keystore/java/android/security/KeyExpiredException.java b/keystore/java/android/security/KeyExpiredException.java index 35a5acc..a02dc33 100644 --- a/keystore/java/android/security/KeyExpiredException.java +++ b/keystore/java/android/security/KeyExpiredException.java @@ -19,8 +19,6 @@ package android.security; /** * Indicates that a cryptographic operation failed because the employed key's validity end date * is in the past. - * - * @hide */ public class KeyExpiredException extends CryptoOperationException { diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java index a22c31c..7ecc47e 100644 --- a/keystore/java/android/security/KeyGeneratorSpec.java +++ b/keystore/java/android/security/KeyGeneratorSpec.java @@ -37,15 +37,13 @@ import javax.crypto.SecretKey; * <p>After generation, the {@code keyStoreAlias} is used with the * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)} * interface to retrieve the {@link SecretKey}. - * - * @hide */ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private final Context mContext; private final String mKeystoreAlias; private final int mFlags; - private final Integer mKeySize; + private final int mKeySize; private final Date mKeyValidityStart; private final Date mKeyValidityForOriginationEnd; private final Date mKeyValidityForConsumptionEnd; @@ -55,12 +53,13 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private final boolean mRandomizedEncryptionRequired; private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; private final int mUserAuthenticationValidityDurationSeconds; + private final boolean mInvalidatedOnNewFingerprintEnrolled; private KeyGeneratorSpec( Context context, String keyStoreAlias, int flags, - Integer keySize, + int keySize, Date keyValidityStart, Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, @@ -69,7 +68,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { String[] blockModes, boolean randomizedEncryptionRequired, @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators, - int userAuthenticationValidityDurationSeconds) { + int userAuthenticationValidityDurationSeconds, + boolean invalidatedOnNewFingerprintEnrolled) { if (context == null) { throw new IllegalArgumentException("context == null"); } else if (TextUtils.isEmpty(keyStoreAlias)) { @@ -94,6 +94,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { mRandomizedEncryptionRequired = randomizedEncryptionRequired; mUserAuthenticators = userAuthenticators; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; + mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } /** @@ -119,9 +120,9 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** - * Gets the requested key size or {@code null} if the default size should be used. + * Returns the requested key size or {@code -1} if default size should be used. */ - public Integer getKeySize() { + public int getKeySize() { return mKeySize; } @@ -208,6 +209,17 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** + * 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}. */ public boolean isEncryptionRequired() { @@ -218,7 +230,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private final Context mContext; private String mKeystoreAlias; private int mFlags; - private Integer mKeySize; + private int mKeySize = -1; private Date mKeyValidityStart; private Date mKeyValidityForOriginationEnd; private Date mKeyValidityForConsumptionEnd; @@ -228,6 +240,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private boolean mRandomizedEncryptionRequired = true; private @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; private int mUserAuthenticationValidityDurationSeconds = -1; + private boolean mInvalidatedOnNewFingerprintEnrolled; /** * Creates a new instance of the {@code Builder} with the given {@code context}. The @@ -436,6 +449,20 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** + * 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}. * * @throws IllegalArgumentException if a required field is missing or violates a constraint. @@ -453,7 +480,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { mBlockModes, mRandomizedEncryptionRequired, mUserAuthenticators, - mUserAuthenticationValidityDurationSeconds); + mUserAuthenticationValidityDurationSeconds, + mInvalidatedOnNewFingerprintEnrolled); } } } diff --git a/keystore/java/android/security/KeyNotYetValidException.java b/keystore/java/android/security/KeyNotYetValidException.java index f1c2cac..964cd7e 100644 --- a/keystore/java/android/security/KeyNotYetValidException.java +++ b/keystore/java/android/security/KeyNotYetValidException.java @@ -19,8 +19,6 @@ package android.security; /** * Indicates that a cryptographic operation failed because the employed key's validity start date * is in the future. - * - * @hide */ public class KeyNotYetValidException extends CryptoOperationException { diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java index fce02df..5e5cf37 100644 --- a/keystore/java/android/security/KeyPairGeneratorSpec.java +++ b/keystore/java/android/security/KeyPairGeneratorSpec.java @@ -99,6 +99,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private final int mUserAuthenticationValidityDurationSeconds; + private final boolean mInvalidatedOnNewFingerprintEnrolled; + /** * Parameter specification for the "{@code AndroidKeyPairGenerator}" * instance of the {@link java.security.KeyPairGenerator} API. The @@ -144,7 +146,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { String[] blockModes, boolean randomizedEncryptionRequired, @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators, - int userAuthenticationValidityDurationSeconds) { + int userAuthenticationValidityDurationSeconds, + boolean invalidatedOnNewFingerprintEnrolled) { if (context == null) { throw new IllegalArgumentException("context == null"); } else if (TextUtils.isEmpty(keyStoreAlias)) { @@ -194,6 +197,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { mRandomizedEncryptionRequired = randomizedEncryptionRequired; mUserAuthenticators = userAuthenticators; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; + mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } /** @@ -203,6 +207,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { public KeyPairGeneratorSpec(Context context, String keyStoreAlias, String keyType, int keySize, AlgorithmParameterSpec spec, X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate, int flags) { + this(context, keyStoreAlias, keyType, @@ -223,7 +228,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { null, // block modes false, // randomized encryption required 0, // user authenticators - -1 // user authentication validity duration (seconds) + -1, // user authentication validity duration (seconds) + false // invalidate on new fingerprint enrolled ); } @@ -317,8 +323,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * Gets the time instant before which the key pair is not yet valid. * * @return instant or {@code null} if not restricted. - * - * @hide */ public Date getKeyValidityStart() { return mKeyValidityStart; @@ -329,8 +333,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * verification. * * @return instant or {@code null} if not restricted. - * - * @hide */ public Date getKeyValidityForConsumptionEnd() { return mKeyValidityForConsumptionEnd; @@ -340,8 +342,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * Gets the time instant after which the key pair is no longer valid for encryption and signing. * * @return instant or {@code null} if not restricted. - * - * @hide */ public Date getKeyValidityForOriginationEnd() { return mKeyValidityForOriginationEnd; @@ -349,8 +349,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * Gets the set of purposes for which the key can be used. - * - * @hide */ public @KeyStoreKeyProperties.PurposeEnum int getPurposes() { return mPurposes; @@ -358,8 +356,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * Gets the set of digest algorithms with which the key can be used. - * - * @hide */ public String[] getDigests() { return ArrayUtils.cloneIfNotEmpty(mDigests); @@ -367,8 +363,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * Gets the set of padding schemes with which the key can be used when encrypting/decrypting. - * - * @hide */ public String[] getEncryptionPaddings() { return ArrayUtils.cloneIfNotEmpty(mEncryptionPaddings); @@ -376,8 +370,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * Gets the set of padding schemes with which the key can be used when signing/verifying. - * - * @hide */ public String[] getSignaturePaddings() { return ArrayUtils.cloneIfNotEmpty(mSignaturePaddings); @@ -385,8 +377,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * Gets the set of block modes with which the key can be used. - * - * @hide */ public String[] getBlockModes() { return ArrayUtils.cloneIfNotEmpty(mBlockModes); @@ -400,8 +390,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * weaknesses due to which ciphertext may leak information about plaintext. For example, if a * given plaintext always produces the same ciphertext, an attacker may see the repeated * ciphertexts and be able to deduce something about the plaintext. - * - * @hide */ public boolean isRandomizedEncryptionRequired() { return mRandomizedEncryptionRequired; @@ -415,8 +403,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * restricted. * * @return user authenticators or {@code 0} if the key can be used without user authentication. - * - * @hide */ public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() { return mUserAuthenticators; @@ -431,14 +417,23 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. - * - * @hide */ 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> * This will build a parameter spec for use with the <a href="{@docRoot} @@ -502,6 +497,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { 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 @@ -649,8 +646,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * <p>By default, the key is valid at any instant. * * @see #setKeyValidityEnd(Date) - * - * @hide */ public Builder setKeyValidityStart(Date startDate) { mKeyValidityStart = startDate; @@ -665,8 +660,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * @see #setKeyValidityStart(Date) * @see #setKeyValidityForConsumptionEnd(Date) * @see #setKeyValidityForOriginationEnd(Date) - * - * @hide */ public Builder setKeyValidityEnd(Date endDate) { setKeyValidityForOriginationEnd(endDate); @@ -680,8 +673,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * <p>By default, the key is valid at any instant. * * @see #setKeyValidityForConsumptionEnd(Date) - * - * @hide */ public Builder setKeyValidityForOriginationEnd(Date endDate) { mKeyValidityForOriginationEnd = endDate; @@ -695,8 +686,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * <p>By default, the key is valid at any instant. * * @see #setKeyValidityForOriginationEnd(Date) - * - * @hide */ public Builder setKeyValidityForConsumptionEnd(Date endDate) { mKeyValidityForConsumptionEnd = endDate; @@ -707,8 +696,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * Sets the set of purposes for which the key can be used. * * <p>This must be specified for all keys. There is no default. - * - * @hide */ public Builder setPurposes(@KeyStoreKeyProperties.PurposeEnum int purposes) { mPurposes = purposes; @@ -720,8 +707,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * to use the key with any other digest will be rejected. * * <p>This must be specified for keys which are used for signing/verification. - * - * @hide */ public Builder setDigests(String... digests) { mDigests = ArrayUtils.cloneIfNotEmpty(digests); @@ -734,8 +719,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * rejected. * * <p>This must be specified for keys which are used for encryption/decryption. - * - * @hide */ public Builder setEncryptionPaddings(String... paddings) { mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(paddings); @@ -748,8 +731,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * rejected. * * <p>This must be specified for RSA keys which are used for signing/verification. - * - * @hide */ public Builder setSignaturePaddings(String... paddings) { mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(paddings); @@ -761,8 +742,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * Attempts to use the key with any other block modes will be rejected. * * <p>This must be specified for encryption/decryption keys. - * - * @hide */ public Builder setBlockModes(String... blockModes) { mBlockModes = ArrayUtils.cloneIfNotEmpty(blockModes); @@ -788,8 +767,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * <li>If you are using RSA encryption without padding, consider switching to padding * schemes which offer {@code IND-CPA}, such as PKCS#1 or OAEP.</li> * </ul> - * - * @hide */ public Builder setRandomizedEncryptionRequired(boolean required) { mRandomizedEncryptionRequired = required; @@ -809,8 +786,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * without user authentication. * * @see #setUserAuthenticationValidityDurationSeconds(int) - * - * @hide */ public Builder setUserAuthenticators( @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators) { @@ -831,8 +806,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * every use of the key. * * @see #setUserAuthenticators(int) - * - * @hide */ public Builder setUserAuthenticationValidityDurationSeconds(int seconds) { mUserAuthenticationValidityDurationSeconds = seconds; @@ -840,6 +813,20 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { } /** + * 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}. * * @throws IllegalArgumentException if a required field is missing @@ -866,7 +853,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { mBlockModes, mRandomizedEncryptionRequired, mUserAuthenticators, - mUserAuthenticationValidityDurationSeconds); + mUserAuthenticationValidityDurationSeconds, + mInvalidatedOnNewFingerprintEnrolled); } } } diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 84a664e..5af0527 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -552,6 +552,9 @@ public class KeyStore { return new KeyNotYetValidException(); case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: return new UserNotAuthenticatedException(); + // TODO: Handle TBD Keymaster error code "invalid key: new fingerprint enrolled" + // case KeymasterDefs.KM_ERROR_TBD + // return new NewFingerprintEnrolledException(); default: return new CryptoOperationException("Crypto operation failed", e); } diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java index 87e7ee6..72c485a 100644 --- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java @@ -133,7 +133,7 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { throw new IllegalStateException("Digest algorithm must be specified for HMAC key"); } } - int keySizeBits = (spec.getKeySize() != null) ? spec.getKeySize() : mDefaultKeySizeBits; + int keySizeBits = (spec.getKeySize() != -1) ? spec.getKeySize() : mDefaultKeySizeBits; args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keySizeBits); @KeyStoreKeyProperties.PurposeEnum int purposes = spec.getPurposes(); int[] keymasterBlockModes = KeymasterUtils.getKeymasterBlockModesFromJcaBlockModes( @@ -168,6 +168,10 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { KeyStoreKeyProperties.UserAuthenticator.allToKeymaster( spec.getUserAuthenticators())); } + 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()); diff --git a/keystore/java/android/security/KeyStoreKeyProperties.java b/keystore/java/android/security/KeyStoreKeyProperties.java index 1077af4..a0faf88 100644 --- a/keystore/java/android/security/KeyStoreKeyProperties.java +++ b/keystore/java/android/security/KeyStoreKeyProperties.java @@ -27,8 +27,6 @@ import java.util.Collection; /** * Properties of {@code AndroidKeyStore} keys. - * - * @hide */ public abstract class KeyStoreKeyProperties { private KeyStoreKeyProperties() {} @@ -125,7 +123,7 @@ public abstract class KeyStoreKeyProperties { @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, - value = {UserAuthenticator.LOCK_SCREEN}) + value = {UserAuthenticator.LOCK_SCREEN, UserAuthenticator.FINGERPRINT_READER}) public @interface UserAuthenticatorEnum {} /** @@ -137,6 +135,9 @@ public abstract class KeyStoreKeyProperties { /** Lock screen. */ public static final int LOCK_SCREEN = 1 << 0; + /** Fingerprint reader/sensor. */ + public static final int FINGERPRINT_READER = 1 << 1; + /** * @hide */ @@ -144,6 +145,8 @@ public abstract class KeyStoreKeyProperties { 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); @@ -157,6 +160,8 @@ public abstract class KeyStoreKeyProperties { 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); @@ -202,6 +207,8 @@ public abstract class KeyStoreKeyProperties { switch (userAuthenticator) { case LOCK_SCREEN: return "LOCK_SCREEN"; + case FINGERPRINT_READER: + return "FINGERPRINT_READER"; default: throw new IllegalArgumentException( "Unknown user authenticator: " + userAuthenticator); diff --git a/keystore/java/android/security/KeyStoreKeySpec.java b/keystore/java/android/security/KeyStoreKeySpec.java index 861ed34..a89e4dd 100644 --- a/keystore/java/android/security/KeyStoreKeySpec.java +++ b/keystore/java/android/security/KeyStoreKeySpec.java @@ -22,8 +22,6 @@ import java.util.Date; /** * Information about a key from the <a href="{@docRoot}training/articles/keystore.html">Android * KeyStore</a>. - * - * @hide */ public class KeyStoreKeySpec implements KeySpec { private final String mKeystoreAlias; @@ -41,7 +39,7 @@ public class KeyStoreKeySpec implements KeySpec { private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mTeeEnforcedUserAuthenticators; private final int mUserAuthenticationValidityDurationSeconds; - + private final boolean mInvalidatedOnNewFingerprintEnrolled; /** * @hide @@ -60,7 +58,8 @@ public class KeyStoreKeySpec implements KeySpec { String[] blockModes, @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators, @KeyStoreKeyProperties.UserAuthenticatorEnum int teeEnforcedUserAuthenticators, - int userAuthenticationValidityDurationSeconds) { + int userAuthenticationValidityDurationSeconds, + boolean invalidatedOnNewFingerprintEnrolled) { mKeystoreAlias = keystoreKeyAlias; mTeeBacked = teeBacked; mOrigin = origin; @@ -78,6 +77,7 @@ public class KeyStoreKeySpec implements KeySpec { mUserAuthenticators = userAuthenticators; mTeeEnforcedUserAuthenticators = teeEnforcedUserAuthenticators; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; + mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } /** @@ -200,4 +200,15 @@ public class KeyStoreKeySpec implements KeySpec { 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. + * + * @see #getUserAuthenticators() + */ + public boolean isInvalidatedOnNewFingerprintEnrolled() { + return mInvalidatedOnNewFingerprintEnrolled; + } } diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java index 9fce177..c24b74f 100644 --- a/keystore/java/android/security/KeyStoreParameter.java +++ b/keystore/java/android/security/KeyStoreParameter.java @@ -51,6 +51,7 @@ public final class KeyStoreParameter implements ProtectionParameter { private final boolean mRandomizedEncryptionRequired; private final @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; private final int mUserAuthenticationValidityDurationSeconds; + private final boolean mInvalidatedOnNewFingerprintEnrolled; private KeyStoreParameter(int flags, Date keyValidityStart, @@ -63,7 +64,8 @@ public final class KeyStoreParameter implements ProtectionParameter { String[] blockModes, boolean randomizedEncryptionRequired, @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators, - int userAuthenticationValidityDurationSeconds) { + int userAuthenticationValidityDurationSeconds, + boolean invalidatedOnNewFingerprintEnrolled) { if ((userAuthenticationValidityDurationSeconds < 0) && (userAuthenticationValidityDurationSeconds != -1)) { throw new IllegalArgumentException( @@ -84,6 +86,7 @@ public final class KeyStoreParameter implements ProtectionParameter { mRandomizedEncryptionRequired = randomizedEncryptionRequired; mUserAuthenticators = userAuthenticators; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; + mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } /** @@ -105,7 +108,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * Gets the time instant before which the key is not yet valid. * * @return instant or {@code null} if not restricted. - * @hide */ public Date getKeyValidityStart() { return mKeyValidityStart; @@ -115,8 +117,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * Gets the time instant after which the key is no long valid for decryption and verification. * * @return instant or {@code null} if not restricted. - * - * @hide */ public Date getKeyValidityForConsumptionEnd() { return mKeyValidityForConsumptionEnd; @@ -126,8 +126,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * Gets the time instant after which the key is no long valid for encryption and signing. * * @return instant or {@code null} if not restricted. - * - * @hide */ public Date getKeyValidityForOriginationEnd() { return mKeyValidityForOriginationEnd; @@ -135,8 +133,6 @@ public final class KeyStoreParameter implements ProtectionParameter { /** * Gets the set of purposes for which the key can be used. - * - * @hide */ public @KeyStoreKeyProperties.PurposeEnum int getPurposes() { return mPurposes; @@ -144,8 +140,6 @@ public final class KeyStoreParameter implements ProtectionParameter { /** * Gets the set of padding schemes with which the key can be used when encrypting/decrypting. - * - * @hide */ public String[] getEncryptionPaddings() { return ArrayUtils.cloneIfNotEmpty(mEncryptionPaddings); @@ -154,8 +148,6 @@ public final class KeyStoreParameter implements ProtectionParameter { /** * Gets the set of padding schemes with which the key can be used when signing or verifying * signatures. - * - * @hide */ public String[] getSignaturePaddings() { return ArrayUtils.cloneIfNotEmpty(mSignaturePaddings); @@ -167,8 +159,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * @throws IllegalStateException if this set has not been specified. * * @see #isDigestsSpecified() - * - * @hide */ public String[] getDigests() { if (mDigests == null) { @@ -182,8 +172,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * specified. * * @see #getDigests() - * - * @hide */ public boolean isDigestsSpecified() { return mDigests != null; @@ -191,8 +179,6 @@ public final class KeyStoreParameter implements ProtectionParameter { /** * Gets the set of block modes with which the key can be used. - * - * @hide */ public String[] getBlockModes() { return ArrayUtils.cloneIfNotEmpty(mBlockModes); @@ -206,8 +192,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * weaknesses due to which ciphertext may leak information about plaintext. For example, if a * given plaintext always produces the same ciphertext, an attacker may see the repeated * ciphertexts and be able to deduce something about the plaintext. - * - * @hide */ public boolean isRandomizedEncryptionRequired() { return mRandomizedEncryptionRequired; @@ -218,8 +202,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * used iff the user has authenticated to at least one of these user authenticators. * * @return user authenticators or {@code 0} if the key can be used without user authentication. - * - * @hide */ public @KeyStoreKeyProperties.UserAuthenticatorEnum int getUserAuthenticators() { return mUserAuthenticators; @@ -231,14 +213,23 @@ public final class KeyStoreParameter implements ProtectionParameter { * * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. - * - * @hide */ 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 KeyStoreParameter} objects. * <p> * This will build protection parameters for use with the @@ -268,6 +259,7 @@ public final class KeyStoreParameter implements ProtectionParameter { private boolean mRandomizedEncryptionRequired = true; private @KeyStoreKeyProperties.UserAuthenticatorEnum int mUserAuthenticators; private int mUserAuthenticationValidityDurationSeconds = -1; + private boolean mInvalidatedOnNewFingerprintEnrolled; /** * Creates a new instance of the {@code Builder} with the given @@ -304,8 +296,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * <p>By default, the key is valid at any instant. * * @see #setKeyValidityEnd(Date) - * - * @hide */ public Builder setKeyValidityStart(Date startDate) { mKeyValidityStart = startDate; @@ -320,8 +310,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * @see #setKeyValidityStart(Date) * @see #setKeyValidityForConsumptionEnd(Date) * @see #setKeyValidityForOriginationEnd(Date) - * - * @hide */ public Builder setKeyValidityEnd(Date endDate) { setKeyValidityForOriginationEnd(endDate); @@ -335,8 +323,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * <p>By default, the key is valid at any instant. * * @see #setKeyValidityForConsumptionEnd(Date) - * - * @hide */ public Builder setKeyValidityForOriginationEnd(Date endDate) { mKeyValidityForOriginationEnd = endDate; @@ -350,8 +336,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * <p>By default, the key is valid at any instant. * * @see #setKeyValidityForOriginationEnd(Date) - * - * @hide */ public Builder setKeyValidityForConsumptionEnd(Date endDate) { mKeyValidityForConsumptionEnd = endDate; @@ -362,8 +346,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * Sets the set of purposes for which the key can be used. * * <p>This must be specified for all keys. There is no default. - * - * @hide */ public Builder setPurposes(@KeyStoreKeyProperties.PurposeEnum int purposes) { mPurposes = purposes; @@ -376,8 +358,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * rejected. * * <p>This must be specified for keys which are used for encryption/decryption. - * - * @hide */ public Builder setEncryptionPaddings(String... paddings) { mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(paddings); @@ -390,8 +370,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * rejected. * * <p>This must be specified for RSA keys which are used for signing/verification. - * - * @hide */ public Builder setSignaturePaddings(String... paddings) { mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(paddings); @@ -405,8 +383,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * * <p>For HMAC keys, the default is the digest specified in {@link Key#getAlgorithm()}. For * asymmetric signing keys this constraint must be specified. - * - * @hide */ public Builder setDigests(String... digests) { mDigests = ArrayUtils.cloneIfNotEmpty(digests); @@ -418,8 +394,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * Attempts to use the key with any other block modes will be rejected. * * <p>This must be specified for encryption/decryption keys. - * - * @hide */ public Builder setBlockModes(String... blockModes) { mBlockModes = ArrayUtils.cloneIfNotEmpty(blockModes); @@ -459,8 +433,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * <li>If you are using RSA encryption without padding, consider switching to padding * schemes which offer {@code IND-CPA}, such as PKCS#1 or OAEP.</li> * </ul> - * - * @hide */ public Builder setRandomizedEncryptionRequired(boolean required) { mRandomizedEncryptionRequired = required; @@ -477,8 +449,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * without user authentication. * * @see #setUserAuthenticationValidityDurationSeconds(int) - * - * @hide */ public Builder setUserAuthenticators( @KeyStoreKeyProperties.UserAuthenticatorEnum int userAuthenticators) { @@ -496,8 +466,6 @@ public final class KeyStoreParameter implements ProtectionParameter { * every use of the key. * * @see #setUserAuthenticators(int) - * - * @hide */ public Builder setUserAuthenticationValidityDurationSeconds(int seconds) { mUserAuthenticationValidityDurationSeconds = seconds; @@ -505,6 +473,20 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** + * 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}. * * @throws IllegalArgumentException if a required field is missing @@ -522,7 +504,8 @@ public final class KeyStoreParameter implements ProtectionParameter { mBlockModes, mRandomizedEncryptionRequired, mUserAuthenticators, - mUserAuthenticationValidityDurationSeconds); + mUserAuthenticationValidityDurationSeconds, + mInvalidatedOnNewFingerprintEnrolled); } } } diff --git a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java index 33073a4..4be0638 100644 --- a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java +++ b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java @@ -160,6 +160,9 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { 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; + return new KeyStoreKeySpec(entryAlias, teeBacked, origin, @@ -174,7 +177,8 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { blockModes, userAuthenticators, teeEnforcedUserAuthenticators, - userAuthenticationValidityDurationSeconds); + userAuthenticationValidityDurationSeconds, + invalidatedOnNewFingerprintEnrolled); } @Override diff --git a/keystore/java/android/security/NewFingerprintEnrolledException.java b/keystore/java/android/security/NewFingerprintEnrolledException.java new file mode 100644 index 0000000..806b214 --- /dev/null +++ b/keystore/java/android/security/NewFingerprintEnrolledException.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +/** + * Indicates that a cryptographic operation could not be performed because the key used by the + * operation is permanently invalid because a new fingerprint was enrolled. + */ +public class NewFingerprintEnrolledException extends CryptoOperationException { + + /** + * Constructs a new {@code NewFingerprintEnrolledException} without detail message and cause. + */ + public NewFingerprintEnrolledException() { + super("Invalid key: new fingerprint enrolled"); + } + + /** + * Constructs a new {@code NewFingerprintEnrolledException} with the provided detail message and + * no cause. + */ + public NewFingerprintEnrolledException(String message) { + super(message); + } +} diff --git a/keystore/java/android/security/UserNotAuthenticatedException.java b/keystore/java/android/security/UserNotAuthenticatedException.java index e6342ef..f5f5f41 100644 --- a/keystore/java/android/security/UserNotAuthenticatedException.java +++ b/keystore/java/android/security/UserNotAuthenticatedException.java @@ -19,8 +19,6 @@ package android.security; /** * Indicates that a cryptographic operation could not be performed because the user has not been * authenticated recently enough. - * - * @hide */ public class UserNotAuthenticatedException extends CryptoOperationException { |