From 83cc7a347f4775821ebeed04a2244b8b847be516 Mon Sep 17 00:00:00 2001 From: Alex Klyubin Date: Tue, 16 Jun 2015 10:44:11 -0700 Subject: Improve documentation for keys requiring user auth. Bug: 18088752 Change-Id: I24eeb33790a74d8d81d10fcdb1eb058d47144c44 --- .../security/keystore/KeyGenParameterSpec.java | 109 +++++++++++++++------ .../java/android/security/keystore/KeyInfo.java | 16 ++- .../KeyPermanentlyInvalidatedException.java | 13 +-- .../android/security/keystore/KeyProtection.java | 87 +++++++++++++--- 4 files changed, 173 insertions(+), 52 deletions(-) (limited to 'keystore') diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 8d4bfcd..5775a87 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -19,16 +19,20 @@ package android.security.keystore; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.KeyguardManager; +import android.hardware.fingerprint.FingerprintManager; import android.text.TextUtils; import java.math.BigInteger; import java.security.KeyPairGenerator; +import java.security.Signature; import java.security.cert.Certificate; import java.security.spec.AlgorithmParameterSpec; import java.util.Date; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; +import javax.crypto.Mac; import javax.security.auth.x500.X500Principal; /** @@ -62,10 +66,15 @@ import javax.security.auth.x500.X500Principal; *

NOTE: If a private key is not authorized to sign the self-signed certificate, then the * certificate will be created with an invalid signature which will not verify. Such a certificate * is still useful because it provides access to the public key. To generate a valid - * signature for the certificate the key needs to be authorized for - * {@link KeyProperties#PURPOSE_SIGN}, a suitable digest or {@link KeyProperties#DIGEST_NONE}, and - * {@link KeyProperties#SIGNATURE_PADDING_RSA_PKCS1} or - * {@link KeyProperties#ENCRYPTION_PADDING_NONE}. + * signature for the certificate the key needs to be authorized for all of the following: + *

* *

NOTE: The key material of the generated symmetric and private keys is not accessible. The key * material of the public keys is accessible. @@ -393,28 +402,32 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { } /** - * Returns {@code true} if user authentication is required for this key to be used. + * Returns {@code true} if the key is authorized to be used only if the user has been + * authenticated. * - *

This restriction applies only to private key operations. Public key operations are not - * restricted. + *

This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. * * @see #getUserAuthenticationValidityDurationSeconds() + * @see Builder#setUserAuthenticationRequired(boolean) */ public boolean isUserAuthenticationRequired() { return mUserAuthenticationRequired; } /** - * Gets 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. + * Gets the duration of time (seconds) for which this key is authorized to be used after the + * user is successfully authenticated. This has effect only if user authentication is required + * (see {@link #isUserAuthenticationRequired()}). * - *

This restriction applies only to private key operations. Public key operations are not - * restricted. + *

This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. * * @return duration in seconds or {@code -1} if authentication is required for every use of the - * key. + * key. * * @see #isUserAuthenticationRequired() + * @see Builder#setUserAuthenticationValidityDurationSeconds(int) */ public int getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; @@ -738,22 +751,38 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { } /** - * Sets whether user authentication is required to use this key. + * Sets whether this key is authorized to be used only if the user has been authenticated. * - *

By default, the key can be used without user authentication. + *

By default, the key is authorized to be used regardless of whether the user has been + * authenticated. * - *

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)}). + *

When user authentication is required: + *

* - *

This restriction applies only to private key operations. Public key operations are not - * restricted. + *

This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. * * @see #setUserAuthenticationValidityDurationSeconds(int) + * @see KeyguardManager#isDeviceSecure() + * @see FingerprintManager#hasEnrolledFingerprints() */ @NonNull public Builder setUserAuthenticationRequired(boolean required) { @@ -762,15 +791,39 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { } /** - * 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. - * - *

By default, the user needs to authenticate for every use of the key. - * - * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for - * every use of the key. + * Sets the duration of time (seconds) for which this key is authorized to be used after the + * user is successfully authenticated. This has effect if the key requires user + * authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}). + * + *

By default, if user authentication is required, it must take place for every use of + * the key. + * + *

Cryptographic operations involving keys which require user authentication to take + * place for every operation can only use fingerprint authentication. This is achieved by + * initializing a cryptographic operation ({@link Signature}, {@link Cipher}, {@link Mac}) + * with the key, wrapping it into a {@link FingerprintManager.CryptoObject}, invoking + * {@code FingerprintManager.authenticate} with {@code CryptoObject}, and proceeding with + * the cryptographic operation only if the authentication flow succeeds. + * + *

Cryptographic operations involving keys which are authorized to be used for a duration + * of time after a successful user authentication event can only use secure lock screen + * authentication. These cryptographic operations will throw + * {@link UserNotAuthenticatedException} during initialization if the user needs to be + * authenticated to proceed. This situation can be resolved by the user unlocking the secure + * lock screen of the Android or by going through the confirm credential flow initiated by + * {@link KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence)}. + * Once resolved, initializing a new cryptographic operation using this key (or any other + * key which is authorized to be used for a fixed duration of time after user + * authentication) should succeed provided the user authentication flow completed + * successfully. + * + * @param seconds duration in seconds or {@code -1} if user authentication must take place + * for every use of the key. * * @see #setUserAuthenticationRequired(boolean) + * @see FingerprintManager + * @see FingerprintManager.CryptoObject + * @see KeyguardManager */ @NonNull public Builder setUserAuthenticationValidityDurationSeconds( diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java index 03b4100..91a9a70 100644 --- a/keystore/java/android/security/keystore/KeyInfo.java +++ b/keystore/java/android/security/keystore/KeyInfo.java @@ -238,17 +238,27 @@ public class KeyInfo implements KeySpec { } /** - * Returns {@code true} if user authentication is required for this key to be used. + * Returns {@code true} if the key is authorized to be used only if the user has been + * authenticated. + * + *

This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. * * @see #getUserAuthenticationValidityDurationSeconds() + * @see KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean) + * @see KeyProtection.Builder#setUserAuthenticationRequired(boolean) */ public boolean isUserAuthenticationRequired() { return mUserAuthenticationRequired; } /** - * Gets 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. + * Gets the duration of time (seconds) for which this key is authorized to be used after the + * user is successfully authenticated. This has effect only if user authentication is required + * (see {@link #isUserAuthenticationRequired()}). + * + *

This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. * * @return duration in seconds or {@code -1} if authentication is required for every use of the * key. diff --git a/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java b/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java index e320c9c..9e82fc0 100644 --- a/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java +++ b/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java @@ -21,12 +21,13 @@ import java.security.InvalidKeyException; /** * Indicates that the key can no longer be used because it has been permanently invalidated. * - *

This can currently occur only for keys that require user authentication. Such keys are - * permanently invalidated once the secure lock screen is disabled (i.e., reconfigured to None, - * Swipe or other mode which does not authenticate the user) or when the secure lock screen is - * forcibly reset (e.g., by Device Admin). Additionally, keys configured to require user - * authentication for every use of the key are also permanently invalidated once a new fingerprint - * is enrolled or once no more fingerprints are enrolled. + *

This only occurs for keys which are authorized to be used only if the user has been + * authenticated. Such keys are permanently and irreversibly invalidated once the secure lock screen + * is disabled (i.e., reconfigured to None, Swipe or other mode which does not authenticate the + * user) or when the secure lock screen is forcibly reset (e.g., by Device Admin). Additionally, + * keys configured to require user authentication to take place for every of the keys, are also + * permanently invalidated once a new fingerprint is enrolled or once no more fingerprints are + * enrolled. */ public class KeyPermanentlyInvalidatedException extends InvalidKeyException { diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index 1e0611c..cd46afa 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -19,13 +19,17 @@ package android.security.keystore; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.KeyguardManager; +import android.hardware.fingerprint.FingerprintManager; import java.security.Key; +import java.security.Signature; import java.security.KeyStore.ProtectionParameter; import java.security.cert.Certificate; import java.util.Date; import javax.crypto.Cipher; +import javax.crypto.Mac; /** * Specification of how a key or key pair is secured when imported into the @@ -257,22 +261,32 @@ public final class KeyProtection implements ProtectionParameter { } /** - * Returns {@code true} if user authentication is required for this key to be used. + * Returns {@code true} if the key is authorized to be used only if the user has been + * authenticated. + * + *

This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. * * @see #getUserAuthenticationValidityDurationSeconds() + * @see Builder#setUserAuthenticationRequired(boolean) */ public boolean isUserAuthenticationRequired() { return mUserAuthenticationRequired; } /** - * Gets 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. + * Gets the duration of time (seconds) for which this key is authorized to be used after the + * user is successfully authenticated. This has effect only if user authentication is required + * (see {@link #isUserAuthenticationRequired()}). + * + *

This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. * * @return duration in seconds or {@code -1} if authentication is required for every use of the * key. * * @see #isUserAuthenticationRequired() + * @see Builder#setUserAuthenticationValidityDurationSeconds(int) */ public int getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; @@ -479,19 +493,38 @@ public final class KeyProtection implements ProtectionParameter { } /** - * Sets whether user authentication is required to use this key. + * Sets whether this key is authorized to be used only if the user has been authenticated. * - *

By default, the key can be used without user authentication. + *

By default, the key is authorized to be used regardless of whether the user has been + * authenticated. * - *

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)}). + *

When user authentication is required: + *

+ * + *

This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. * * @see #setUserAuthenticationValidityDurationSeconds(int) + * @see KeyguardManager#isDeviceSecure() + * @see FingerprintManager#hasEnrolledFingerprints() */ @NonNull public Builder setUserAuthenticationRequired(boolean required) { @@ -500,15 +533,39 @@ public final class KeyProtection implements ProtectionParameter { } /** - * 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. + * Sets the duration of time (seconds) for which this key is authorized to be used after the + * user is successfully authenticated. This has effect if the key requires user + * authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}). + * + *

By default, if user authentication is required, it must take place for every use of + * the key. + * + *

Cryptographic operations involving keys which require user authentication to take + * place for every operation can only use fingerprint authentication. This is achieved by + * initializing a cryptographic operation ({@link Signature}, {@link Cipher}, {@link Mac}) + * with the key, wrapping it into a {@link FingerprintManager.CryptoObject}, invoking + * {@code FingerprintManager.authenticate} with {@code CryptoObject}, and proceeding with + * the cryptographic operation only if the authentication flow succeeds. * - *

By default, the user needs to authenticate for every use of the key. + *

Cryptographic operations involving keys which are authorized to be used for a duration + * of time after a successful user authentication event can only use secure lock screen + * authentication. These cryptographic operations will throw + * {@link UserNotAuthenticatedException} during initialization if the user needs to be + * authenticated to proceed. This situation can be resolved by the user unlocking the secure + * lock screen of the Android or by going through the confirm credential flow initiated by + * {@link KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence)}. + * Once resolved, initializing a new cryptographic operation using this key (or any other + * key which is authorized to be used for a fixed duration of time after user + * authentication) should succeed provided the user authentication flow completed + * successfully. * - * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for - * every use of the key. + * @param seconds duration in seconds or {@code -1} if user authentication must take place + * for every use of the key. * * @see #setUserAuthenticationRequired(boolean) + * @see FingerprintManager + * @see FingerprintManager.CryptoObject + * @see KeyguardManager */ @NonNull public Builder setUserAuthenticationValidityDurationSeconds( -- cgit v1.1