diff options
author | Alex Klyubin <klyubin@google.com> | 2015-04-01 14:41:28 -0700 |
---|---|---|
committer | Alex Klyubin <klyubin@google.com> | 2015-04-01 18:35:36 -0700 |
commit | 2ea13d42689ab10456a575772d069c91ae9b6075 (patch) | |
tree | 06f9b1c815855c276132d8ace87850e86d13bada /keystore | |
parent | 6c3d3db3b4644aee68a6ac9e80dfe21ee62ac597 (diff) | |
download | frameworks_base-2ea13d42689ab10456a575772d069c91ae9b6075.zip frameworks_base-2ea13d42689ab10456a575772d069c91ae9b6075.tar.gz frameworks_base-2ea13d42689ab10456a575772d069c91ae9b6075.tar.bz2 |
Add fingerprint-specific AndroidKeyStore API.
Bug: 18088752
Change-Id: I333d3ffc820d28ae678e28dafc2e8a24cb7eb073
Diffstat (limited to 'keystore')
9 files changed, 153 insertions, 6 deletions
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java index dcc79be..0bd1dbd 100644 --- a/keystore/java/android/security/AndroidKeyStore.java +++ b/keystore/java/android/security/AndroidKeyStore.java @@ -540,6 +540,10 @@ public class AndroidKeyStore extends KeyStoreSpi { KeyStoreKeyConstraints.UserAuthenticator.allToKeymaster( params.getUserAuthenticators())); } + if (params.isInvalidatedOnNewFingerprintEnrolled()) { + // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports + // that. + } if (params.getUserAuthenticationValidityDurationSeconds() != null) { args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, params.getUserAuthenticationValidityDurationSeconds()); diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java index 9122d8e..02b0816 100644 --- a/keystore/java/android/security/KeyGeneratorSpec.java +++ b/keystore/java/android/security/KeyGeneratorSpec.java @@ -59,6 +59,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private final Integer mMaxUsesPerBoot; private final Set<Integer> mUserAuthenticators; private final Integer mUserAuthenticationValidityDurationSeconds; + private final boolean mInvalidatedOnNewFingerprintEnrolled; private KeyGeneratorSpec( Context context, @@ -74,7 +75,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { Integer minSecondsBetweenOperations, Integer maxUsesPerBoot, Set<Integer> userAuthenticators, - Integer userAuthenticationValidityDurationSeconds) { + Integer userAuthenticationValidityDurationSeconds, + boolean invalidatedOnNewFingerprintEnrolled) { if (context == null) { throw new IllegalArgumentException("context == null"); } else if (TextUtils.isEmpty(keyStoreAlias)) { @@ -101,6 +103,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { ? new HashSet<Integer>(userAuthenticators) : Collections.<Integer>emptySet(); mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; + mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } /** @@ -239,6 +242,19 @@ 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() + * + * @hide + */ + public boolean isInvalidatedOnNewFingerprintEnrolled() { + return mInvalidatedOnNewFingerprintEnrolled; + } + + /** * Returns {@code true} if the key must be encrypted in the {@link java.security.KeyStore}. */ public boolean isEncryptionRequired() { @@ -260,6 +276,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private Integer mMaxUsesPerBoot; private Set<Integer> mUserAuthenticators; private Integer mUserAuthenticationValidityDurationSeconds; + private boolean mInvalidatedOnNewFingerprintEnrolled; /** * Creates a new instance of the {@code Builder} with the given {@code context}. The @@ -473,6 +490,22 @@ 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) + * + * @hide + */ + 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. @@ -481,7 +514,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { return new KeyGeneratorSpec(mContext, mKeystoreAlias, mFlags, mKeySize, mKeyValidityStart, mKeyValidityForOriginationEnd, mKeyValidityForConsumptionEnd, mPurposes, mPadding, mBlockMode, mMinSecondsBetweenOperations, mMaxUsesPerBoot, - mUserAuthenticators, mUserAuthenticationValidityDurationSeconds); + mUserAuthenticators, mUserAuthenticationValidityDurationSeconds, + mInvalidatedOnNewFingerprintEnrolled); } } } diff --git a/keystore/java/android/security/KeyStoreKeyConstraints.java b/keystore/java/android/security/KeyStoreKeyConstraints.java index c27ccb1..75034d1 100644 --- a/keystore/java/android/security/KeyStoreKeyConstraints.java +++ b/keystore/java/android/security/KeyStoreKeyConstraints.java @@ -537,6 +537,9 @@ public abstract class KeyStoreKeyConstraints { /** Lock screen. */ public static final int LOCK_SCREEN = 1; + /** Fingerprint reader/sensor. */ + public static final int FINGERPRINT_READER = 1 << 1; + /** * @hide */ @@ -544,6 +547,8 @@ public abstract class KeyStoreKeyConstraints { switch (userAuthenticator) { case LOCK_SCREEN: return LOCK_SCREEN; + case FINGERPRINT_READER: + return FINGERPRINT_READER; default: throw new IllegalArgumentException( "Unknown user authenticator: " + userAuthenticator); @@ -557,6 +562,8 @@ public abstract class KeyStoreKeyConstraints { switch (userAuthenticator) { case LOCK_SCREEN: return LOCK_SCREEN; + case FINGERPRINT_READER: + return FINGERPRINT_READER; default: throw new IllegalArgumentException( "Unknown user authenticator: " + userAuthenticator); @@ -600,6 +607,8 @@ public abstract class KeyStoreKeyConstraints { 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/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java index 69533b4..8b0a3e9 100644 --- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java @@ -141,6 +141,10 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { KeyStoreKeyConstraints.UserAuthenticator.allToKeymaster( spec.getUserAuthenticators())); } + if (spec.isInvalidatedOnNewFingerprintEnrolled()) { + // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports + // that. + } if (spec.getUserAuthenticationValidityDurationSeconds() != null) { args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, spec.getUserAuthenticationValidityDurationSeconds()); diff --git a/keystore/java/android/security/KeyStoreKeySpec.java b/keystore/java/android/security/KeyStoreKeySpec.java index ddeefbd..e5e5acc 100644 --- a/keystore/java/android/security/KeyStoreKeySpec.java +++ b/keystore/java/android/security/KeyStoreKeySpec.java @@ -45,6 +45,7 @@ public class KeyStoreKeySpec implements KeySpec { private final Set<Integer> mUserAuthenticators; private final Set<Integer> mTeeBackedUserAuthenticators; private final Integer mUserAuthenticationValidityDurationSeconds; + private final boolean mInvalidatedOnNewFingerprintEnrolled; /** @@ -63,7 +64,8 @@ public class KeyStoreKeySpec implements KeySpec { Integer maxUsesPerBoot, Set<Integer> userAuthenticators, Set<Integer> teeBackedUserAuthenticators, - Integer userAuthenticationValidityDurationSeconds) { + Integer userAuthenticationValidityDurationSeconds, + boolean invalidatedOnNewFingerprintEnrolled) { mKeystoreAlias = keystoreKeyAlias; mOrigin = origin; mKeySize = keySize; @@ -84,6 +86,7 @@ public class KeyStoreKeySpec implements KeySpec { ? new HashSet<Integer>(teeBackedUserAuthenticators) : Collections.<Integer>emptySet(); mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; + mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } /** @@ -223,4 +226,15 @@ public class KeyStoreKeySpec implements KeySpec { public Integer 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 2428c2a..b1b638f 100644 --- a/keystore/java/android/security/KeyStoreParameter.java +++ b/keystore/java/android/security/KeyStoreParameter.java @@ -59,6 +59,7 @@ public final class KeyStoreParameter implements ProtectionParameter { private final Integer mMaxUsesPerBoot; private final Set<Integer> mUserAuthenticators; private final Integer mUserAuthenticationValidityDurationSeconds; + private final boolean mInvalidatedOnNewFingerprintEnrolled; private KeyStoreParameter(int flags, Date keyValidityStart, Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, @@ -70,7 +71,8 @@ public final class KeyStoreParameter implements ProtectionParameter { Integer minSecondsBetweenOperations, Integer maxUsesPerBoot, Set<Integer> userAuthenticators, - Integer userAuthenticationValidityDurationSeconds) { + Integer userAuthenticationValidityDurationSeconds, + boolean invalidatedOnNewFingerprintEnrolled) { if ((userAuthenticationValidityDurationSeconds != null) && (userAuthenticationValidityDurationSeconds < 0)) { throw new IllegalArgumentException( @@ -92,6 +94,7 @@ public final class KeyStoreParameter implements ProtectionParameter { ? new HashSet<Integer>(userAuthenticators) : Collections.<Integer>emptySet(); mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; + mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } /** @@ -245,6 +248,19 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** + * 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() + * + * @hide + */ + public boolean isInvalidatedOnNewFingerprintEnrolled() { + return mInvalidatedOnNewFingerprintEnrolled; + } + + /** * Builder class for {@link KeyStoreParameter} objects. * <p> * This will build protection parameters for use with the @@ -275,6 +291,7 @@ public final class KeyStoreParameter implements ProtectionParameter { private Integer mMaxUsesPerBoot; private Set<Integer> mUserAuthenticators; private Integer mUserAuthenticationValidityDurationSeconds; + private boolean mInvalidatedOnNewFingerprintEnrolled; /** * Creates a new instance of the {@code Builder} with the given @@ -496,6 +513,22 @@ 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) + * + * @hide + */ + public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) { + mInvalidatedOnNewFingerprintEnrolled = invalidated; + return this; + } + + /** * Builds the instance of the {@code KeyStoreParameter}. * * @throws IllegalArgumentException if a required field is missing @@ -506,7 +539,8 @@ public final class KeyStoreParameter implements ProtectionParameter { mKeyValidityForOriginationEnd, mKeyValidityForConsumptionEnd, mPurposes, mAlgorithm, mPadding, mDigest, mBlockMode, mMinSecondsBetweenOperations, mMaxUsesPerBoot, mUserAuthenticators, - mUserAuthenticationValidityDurationSeconds); + mUserAuthenticationValidityDurationSeconds, + mInvalidatedOnNewFingerprintEnrolled); } } } diff --git a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java index f552759..c205d9d 100644 --- a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java +++ b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java @@ -142,6 +142,9 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { KeyStoreKeyConstraints.UserAuthenticator.allFromKeymaster( hwEnforcedUserAuthenticatorIds); + // TODO: Populate the value below from key characteristics once Keymaster is ready. + boolean invalidatedOnNewFingerprintEnrolled = false; + return new KeyStoreKeySpec(entryAlias, origin, keySize, @@ -158,7 +161,8 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_MAX_USES_PER_BOOT), userAuthenticators, teeBackedUserAuthenticators, - KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_AUTH_TIMEOUT)); + KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_AUTH_TIMEOUT), + invalidatedOnNewFingerprintEnrolled); } @Override diff --git a/keystore/java/android/security/KeymasterUtils.java b/keystore/java/android/security/KeymasterUtils.java index 2645cf4..c3092d5 100644 --- a/keystore/java/android/security/KeymasterUtils.java +++ b/keystore/java/android/security/KeymasterUtils.java @@ -46,6 +46,9 @@ public abstract class KeymasterUtils { switch (e.getErrorCode()) { 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/NewFingerprintEnrolledException.java b/keystore/java/android/security/NewFingerprintEnrolledException.java new file mode 100644 index 0000000..6da4a2a --- /dev/null +++ b/keystore/java/android/security/NewFingerprintEnrolledException.java @@ -0,0 +1,41 @@ +/* + * 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. + * + * @hide + */ +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); + } +} |