summaryrefslogtreecommitdiffstats
path: root/keystore
diff options
context:
space:
mode:
Diffstat (limited to 'keystore')
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java7
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java9
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreSpi.java174
-rw-r--r--keystore/java/android/security/keystore/KeymasterUtils.java4
4 files changed, 105 insertions, 89 deletions
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index 258133d..6a7930a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -239,6 +239,13 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
"At least one digest algorithm must be specified");
}
}
+
+ // Check that user authentication related parameters are acceptable. This method
+ // will throw an IllegalStateException if there are issues (e.g., secure lock screen
+ // not set up).
+ KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
+ spec.isUserAuthenticationRequired(),
+ spec.getUserAuthenticationValidityDurationSeconds());
} catch (IllegalStateException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 459514d..6b36a58 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -310,7 +310,14 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
} else {
mKeymasterDigests = EmptyArray.INT;
}
- } catch (IllegalArgumentException e) {
+
+ // Check that user authentication related parameters are acceptable. This method
+ // will throw an IllegalStateException if there are issues (e.g., secure lock screen
+ // not set up).
+ KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
+ mSpec.isUserAuthenticationRequired(),
+ mSpec.getUserAuthenticationValidityDurationSeconds());
+ } catch (IllegalArgumentException | IllegalStateException e) {
throw new InvalidAlgorithmParameterException(e);
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index dc8f1e3..e9f19cd 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -484,8 +484,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
spec.getKeyValidityForOriginationEnd());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
spec.getKeyValidityForConsumptionEnd());
- } catch (IllegalArgumentException e) {
- throw new KeyStoreException("Invalid parameter", e);
+ } catch (IllegalArgumentException | IllegalStateException e) {
+ throw new KeyStoreException(e);
}
}
@@ -598,102 +598,100 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
+ " RAW format export");
}
- String keyAlgorithmString = key.getAlgorithm();
- int keymasterAlgorithm;
- int keymasterDigest;
- try {
- keymasterAlgorithm =
- KeyProperties.KeyAlgorithm.toKeymasterSecretKeyAlgorithm(keyAlgorithmString);
- keymasterDigest = KeyProperties.KeyAlgorithm.toKeymasterDigest(keyAlgorithmString);
- } catch (IllegalArgumentException e) {
- throw new KeyStoreException("Unsupported secret key algorithm: " + keyAlgorithmString);
- }
-
KeymasterArguments args = new KeymasterArguments();
- args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
-
- int[] keymasterDigests;
- if (params.isDigestsSpecified()) {
- // Digest(s) specified in parameters
- keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
- if (keymasterDigest != -1) {
- // Digest also specified in the JCA key algorithm name.
- if (!com.android.internal.util.ArrayUtils.contains(
- keymasterDigests, keymasterDigest)) {
- throw new KeyStoreException("Key digest mismatch"
- + ". Key: " + keyAlgorithmString
- + ", parameter spec: " + Arrays.asList(params.getDigests()));
- }
- // When the key is read back from keystore we reconstruct the JCA key algorithm
- // name from the KM_TAG_ALGORITHM and the first KM_TAG_DIGEST. Thus we need to
- // ensure that the digest reflected in the JCA key algorithm name is the first
- // KM_TAG_DIGEST tag.
- if (keymasterDigests[0] != keymasterDigest) {
- // The first digest is not the one implied by the JCA key algorithm name.
- // Swap the implied digest with the first one.
- for (int i = 0; i < keymasterDigests.length; i++) {
- if (keymasterDigests[i] == keymasterDigest) {
- keymasterDigests[i] = keymasterDigests[0];
- keymasterDigests[0] = keymasterDigest;
- break;
+ try {
+ int keymasterAlgorithm =
+ KeyProperties.KeyAlgorithm.toKeymasterSecretKeyAlgorithm(key.getAlgorithm());
+ args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
+
+ int[] keymasterDigests;
+ int keymasterDigest = KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
+ if (params.isDigestsSpecified()) {
+ // Digest(s) specified in parameters
+ keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
+ if (keymasterDigest != -1) {
+ // Digest also specified in the JCA key algorithm name.
+ if (!com.android.internal.util.ArrayUtils.contains(
+ keymasterDigests, keymasterDigest)) {
+ throw new KeyStoreException("Digest specified in key algorithm "
+ + key.getAlgorithm() + " not specified in protection parameters: "
+ + Arrays.asList(params.getDigests()));
+ }
+ // When the key is read back from keystore we reconstruct the JCA key algorithm
+ // name from the KM_TAG_ALGORITHM and the first KM_TAG_DIGEST. Thus we need to
+ // ensure that the digest reflected in the JCA key algorithm name is the first
+ // KM_TAG_DIGEST tag.
+ if (keymasterDigests[0] != keymasterDigest) {
+ // The first digest is not the one implied by the JCA key algorithm name.
+ // Swap the implied digest with the first one.
+ for (int i = 0; i < keymasterDigests.length; i++) {
+ if (keymasterDigests[i] == keymasterDigest) {
+ keymasterDigests[i] = keymasterDigests[0];
+ keymasterDigests[0] = keymasterDigest;
+ break;
+ }
}
}
}
- }
- } else {
- // No digest specified in parameters
- if (keymasterDigest != -1) {
- // Digest specified in the JCA key algorithm name.
- keymasterDigests = new int[] {keymasterDigest};
} else {
- keymasterDigests = EmptyArray.INT;
+ // No digest specified in parameters
+ if (keymasterDigest != -1) {
+ // Digest specified in the JCA key algorithm name.
+ keymasterDigests = new int[] {keymasterDigest};
+ } else {
+ keymasterDigests = EmptyArray.INT;
+ }
}
- }
- args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
- if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
- if (keymasterDigests.length == 0) {
- throw new KeyStoreException("At least one digest algorithm must be specified"
- + " for key algorithm " + keyAlgorithmString);
+ args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
+ if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
+ if (keymasterDigests.length == 0) {
+ throw new KeyStoreException("At least one digest algorithm must be specified"
+ + " for key algorithm " + key.getAlgorithm());
+ }
}
- }
- @KeyProperties.PurposeEnum int purposes = params.getPurposes();
- int[] keymasterBlockModes =
- KeyProperties.BlockMode.allToKeymaster(params.getBlockModes());
- if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
- && (params.isRandomizedEncryptionRequired())) {
- for (int keymasterBlockMode : keymasterBlockModes) {
- if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(
- keymasterBlockMode)) {
- throw new KeyStoreException(
- "Randomized encryption (IND-CPA) required but may be violated by block"
- + " mode: "
- + KeyProperties.BlockMode.fromKeymaster(keymasterBlockMode)
- + ". See KeyProtection documentation.");
+ @KeyProperties.PurposeEnum int purposes = params.getPurposes();
+ int[] keymasterBlockModes =
+ KeyProperties.BlockMode.allToKeymaster(params.getBlockModes());
+ if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
+ && (params.isRandomizedEncryptionRequired())) {
+ for (int keymasterBlockMode : keymasterBlockModes) {
+ if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(
+ keymasterBlockMode)) {
+ throw new KeyStoreException(
+ "Randomized encryption (IND-CPA) required but may be violated by"
+ + " block mode: "
+ + KeyProperties.BlockMode.fromKeymaster(keymasterBlockMode)
+ + ". See KeyProtection documentation.");
+ }
}
}
- }
- args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, KeyProperties.Purpose.allToKeymaster(purposes));
- args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
- if (params.getSignaturePaddings().length > 0) {
- throw new KeyStoreException("Signature paddings not supported for symmetric keys");
- }
- int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
- params.getEncryptionPaddings());
- args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
- KeymasterUtils.addUserAuthArgs(args,
- params.isUserAuthenticationRequired(),
- params.getUserAuthenticationValidityDurationSeconds());
- args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, params.getKeyValidityStart());
- args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
- params.getKeyValidityForOriginationEnd());
- args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
- params.getKeyValidityForConsumptionEnd());
-
- if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
- && (!params.isRandomizedEncryptionRequired())) {
- // Permit caller-provided IV when encrypting with this key
- args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
+ args.addEnums(KeymasterDefs.KM_TAG_PURPOSE,
+ KeyProperties.Purpose.allToKeymaster(purposes));
+ args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
+ if (params.getSignaturePaddings().length > 0) {
+ throw new KeyStoreException("Signature paddings not supported for symmetric keys");
+ }
+ int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
+ params.getEncryptionPaddings());
+ args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
+ KeymasterUtils.addUserAuthArgs(args,
+ params.isUserAuthenticationRequired(),
+ params.getUserAuthenticationValidityDurationSeconds());
+ args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
+ params.getKeyValidityStart());
+ args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+ params.getKeyValidityForOriginationEnd());
+ args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
+ params.getKeyValidityForConsumptionEnd());
+
+ if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
+ && (!params.isRandomizedEncryptionRequired())) {
+ // Permit caller-provided IV when encrypting with this key
+ args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
+ }
+ } catch (IllegalArgumentException | IllegalStateException e) {
+ throw new KeyStoreException(e);
}
Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias);
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 3cd3f2a..92d636c 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -87,6 +87,10 @@ public abstract class KeymasterUtils {
* @param userAuthenticationValidityDurationSeconds duration of time (seconds) for which user
* authentication is valid as authorization for using the key or {@code -1} if every
* use of the key needs authorization.
+ *
+ * @throws IllegalStateException if user authentication is required but the system is in a wrong
+ * state (e.g., secure lock screen not set up) for generating or importing keys that
+ * require user authentication.
*/
public static void addUserAuthArgs(KeymasterArguments args,
boolean userAuthenticationRequired,