diff options
author | Alex Klyubin <klyubin@google.com> | 2015-04-30 16:12:32 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-04-30 16:12:33 +0000 |
commit | 403ac2d64f7ad53ecf9ccd713951cf151ea2f2bc (patch) | |
tree | dee1473b960cf0749c1d5a5febd066fb787a328e /keystore | |
parent | 8310f87d96791e8b864df5e821fe65273c2dd874 (diff) | |
parent | 4812563f68c87278af68309662433279d10f573e (diff) | |
download | frameworks_base-403ac2d64f7ad53ecf9ccd713951cf151ea2f2bc.zip frameworks_base-403ac2d64f7ad53ecf9ccd713951cf151ea2f2bc.tar.gz frameworks_base-403ac2d64f7ad53ecf9ccd713951cf151ea2f2bc.tar.bz2 |
Merge "AndroidKeyStore keys should not be handled by Bouncy Castle." into mnc-dev
Diffstat (limited to 'keystore')
-rw-r--r-- | keystore/java/android/security/AndroidKeyStoreBCWorkaroundProvider.java | 83 | ||||
-rw-r--r-- | keystore/java/android/security/AndroidKeyStoreProvider.java | 61 |
2 files changed, 113 insertions, 31 deletions
diff --git a/keystore/java/android/security/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/AndroidKeyStoreBCWorkaroundProvider.java new file mode 100644 index 0000000..45329cf --- /dev/null +++ b/keystore/java/android/security/AndroidKeyStoreBCWorkaroundProvider.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +import java.security.Provider; + +/** + * {@link Provider} of JCA crypto operations operating on Android KeyStore keys. + * + * <p>This provider was separated out of {@link AndroidKeyStoreProvider} to work around the issue + * that Bouncy Castle provider incorrectly declares that it accepts arbitrary keys (incl. Android + * KeyStore ones). This causes JCA to select the Bouncy Castle's implementation of JCA crypto + * operations for Android KeyStore keys unless Android KeyStore's own implementations are installed + * as higher-priority than Bouncy Castle ones. The purpose of this provider is to do just that: to + * offer crypto operations operating on Android KeyStore keys and to be installed at higher priority + * than the Bouncy Castle provider. + * + * <p>Once Bouncy Castle provider is fixed, this provider can be merged into the + * {@code AndroidKeyStoreProvider}. + * + * @hide + */ +class AndroidKeyStoreBCWorkaroundProvider extends Provider { + + // IMPLEMENTATION NOTE: Class names are hard-coded in this provider to avoid loading these + // classes when this provider is instantiated and installed early on during each app's + // initialization process. + + private static final String PACKAGE_NAME = "android.security"; + private static final String KEYSTORE_SECRET_KEY_CLASS_NAME = + PACKAGE_NAME + ".KeyStoreSecretKey"; + + AndroidKeyStoreBCWorkaroundProvider() { + super("AndroidKeyStoreBCWorkaround", + 1.0, + "Android KeyStore security provider to work around Bouncy Castle"); + + // javax.crypto.Mac + putMacImpl("HmacSHA1", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA1"); + putMacImpl("HmacSHA224", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA224"); + putMacImpl("HmacSHA256", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA256"); + putMacImpl("HmacSHA384", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA384"); + putMacImpl("HmacSHA512", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA512"); + + // javax.crypto.Cipher + putSymmetricCipherImpl("AES/ECB/NoPadding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$NoPadding"); + putSymmetricCipherImpl("AES/ECB/PKCS7Padding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$PKCS7Padding"); + + putSymmetricCipherImpl("AES/CBC/NoPadding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$NoPadding"); + putSymmetricCipherImpl("AES/CBC/PKCS7Padding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$PKCS7Padding"); + + putSymmetricCipherImpl("AES/CTR/NoPadding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CTR$NoPadding"); + } + + private void putMacImpl(String algorithm, String implClass) { + put("Mac." + algorithm, implClass); + put("Mac." + algorithm + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME); + } + + private void putSymmetricCipherImpl(String transformation, String implClass) { + put("Cipher." + transformation, implClass); + put("Cipher." + transformation + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME); + } +} diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java index 43f3b30..518067b 100644 --- a/keystore/java/android/security/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/AndroidKeyStoreProvider.java @@ -17,6 +17,7 @@ package android.security; import java.security.Provider; +import java.security.Security; import javax.crypto.Cipher; import javax.crypto.Mac; @@ -32,10 +33,12 @@ public class AndroidKeyStoreProvider extends Provider { // IMPLEMENTATION NOTE: Class names are hard-coded in this provider to avoid loading these // classes when this provider is instantiated and installed early on during each app's // initialization process. + // + // Crypto operations operating on the AndroidKeyStore keys must not be offered by this provider. + // Instead, they need to be offered by AndroidKeyStoreBCWorkaroundProvider. See its Javadoc + // for details. private static final String PACKAGE_NAME = "android.security"; - private static final String KEYSTORE_SECRET_KEY_CLASS_NAME = - PACKAGE_NAME + ".KeyStoreSecretKey"; public AndroidKeyStoreProvider() { super(PROVIDER_NAME, 1.0, "Android KeyStore security provider"); @@ -62,43 +65,39 @@ public class AndroidKeyStoreProvider extends Provider { putSecretKeyFactoryImpl("HmacSHA256"); putSecretKeyFactoryImpl("HmacSHA384"); putSecretKeyFactoryImpl("HmacSHA512"); + } - // javax.crypto.Mac - putMacImpl("HmacSHA1", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA1"); - putMacImpl("HmacSHA224", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA224"); - putMacImpl("HmacSHA256", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA256"); - putMacImpl("HmacSHA384", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA384"); - putMacImpl("HmacSHA512", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA512"); - - // javax.crypto.Cipher - putSymmetricCipherImpl("AES/ECB/NoPadding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$NoPadding"); - putSymmetricCipherImpl("AES/ECB/PKCS7Padding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$PKCS7Padding"); - - putSymmetricCipherImpl("AES/CBC/NoPadding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$NoPadding"); - putSymmetricCipherImpl("AES/CBC/PKCS7Padding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$PKCS7Padding"); + /** + * Installs a new instance of this provider (and the + * {@link AndroidKeyStoreBCWorkaroundProvider}). + */ + public static void install() { + Provider[] providers = Security.getProviders(); + int bcProviderPosition = -1; + for (int position = 0; position < providers.length; position++) { + Provider provider = providers[position]; + if ("BC".equals(provider.getName())) { + bcProviderPosition = position; + break; + } + } - putSymmetricCipherImpl("AES/CTR/NoPadding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CTR$NoPadding"); + Security.addProvider(new AndroidKeyStoreProvider()); + Provider workaroundProvider = new AndroidKeyStoreBCWorkaroundProvider(); + if (bcProviderPosition != -1) { + // Bouncy Castle provider found -- install the workaround provider above it. + Security.insertProviderAt(workaroundProvider, bcProviderPosition); + } else { + // Bouncy Castle provider not found -- install the workaround provider at lowest + // priority. + Security.addProvider(workaroundProvider); + } } private void putSecretKeyFactoryImpl(String algorithm) { put("SecretKeyFactory." + algorithm, PACKAGE_NAME + ".KeyStoreSecretKeyFactorySpi"); } - private void putMacImpl(String algorithm, String implClass) { - put("Mac." + algorithm, implClass); - put("Mac." + algorithm + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME); - } - - private void putSymmetricCipherImpl(String transformation, String implClass) { - put("Cipher." + transformation, implClass); - put("Cipher." + transformation + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME); - } - /** * Gets the {@link KeyStore} operation handle corresponding to the provided JCA crypto * primitive. |