diff options
-rw-r--r-- | keystore/java/android/security/KeyGeneratorSpec.java | 4 | ||||
-rw-r--r-- | keystore/java/android/security/KeyPairGeneratorSpec.java | 436 | ||||
-rw-r--r-- | keystore/java/android/security/KeyStoreParameter.java | 35 |
3 files changed, 458 insertions, 17 deletions
diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java index 02b0816..7058383 100644 --- a/keystore/java/android/security/KeyGeneratorSpec.java +++ b/keystore/java/android/security/KeyGeneratorSpec.java @@ -145,7 +145,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** - * Gets the time instant after which the key is no long valid for decryption and verification. + * Gets the time instant after which the key is no longer valid for decryption and verification. * * @return instant or {@code null} if not restricted. * @@ -156,7 +156,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** - * Gets the time instant after which the key is no long valid for encryption and signing. + * Gets the time instant after which the key is no longer valid for encryption and signing. * * @return instant or {@code null} if not restricted. */ diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java index cc097aa..0001604 100644 --- a/keystore/java/android/security/KeyPairGeneratorSpec.java +++ b/keystore/java/android/security/KeyPairGeneratorSpec.java @@ -24,7 +24,10 @@ import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; 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.security.auth.x500.X500Principal; @@ -72,6 +75,28 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private final int mFlags; + private final Date mKeyValidityStart; + + private final Date mKeyValidityForOriginationEnd; + + private final Date mKeyValidityForConsumptionEnd; + + private final @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; + + private final @KeyStoreKeyConstraints.DigestEnum Integer mDigest; + + 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; + /** * Parameter specification for the "{@code AndroidKeyPairGenerator}" * instance of the {@link java.security.KeyPairGenerator} API. The @@ -106,7 +131,18 @@ 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) { + Date startDate, Date endDate, int flags, + Date keyValidityStart, + Date keyValidityForOriginationEnd, + Date keyValidityForConsumptionEnd, + @KeyStoreKeyConstraints.PurposeEnum Integer purposes, + @KeyStoreKeyConstraints.DigestEnum Integer digest, + @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)) { @@ -121,6 +157,10 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { throw new IllegalArgumentException("endDate == null"); } else if (endDate.before(startDate)) { throw new IllegalArgumentException("endDate < startDate"); + } else if ((userAuthenticationValidityDurationSeconds != null) + && (userAuthenticationValidityDurationSeconds < 0)) { + throw new IllegalArgumentException( + "userAuthenticationValidityDurationSeconds must not be negative"); } mContext = context; @@ -133,6 +173,31 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { mStartDate = startDate; mEndDate = endDate; mFlags = flags; + mKeyValidityStart = keyValidityStart; + mKeyValidityForOriginationEnd = keyValidityForOriginationEnd; + mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd; + mPurposes = purposes; + mDigest = digest; + mPadding = padding; + mBlockMode = blockMode; + mMinSecondsBetweenOperations = minSecondsBetweenOperations; + mMaxUsesPerBoot = maxUsesPerBoot; + mUserAuthenticators = (userAuthenticators != null) + ? new HashSet<Integer>(userAuthenticators) + : Collections.<Integer>emptySet(); + mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; + } + + /** + * TODO: Remove this constructor once tests are switched over to the new one above. + * @hide + */ + 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, keySize, spec, subjectDN, serialNumber, startDate, + endDate, flags, startDate, endDate, endDate, null, null, null, null, null, null, + null, null); } /** @@ -222,6 +287,145 @@ 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; + } + + /** + * Gets the time instant after which the key pair is no longer 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 pair is no longer valid for encryption and signing. + * + * @return instant or {@code null} if not restricted. + * + * @hide + */ + public Date getKeyValidityForOriginationEnd() { + return mKeyValidityForOriginationEnd; + } + + /** + * Gets the set of purposes for which the key can be used. + * + * @return set of purposes or {@code null} if the key can be used for any purpose. + * + * @hide + */ + public @KeyStoreKeyConstraints.PurposeEnum Integer getPurposes() { + return mPurposes; + } + + /** + * Gets the digest to which the key is restricted. + * + * @return digest or {@code null} if the digest is not restricted. + * + * @hide + */ + public @KeyStoreKeyConstraints.DigestEnum Integer getDigest() { + return mDigest; + } + + /** + * Gets the padding scheme to which the key is restricted. + * + * @return padding scheme or {@code null} if the padding scheme is not restricted. + * + * @hide + */ + 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 private + * key before it can be used again. + * + * <p>This restriction applies only to private key operations. Public key operations are not + * restricted. + * + * @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 private key can be used without rebooting the device. + * + * <p>This restriction applies only to private key operations. Public key operations are not + * restricted. + * + * @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 the private key. The key can only be + * used iff the user has authenticated to at least one of these user authenticators. + * + * <p>This restriction applies only to private key operations. Public key operations are not + * restricted. + * + * @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 the private key can be used after the user + * successfully authenticates to one of the associated user authenticators. + * + * <p>This restriction applies only to private key operations. Public key operations are not + * restricted. + * + * @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; + } + + /** * Builder class for {@link KeyPairGeneratorSpec} objects. * <p> * This will build a parameter spec for use with the <a href="{@docRoot} @@ -263,6 +467,28 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private int mFlags; + private Date mKeyValidityStart; + + private Date mKeyValidityForOriginationEnd; + + private Date mKeyValidityForConsumptionEnd; + + private @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; + + private @KeyStoreKeyConstraints.DigestEnum Integer mDigest; + + 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 @@ -389,14 +615,218 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { } /** + * 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 digest. Attempts to use the key + * with any other digests be rejected. + * + * <p>This restriction must be specified for keys which are used for signing/verification. + * + * @hide + */ + public Builder setDigest(@KeyStoreKeyConstraints.DigestEnum int digest) { + mDigest = digest; + 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. + * + * <p>This restriction applies only to private key operations. Public key operations are not + * restricted. + * + * @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. + * + * <p>This restriction applies only to private key operations. Public key operations are not + * restricted. + * + * @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. + * + * <p>This restriction applies only to private key operations. Public key operations are not + * restricted. + * + * @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. + * + * <p>This restriction applies only to private key operations. Public key operations are not + * restricted. + * + * @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 the instance of the {@code KeyPairGeneratorSpec}. * * @throws IllegalArgumentException if a required field is missing * @return built instance of {@code KeyPairGeneratorSpec} */ public KeyPairGeneratorSpec build() { - return new KeyPairGeneratorSpec(mContext, mKeystoreAlias, mKeyType, mKeySize, mSpec, - mSubjectDN, mSerialNumber, mStartDate, mEndDate, mFlags); + return new KeyPairGeneratorSpec(mContext, + mKeystoreAlias, + mKeyType, + mKeySize, + mSpec, + mSubjectDN, + mSerialNumber, + mStartDate, + mEndDate, + mFlags, + mKeyValidityStart, + mKeyValidityForOriginationEnd, + mKeyValidityForConsumptionEnd, + mPurposes, + mDigest, + mPadding, + mBlockMode, + mMinSecondsBetweenOperations, + mMaxUsesPerBoot, + mUserAuthenticators, + mUserAuthenticationValidityDurationSeconds); } } } diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java index b1b638f..88bd6b4 100644 --- a/keystore/java/android/security/KeyStoreParameter.java +++ b/keystore/java/android/security/KeyStoreParameter.java @@ -61,8 +61,10 @@ public final class KeyStoreParameter implements ProtectionParameter { private final Integer mUserAuthenticationValidityDurationSeconds; private final boolean mInvalidatedOnNewFingerprintEnrolled; - private KeyStoreParameter(int flags, Date keyValidityStart, - Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, + private KeyStoreParameter(int flags, + Date keyValidityStart, + Date keyValidityForOriginationEnd, + Date keyValidityForConsumptionEnd, @KeyStoreKeyConstraints.PurposeEnum Integer purposes, @KeyStoreKeyConstraints.AlgorithmEnum Integer algorithm, @KeyStoreKeyConstraints.PaddingEnum Integer padding, @@ -177,8 +179,8 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** - * Gets the digest to which the key is restricted when generating Message Authentication Codes - * (MACs). + * Gets the digest to which the key is restricted when generating signatures or Message + * Authentication Codes (MACs). * * @return digest or {@code null} if the digest is not restricted. * @@ -421,12 +423,13 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** - * Restricts the key to being used only with the provided digest when generating Message - * Authentication Codes (MACs). Attempts to use the key with any other digest will be - * rejected. + * Restricts the key to being used only with the provided digest when generating signatures + * or Message Authentication Codes (MACs). Attempts to use the key with any other digest + * will be rejected. * * <p>For MAC keys, the default is to restrict to the digest specified in the key algorithm - * name. + * name. For asymmetric signing keys this constraint must be specified because there is no + * default. * * @see java.security.Key#getAlgorithm() * @@ -535,10 +538,18 @@ public final class KeyStoreParameter implements ProtectionParameter { * @return built instance of {@code KeyStoreParameter} */ public KeyStoreParameter build() { - return new KeyStoreParameter(mFlags, mKeyValidityStart, - mKeyValidityForOriginationEnd, mKeyValidityForConsumptionEnd, mPurposes, - mAlgorithm, mPadding, mDigest, mBlockMode, mMinSecondsBetweenOperations, - mMaxUsesPerBoot, mUserAuthenticators, + return new KeyStoreParameter(mFlags, + mKeyValidityStart, + mKeyValidityForOriginationEnd, + mKeyValidityForConsumptionEnd, + mPurposes, + mAlgorithm, + mPadding, + mDigest, + mBlockMode, + mMinSecondsBetweenOperations, + mMaxUsesPerBoot, + mUserAuthenticators, mUserAuthenticationValidityDurationSeconds, mInvalidatedOnNewFingerprintEnrolled); } |