Chromium Code Reviews| 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..ed5fb6a5eef87f157f807e931483ff6a9e093bda 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, "Uable to reload the default TrustManager", |
| + e); |
| + } |
| + catch (KeyStoreException e) { |
| + Log.e(TAG, "Uable to reload the default TrustManager", |
| + e); |
| + } |
| + catch (NoSuchAlgorithmException e) { |
| + Log.e(TAG, "Uable 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 listen to change in the system keystore to invalidate certificate |
|
wtc
2013/10/16 15:37:34
Nit: listen => listens
qsr
2013/10/16 16:02:09
Done.
|
| + * 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, |
| + new IntentFilter(KeyChain.ACTION_STORAGE_CHANGED)); |
| + } |
| } |
| } |
| @@ -108,19 +148,29 @@ public class X509Util { |
| } |
| /** |
| + * After each modification by the systen of the key store, trust manager has to be regenerated. |
|
wtc
2013/10/16 15:37:34
Typo: systen => system
qsr
2013/10/16 16:02:09
Done.
|
| + */ |
| + 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 cert database that the system database has been updated. |
|
wtc
2013/10/16 15:37:34
Nit: cert database => net::CertDatabase class
to
qsr
2013/10/16 16:02:09
Done.
|
| + */ |
| + private static native void nativeNotifyCertDatabaseUpdated(); |
| + |
| } |