diff options
Diffstat (limited to 'keystore/java/android/security/AndroidKeyStore.java')
-rw-r--r-- | keystore/java/android/security/AndroidKeyStore.java | 115 |
1 files changed, 52 insertions, 63 deletions
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java index 55a8b4f971f3..fcee9fc87215 100644 --- a/keystore/java/android/security/AndroidKeyStore.java +++ b/keystore/java/android/security/AndroidKeyStore.java @@ -19,6 +19,8 @@ package android.security; import com.android.org.conscrypt.OpenSSLEngine; import com.android.org.conscrypt.OpenSSLKeyHolder; +import libcore.util.EmptyArray; + import android.security.keymaster.KeyCharacteristics; import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterDefs; @@ -46,6 +48,7 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; @@ -112,13 +115,6 @@ public class AndroidKeyStore extends KeyStoreSpi { if (keymasterAlgorithm == -1) { throw new UnrecoverableKeyException("Key algorithm unknown"); } - @KeyStoreKeyConstraints.AlgorithmEnum int keyAlgorithm; - try { - keyAlgorithm = KeyStoreKeyConstraints.Algorithm.fromKeymaster(keymasterAlgorithm); - } catch (IllegalArgumentException e) { - throw (UnrecoverableKeyException) - new UnrecoverableKeyException("Unsupported key algorithm").initCause(e); - } int keymasterDigest = keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_DIGEST, -1); @@ -126,20 +122,11 @@ public class AndroidKeyStore extends KeyStoreSpi { keymasterDigest = keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_DIGEST, -1); } - @KeyStoreKeyConstraints.DigestEnum Integer digest = null; - if (keymasterDigest != -1) { - try { - digest = KeyStoreKeyConstraints.Digest.fromKeymaster(keymasterDigest); - } catch (IllegalArgumentException e) { - throw (UnrecoverableKeyException) - new UnrecoverableKeyException("Unsupported digest").initCause(e); - } - } String keyAlgorithmString; try { - keyAlgorithmString = KeyStoreKeyConstraints.Algorithm.toJCASecretKeyAlgorithm( - keyAlgorithm, digest); + keyAlgorithmString = KeymasterUtils.getJcaSecretKeyAlgorithm( + keymasterAlgorithm, keymasterDigest); } catch (IllegalArgumentException e) { throw (UnrecoverableKeyException) new UnrecoverableKeyException("Unsupported secret key type").initCause(e); @@ -456,90 +443,92 @@ public class AndroidKeyStore extends KeyStoreSpi { } String keyAlgorithmString = key.getAlgorithm(); - @KeyStoreKeyConstraints.AlgorithmEnum int keyAlgorithm; - @KeyStoreKeyConstraints.DigestEnum Integer digest; + int keymasterAlgorithm; + int keymasterDigest; try { - keyAlgorithm = - KeyStoreKeyConstraints.Algorithm.fromJCASecretKeyAlgorithm(keyAlgorithmString); - digest = KeyStoreKeyConstraints.Digest.fromJCASecretKeyAlgorithm(keyAlgorithmString); + keymasterAlgorithm = KeymasterUtils.getKeymasterAlgorithmFromJcaSecretKeyAlgorithm( + keyAlgorithmString); + keymasterDigest = + KeymasterUtils.getKeymasterDigestfromJcaSecretKeyAlgorithm(keyAlgorithmString); } catch (IllegalArgumentException e) { throw new KeyStoreException("Unsupported secret key algorithm: " + keyAlgorithmString); } KeymasterArguments args = new KeymasterArguments(); - args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, - KeyStoreKeyConstraints.Algorithm.toKeymaster(keyAlgorithm)); + args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm); - @KeyStoreKeyConstraints.DigestEnum int digests; + int[] keymasterDigests; if (params.isDigestsSpecified()) { // Digest(s) specified in parameters - if (digest != null) { + keymasterDigests = + KeymasterUtils.getKeymasterDigestsFromJcaDigestAlgorithms(params.getDigests()); + if (keymasterDigest != -1) { // Digest also specified in the JCA key algorithm name. - if ((params.getDigests() & digest) != digest) { + if (!com.android.internal.util.ArrayUtils.contains( + keymasterDigests, keymasterDigest)) { throw new KeyStoreException("Key digest mismatch" + ". Key: " + keyAlgorithmString - + ", parameter spec: " - + KeyStoreKeyConstraints.Digest.allToString(params.getDigests())); + + ", parameter spec: " + Arrays.asList(params.getDigests())); } } - digests = params.getDigests(); } else { // No digest specified in parameters - if (digest != null) { + if (keymasterDigest != -1) { // Digest specified in the JCA key algorithm name. - digests = digest; + keymasterDigests = new int[] {keymasterDigest}; } else { - digests = 0; + keymasterDigests = EmptyArray.INT; } } - for (int keymasterDigest : KeyStoreKeyConstraints.Digest.allToKeymaster(digests)) { - args.addInt(KeymasterDefs.KM_TAG_DIGEST, keymasterDigest); - } - if (digests != 0) { + args.addInts(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests); + if (keymasterDigests.length > 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) { + int digestOutputSizeBytes = + KeymasterUtils.getDigestOutputSizeBytes(keymasterDigests[0]); + if (digestOutputSizeBytes != -1) { // 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 (digests == 0) { + 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); } } - @KeyStoreKeyConstraints.PurposeEnum int purposes = params.getPurposes(); - @KeyStoreKeyConstraints.BlockModeEnum int blockModes = params.getBlockModes(); - if (((purposes & KeyStoreKeyConstraints.Purpose.ENCRYPT) != 0) + @KeyStoreKeyProperties.PurposeEnum int purposes = params.getPurposes(); + int[] keymasterBlockModes = KeymasterUtils.getKeymasterBlockModesFromJcaBlockModes( + params.getBlockModes()); + if (((purposes & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0) && (params.isRandomizedEncryptionRequired())) { - @KeyStoreKeyConstraints.BlockModeEnum int incompatibleBlockModes = - blockModes & ~KeyStoreKeyConstraints.BlockMode.IND_CPA_COMPATIBLE_MODES; - if (incompatibleBlockModes != 0) { - throw new KeyStoreException("Randomized encryption (IND-CPA) required but may be" - + " violated by block mode(s): " - + KeyStoreKeyConstraints.BlockMode.allToString(incompatibleBlockModes) - + ". See KeyStoreParameter documentation."); + for (int keymasterBlockMode : keymasterBlockModes) { + if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatible(keymasterBlockMode)) { + throw new KeyStoreException( + "Randomized encryption (IND-CPA) required but may be violated by block" + + " mode: " + + KeymasterUtils.getJcaBlockModeFromKeymasterBlockMode( + keymasterBlockMode) + + ". See KeyStoreParameter documentation."); + } } } - for (int keymasterPurpose : KeyStoreKeyConstraints.Purpose.allToKeymaster(purposes)) { + for (int keymasterPurpose : KeyStoreKeyProperties.Purpose.allToKeymaster(purposes)) { args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose); } - for (int keymasterBlockMode : KeyStoreKeyConstraints.BlockMode.allToKeymaster(blockModes)) { - args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockMode); - } - for (int keymasterPadding : - KeyStoreKeyConstraints.Padding.allToKeymaster(params.getPaddings())) { - args.addInt(KeymasterDefs.KM_TAG_PADDING, keymasterPadding); - } + args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes); + int[] keymasterPaddings = ArrayUtils.concat( + KeymasterUtils.getKeymasterPaddingsFromJcaEncryptionPaddings( + params.getEncryptionPaddings()), + KeymasterUtils.getKeymasterPaddingsFromJcaSignaturePaddings( + params.getSignaturePaddings())); + args.addInts(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings); if (params.getUserAuthenticators() == 0) { args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); } else { args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, - KeyStoreKeyConstraints.UserAuthenticator.allToKeymaster( + KeyStoreKeyProperties.UserAuthenticator.allToKeymaster( params.getUserAuthenticators())); } if (params.getUserAuthenticationValidityDurationSeconds() != -1) { @@ -559,7 +548,7 @@ public class AndroidKeyStore extends KeyStoreSpi { // TODO: Remove this once keymaster does not require us to specify the size of imported key. args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keyMaterial.length * 8); - if (((purposes & KeyStoreKeyConstraints.Purpose.ENCRYPT) != 0) + if (((purposes & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0) && (!params.isRandomizedEncryptionRequired())) { // Permit caller-provided IV when encrypting with this key args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE); |