summaryrefslogtreecommitdiffstats
path: root/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
diff options
context:
space:
mode:
authorAlex Klyubin <klyubin@google.com>2015-07-08 09:31:23 -0700
committerAlex Klyubin <klyubin@google.com>2015-07-16 09:59:51 -0700
commitc58153b2d7418f44f2b0e397478be808e91decef (patch)
tree281c3d80d1265fa344fffe460d4e45509fba0e3e /keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
parent532737df65330200dc55ae42d31140d19c4024be (diff)
downloadframeworks_base-c58153b2d7418f44f2b0e397478be808e91decef.zip
frameworks_base-c58153b2d7418f44f2b0e397478be808e91decef.tar.gz
frameworks_base-c58153b2d7418f44f2b0e397478be808e91decef.tar.bz2
HMAC keys are authorized for exactly one digest.
This is in preparation for enforcing the minimum length of MACs which in the case of HMAC keys generated or imported by Android Keystore will be set to the length of the digest for which the key is authorized. Bug: 22337277 Change-Id: I0255d5ba184dabfb6b45d8f32ddadeb84ab7fc19
Diffstat (limited to 'keystore/java/android/security/keystore/AndroidKeyStoreSpi.java')
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreSpi.java66
1 files changed, 30 insertions, 36 deletions
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index e9f19cd..88858de 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -41,6 +41,7 @@ import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
+import java.security.ProviderException;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
@@ -605,50 +606,43 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
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;
- }
- }
+ if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
+ // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
+ // implies SHA-256 digest). Because keymaster HMAC key is authorized only for one
+ // digest, we don't let import parameters override the digest implied by the key.
+ // If the parameters specify digests at all, they must specify only one digest, the
+ // only implied by key algorithm.
+ int keymasterImpliedDigest =
+ KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
+ if (keymasterImpliedDigest == -1) {
+ throw new ProviderException(
+ "HMAC key algorithm digest unknown for key algorithm "
+ + key.getAlgorithm());
+ }
+ keymasterDigests = new int[] {keymasterImpliedDigest};
+ if (params.isDigestsSpecified()) {
+ // Digest(s) explicitly specified in params -- check that the list consists of
+ // exactly one digest, the one implied by key algorithm.
+ int[] keymasterDigestsFromParams =
+ KeyProperties.Digest.allToKeymaster(params.getDigests());
+ if ((keymasterDigestsFromParams.length != 1)
+ || (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) {
+ throw new KeyStoreException(
+ "Unsupported digests specification: "
+ + Arrays.asList(params.getDigests()) + ". Only "
+ + KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest)
+ + " supported for HMAC key algorithm " + key.getAlgorithm());
}
}
} else {
- // No digest specified in parameters
- if (keymasterDigest != -1) {
- // Digest specified in the JCA key algorithm name.
- keymasterDigests = new int[] {keymasterDigest};
+ // Key algorithm does not imply a digest.
+ if (params.isDigestsSpecified()) {
+ keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
} 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 " + key.getAlgorithm());
- }
- }
@KeyProperties.PurposeEnum int purposes = params.getPurposes();
int[] keymasterBlockModes =