From c46e9e7da4558f6bc99262361fd1ca35c3a44090 Mon Sep 17 00:00:00 2001 From: Alex Klyubin Date: Mon, 6 Apr 2015 15:36:25 -0700 Subject: Make the new AndroidKeyStore API conformant. This makes the new AndroidKeyStore API conform with the latest Keymaster API changes as well as the latest Android framework API design guidelines. Keymaster changes: * Multiple paddings, block modes, and digests can be set on a key. * "max uses per boot" and "min seconds between use" restrictions will not be exposed in the framework API. * Padding scheme ZERO will not be exposed. Changes due to Android framework design guidelines: * Sets of enum values have been replaced with bitsets represented as ints. * Integer has been replaced with int, with null being represented with a special value (e.g., -1 or 0) where possible. Bug: 18088752 Change-Id: Ib21739aa9b42d48895cb7a681e836a5c6d972ac6 --- .../java/android/security/AndroidKeyStore.java | 81 ++++++++++------------ 1 file changed, 36 insertions(+), 45 deletions(-) (limited to 'keystore/java/android/security/AndroidKeyStore.java') diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java index dcc79be5eaa9..f72c7acd182b 100644 --- a/keystore/java/android/security/AndroidKeyStore.java +++ b/keystore/java/android/security/AndroidKeyStore.java @@ -466,81 +466,72 @@ 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, KeyStoreKeyConstraints.UserAuthenticator.allToKeymaster( params.getUserAuthenticators())); } - if (params.getUserAuthenticationValidityDurationSeconds() != null) { + if (params.getUserAuthenticationValidityDurationSeconds() != -1) { args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, params.getUserAuthenticationValidityDurationSeconds()); } -- cgit v1.2.3