Loading core/java/android/security/keymaster/KeymasterDefs.java +49 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.security.keymaster; import java.util.HashMap; import java.util.Map; /** * Class tracking all the keymaster enum values needed for the binder API to keystore. * This must be kept in sync with hardware/libhardware/include/hardware/keymaster_defs.h Loading Loading @@ -224,7 +227,53 @@ public final class KeymasterDefs { public static final int KM_ERROR_VERSION_MISMATCH = -101; public static final int KM_ERROR_UNKNOWN_ERROR = -1000; public static final Map<Integer, String> sErrorCodeToString = new HashMap<Integer, String>(); static { sErrorCodeToString.put(KM_ERROR_OK, "OK"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_PURPOSE, "Unsupported purpose"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_PURPOSE, "Incompatible purpose"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_ALGORITHM, "Unsupported algorithm"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_ALGORITHM, "Incompatible algorithm"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_KEY_SIZE, "Unsupported key size"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_BLOCK_MODE, "Unsupported block mode"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_BLOCK_MODE, "Incompatible block mode"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_TAG_LENGTH, "Unsupported authentication tag length"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_PADDING_MODE, "Unsupported padding mode"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_PADDING_MODE, "Incompatible padding mode"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_DIGEST, "Unsupported digest"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_DIGEST, "Incompatible digest"); sErrorCodeToString.put(KM_ERROR_INVALID_EXPIRATION_TIME, "Invalid expiration time"); sErrorCodeToString.put(KM_ERROR_INVALID_USER_ID, "Invalid user ID"); sErrorCodeToString.put(KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT, "Invalid user authorization timeout"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_KEY_FORMAT, "Unsupported key format"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_KEY_FORMAT, "Incompatible key format"); sErrorCodeToString.put(KM_ERROR_INVALID_INPUT_LENGTH, "Invalid input length"); sErrorCodeToString.put(KM_ERROR_KEY_NOT_YET_VALID, "Key not yet valid"); sErrorCodeToString.put(KM_ERROR_KEY_EXPIRED, "Key expired"); sErrorCodeToString.put(KM_ERROR_KEY_USER_NOT_AUTHENTICATED, "Key user not authenticated"); sErrorCodeToString.put(KM_ERROR_INVALID_OPERATION_HANDLE, "Invalid operation handle"); sErrorCodeToString.put(KM_ERROR_VERIFICATION_FAILED, "Signature/MAC verification failed"); sErrorCodeToString.put(KM_ERROR_TOO_MANY_OPERATIONS, "Too many operations"); sErrorCodeToString.put(KM_ERROR_INVALID_KEY_BLOB, "Invalid key blob"); sErrorCodeToString.put(KM_ERROR_INVALID_ARGUMENT, "Invalid argument"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_TAG, "Unsupported tag"); sErrorCodeToString.put(KM_ERROR_INVALID_TAG, "Invalid tag"); sErrorCodeToString.put(KM_ERROR_MEMORY_ALLOCATION_FAILED, "Memory allocation failed"); sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented"); sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error"); } public static int getTagType(int tag) { return tag & (0xF << 28); } public static String getErrorMessage(int errorCode) { String result = sErrorCodeToString.get(errorCode); if (result != null) { return result; } return String.valueOf(errorCode); } } keystore/java/android/security/AndroidKeyStoreProvider.java +4 −0 Original line number Diff line number Diff line Loading @@ -35,5 +35,9 @@ public class AndroidKeyStoreProvider extends Provider { // java.security.KeyPairGenerator put("KeyPairGenerator.EC", AndroidKeyPairGenerator.EC.class.getName()); put("KeyPairGenerator.RSA", AndroidKeyPairGenerator.RSA.class.getName()); // javax.crypto.KeyGenerator put("KeyGenerator.AES", KeyStoreKeyGeneratorSpi.AES.class.getName()); put("KeyGenerator.HmacSHA256", KeyStoreKeyGeneratorSpi.HmacSHA256.class.getName()); } } keystore/java/android/security/CryptoOperationException.java 0 → 100644 +45 −0 Original line number Diff line number Diff line package android.security; /** * Base class for exceptions during cryptographic operations which cannot throw a suitable checked * exception. * * <p>The contract of the majority of crypto primitives/operations (e.g. {@code Cipher} or * {@code Signature}) is that they can throw a checked exception during initialization, but are not * 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 { /** * Constructs a new {@code CryptoOperationException} without detail message and cause. */ public CryptoOperationException() { super(); } /** * Constructs a new {@code CryptoOperationException} with the provided detail message and no * cause. */ public CryptoOperationException(String message) { super(message); } /** * Constructs a new {@code CryptoOperationException} with the provided detail message and cause. */ public CryptoOperationException(String message, Throwable cause) { super(message, cause); } /** * Constructs a new {@code CryptoOperationException} with the provided cause. */ public CryptoOperationException(Throwable cause) { super(cause); } } keystore/java/android/security/KeyGeneratorSpec.java 0 → 100644 +471 −0 Original line number Diff line number Diff line package android.security; import android.content.Context; import android.text.TextUtils; import java.security.cert.Certificate; import java.security.spec.AlgorithmParameterSpec; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; /** * {@link AlgorithmParameterSpec} for initializing a {@code KeyGenerator} that works with * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>. * * <p>The Android KeyStore facility is accessed through a {@link KeyGenerator} API * using the {@code AndroidKeyStore} provider. The {@code context} passed in may be used to pop up * some UI to ask the user to unlock or initialize the Android KeyStore facility. * * <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} and its associated {@link Certificate} chain. * * @hide */ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private final Context mContext; private final String mKeystoreAlias; private final int mFlags; private final Integer mKeySize; private final Date mKeyValidityStart; private final Date mKeyValidityForOriginationEnd; private final Date mKeyValidityForConsumptionEnd; private final @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; private final @KeyStoreKeyConstraints.PaddingEnum Integer mPadding; private final @KeyStoreKeyConstraints.BlockModeEnum Integer mBlockMode; private final Integer mMinSecondsBetweenOperations; private final Integer mMaxUsesPerBoot; private final Set<Integer> mUserAuthenticators; private final Integer mUserAuthenticationValidityDurationSeconds; private KeyGeneratorSpec( Context context, String keyStoreAlias, int flags, Integer keySize, Date keyValidityStart, Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, @KeyStoreKeyConstraints.PurposeEnum Integer purposes, @KeyStoreKeyConstraints.PaddingEnum Integer padding, @KeyStoreKeyConstraints.BlockModeEnum Integer blockMode, Integer minSecondsBetweenOperations, Integer maxUsesPerBoot, Set<Integer> userAuthenticators, Integer userAuthenticationValidityDurationSeconds) { if (context == null) { throw new IllegalArgumentException("context == null"); } else if (TextUtils.isEmpty(keyStoreAlias)) { throw new IllegalArgumentException("keyStoreAlias must not be empty"); } else if ((userAuthenticationValidityDurationSeconds != null) && (userAuthenticationValidityDurationSeconds < 0)) { throw new IllegalArgumentException( "userAuthenticationValidityDurationSeconds must not be negative"); } mContext = context; mKeystoreAlias = keyStoreAlias; mFlags = flags; mKeySize = keySize; mKeyValidityStart = keyValidityStart; mKeyValidityForOriginationEnd = keyValidityForOriginationEnd; mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd; mPurposes = purposes; mPadding = padding; mBlockMode = blockMode; mMinSecondsBetweenOperations = minSecondsBetweenOperations; mMaxUsesPerBoot = maxUsesPerBoot; mUserAuthenticators = (userAuthenticators != null) ? new HashSet<Integer>(userAuthenticators) : Collections.<Integer>emptySet(); mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; } /** * Gets the Android context used for operations with this instance. */ public Context getContext() { return mContext; } /** * Returns the alias that will be used in the {@code java.security.KeyStore} in conjunction with * the {@code AndroidKeyStore}. */ public String getKeystoreAlias() { return mKeystoreAlias; } /** * @hide */ public int getFlags() { return mFlags; } /** * Gets the requested key size or {@code null} if the default size should be used. */ public Integer getKeySize() { return mKeySize; } /** * Gets the time instant before which the key is not yet valid. * * @return instant or {@code null} if not restricted. */ public Date getKeyValidityStart() { return mKeyValidityStart; } /** * 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; } /** * Gets the time instant after which the key is no long valid for encryption and signing. * * @return instant or {@code null} if not restricted. */ public Date getKeyValidityForOriginationEnd() { return mKeyValidityForOriginationEnd; } /** * Gets the set of purposes for which the key can be used to the provided set of purposes. * * @return set of purposes or {@code null} if the key can be used for any purpose. */ public @KeyStoreKeyConstraints.PurposeEnum Integer getPurposes() { return mPurposes; } /** * Gets the padding scheme to which the key is restricted. * * @return padding scheme or {@code null} if the padding scheme is not restricted. */ public @KeyStoreKeyConstraints.PaddingEnum Integer getPadding() { return mPadding; } /** * Gets the block mode to which the key is restricted when used for encryption or decryption. * * @return block more or {@code null} if block mode is not restricted. * * @hide */ public @KeyStoreKeyConstraints.BlockModeEnum Integer getBlockMode() { return mBlockMode; } /** * Gets the minimum number of seconds that must expire since the most recent use of the key * before it can be used again. * * @return number of seconds or {@code null} if there is no restriction on how frequently a key * can be used. * * @hide */ public Integer getMinSecondsBetweenOperations() { return mMinSecondsBetweenOperations; } /** * Gets the number of times the key can be used without rebooting the device. * * @return maximum number of times or {@code null} if there is no restriction. * @hide */ public Integer getMaxUsesPerBoot() { return mMaxUsesPerBoot; } /** * Gets 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. * * @return user authenticators or empty set if the key can be used without user authentication. * * @hide */ public Set<Integer> getUserAuthenticators() { return new HashSet<Integer>(mUserAuthenticators); } /** * 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. * * @return duration in seconds or {@code null} if not restricted. {@code 0} means authentication * is required for every use of the key. * * @hide */ public Integer getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; } /** * Returns {@code true} if the key must be encrypted in the {@link java.security.KeyStore}. */ public boolean isEncryptionRequired() { return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0; } public static class Builder { private final Context mContext; private String mKeystoreAlias; private int mFlags; private Integer mKeySize; private Date mKeyValidityStart; private Date mKeyValidityForOriginationEnd; private Date mKeyValidityForConsumptionEnd; private @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; private @KeyStoreKeyConstraints.PaddingEnum Integer mPadding; private @KeyStoreKeyConstraints.BlockModeEnum Integer mBlockMode; private Integer mMinSecondsBetweenOperations; private Integer mMaxUsesPerBoot; private Set<Integer> mUserAuthenticators; private Integer mUserAuthenticationValidityDurationSeconds; /** * Creates a new instance of the {@code Builder} with the given {@code context}. The * {@code context} passed in may be used to pop up some UI to ask the user to unlock or * initialize the Android KeyStore facility. */ public Builder(Context context) { if (context == null) { throw new NullPointerException("context == null"); } mContext = context; } /** * Sets the alias to be used to retrieve the key later from a {@link java.security.KeyStore} * instance using the {@code AndroidKeyStore} provider. * * <p>The alias must be provided. There is no default. */ public Builder setAlias(String alias) { if (alias == null) { throw new NullPointerException("alias == null"); } mKeystoreAlias = alias; return this; } /** * Sets the size (in bits) of the key to be generated. * * <p>By default, the key size will be determines based on the key algorithm. For example, * for {@code HmacSHA256}, the key size will default to {@code 256}. */ public Builder setKeySize(int keySize) { mKeySize = keySize; return this; } /** * Indicates that this key must be encrypted at rest on storage. Note that enabling this * will require that the user enable a strong lock screen (e.g., PIN, password) before * creating or using the generated key is successful. */ public Builder setEncryptionRequired(boolean required) { if (required) { mFlags |= KeyStore.FLAG_ENCRYPTED; } else { mFlags &= ~KeyStore.FLAG_ENCRYPTED; } return this; } /** * Sets the time instant before which the key is not yet valid. * * <b>By default, the key is valid at any instant. * * @see #setKeyValidityEnd(Date) * * @hide */ public Builder setKeyValidityStart(Date startDate) { mKeyValidityStart = startDate; return this; } /** * Sets the time instant after which the key is no longer valid. * * <b>By default, the key is valid at any instant. * * @see #setKeyValidityStart(Date) * @see #setKeyValidityForConsumptionEnd(Date) * @see #setKeyValidityForOriginationEnd(Date) * * @hide */ public Builder setKeyValidityEnd(Date endDate) { setKeyValidityForOriginationEnd(endDate); setKeyValidityForConsumptionEnd(endDate); return this; } /** * Sets the time instant after which the key is no longer valid for encryption and signing. * * <b>By default, the key is valid at any instant. * * @see #setKeyValidityForConsumptionEnd(Date) * * @hide */ public Builder setKeyValidityForOriginationEnd(Date endDate) { mKeyValidityForOriginationEnd = endDate; return this; } /** * Sets the time instant after which the key is no longer valid for decryption and * verification. * * <b>By default, the key is valid at any instant. * * @see #setKeyValidityForOriginationEnd(Date) * * @hide */ public Builder setKeyValidityForConsumptionEnd(Date endDate) { mKeyValidityForConsumptionEnd = endDate; return this; } /** * Restricts the purposes for which the key can be used to the provided set of purposes. * * <p>By default, the key can be used for encryption, decryption, signing, and verification. * * @hide */ public Builder setPurposes(@KeyStoreKeyConstraints.PurposeEnum int purposes) { mPurposes = purposes; return this; } /** * Restricts the key to being used only with the provided padding scheme. Attempts to use * the key with any other padding will be rejected. * * <p>This restriction must be specified for keys which are used for encryption/decryption. * * @hide */ public Builder setPadding(@KeyStoreKeyConstraints.PaddingEnum int padding) { mPadding = padding; return this; } /** * Restricts the key to being used only with the provided block mode when encrypting or * decrypting. Attempts to use the key with any other block modes will be rejected. * * <p>This restriction must be specified for keys which are used for encryption/decryption. * * @hide */ public Builder setBlockMode(@KeyStoreKeyConstraints.BlockModeEnum int blockMode) { mBlockMode = blockMode; return this; } /** * Sets the minimum number of seconds that must expire since the most recent use of the key * before it can be used again. * * <p>By default, there is no restriction on how frequently a key can be used. * * @hide */ public Builder setMinSecondsBetweenOperations(int seconds) { mMinSecondsBetweenOperations = seconds; return this; } /** * Sets the maximum number of times a key can be used without rebooting the device. * * <p>By default, the key can be used for an unlimited number of times. * * @hide */ public Builder setMaxUsesPerBoot(int count) { mMaxUsesPerBoot = count; return this; } /** * 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. * * <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. * * @see #setUserAuthenticationValidityDurationSeconds(int) * * @hide */ public Builder setUserAuthenticators(Set<Integer> userAuthenticators) { mUserAuthenticators = (userAuthenticators != null) ? new HashSet<Integer>(userAuthenticators) : null; 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. * * <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(Set) * * @hide */ public Builder setUserAuthenticationValidityDurationSeconds(int seconds) { mUserAuthenticationValidityDurationSeconds = seconds; return this; } /** * Builds a new instance instance of {@code KeyGeneratorSpec}. * * @throws IllegalArgumentException if a required field is missing or violates a constraint. */ public KeyGeneratorSpec build() { return new KeyGeneratorSpec(mContext, mKeystoreAlias, mFlags, mKeySize, mKeyValidityStart, mKeyValidityForOriginationEnd, mKeyValidityForConsumptionEnd, mPurposes, mPadding, mBlockMode, mMinSecondsBetweenOperations, mMaxUsesPerBoot, mUserAuthenticators, mUserAuthenticationValidityDurationSeconds); } } } keystore/java/android/security/KeyStoreKeyConstraints.java +28 −0 Original line number Diff line number Diff line Loading @@ -290,6 +290,22 @@ public abstract class KeyStoreKeyConstraints { throw new IllegalArgumentException("Unknown padding: " + padding); } } /** * @hide */ public static String toString(@PaddingEnum int padding) { switch (padding) { case NONE: return "NONE"; case ZERO: return "ZERO"; case PKCS7: return "PKCS#7"; default: throw new IllegalArgumentException("Unknown padding: " + padding); } } } @Retention(RetentionPolicy.SOURCE) Loading Loading @@ -425,5 +441,17 @@ public abstract class KeyStoreKeyConstraints { throw new IllegalArgumentException("Unknown block mode: " + mode); } } /** * @hide */ public static String toString(@BlockModeEnum int mode) { switch (mode) { case ECB: return "ECB"; default: throw new IllegalArgumentException("Unknown block mode: " + mode); } } } } Loading
core/java/android/security/keymaster/KeymasterDefs.java +49 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.security.keymaster; import java.util.HashMap; import java.util.Map; /** * Class tracking all the keymaster enum values needed for the binder API to keystore. * This must be kept in sync with hardware/libhardware/include/hardware/keymaster_defs.h Loading Loading @@ -224,7 +227,53 @@ public final class KeymasterDefs { public static final int KM_ERROR_VERSION_MISMATCH = -101; public static final int KM_ERROR_UNKNOWN_ERROR = -1000; public static final Map<Integer, String> sErrorCodeToString = new HashMap<Integer, String>(); static { sErrorCodeToString.put(KM_ERROR_OK, "OK"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_PURPOSE, "Unsupported purpose"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_PURPOSE, "Incompatible purpose"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_ALGORITHM, "Unsupported algorithm"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_ALGORITHM, "Incompatible algorithm"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_KEY_SIZE, "Unsupported key size"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_BLOCK_MODE, "Unsupported block mode"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_BLOCK_MODE, "Incompatible block mode"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_TAG_LENGTH, "Unsupported authentication tag length"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_PADDING_MODE, "Unsupported padding mode"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_PADDING_MODE, "Incompatible padding mode"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_DIGEST, "Unsupported digest"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_DIGEST, "Incompatible digest"); sErrorCodeToString.put(KM_ERROR_INVALID_EXPIRATION_TIME, "Invalid expiration time"); sErrorCodeToString.put(KM_ERROR_INVALID_USER_ID, "Invalid user ID"); sErrorCodeToString.put(KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT, "Invalid user authorization timeout"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_KEY_FORMAT, "Unsupported key format"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_KEY_FORMAT, "Incompatible key format"); sErrorCodeToString.put(KM_ERROR_INVALID_INPUT_LENGTH, "Invalid input length"); sErrorCodeToString.put(KM_ERROR_KEY_NOT_YET_VALID, "Key not yet valid"); sErrorCodeToString.put(KM_ERROR_KEY_EXPIRED, "Key expired"); sErrorCodeToString.put(KM_ERROR_KEY_USER_NOT_AUTHENTICATED, "Key user not authenticated"); sErrorCodeToString.put(KM_ERROR_INVALID_OPERATION_HANDLE, "Invalid operation handle"); sErrorCodeToString.put(KM_ERROR_VERIFICATION_FAILED, "Signature/MAC verification failed"); sErrorCodeToString.put(KM_ERROR_TOO_MANY_OPERATIONS, "Too many operations"); sErrorCodeToString.put(KM_ERROR_INVALID_KEY_BLOB, "Invalid key blob"); sErrorCodeToString.put(KM_ERROR_INVALID_ARGUMENT, "Invalid argument"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_TAG, "Unsupported tag"); sErrorCodeToString.put(KM_ERROR_INVALID_TAG, "Invalid tag"); sErrorCodeToString.put(KM_ERROR_MEMORY_ALLOCATION_FAILED, "Memory allocation failed"); sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented"); sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error"); } public static int getTagType(int tag) { return tag & (0xF << 28); } public static String getErrorMessage(int errorCode) { String result = sErrorCodeToString.get(errorCode); if (result != null) { return result; } return String.valueOf(errorCode); } }
keystore/java/android/security/AndroidKeyStoreProvider.java +4 −0 Original line number Diff line number Diff line Loading @@ -35,5 +35,9 @@ public class AndroidKeyStoreProvider extends Provider { // java.security.KeyPairGenerator put("KeyPairGenerator.EC", AndroidKeyPairGenerator.EC.class.getName()); put("KeyPairGenerator.RSA", AndroidKeyPairGenerator.RSA.class.getName()); // javax.crypto.KeyGenerator put("KeyGenerator.AES", KeyStoreKeyGeneratorSpi.AES.class.getName()); put("KeyGenerator.HmacSHA256", KeyStoreKeyGeneratorSpi.HmacSHA256.class.getName()); } }
keystore/java/android/security/CryptoOperationException.java 0 → 100644 +45 −0 Original line number Diff line number Diff line package android.security; /** * Base class for exceptions during cryptographic operations which cannot throw a suitable checked * exception. * * <p>The contract of the majority of crypto primitives/operations (e.g. {@code Cipher} or * {@code Signature}) is that they can throw a checked exception during initialization, but are not * 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 { /** * Constructs a new {@code CryptoOperationException} without detail message and cause. */ public CryptoOperationException() { super(); } /** * Constructs a new {@code CryptoOperationException} with the provided detail message and no * cause. */ public CryptoOperationException(String message) { super(message); } /** * Constructs a new {@code CryptoOperationException} with the provided detail message and cause. */ public CryptoOperationException(String message, Throwable cause) { super(message, cause); } /** * Constructs a new {@code CryptoOperationException} with the provided cause. */ public CryptoOperationException(Throwable cause) { super(cause); } }
keystore/java/android/security/KeyGeneratorSpec.java 0 → 100644 +471 −0 Original line number Diff line number Diff line package android.security; import android.content.Context; import android.text.TextUtils; import java.security.cert.Certificate; import java.security.spec.AlgorithmParameterSpec; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; /** * {@link AlgorithmParameterSpec} for initializing a {@code KeyGenerator} that works with * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>. * * <p>The Android KeyStore facility is accessed through a {@link KeyGenerator} API * using the {@code AndroidKeyStore} provider. The {@code context} passed in may be used to pop up * some UI to ask the user to unlock or initialize the Android KeyStore facility. * * <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} and its associated {@link Certificate} chain. * * @hide */ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private final Context mContext; private final String mKeystoreAlias; private final int mFlags; private final Integer mKeySize; private final Date mKeyValidityStart; private final Date mKeyValidityForOriginationEnd; private final Date mKeyValidityForConsumptionEnd; private final @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; private final @KeyStoreKeyConstraints.PaddingEnum Integer mPadding; private final @KeyStoreKeyConstraints.BlockModeEnum Integer mBlockMode; private final Integer mMinSecondsBetweenOperations; private final Integer mMaxUsesPerBoot; private final Set<Integer> mUserAuthenticators; private final Integer mUserAuthenticationValidityDurationSeconds; private KeyGeneratorSpec( Context context, String keyStoreAlias, int flags, Integer keySize, Date keyValidityStart, Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, @KeyStoreKeyConstraints.PurposeEnum Integer purposes, @KeyStoreKeyConstraints.PaddingEnum Integer padding, @KeyStoreKeyConstraints.BlockModeEnum Integer blockMode, Integer minSecondsBetweenOperations, Integer maxUsesPerBoot, Set<Integer> userAuthenticators, Integer userAuthenticationValidityDurationSeconds) { if (context == null) { throw new IllegalArgumentException("context == null"); } else if (TextUtils.isEmpty(keyStoreAlias)) { throw new IllegalArgumentException("keyStoreAlias must not be empty"); } else if ((userAuthenticationValidityDurationSeconds != null) && (userAuthenticationValidityDurationSeconds < 0)) { throw new IllegalArgumentException( "userAuthenticationValidityDurationSeconds must not be negative"); } mContext = context; mKeystoreAlias = keyStoreAlias; mFlags = flags; mKeySize = keySize; mKeyValidityStart = keyValidityStart; mKeyValidityForOriginationEnd = keyValidityForOriginationEnd; mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd; mPurposes = purposes; mPadding = padding; mBlockMode = blockMode; mMinSecondsBetweenOperations = minSecondsBetweenOperations; mMaxUsesPerBoot = maxUsesPerBoot; mUserAuthenticators = (userAuthenticators != null) ? new HashSet<Integer>(userAuthenticators) : Collections.<Integer>emptySet(); mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; } /** * Gets the Android context used for operations with this instance. */ public Context getContext() { return mContext; } /** * Returns the alias that will be used in the {@code java.security.KeyStore} in conjunction with * the {@code AndroidKeyStore}. */ public String getKeystoreAlias() { return mKeystoreAlias; } /** * @hide */ public int getFlags() { return mFlags; } /** * Gets the requested key size or {@code null} if the default size should be used. */ public Integer getKeySize() { return mKeySize; } /** * Gets the time instant before which the key is not yet valid. * * @return instant or {@code null} if not restricted. */ public Date getKeyValidityStart() { return mKeyValidityStart; } /** * 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; } /** * Gets the time instant after which the key is no long valid for encryption and signing. * * @return instant or {@code null} if not restricted. */ public Date getKeyValidityForOriginationEnd() { return mKeyValidityForOriginationEnd; } /** * Gets the set of purposes for which the key can be used to the provided set of purposes. * * @return set of purposes or {@code null} if the key can be used for any purpose. */ public @KeyStoreKeyConstraints.PurposeEnum Integer getPurposes() { return mPurposes; } /** * Gets the padding scheme to which the key is restricted. * * @return padding scheme or {@code null} if the padding scheme is not restricted. */ public @KeyStoreKeyConstraints.PaddingEnum Integer getPadding() { return mPadding; } /** * Gets the block mode to which the key is restricted when used for encryption or decryption. * * @return block more or {@code null} if block mode is not restricted. * * @hide */ public @KeyStoreKeyConstraints.BlockModeEnum Integer getBlockMode() { return mBlockMode; } /** * Gets the minimum number of seconds that must expire since the most recent use of the key * before it can be used again. * * @return number of seconds or {@code null} if there is no restriction on how frequently a key * can be used. * * @hide */ public Integer getMinSecondsBetweenOperations() { return mMinSecondsBetweenOperations; } /** * Gets the number of times the key can be used without rebooting the device. * * @return maximum number of times or {@code null} if there is no restriction. * @hide */ public Integer getMaxUsesPerBoot() { return mMaxUsesPerBoot; } /** * Gets 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. * * @return user authenticators or empty set if the key can be used without user authentication. * * @hide */ public Set<Integer> getUserAuthenticators() { return new HashSet<Integer>(mUserAuthenticators); } /** * 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. * * @return duration in seconds or {@code null} if not restricted. {@code 0} means authentication * is required for every use of the key. * * @hide */ public Integer getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; } /** * Returns {@code true} if the key must be encrypted in the {@link java.security.KeyStore}. */ public boolean isEncryptionRequired() { return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0; } public static class Builder { private final Context mContext; private String mKeystoreAlias; private int mFlags; private Integer mKeySize; private Date mKeyValidityStart; private Date mKeyValidityForOriginationEnd; private Date mKeyValidityForConsumptionEnd; private @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; private @KeyStoreKeyConstraints.PaddingEnum Integer mPadding; private @KeyStoreKeyConstraints.BlockModeEnum Integer mBlockMode; private Integer mMinSecondsBetweenOperations; private Integer mMaxUsesPerBoot; private Set<Integer> mUserAuthenticators; private Integer mUserAuthenticationValidityDurationSeconds; /** * Creates a new instance of the {@code Builder} with the given {@code context}. The * {@code context} passed in may be used to pop up some UI to ask the user to unlock or * initialize the Android KeyStore facility. */ public Builder(Context context) { if (context == null) { throw new NullPointerException("context == null"); } mContext = context; } /** * Sets the alias to be used to retrieve the key later from a {@link java.security.KeyStore} * instance using the {@code AndroidKeyStore} provider. * * <p>The alias must be provided. There is no default. */ public Builder setAlias(String alias) { if (alias == null) { throw new NullPointerException("alias == null"); } mKeystoreAlias = alias; return this; } /** * Sets the size (in bits) of the key to be generated. * * <p>By default, the key size will be determines based on the key algorithm. For example, * for {@code HmacSHA256}, the key size will default to {@code 256}. */ public Builder setKeySize(int keySize) { mKeySize = keySize; return this; } /** * Indicates that this key must be encrypted at rest on storage. Note that enabling this * will require that the user enable a strong lock screen (e.g., PIN, password) before * creating or using the generated key is successful. */ public Builder setEncryptionRequired(boolean required) { if (required) { mFlags |= KeyStore.FLAG_ENCRYPTED; } else { mFlags &= ~KeyStore.FLAG_ENCRYPTED; } return this; } /** * Sets the time instant before which the key is not yet valid. * * <b>By default, the key is valid at any instant. * * @see #setKeyValidityEnd(Date) * * @hide */ public Builder setKeyValidityStart(Date startDate) { mKeyValidityStart = startDate; return this; } /** * Sets the time instant after which the key is no longer valid. * * <b>By default, the key is valid at any instant. * * @see #setKeyValidityStart(Date) * @see #setKeyValidityForConsumptionEnd(Date) * @see #setKeyValidityForOriginationEnd(Date) * * @hide */ public Builder setKeyValidityEnd(Date endDate) { setKeyValidityForOriginationEnd(endDate); setKeyValidityForConsumptionEnd(endDate); return this; } /** * Sets the time instant after which the key is no longer valid for encryption and signing. * * <b>By default, the key is valid at any instant. * * @see #setKeyValidityForConsumptionEnd(Date) * * @hide */ public Builder setKeyValidityForOriginationEnd(Date endDate) { mKeyValidityForOriginationEnd = endDate; return this; } /** * Sets the time instant after which the key is no longer valid for decryption and * verification. * * <b>By default, the key is valid at any instant. * * @see #setKeyValidityForOriginationEnd(Date) * * @hide */ public Builder setKeyValidityForConsumptionEnd(Date endDate) { mKeyValidityForConsumptionEnd = endDate; return this; } /** * Restricts the purposes for which the key can be used to the provided set of purposes. * * <p>By default, the key can be used for encryption, decryption, signing, and verification. * * @hide */ public Builder setPurposes(@KeyStoreKeyConstraints.PurposeEnum int purposes) { mPurposes = purposes; return this; } /** * Restricts the key to being used only with the provided padding scheme. Attempts to use * the key with any other padding will be rejected. * * <p>This restriction must be specified for keys which are used for encryption/decryption. * * @hide */ public Builder setPadding(@KeyStoreKeyConstraints.PaddingEnum int padding) { mPadding = padding; return this; } /** * Restricts the key to being used only with the provided block mode when encrypting or * decrypting. Attempts to use the key with any other block modes will be rejected. * * <p>This restriction must be specified for keys which are used for encryption/decryption. * * @hide */ public Builder setBlockMode(@KeyStoreKeyConstraints.BlockModeEnum int blockMode) { mBlockMode = blockMode; return this; } /** * Sets the minimum number of seconds that must expire since the most recent use of the key * before it can be used again. * * <p>By default, there is no restriction on how frequently a key can be used. * * @hide */ public Builder setMinSecondsBetweenOperations(int seconds) { mMinSecondsBetweenOperations = seconds; return this; } /** * Sets the maximum number of times a key can be used without rebooting the device. * * <p>By default, the key can be used for an unlimited number of times. * * @hide */ public Builder setMaxUsesPerBoot(int count) { mMaxUsesPerBoot = count; return this; } /** * 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. * * <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. * * @see #setUserAuthenticationValidityDurationSeconds(int) * * @hide */ public Builder setUserAuthenticators(Set<Integer> userAuthenticators) { mUserAuthenticators = (userAuthenticators != null) ? new HashSet<Integer>(userAuthenticators) : null; 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. * * <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(Set) * * @hide */ public Builder setUserAuthenticationValidityDurationSeconds(int seconds) { mUserAuthenticationValidityDurationSeconds = seconds; return this; } /** * Builds a new instance instance of {@code KeyGeneratorSpec}. * * @throws IllegalArgumentException if a required field is missing or violates a constraint. */ public KeyGeneratorSpec build() { return new KeyGeneratorSpec(mContext, mKeystoreAlias, mFlags, mKeySize, mKeyValidityStart, mKeyValidityForOriginationEnd, mKeyValidityForConsumptionEnd, mPurposes, mPadding, mBlockMode, mMinSecondsBetweenOperations, mMaxUsesPerBoot, mUserAuthenticators, mUserAuthenticationValidityDurationSeconds); } } }
keystore/java/android/security/KeyStoreKeyConstraints.java +28 −0 Original line number Diff line number Diff line Loading @@ -290,6 +290,22 @@ public abstract class KeyStoreKeyConstraints { throw new IllegalArgumentException("Unknown padding: " + padding); } } /** * @hide */ public static String toString(@PaddingEnum int padding) { switch (padding) { case NONE: return "NONE"; case ZERO: return "ZERO"; case PKCS7: return "PKCS#7"; default: throw new IllegalArgumentException("Unknown padding: " + padding); } } } @Retention(RetentionPolicy.SOURCE) Loading Loading @@ -425,5 +441,17 @@ public abstract class KeyStoreKeyConstraints { throw new IllegalArgumentException("Unknown block mode: " + mode); } } /** * @hide */ public static String toString(@BlockModeEnum int mode) { switch (mode) { case ECB: return "ECB"; default: throw new IllegalArgumentException("Unknown block mode: " + mode); } } } }