summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityThread.java3
-rw-r--r--keystore/java/android/security/AndroidKeyStoreBCWorkaroundProvider.java83
-rw-r--r--keystore/java/android/security/AndroidKeyStoreProvider.java61
-rw-r--r--preloaded-classes1
4 files changed, 115 insertions, 33 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9bad9bb..2e45b79 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -114,7 +114,6 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
-import java.security.Security;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
@@ -5338,7 +5337,7 @@ public final class ActivityThread {
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
- Security.addProvider(new AndroidKeyStoreProvider());
+ AndroidKeyStoreProvider.install();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
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.
diff --git a/preloaded-classes b/preloaded-classes
index c94623a..d2ed762 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1152,6 +1152,7 @@ android.provider.Settings$SettingNotFoundException
android.provider.Settings$System
android.provider.Telephony$Mms
android.renderscript.RenderScript
+android.security.AndroidKeyStoreBCWorkaroundProvider
android.security.AndroidKeyStoreProvider
android.speech.tts.TextToSpeechService
android.speech.tts.TextToSpeechService$SpeechItemV1