Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Unified Diff: net/android/java/src/org/chromium/net/X509Util.java

Issue 27500004: Listen for new system certificates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Follow review Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/android/java/src/org/chromium/net/X509Util.java
diff --git a/net/android/java/src/org/chromium/net/X509Util.java b/net/android/java/src/org/chromium/net/X509Util.java
index 30007caab17d9ed60f8237f806d39e641e62634d..06cede71adf86c69ea6e0a96f60439596a62dd03 100644
--- a/net/android/java/src/org/chromium/net/X509Util.java
+++ b/net/android/java/src/org/chromium/net/X509Util.java
@@ -4,8 +4,14 @@
package org.chromium.net;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.security.KeyChain;
import android.util.Log;
+import org.chromium.base.JNINamespace;
import org.chromium.net.CertVerifyResultAndroid;
import java.io.ByteArrayInputStream;
@@ -25,10 +31,33 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
+@JNINamespace("net")
public class X509Util {
private static final String TAG = "X509Util";
+ public static final class TrustStorageListener extends BroadcastReceiver {
+ @Override public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) {
+ try {
+ reloadDefaultTrustManager(context);
+ }
+ catch (CertificateException e) {
+ Log.e(TAG, "Unable to reload the default TrustManager",
+ e);
joth 2013/10/17 22:43:54 nit: use 100-columns in java, no need to line wrap
qsr 2013/10/18 10:35:14 Done.
+ }
+ catch (KeyStoreException e) {
+ Log.e(TAG, "Unable to reload the default TrustManager",
+ e);
+ }
+ catch (NoSuchAlgorithmException e) {
+ Log.e(TAG, "Unable to reload the default TrustManager",
+ e);
+ }
+ }
+ }
+ }
+
private static CertificateFactory sCertificateFactory;
private static final String OID_TLS_SERVER_AUTH = "1.3.6.1.5.5.7.3.1";
@@ -45,6 +74,12 @@ public class X509Util {
private static X509TrustManager sDefaultTrustManager;
/**
+ * BroadcastReceiver that listens to change in the system keystore to invalidate certificate
+ * caches.
+ */
+ private static TrustStorageListener sTrustStorageListener;
+
+ /**
* Trust manager backed up by a custom certificate store. We need such manager to plant test
* root CA to the trust store in testing.
*/
@@ -59,7 +94,7 @@ public class X509Util {
/**
* Ensures that the trust managers and certificate factory are initialized.
*/
- private static void ensureInitialized() throws CertificateException,
+ private static void ensureInitialized(Context context) throws CertificateException,
KeyStoreException, NoSuchAlgorithmException {
synchronized(sLock) {
if (sCertificateFactory == null) {
@@ -77,6 +112,11 @@ public class X509Util {
if (sTestTrustManager == null) {
sTestTrustManager = X509Util.createTrustManager(sTestKeyStore);
}
+ if (sTrustStorageListener == null) {
+ sTrustStorageListener = new TrustStorageListener();
+ context.registerReceiver(sTrustStorageListener,
joth 2013/10/17 22:43:54 rather than plumb the context through numerous lay
qsr 2013/10/18 10:35:14 Done.
+ new IntentFilter(KeyChain.ACTION_STORAGE_CHANGED));
joth 2013/10/17 22:43:54 again, don't align with open paren
qsr 2013/10/18 10:35:14 Done.
+ }
}
}
@@ -108,19 +148,29 @@ public class X509Util {
}
/**
+ * After each modification by the system of the key store, trust manager has to be regenerated.
+ */
+ private static void reloadDefaultTrustManager(Context context) throws KeyStoreException,
+ NoSuchAlgorithmException, CertificateException {
+ sDefaultTrustManager = null;
+ nativeNotifyCertDatabaseUpdated();
+ ensureInitialized(context);
+ }
+
+ /**
* Convert a DER encoded certificate to an X509Certificate.
*/
- public static X509Certificate createCertificateFromBytes(byte[] derBytes) throws
- CertificateException, KeyStoreException, NoSuchAlgorithmException {
- ensureInitialized();
+ public static X509Certificate createCertificateFromBytes(Context context, byte[] derBytes)
+ throws CertificateException, KeyStoreException, NoSuchAlgorithmException {
+ ensureInitialized(context);
return (X509Certificate) sCertificateFactory.generateCertificate(
new ByteArrayInputStream(derBytes));
}
- public static void addTestRootCertificate(byte[] rootCertBytes) throws CertificateException,
- KeyStoreException, NoSuchAlgorithmException {
- ensureInitialized();
- X509Certificate rootCert = createCertificateFromBytes(rootCertBytes);
+ public static void addTestRootCertificate(Context context, byte[] rootCertBytes)
+ throws CertificateException, KeyStoreException, NoSuchAlgorithmException {
+ ensureInitialized(context);
+ X509Certificate rootCert = createCertificateFromBytes(context, rootCertBytes);
synchronized (sLock) {
sTestKeyStore.setCertificateEntry(
"root_cert_" + Integer.toString(sTestKeyStore.size()), rootCert);
@@ -128,9 +178,9 @@ public class X509Util {
}
}
- public static void clearTestRootCertificates() throws NoSuchAlgorithmException,
+ public static void clearTestRootCertificates(Context context) throws NoSuchAlgorithmException,
CertificateException, KeyStoreException {
- ensureInitialized();
+ ensureInitialized(context);
synchronized (sLock) {
try {
sTestKeyStore.load(null);
@@ -174,7 +224,7 @@ public class X509Util {
return false;
}
- public static int verifyServerCertificates(byte[][] certChain, String authType)
+ public static int verifyServerCertificates(Context context, byte[][] certChain, String authType)
throws KeyStoreException, NoSuchAlgorithmException {
if (certChain == null || certChain.length == 0 || certChain[0] == null) {
throw new IllegalArgumentException("Expected non-null and non-empty certificate " +
@@ -182,7 +232,7 @@ public class X509Util {
}
try {
- ensureInitialized();
+ ensureInitialized(context);
} catch (CertificateException e) {
return CertVerifyResultAndroid.VERIFY_FAILED;
}
@@ -190,7 +240,7 @@ public class X509Util {
X509Certificate[] serverCertificates = new X509Certificate[certChain.length];
try {
for (int i = 0; i < certChain.length; ++i) {
- serverCertificates[i] = createCertificateFromBytes(certChain[i]);
+ serverCertificates[i] = createCertificateFromBytes(context, certChain[i]);
}
} catch (CertificateException e) {
return CertVerifyResultAndroid.VERIFY_UNABLE_TO_PARSE;
@@ -230,4 +280,10 @@ public class X509Util {
}
}
}
+
+ /**
+ * Notify the native net::CertDatabase instance that the system database has been updated.
+ */
+ private static native void nativeNotifyCertDatabaseUpdated();
wtc 2013/10/17 20:43:59 Nit: Perhaps this native method should be renamed
qsr 2013/10/18 10:35:14 Done.
+
}

Powered by Google App Engine
This is Rietveld 408576698