diff options
9 files changed, 475 insertions, 700 deletions
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index e94a312..5e2accd 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -171,6 +171,10 @@ public final class KeymasterDefs { public static final int KM_KEY_FORMAT_PKCS12 = 2; public static final int KM_KEY_FORMAT_RAW = 3; + // User authenticators. + public static final int HW_AUTH_PASSWORD = 1 << 0; + public static final int HW_AUTH_FINGERPRINT = 1 << 1; + // Error codes. public static final int KM_ERROR_OK = 0; public static final int KM_ERROR_ROOT_OF_TRUST_ALREADY_SET = -1; diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java index 0bd1dbd..ed690de 100644 --- a/keystore/java/android/security/AndroidKeyStore.java +++ b/keystore/java/android/security/AndroidKeyStore.java @@ -466,74 +466,65 @@ public class AndroidKeyStore extends KeyStoreSpi { throw new KeyStoreException("Unsupported secret key algorithm: " + keyAlgorithmString); } - if ((params.getAlgorithm() != null) && (params.getAlgorithm() != keyAlgorithm)) { - throw new KeyStoreException("Key algorithm mismatch. Key: " + keyAlgorithmString - + ", parameter spec: " - + KeyStoreKeyConstraints.Algorithm.toString(params.getAlgorithm())); - } - KeymasterArguments args = new KeymasterArguments(); args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeyStoreKeyConstraints.Algorithm.toKeymaster(keyAlgorithm)); - if (digest != null) { - // Digest available from JCA key algorithm - if (params.getDigest() != null) { - // Digest also specified in parameters -- check that these two match - if (digest != params.getDigest()) { - throw new KeyStoreException("Key digest mismatch. Key: " + keyAlgorithmString + @KeyStoreKeyConstraints.DigestEnum int digests; + if (params.isDigestsSpecified()) { + // Digest(s) specified in parameters + if (digest != null) { + // Digest also specified in the JCA key algorithm name. + if ((params.getDigests() & digest) != digest) { + throw new KeyStoreException("Key digest mismatch" + + ". Key: " + keyAlgorithmString + ", parameter spec: " - + KeyStoreKeyConstraints.Digest.toString(params.getDigest())); + + KeyStoreKeyConstraints.Digest.allToString(params.getDigests())); } } + digests = params.getDigests(); } else { - // Digest not available from JCA key algorithm - digest = params.getDigest(); + // No digest specified in parameters + if (digest != null) { + // Digest specified in the JCA key algorithm name. + digests = digest; + } else { + digests = 0; + } } - if (digest != null) { - args.addInt(KeymasterDefs.KM_TAG_DIGEST, - KeyStoreKeyConstraints.Digest.toKeymaster(digest)); + for (int keymasterDigest : KeyStoreKeyConstraints.Digest.allToKeymaster(digests)) { + args.addInt(KeymasterDefs.KM_TAG_DIGEST, keymasterDigest); + } + if (digests != 0) { + // TODO: Remove MAC length constraint once Keymaster API no longer requires it. + // This code will blow up if mode than one digest is specified. Integer digestOutputSizeBytes = KeyStoreKeyConstraints.Digest.getOutputSizeBytes(digest); if (digestOutputSizeBytes != null) { - // TODO: Remove MAC length constraint once Keymaster API no longer requires it. // TODO: Switch to bits instead of bytes, once this is fixed in Keymaster args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, digestOutputSizeBytes); } } if (keyAlgorithm == KeyStoreKeyConstraints.Algorithm.HMAC) { - if (digest == null) { - throw new IllegalStateException("Digest algorithm must be specified for key" - + " algorithm " + keyAlgorithmString); + if (digests == 0) { + throw new KeyStoreException("At least one digest algorithm must be specified" + + " for key algorithm " + keyAlgorithmString); } } - @KeyStoreKeyConstraints.PurposeEnum int purposes = (params.getPurposes() != null) - ? params.getPurposes() - : (KeyStoreKeyConstraints.Purpose.ENCRYPT - | KeyStoreKeyConstraints.Purpose.DECRYPT - | KeyStoreKeyConstraints.Purpose.SIGN - | KeyStoreKeyConstraints.Purpose.VERIFY); - for (int keymasterPurpose : - KeyStoreKeyConstraints.Purpose.allToKeymaster(purposes)) { + int purposes = params.getPurposes(); + for (int keymasterPurpose : KeyStoreKeyConstraints.Purpose.allToKeymaster(purposes)) { args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose); } - if (params.getBlockMode() != null) { - args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, - KeyStoreKeyConstraints.BlockMode.toKeymaster(params.getBlockMode())); - } - if (params.getPadding() != null) { - args.addInt(KeymasterDefs.KM_TAG_PADDING, - KeyStoreKeyConstraints.Padding.toKeymaster(params.getPadding())); - } - if (params.getMaxUsesPerBoot() != null) { - args.addInt(KeymasterDefs.KM_TAG_MAX_USES_PER_BOOT, params.getMaxUsesPerBoot()); + for (int keymasterBlockMode : + KeyStoreKeyConstraints.BlockMode.allToKeymaster(params.getBlockModes())) { + args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockMode); } - if (params.getMinSecondsBetweenOperations() != null) { - args.addInt(KeymasterDefs.KM_TAG_MIN_SECONDS_BETWEEN_OPS, - params.getMinSecondsBetweenOperations()); + for (int keymasterPadding : + KeyStoreKeyConstraints.Padding.allToKeymaster(params.getPaddings())) { + args.addInt(KeymasterDefs.KM_TAG_PADDING, keymasterPadding); } - if (params.getUserAuthenticators().isEmpty()) { + if (params.getUserAuthenticators() == 0) { args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); } else { args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, @@ -544,7 +535,7 @@ public class AndroidKeyStore extends KeyStoreSpi { // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports // that. } - if (params.getUserAuthenticationValidityDurationSeconds() != null) { + if (params.getUserAuthenticationValidityDurationSeconds() != -1) { 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 7058383..0e490cd 100644 --- a/keystore/java/android/security/KeyGeneratorSpec.java +++ b/keystore/java/android/security/KeyGeneratorSpec.java @@ -19,12 +19,8 @@ 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; @@ -33,13 +29,13 @@ 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>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. + * interface to retrieve the {@link SecretKey}. * * @hide */ @@ -52,13 +48,11 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { 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 final @KeyStoreKeyConstraints.PurposeEnum int mPurposes; + private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings; + private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes; + private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators; + private final int mUserAuthenticationValidityDurationSeconds; private final boolean mInvalidatedOnNewFingerprintEnrolled; private KeyGeneratorSpec( @@ -69,20 +63,18 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { 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, + @KeyStoreKeyConstraints.PurposeEnum int purposes, + @KeyStoreKeyConstraints.PaddingEnum int paddings, + @KeyStoreKeyConstraints.BlockModeEnum int blockModes, + @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators, + int userAuthenticationValidityDurationSeconds, boolean invalidatedOnNewFingerprintEnrolled) { 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)) { + } else if ((userAuthenticationValidityDurationSeconds < 0) + && (userAuthenticationValidityDurationSeconds != -1)) { throw new IllegalArgumentException( "userAuthenticationValidityDurationSeconds must not be negative"); } @@ -95,13 +87,9 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { mKeyValidityForOriginationEnd = keyValidityForOriginationEnd; mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd; mPurposes = purposes; - mPadding = padding; - mBlockMode = blockMode; - mMinSecondsBetweenOperations = minSecondsBetweenOperations; - mMaxUsesPerBoot = maxUsesPerBoot; - mUserAuthenticators = (userAuthenticators != null) - ? new HashSet<Integer>(userAuthenticators) - : Collections.<Integer>emptySet(); + mPaddings = paddings; + mBlockModes = blockModes; + mUserAuthenticators = userAuthenticators; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } @@ -148,8 +136,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * Gets the time instant after which the key is no longer valid for decryption and verification. * * @return instant or {@code null} if not restricted. - * - * @hide */ public Date getKeyValidityForConsumptionEnd() { return mKeyValidityForConsumptionEnd; @@ -166,78 +152,43 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { /** * 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. */ - public @KeyStoreKeyConstraints.PurposeEnum Integer getPurposes() { + public @KeyStoreKeyConstraints.PurposeEnum int 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 + * Gets the set of padding schemes to which the key is restricted. */ - public Integer getMinSecondsBetweenOperations() { - return mMinSecondsBetweenOperations; + public @KeyStoreKeyConstraints.PaddingEnum int getPaddings() { + return mPaddings; } /** - * 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 + * Gets the set of block modes to which the key is restricted. */ - public Integer getMaxUsesPerBoot() { - return mMaxUsesPerBoot; + public @KeyStoreKeyConstraints.BlockModeEnum int getBlockModes() { + return mBlockModes; } /** - * 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. + * Gets the set of 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. * - * @hide + * @return user authenticators or {@code 0} if the key can be used without user authentication. */ - public Set<Integer> getUserAuthenticators() { - return new HashSet<Integer>(mUserAuthenticators); + public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getUserAuthenticators() { + return 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 + * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. - * - * @hide */ - public Integer getUserAuthenticationValidityDurationSeconds() { + public int getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; } @@ -269,13 +220,11 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { 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; + private @KeyStoreKeyConstraints.PurposeEnum int mPurposes; + private @KeyStoreKeyConstraints.PaddingEnum int mPaddings; + private @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes; + private @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators; + private int mUserAuthenticationValidityDurationSeconds = -1; private boolean mInvalidatedOnNewFingerprintEnrolled; /** @@ -335,8 +284,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * <b>By default, the key is valid at any instant. * * @see #setKeyValidityEnd(Date) - * - * @hide */ public Builder setKeyValidityStart(Date startDate) { mKeyValidityStart = startDate; @@ -351,8 +298,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * @see #setKeyValidityStart(Date) * @see #setKeyValidityForConsumptionEnd(Date) * @see #setKeyValidityForOriginationEnd(Date) - * - * @hide */ public Builder setKeyValidityEnd(Date endDate) { setKeyValidityForOriginationEnd(endDate); @@ -366,8 +311,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * <b>By default, the key is valid at any instant. * * @see #setKeyValidityForConsumptionEnd(Date) - * - * @hide */ public Builder setKeyValidityForOriginationEnd(Date endDate) { mKeyValidityForOriginationEnd = endDate; @@ -381,8 +324,6 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * <b>By default, the key is valid at any instant. * * @see #setKeyValidityForOriginationEnd(Date) - * - * @hide */ public Builder setKeyValidityForConsumptionEnd(Date endDate) { mKeyValidityForConsumptionEnd = endDate; @@ -390,11 +331,9 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** - * Restricts the purposes for which the key can be used to the provided set of purposes. + * Restricts the key to being used only for the provided set of purposes. * - * <p>By default, the key can be used for encryption, decryption, signing, and verification. - * - * @hide + * <p>This restriction must be specified. There is no default. */ public Builder setPurposes(@KeyStoreKeyConstraints.PurposeEnum int purposes) { mPurposes = purposes; @@ -402,53 +341,24 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { } /** - * Restricts the key to being used only with the provided padding scheme. Attempts to use + * Restricts the key to being used only with the provided padding schemes. 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; + public Builder setPaddings(@KeyStoreKeyConstraints.PaddingEnum int paddings) { + mPaddings = paddings; 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. + * Restricts the key to being used only with the provided block modes. 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; + public Builder setBlockModes(@KeyStoreKeyConstraints.BlockModeEnum int blockModes) { + mBlockModes = blockModes; return this; } @@ -462,12 +372,10 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * without user authentication. * * @see #setUserAuthenticationValidityDurationSeconds(int) - * - * @hide */ - public Builder setUserAuthenticators(Set<Integer> userAuthenticators) { - mUserAuthenticators = - (userAuthenticators != null) ? new HashSet<Integer>(userAuthenticators) : null; + public Builder setUserAuthenticators( + @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators) { + mUserAuthenticators = userAuthenticators; return this; } @@ -480,9 +388,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for * every use of the key. * - * @see #setUserAuthenticators(Set) - * - * @hide + * @see #setUserAuthenticators(int) */ public Builder setUserAuthenticationValidityDurationSeconds(int seconds) { mUserAuthenticationValidityDurationSeconds = seconds; @@ -511,10 +417,18 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * @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, + return new KeyGeneratorSpec(mContext, + mKeystoreAlias, + mFlags, + mKeySize, + mKeyValidityStart, + mKeyValidityForOriginationEnd, + mKeyValidityForConsumptionEnd, + mPurposes, + mPaddings, + mBlockModes, + mUserAuthenticators, + mUserAuthenticationValidityDurationSeconds, mInvalidatedOnNewFingerprintEnrolled); } } diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java index dd62e9a..52b7097 100644 --- a/keystore/java/android/security/KeyPairGeneratorSpec.java +++ b/keystore/java/android/security/KeyPairGeneratorSpec.java @@ -24,10 +24,7 @@ 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; @@ -81,21 +78,17 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private final Date mKeyValidityForConsumptionEnd; - private final @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; + private final @KeyStoreKeyConstraints.PurposeEnum int mPurposes; - private final @KeyStoreKeyConstraints.DigestEnum Integer mDigest; + private final @KeyStoreKeyConstraints.DigestEnum int mDigests; - private final @KeyStoreKeyConstraints.PaddingEnum Integer mPadding; + private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings; - private final @KeyStoreKeyConstraints.BlockModeEnum Integer mBlockMode; + private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes; - private final Integer mMinSecondsBetweenOperations; + private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators; - private final Integer mMaxUsesPerBoot; - - private final Set<Integer> mUserAuthenticators; - - private final Integer mUserAuthenticationValidityDurationSeconds; + private final int mUserAuthenticationValidityDurationSeconds; private final boolean mInvalidatedOnNewFingerprintEnrolled; @@ -137,14 +130,12 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { 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, + @KeyStoreKeyConstraints.PurposeEnum int purposes, + @KeyStoreKeyConstraints.DigestEnum int digests, + @KeyStoreKeyConstraints.PaddingEnum int paddings, + @KeyStoreKeyConstraints.BlockModeEnum int blockModes, + @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators, + int userAuthenticationValidityDurationSeconds, boolean invalidatedOnNewFingerprintEnrolled) { if (context == null) { throw new IllegalArgumentException("context == null"); @@ -160,8 +151,8 @@ 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)) { + } else if ((userAuthenticationValidityDurationSeconds < 0) + && (userAuthenticationValidityDurationSeconds != -1)) { throw new IllegalArgumentException( "userAuthenticationValidityDurationSeconds must not be negative"); } @@ -180,14 +171,10 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { 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(); + mDigests = digests; + mPaddings = paddings; + mBlockModes = blockModes; + mUserAuthenticators = userAuthenticators; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } @@ -200,8 +187,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { 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, false); + endDate, flags, startDate, endDate, endDate, 0, 0, 0, 0, 0, -1, false); } /** @@ -327,90 +313,52 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * 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() { + public @KeyStoreKeyConstraints.PurposeEnum int 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. + * Gets the set of digests to which the key is restricted. * * @hide */ - public @KeyStoreKeyConstraints.BlockModeEnum Integer getBlockMode() { - return mBlockMode; + public @KeyStoreKeyConstraints.DigestEnum int getDigests() { + return mDigests; } /** - * 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. + * Gets the set of padding schemes to which the key is restricted. * * @hide */ - public Integer getMinSecondsBetweenOperations() { - return mMinSecondsBetweenOperations; + public @KeyStoreKeyConstraints.PaddingEnum int getPaddings() { + return mPaddings; } /** - * 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. + * Gets the set of block modes to which the key is restricted. * * @hide */ - public Integer getMaxUsesPerBoot() { - return mMaxUsesPerBoot; + public @KeyStoreKeyConstraints.BlockModeEnum int getBlockModes() { + return mBlockModes; } /** - * 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. + * Gets the set of 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. + * @return user authenticators or {@code 0} if the key can be used without user authentication. * * @hide */ - public Set<Integer> getUserAuthenticators() { - return new HashSet<Integer>(mUserAuthenticators); + public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getUserAuthenticators() { + return mUserAuthenticators; } /** @@ -420,12 +368,12 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * <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 + * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. * * @hide */ - public Integer getUserAuthenticationValidityDurationSeconds() { + public int getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; } @@ -490,21 +438,17 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private Date mKeyValidityForConsumptionEnd; - private @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; + private @KeyStoreKeyConstraints.PurposeEnum int mPurposes; - private @KeyStoreKeyConstraints.DigestEnum Integer mDigest; + private @KeyStoreKeyConstraints.DigestEnum int mDigests; - private @KeyStoreKeyConstraints.PaddingEnum Integer mPadding; + private @KeyStoreKeyConstraints.PaddingEnum int mPaddings; - private @KeyStoreKeyConstraints.BlockModeEnum Integer mBlockMode; + private @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes; - private Integer mMinSecondsBetweenOperations; + private @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators; - private Integer mMaxUsesPerBoot; - - private Set<Integer> mUserAuthenticators; - - private Integer mUserAuthenticationValidityDurationSeconds; + private int mUserAuthenticationValidityDurationSeconds = -1; private boolean mInvalidatedOnNewFingerprintEnrolled; @@ -694,9 +638,9 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { } /** - * Restricts the purposes for which the key can be used to the provided set of purposes. + * Restricts the key to being used only for the provided set of purposes. * - * <p>By default, the key can be used for encryption, decryption, signing, and verification. + * <p>This restriction must be specified. There is no default. * * @hide */ @@ -706,28 +650,28 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { } /** - * Restricts the key to being used only with the provided digest. Attempts to use the key + * Restricts the key to being used only with the provided digests. 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; + public Builder setDigests(@KeyStoreKeyConstraints.DigestEnum int digests) { + mDigests = digests; return this; } /** - * Restricts the key to being used only with the provided padding scheme. Attempts to use + * Restricts the key to being used only with the provided padding schemes. 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; + public Builder setPaddings(@KeyStoreKeyConstraints.PaddingEnum int paddings) { + mPaddings = paddings; return this; } @@ -739,39 +683,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * * @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; + public Builder setBlockModes(@KeyStoreKeyConstraints.BlockModeEnum int blockModes) { + mBlockModes = blockModes; return this; } @@ -784,16 +697,16 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * <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 + * @param userAuthenticators user authenticators or {@code 0} 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; + public Builder setUserAuthenticators( + @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators) { + mUserAuthenticators = userAuthenticators; return this; } @@ -809,7 +722,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for * every use of the key. * - * @see #setUserAuthenticators(Set) + * @see #setUserAuthenticators(int) * * @hide */ @@ -855,11 +768,9 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { mKeyValidityForOriginationEnd, mKeyValidityForConsumptionEnd, mPurposes, - mDigest, - mPadding, - mBlockMode, - mMinSecondsBetweenOperations, - mMaxUsesPerBoot, + mDigests, + mPaddings, + mBlockModes, mUserAuthenticators, mUserAuthenticationValidityDurationSeconds, mInvalidatedOnNewFingerprintEnrolled); diff --git a/keystore/java/android/security/KeyStoreKeyConstraints.java b/keystore/java/android/security/KeyStoreKeyConstraints.java index 75034d1..7137a9a 100644 --- a/keystore/java/android/security/KeyStoreKeyConstraints.java +++ b/keystore/java/android/security/KeyStoreKeyConstraints.java @@ -21,12 +21,8 @@ import android.security.keymaster.KeymasterDefs; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; import java.util.Locale; -import java.util.Set; /** * Constraints for {@code AndroidKeyStore} keys. @@ -37,7 +33,8 @@ public abstract class KeyStoreKeyConstraints { private KeyStoreKeyConstraints() {} @Retention(RetentionPolicy.SOURCE) - @IntDef(flag=true, value={Purpose.ENCRYPT, Purpose.DECRYPT, Purpose.SIGN, Purpose.VERIFY}) + @IntDef(flag = true, + value = {Purpose.ENCRYPT, Purpose.DECRYPT, Purpose.SIGN, Purpose.VERIFY}) public @interface PurposeEnum {} /** @@ -67,11 +64,6 @@ public abstract class KeyStoreKeyConstraints { public static final int VERIFY = 1 << 3; /** - * Number of flags defined above. Needs to be kept in sync with the flags above. - */ - private static final int VALUE_COUNT = 4; - - /** * @hide */ public static int toKeymaster(@PurposeEnum int purpose) { @@ -110,22 +102,12 @@ public abstract class KeyStoreKeyConstraints { /** * @hide */ - public static int[] allToKeymaster(int purposes) { - int[] result = new int[VALUE_COUNT]; - int resultCount = 0; - int purpose = 1; - for (int i = 0; i < 32; i++) { - if ((purposes & 1) != 0) { - result[resultCount] = toKeymaster(purpose); - resultCount++; - } - purposes >>>= 1; - purpose <<= 1; - if (purposes == 0) { - break; - } + public static int[] allToKeymaster(@PurposeEnum int purposes) { + int[] result = getSetFlags(purposes); + for (int i = 0; i < result.length; i++) { + result[i] = toKeymaster(result[i]); } - return Arrays.copyOf(result, resultCount); + return result; } /** @@ -244,7 +226,8 @@ public abstract class KeyStoreKeyConstraints { } @Retention(RetentionPolicy.SOURCE) - @IntDef({Padding.NONE, Padding.ZERO, Padding.PKCS7}) + @IntDef(flag = true, + value = {Padding.NONE, Padding.PKCS7}) public @interface PaddingEnum {} /** @@ -256,17 +239,12 @@ public abstract class KeyStoreKeyConstraints { /** * No padding. */ - public static final int NONE = 0; - - /** - * Pad with zeros. - */ - public static final int ZERO = 1; + public static final int NONE = 1 << 0; /** * PKCS#7 padding. */ - public static final int PKCS7 = 2; + public static final int PKCS7 = 1 << 1; /** * @hide @@ -275,8 +253,6 @@ public abstract class KeyStoreKeyConstraints { switch (padding) { case NONE: return KeymasterDefs.KM_PAD_NONE; - case ZERO: - return KeymasterDefs.KM_PAD_ZERO; case PKCS7: return KeymasterDefs.KM_PAD_PKCS7; default: @@ -291,8 +267,6 @@ public abstract class KeyStoreKeyConstraints { switch (padding) { case KeymasterDefs.KM_PAD_NONE: return NONE; - case KeymasterDefs.KM_PAD_ZERO: - return ZERO; case KeymasterDefs.KM_PAD_PKCS7: return PKCS7; default: @@ -307,8 +281,6 @@ public abstract class KeyStoreKeyConstraints { switch (padding) { case NONE: return "NONE"; - case ZERO: - return "ZERO"; case PKCS7: return "PKCS#7"; default: @@ -329,10 +301,33 @@ public abstract class KeyStoreKeyConstraints { throw new IllegalArgumentException("Unknown padding: " + padding); } } + + /** + * @hide + */ + public static int[] allToKeymaster(@PaddingEnum int paddings) { + int[] result = getSetFlags(paddings); + for (int i = 0; i < result.length; i++) { + result[i] = toKeymaster(result[i]); + } + return result; + } + + /** + * @hide + */ + public static @PaddingEnum int allFromKeymaster(Collection<Integer> paddings) { + @PaddingEnum int result = 0; + for (int keymasterPadding : paddings) { + result |= fromKeymaster(keymasterPadding); + } + return result; + } } @Retention(RetentionPolicy.SOURCE) - @IntDef({Digest.NONE, Digest.SHA256}) + @IntDef(flag = true, + value = {Digest.NONE, Digest.SHA256}) public @interface DigestEnum {} /** @@ -345,12 +340,12 @@ public abstract class KeyStoreKeyConstraints { /** * No digest: sign/authenticate the raw message. */ - public static final int NONE = 0; + public static final int NONE = 1 << 0; /** * SHA-256 digest. */ - public static final int SHA256 = 1; + public static final int SHA256 = 1 << 1; /** * @hide @@ -369,6 +364,18 @@ public abstract class KeyStoreKeyConstraints { /** * @hide */ + public static String[] allToString(@DigestEnum int digests) { + int[] values = getSetFlags(digests); + String[] result = new String[values.length]; + for (int i = 0; i < values.length; i++) { + result[i] = toString(values[i]); + } + return result; + } + + /** + * @hide + */ public static int toKeymaster(@DigestEnum int digest) { switch (digest) { case NONE: @@ -397,6 +404,28 @@ public abstract class KeyStoreKeyConstraints { /** * @hide */ + public static int[] allToKeymaster(@DigestEnum int digests) { + int[] result = getSetFlags(digests); + for (int i = 0; i < result.length; i++) { + result[i] = toKeymaster(result[i]); + } + return result; + } + + /** + * @hide + */ + public static @DigestEnum int allFromKeymaster(Collection<Integer> digests) { + @DigestEnum int result = 0; + for (int keymasterDigest : digests) { + result |= fromKeymaster(keymasterDigest); + } + return result; + } + + /** + * @hide + */ public static @DigestEnum Integer fromJCASecretKeyAlgorithm(String algorithm) { String algorithmLower = algorithm.toLowerCase(Locale.US); if (algorithmLower.startsWith("hmac")) { @@ -441,7 +470,8 @@ public abstract class KeyStoreKeyConstraints { } @Retention(RetentionPolicy.SOURCE) - @IntDef({BlockMode.ECB, BlockMode.CBC, BlockMode.CTR}) + @IntDef(flag = true, + value = {BlockMode.ECB, BlockMode.CBC, BlockMode.CTR}) public @interface BlockModeEnum {} /** @@ -451,13 +481,13 @@ public abstract class KeyStoreKeyConstraints { private BlockMode() {} /** Electronic Codebook (ECB) block mode. */ - public static final int ECB = 0; + public static final int ECB = 1 << 0; /** Cipher Block Chaining (CBC) block mode. */ - public static final int CBC = 1; + public static final int CBC = 1 << 1; /** Counter (CTR) block mode. */ - public static final int CTR = 2; + public static final int CTR = 1 << 2; /** * @hide @@ -494,6 +524,28 @@ public abstract class KeyStoreKeyConstraints { /** * @hide */ + public static int[] allToKeymaster(@BlockModeEnum int modes) { + int[] result = getSetFlags(modes); + for (int i = 0; i < result.length; i++) { + result[i] = toKeymaster(result[i]); + } + return result; + } + + /** + * @hide + */ + public static @BlockModeEnum int allFromKeymaster(Collection<Integer> modes) { + @BlockModeEnum int result = 0; + for (int keymasterMode : modes) { + result |= fromKeymaster(keymasterMode); + } + return result; + } + + /** + * @hide + */ public static String toString(@BlockModeEnum int mode) { switch (mode) { case ECB: @@ -525,7 +577,8 @@ public abstract class KeyStoreKeyConstraints { } @Retention(RetentionPolicy.SOURCE) - @IntDef({UserAuthenticator.LOCK_SCREEN}) + @IntDef(flag = true, + value = {UserAuthenticator.LOCK_SCREEN}) public @interface UserAuthenticatorEnum {} /** @@ -535,7 +588,7 @@ public abstract class KeyStoreKeyConstraints { private UserAuthenticator() {} /** Lock screen. */ - public static final int LOCK_SCREEN = 1; + public static final int LOCK_SCREEN = 1 << 0; /** Fingerprint reader/sensor. */ public static final int FINGERPRINT_READER = 1 << 1; @@ -546,9 +599,9 @@ public abstract class KeyStoreKeyConstraints { public static int toKeymaster(@UserAuthenticatorEnum int userAuthenticator) { switch (userAuthenticator) { case LOCK_SCREEN: - return LOCK_SCREEN; + return KeymasterDefs.HW_AUTH_PASSWORD; case FINGERPRINT_READER: - return FINGERPRINT_READER; + return KeymasterDefs.HW_AUTH_FINGERPRINT; default: throw new IllegalArgumentException( "Unknown user authenticator: " + userAuthenticator); @@ -560,7 +613,7 @@ public abstract class KeyStoreKeyConstraints { */ public static @UserAuthenticatorEnum int fromKeymaster(int userAuthenticator) { switch (userAuthenticator) { - case LOCK_SCREEN: + case KeymasterDefs.HW_AUTH_PASSWORD: return LOCK_SCREEN; case FINGERPRINT_READER: return FINGERPRINT_READER; @@ -573,10 +626,15 @@ public abstract class KeyStoreKeyConstraints { /** * @hide */ - public static int allToKeymaster(Set<Integer> userAuthenticators) { + public static int allToKeymaster(@UserAuthenticatorEnum int userAuthenticators) { int result = 0; - for (@UserAuthenticatorEnum int userAuthenticator : userAuthenticators) { - result |= toKeymaster(userAuthenticator); + int userAuthenticator = 1; + while (userAuthenticators != 0) { + if ((userAuthenticators & 1) != 0) { + result |= toKeymaster(userAuthenticator); + } + userAuthenticators >>>= 1; + userAuthenticator <<= 1; } return result; } @@ -584,20 +642,17 @@ public abstract class KeyStoreKeyConstraints { /** * @hide */ - public static Set<Integer> allFromKeymaster(int userAuthenticators) { + public static @UserAuthenticatorEnum int allFromKeymaster(int userAuthenticators) { + @UserAuthenticatorEnum int result = 0; int userAuthenticator = 1; - Set<Integer> result = null; while (userAuthenticators != 0) { if ((userAuthenticators & 1) != 0) { - if (result == null) { - result = new HashSet<Integer>(); - } - result.add(fromKeymaster(userAuthenticator)); + result |= fromKeymaster(userAuthenticator); } userAuthenticators >>>= 1; userAuthenticator <<= 1; } - return (result != null) ? result : Collections.<Integer>emptySet(); + return result; } /** @@ -615,4 +670,38 @@ public abstract class KeyStoreKeyConstraints { } } } + + private static final int[] EMPTY_INT_ARRAY = new int[0]; + + private static int[] getSetFlags(int flags) { + if (flags == 0) { + return EMPTY_INT_ARRAY; + } + int result[] = new int[getSetBitCount(flags)]; + int resultOffset = 0; + int flag = 1; + while (flags != 0) { + if ((flags & 1) != 0) { + result[resultOffset] = flag; + resultOffset++; + } + flags >>>= 1; + flag <<= 1; + } + return result; + } + + private static int getSetBitCount(int value) { + if (value == 0) { + return 0; + } + int result = 0; + while (value != 0) { + if ((value & 1) != 0) { + result++; + } + value >>>= 1; + } + return result; + } } diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java index 48b6d06..abce32d 100644 --- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java @@ -109,32 +109,20 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { } int keySizeBits = (spec.getKeySize() != null) ? spec.getKeySize() : mDefaultKeySizeBits; args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keySizeBits); - @KeyStoreKeyConstraints.PurposeEnum int purposes = (spec.getPurposes() != null) - ? spec.getPurposes() - : (KeyStoreKeyConstraints.Purpose.ENCRYPT - | KeyStoreKeyConstraints.Purpose.DECRYPT - | KeyStoreKeyConstraints.Purpose.SIGN - | KeyStoreKeyConstraints.Purpose.VERIFY); + int purposes = spec.getPurposes(); for (int keymasterPurpose : KeyStoreKeyConstraints.Purpose.allToKeymaster(purposes)) { args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose); } - if (spec.getBlockMode() != null) { - args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, - KeyStoreKeyConstraints.BlockMode.toKeymaster(spec.getBlockMode())); + for (int keymasterBlockMode : + KeyStoreKeyConstraints.BlockMode.allToKeymaster(spec.getBlockModes())) { + args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockMode); } - if (spec.getPadding() != null) { - args.addInt(KeymasterDefs.KM_TAG_PADDING, - KeyStoreKeyConstraints.Padding.toKeymaster(spec.getPadding())); + for (int keymasterPadding : + KeyStoreKeyConstraints.Padding.allToKeymaster(spec.getPaddings())) { + args.addInt(KeymasterDefs.KM_TAG_PADDING, keymasterPadding); } - if (spec.getMaxUsesPerBoot() != null) { - args.addInt(KeymasterDefs.KM_TAG_MAX_USES_PER_BOOT, spec.getMaxUsesPerBoot()); - } - if (spec.getMinSecondsBetweenOperations() != null) { - args.addInt(KeymasterDefs.KM_TAG_MIN_SECONDS_BETWEEN_OPS, - spec.getMinSecondsBetweenOperations()); - } - if (spec.getUserAuthenticators().isEmpty()) { + if (spec.getUserAuthenticators() == 0) { args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); } else { args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, @@ -145,7 +133,7 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports // that. } - if (spec.getUserAuthenticationValidityDurationSeconds() != null) { + if (spec.getUserAuthenticationValidityDurationSeconds() != -1) { 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 e5e5acc..256d9b3 100644 --- a/keystore/java/android/security/KeyStoreKeySpec.java +++ b/keystore/java/android/security/KeyStoreKeySpec.java @@ -17,10 +17,7 @@ package android.security; import java.security.spec.KeySpec; -import java.util.Collections; import java.util.Date; -import java.util.HashSet; -import java.util.Set; /** * Information about a key from the <a href="{@docRoot}training/articles/keystore.html">Android @@ -37,34 +34,31 @@ public class KeyStoreKeySpec implements KeySpec { private final Date mKeyValidityForConsumptionEnd; private final @KeyStoreKeyConstraints.PurposeEnum int mPurposes; private final @KeyStoreKeyConstraints.AlgorithmEnum int mAlgorithm; - private final @KeyStoreKeyConstraints.PaddingEnum Integer mPadding; - private final @KeyStoreKeyConstraints.DigestEnum Integer mDigest; - private final @KeyStoreKeyConstraints.BlockModeEnum Integer mBlockMode; - private final Integer mMinSecondsBetweenOperations; - private final Integer mMaxUsesPerBoot; - private final Set<Integer> mUserAuthenticators; - private final Set<Integer> mTeeBackedUserAuthenticators; - private final Integer mUserAuthenticationValidityDurationSeconds; + private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings; + private final @KeyStoreKeyConstraints.DigestEnum int mDigests; + private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes; + private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators; + private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mTeeEnforcedUserAuthenticators; + private final int mUserAuthenticationValidityDurationSeconds; private final boolean mInvalidatedOnNewFingerprintEnrolled; - /** * @hide */ KeyStoreKeySpec(String keystoreKeyAlias, @KeyStoreKeyCharacteristics.OriginEnum int origin, - int keySize, Date keyValidityStart, Date keyValidityForOriginationEnd, + int keySize, + Date keyValidityStart, + Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, @KeyStoreKeyConstraints.PurposeEnum int purposes, @KeyStoreKeyConstraints.AlgorithmEnum int algorithm, - @KeyStoreKeyConstraints.PaddingEnum Integer padding, - @KeyStoreKeyConstraints.DigestEnum Integer digest, - @KeyStoreKeyConstraints.BlockModeEnum Integer blockMode, - Integer minSecondsBetweenOperations, - Integer maxUsesPerBoot, - Set<Integer> userAuthenticators, - Set<Integer> teeBackedUserAuthenticators, - Integer userAuthenticationValidityDurationSeconds, + @KeyStoreKeyConstraints.PaddingEnum int paddings, + @KeyStoreKeyConstraints.DigestEnum int digests, + @KeyStoreKeyConstraints.BlockModeEnum int blockModes, + @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators, + @KeyStoreKeyConstraints.UserAuthenticatorEnum int teeEnforcedUserAuthenticators, + int userAuthenticationValidityDurationSeconds, boolean invalidatedOnNewFingerprintEnrolled) { mKeystoreAlias = keystoreKeyAlias; mOrigin = origin; @@ -74,17 +68,11 @@ public class KeyStoreKeySpec implements KeySpec { mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd; mPurposes = purposes; mAlgorithm = algorithm; - mPadding = padding; - mDigest = digest; - mBlockMode = blockMode; - mMinSecondsBetweenOperations = minSecondsBetweenOperations; - mMaxUsesPerBoot = maxUsesPerBoot; - mUserAuthenticators = (userAuthenticators != null) - ? new HashSet<Integer>(userAuthenticators) - : Collections.<Integer>emptySet(); - mTeeBackedUserAuthenticators = (teeBackedUserAuthenticators != null) - ? new HashSet<Integer>(teeBackedUserAuthenticators) - : Collections.<Integer>emptySet(); + mPaddings = paddings; + mDigests = digests; + mBlockModes = blockModes; + mUserAuthenticators = userAuthenticators; + mTeeEnforcedUserAuthenticators = teeEnforcedUserAuthenticators; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } @@ -104,7 +92,7 @@ public class KeyStoreKeySpec implements KeySpec { } /** - * Gets the key's size in bits. + * Gets the size of the key in bits. */ public int getKeySize() { return mKeySize; @@ -152,78 +140,53 @@ public class KeyStoreKeySpec implements KeySpec { } /** - * Gets the only block mode with which the key can be used. - * - * @return block mode or {@code null} if the block mode is not restricted. - */ - public @KeyStoreKeyConstraints.BlockModeEnum Integer getBlockMode() { - return mBlockMode; - } - - /** - * Gets the only padding mode with which the key can be used. - * - * @return padding mode or {@code null} if the padding mode is not restricted. - */ - public @KeyStoreKeyConstraints.PaddingEnum Integer getPadding() { - return mPadding; - } - - /** - * Gets the only digest algorithm with which the key can be used. - * - * @return digest algorithm or {@code null} if the digest algorithm is not restricted. + * Gets the set of block modes with which the key can be used. */ - public @KeyStoreKeyConstraints.DigestEnum Integer getDigest() { - return mDigest; + public @KeyStoreKeyConstraints.BlockModeEnum int getBlockModes() { + return mBlockModes; } /** - * 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. + * Gets the set of padding modes with which the key can be used. */ - public Integer getMinSecondsBetweenOperations() { - return mMinSecondsBetweenOperations; + public @KeyStoreKeyConstraints.PaddingEnum int getPaddings() { + return mPaddings; } /** - * 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. + * Gets the set of digest algorithms with which the key can be used. */ - public Integer getMaxUsesPerBoot() { - return mMaxUsesPerBoot; + public @KeyStoreKeyConstraints.DigestEnum int getDigests() { + return mDigests; } /** - * Gets the user authenticators which protect access to the key. The key can only be used iff - * the user has authenticated to at least one of these user authenticators. + * Gets the set of user authenticators which protect access to the 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. + * @return user authenticators or {@code 0} if the key can be used without user authentication. */ - public Set<Integer> getUserAuthenticators() { - return new HashSet<Integer>(mUserAuthenticators); + public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getUserAuthenticators() { + return mUserAuthenticators; } /** - * Gets the TEE-backed user authenticators which protect access to the key. This is a subset of - * the user authentications returned by {@link #getUserAuthenticators()}. + * Gets the set of user authenticators for which the TEE enforces access restrictions for this + * key. This is a subset of the user authentications returned by + * {@link #getUserAuthenticators()}. */ - public Set<Integer> getTeeBackedUserAuthenticators() { - return new HashSet<Integer>(mTeeBackedUserAuthenticators); + public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getTeeEnforcedUserAuthenticators() { + return mTeeEnforcedUserAuthenticators; } /** * Gets the duration of time (seconds) for which the 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 + * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. */ - public Integer getUserAuthenticationValidityDurationSeconds() { + public int getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; } diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java index 88bd6b4..0b2f9b6 100644 --- a/keystore/java/android/security/KeyStoreParameter.java +++ b/keystore/java/android/security/KeyStoreParameter.java @@ -18,12 +18,10 @@ package android.security; import android.content.Context; +import java.security.Key; import java.security.KeyPairGenerator; import java.security.KeyStore.ProtectionParameter; -import java.util.Collections; import java.util.Date; -import java.util.HashSet; -import java.util.Set; /** * This provides the optional parameters that can be specified for @@ -50,33 +48,27 @@ public final class KeyStoreParameter implements ProtectionParameter { private final Date mKeyValidityStart; private final Date mKeyValidityForOriginationEnd; private final Date mKeyValidityForConsumptionEnd; - private final @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; - private final @KeyStoreKeyConstraints.AlgorithmEnum Integer mAlgorithm; - private final @KeyStoreKeyConstraints.PaddingEnum Integer mPadding; - private final @KeyStoreKeyConstraints.DigestEnum Integer mDigest; - private final @KeyStoreKeyConstraints.BlockModeEnum Integer mBlockMode; - private final Integer mMinSecondsBetweenOperations; - private final Integer mMaxUsesPerBoot; - private final Set<Integer> mUserAuthenticators; - private final Integer mUserAuthenticationValidityDurationSeconds; + private final @KeyStoreKeyConstraints.PurposeEnum int mPurposes; + private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings; + private final @KeyStoreKeyConstraints.DigestEnum Integer mDigests; + private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes; + private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators; + private final int mUserAuthenticationValidityDurationSeconds; private final boolean mInvalidatedOnNewFingerprintEnrolled; private KeyStoreParameter(int flags, Date keyValidityStart, Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, - @KeyStoreKeyConstraints.PurposeEnum Integer purposes, - @KeyStoreKeyConstraints.AlgorithmEnum Integer algorithm, - @KeyStoreKeyConstraints.PaddingEnum Integer padding, - @KeyStoreKeyConstraints.DigestEnum Integer digest, - @KeyStoreKeyConstraints.BlockModeEnum Integer blockMode, - Integer minSecondsBetweenOperations, - Integer maxUsesPerBoot, - Set<Integer> userAuthenticators, - Integer userAuthenticationValidityDurationSeconds, + @KeyStoreKeyConstraints.PurposeEnum int purposes, + @KeyStoreKeyConstraints.PaddingEnum int paddings, + @KeyStoreKeyConstraints.DigestEnum Integer digests, + @KeyStoreKeyConstraints.BlockModeEnum int blockModes, + @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators, + int userAuthenticationValidityDurationSeconds, boolean invalidatedOnNewFingerprintEnrolled) { - if ((userAuthenticationValidityDurationSeconds != null) - && (userAuthenticationValidityDurationSeconds < 0)) { + if ((userAuthenticationValidityDurationSeconds < 0) + && (userAuthenticationValidityDurationSeconds != -1)) { throw new IllegalArgumentException( "userAuthenticationValidityDurationSeconds must not be negative"); } @@ -86,15 +78,10 @@ public final class KeyStoreParameter implements ProtectionParameter { mKeyValidityForOriginationEnd = keyValidityForOriginationEnd; mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd; mPurposes = purposes; - mAlgorithm = algorithm; - mPadding = padding; - mDigest = digest; - mBlockMode = blockMode; - mMinSecondsBetweenOperations = minSecondsBetweenOperations; - mMaxUsesPerBoot = maxUsesPerBoot; - mUserAuthenticators = (userAuthenticators != null) - ? new HashSet<Integer>(userAuthenticators) - : Collections.<Integer>emptySet(); + mPaddings = paddings; + mDigests = digests; + mBlockModes = blockModes; + mUserAuthenticators = userAuthenticators; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled; } @@ -147,105 +134,81 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** - * 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. + * Gets the set of purposes for which the key can be used. * * @hide */ - public @KeyStoreKeyConstraints.PurposeEnum Integer getPurposes() { + public @KeyStoreKeyConstraints.PurposeEnum int getPurposes() { return mPurposes; } /** - * Gets the algorithm to which the key is restricted. + * Gets the set of padding schemes to which the key is restricted. * - * @return algorithm or {@code null} if it's not restricted. * @hide */ - public @KeyStoreKeyConstraints.AlgorithmEnum Integer getAlgorithm() { - return mAlgorithm; + public @KeyStoreKeyConstraints.PaddingEnum int getPaddings() { + return mPaddings; } /** - * Gets the padding scheme to which the key is restricted. + * Gets the set of digests to which the key is restricted. * - * @return padding scheme or {@code null} if the padding scheme is not restricted. + * @throws IllegalStateException if this restriction has not been specified. * - * @hide - */ - public @KeyStoreKeyConstraints.PaddingEnum Integer getPadding() { - return mPadding; - } - - /** - * 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. + * @see #isDigestsSpecified() * * @hide */ - public @KeyStoreKeyConstraints.DigestEnum Integer getDigest() { - return mDigest; - } - - /** - * 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; + public @KeyStoreKeyConstraints.DigestEnum int getDigests() { + if (mDigests == null) { + throw new IllegalStateException("Digests not specified"); + } + return mDigests; } /** - * Gets the minimum number of seconds that must expire since the most recent use of the key - * before it can be used again. + * Returns {@code true} if digest restrictions have been specified. * - * @return number of seconds or {@code null} if there is no restriction on how frequently a key - * can be used. + * @see #getDigests() * * @hide */ - public Integer getMinSecondsBetweenOperations() { - return mMinSecondsBetweenOperations; + public boolean isDigestsSpecified() { + return mDigests != null; } /** - * Gets the number of times the key can be used without rebooting the device. + * Gets the set of block modes to which the key is restricted. * - * @return maximum number of times or {@code null} if there is no restriction. * @hide */ - public Integer getMaxUsesPerBoot() { - return mMaxUsesPerBoot; + public @KeyStoreKeyConstraints.BlockModeEnum int getBlockModes() { + return mBlockModes; } /** - * 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. + * Gets the set of 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. + * @return user authenticators or {@code 0} if the key can be used without user authentication. * * @hide */ - public Set<Integer> getUserAuthenticators() { - return new HashSet<Integer>(mUserAuthenticators); + public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getUserAuthenticators() { + return 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 + * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication * is required for every use of the key. * * @hide */ - public Integer getUserAuthenticationValidityDurationSeconds() { + public int getUserAuthenticationValidityDurationSeconds() { return mUserAuthenticationValidityDurationSeconds; } @@ -284,15 +247,12 @@ public final class KeyStoreParameter implements ProtectionParameter { private Date mKeyValidityStart; private Date mKeyValidityForOriginationEnd; private Date mKeyValidityForConsumptionEnd; - private @KeyStoreKeyConstraints.PurposeEnum Integer mPurposes; - private @KeyStoreKeyConstraints.AlgorithmEnum Integer mAlgorithm; - private @KeyStoreKeyConstraints.PaddingEnum Integer mPadding; - private @KeyStoreKeyConstraints.DigestEnum Integer mDigest; - private @KeyStoreKeyConstraints.BlockModeEnum Integer mBlockMode; - private Integer mMinSecondsBetweenOperations; - private Integer mMaxUsesPerBoot; - private Set<Integer> mUserAuthenticators; - private Integer mUserAuthenticationValidityDurationSeconds; + private @KeyStoreKeyConstraints.PurposeEnum int mPurposes; + private @KeyStoreKeyConstraints.PaddingEnum int mPaddings; + private @KeyStoreKeyConstraints.DigestEnum Integer mDigests; + private @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes; + private @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators; + private int mUserAuthenticationValidityDurationSeconds = -1; private boolean mInvalidatedOnNewFingerprintEnrolled; /** @@ -385,9 +345,9 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** - * Restricts the purposes for which the key can be used to the provided set of purposes. + * Restricts the key to being used only for the provided set of purposes. * - * <p>By default, the key can be used for encryption, decryption, signing, and verification. + * <p>This restriction must be specified. There is no default. * * @hide */ @@ -397,84 +357,43 @@ public final class KeyStoreParameter implements ProtectionParameter { } /** - * Sets the algorithm of the key. - * - * <p>The algorithm of symmetric keys can be deduced from the key itself. Thus, explicitly - * specifying the algorithm of symmetric keys using this method is not necessary. - * - * @hide - */ - public Builder setAlgorithm(@KeyStoreKeyConstraints.AlgorithmEnum int algorithm) { - mAlgorithm = algorithm; - return this; - } - - /** - * Restricts the key to being used only with the provided padding scheme. Attempts to use + * Restricts the key to being used only with the provided padding schemes. 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; + public Builder setPaddings(@KeyStoreKeyConstraints.PaddingEnum int paddings) { + mPaddings = paddings; return this; } /** - * 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. For asymmetric signing keys this constraint must be specified because there is no - * default. + * Restricts the key to being used only with the provided digests when generating signatures + * or HMACs. Attempts to use the key with any other digest will be rejected. * - * @see java.security.Key#getAlgorithm() + * <p>For HMAC keys, the default is to restrict to the digest specified in + * {@link Key#getAlgorithm()}. For asymmetric signing keys this constraint must be specified + * because there is no default. * * @hide */ - public Builder setDigest(@KeyStoreKeyConstraints.DigestEnum int digest) { - mDigest = digest; + public Builder setDigests(@KeyStoreKeyConstraints.DigestEnum int digests) { + mDigests = digests; 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. + * Restricts the key to being used only with the provided block modes. 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. + * <p>This restriction must be specified for symmetric encryption/decryption keys. * * @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; + public Builder setBlockModes(@KeyStoreKeyConstraints.BlockModeEnum int blockModes) { + mBlockModes = blockModes; return this; } @@ -484,16 +403,16 @@ public final class KeyStoreParameter implements ProtectionParameter { * * <p>By default, the key can be used without user authentication. * - * @param userAuthenticators user authenticators or empty list if this key can be accessed + * @param userAuthenticators user authenticators or {@code 0} 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; + public Builder setUserAuthenticators( + @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators) { + mUserAuthenticators = userAuthenticators; return this; } @@ -506,7 +425,7 @@ public final class KeyStoreParameter implements ProtectionParameter { * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for * every use of the key. * - * @see #setUserAuthenticators(Set) + * @see #setUserAuthenticators(int) * * @hide */ @@ -543,12 +462,9 @@ public final class KeyStoreParameter implements ProtectionParameter { mKeyValidityForOriginationEnd, mKeyValidityForConsumptionEnd, mPurposes, - mAlgorithm, - mPadding, - mDigest, - mBlockMode, - mMinSecondsBetweenOperations, - mMaxUsesPerBoot, + mPaddings, + mDigests, + mBlockModes, mUserAuthenticators, mUserAuthenticationValidityDurationSeconds, mInvalidatedOnNewFingerprintEnrolled); diff --git a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java index c205d9d..8bf228a 100644 --- a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java +++ b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java @@ -23,7 +23,6 @@ import java.security.InvalidKeyException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.util.Date; -import java.util.Set; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactorySpi; @@ -75,9 +74,11 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { int keySize; @KeyStoreKeyConstraints.PurposeEnum int purposes; @KeyStoreKeyConstraints.AlgorithmEnum int algorithm; - @KeyStoreKeyConstraints.PaddingEnum Integer padding; - @KeyStoreKeyConstraints.DigestEnum Integer digest; - @KeyStoreKeyConstraints.BlockModeEnum Integer blockMode; + @KeyStoreKeyConstraints.PaddingEnum int paddings; + @KeyStoreKeyConstraints.DigestEnum int digests; + @KeyStoreKeyConstraints.BlockModeEnum int blockModes; + @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators; + @KeyStoreKeyConstraints.UserAuthenticatorEnum int teeEnforcedUserAuthenticators; try { origin = KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_ORIGIN); if (origin == null) { @@ -97,18 +98,27 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { throw new InvalidKeySpecException("Key algorithm not available"); } algorithm = KeyStoreKeyConstraints.Algorithm.fromKeymaster(alg); - padding = KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_PADDING); - if (padding != null) { - padding = KeyStoreKeyConstraints.Padding.fromKeymaster(padding); - } - digest = KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_DIGEST); - if (digest != null) { - digest = KeyStoreKeyConstraints.Digest.fromKeymaster(digest); - } - blockMode = KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_BLOCK_MODE); - if (blockMode != null) { - blockMode = KeyStoreKeyConstraints.BlockMode.fromKeymaster(blockMode); - } + paddings = KeyStoreKeyConstraints.Padding.allFromKeymaster( + KeymasterUtils.getInts(keyCharacteristics, KeymasterDefs.KM_TAG_PADDING)); + digests = KeyStoreKeyConstraints.Digest.allFromKeymaster( + KeymasterUtils.getInts(keyCharacteristics, KeymasterDefs.KM_TAG_DIGEST)); + blockModes = KeyStoreKeyConstraints.BlockMode.allFromKeymaster( + KeymasterUtils.getInts(keyCharacteristics, KeymasterDefs.KM_TAG_BLOCK_MODE)); + + @KeyStoreKeyConstraints.UserAuthenticatorEnum + int swEnforcedKeymasterUserAuthenticators = + keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); + @KeyStoreKeyConstraints.UserAuthenticatorEnum + int hwEnforcedKeymasterUserAuthenticators = + keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); + @KeyStoreKeyConstraints.UserAuthenticatorEnum + int keymasterUserAuthenticators = + swEnforcedKeymasterUserAuthenticators | hwEnforcedKeymasterUserAuthenticators; + userAuthenticators = KeyStoreKeyConstraints.UserAuthenticator.allFromKeymaster( + keymasterUserAuthenticators); + teeEnforcedUserAuthenticators = + KeyStoreKeyConstraints.UserAuthenticator.allFromKeymaster( + hwEnforcedKeymasterUserAuthenticators); } catch (IllegalArgumentException e) { throw new InvalidKeySpecException("Unsupported key characteristic", e); } @@ -130,17 +140,8 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { && (keyValidityForConsumptionEnd.getTime() == Long.MAX_VALUE)) { keyValidityForConsumptionEnd = null; } - - int swEnforcedUserAuthenticatorIds = - keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); - int hwEnforcedUserAuthenticatorIds = - keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); - int userAuthenticatorIds = swEnforcedUserAuthenticatorIds | hwEnforcedUserAuthenticatorIds; - Set<Integer> userAuthenticators = - KeyStoreKeyConstraints.UserAuthenticator.allFromKeymaster(userAuthenticatorIds); - Set<Integer> teeBackedUserAuthenticators = - KeyStoreKeyConstraints.UserAuthenticator.allFromKeymaster( - hwEnforcedUserAuthenticatorIds); + Integer userAuthenticationValidityDurationSeconds = + KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_AUTH_TIMEOUT); // TODO: Populate the value below from key characteristics once Keymaster is ready. boolean invalidatedOnNewFingerprintEnrolled = false; @@ -153,15 +154,13 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { keyValidityForConsumptionEnd, purposes, algorithm, - padding, - digest, - blockMode, - KeymasterUtils.getInt(keyCharacteristics, - KeymasterDefs.KM_TAG_MIN_SECONDS_BETWEEN_OPS), - KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_MAX_USES_PER_BOOT), + paddings, + digests, + blockModes, userAuthenticators, - teeBackedUserAuthenticators, - KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_AUTH_TIMEOUT), + teeEnforcedUserAuthenticators, + ((userAuthenticationValidityDurationSeconds != null) + ? userAuthenticationValidityDurationSeconds : -1), invalidatedOnNewFingerprintEnrolled); } |