summaryrefslogtreecommitdiffstats
path: root/net/android
diff options
context:
space:
mode:
authorppi@chromium.org <ppi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-12 01:31:55 +0000
committerppi@chromium.org <ppi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-12 01:31:55 +0000
commit87ccb9908e00752d2aa07b5971c0b10210f61a9a (patch)
tree934842c1ae7df745ec5199844296eae91c5e2b25 /net/android
parent96a59d246092ff9ff5ad9e3a9d0a3f09125e6f78 (diff)
downloadchromium_src-87ccb9908e00752d2aa07b5971c0b10210f61a9a.zip
chromium_src-87ccb9908e00752d2aa07b5971c0b10210f61a9a.tar.gz
chromium_src-87ccb9908e00752d2aa07b5971c0b10210f61a9a.tar.bz2
Implement TestRootCerts for Android
Currently we are unable to plant our test root certificate in Android trust store to run our certificate verification tests against it. The patch adds custom test trust store to the java backend, allowing to run the certificate verification tests against custom set of root certificates. The actual installation of our test root certificate is being done by TestRootCerts class, consistently with what we do on other platforms. BUG=147786 Review URL: https://chromiumcodereview.appspot.com/11316210 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@172488 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/android')
-rw-r--r--net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java21
-rw-r--r--net/android/java/src/org/chromium/net/X509Util.java114
-rw-r--r--net/android/network_library.cc12
-rw-r--r--net/android/network_library.h7
4 files changed, 126 insertions, 28 deletions
diff --git a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
index 73225bd..69a5722 100644
--- a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
+++ b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
@@ -207,4 +207,23 @@ class AndroidNetworkLibrary {
return X509Util.verifyServerCertificates(certChain, authType);
}
-}
+ /**
+ * Adds a test root certificate to the local trust store.
+ * @param rootCert DER encoded bytes of the certificate.
+ */
+ @CalledByNativeUnchecked
+ public static void addTestRootCertificate(byte[] rootCert) throws CertificateException,
+ KeyStoreException, NoSuchAlgorithmException {
+ X509Util.addTestRootCertificate(rootCert);
+ }
+
+ /**
+ * Removes all test root certificates added by |addTestRootCertificate| calls from the local
+ * trust store.
+ */
+ @CalledByNativeUnchecked
+ public static void clearTestRootCertificates() throws NoSuchAlgorithmException,
+ CertificateException, KeyStoreException {
+ X509Util.clearTestRootCertificates();
+ }
+} \ No newline at end of file
diff --git a/net/android/java/src/org/chromium/net/X509Util.java b/net/android/java/src/org/chromium/net/X509Util.java
index 0c43b29..cbd4f4cf 100644
--- a/net/android/java/src/org/chromium/net/X509Util.java
+++ b/net/android/java/src/org/chromium/net/X509Util.java
@@ -7,6 +7,7 @@ package org.chromium.net;
import android.util.Log;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@@ -25,37 +26,56 @@ public class X509Util {
private static CertificateFactory sCertificateFactory;
/**
- * Default sources of authentication trust decisions and certificate object
- * creation.
+ * Trust manager backed up by the read-only system certificate store.
*/
private static X509TrustManager sDefaultTrustManager;
/**
- * Ensures that |sCertificateFactory| and |sDefaultTrustManager| are
- * initialized.
+ * Trust manager backed up by a custom certificate store. We need such manager to plant test
+ * root CA to the trust store in testing.
*/
- private static synchronized void ensureInitialized() throws CertificateException,
+ private static X509TrustManager sTestTrustManager;
+ private static KeyStore sTestKeyStore;
+
+ /**
+ * Lock object used to synchronize all calls that modify or depend on the trust managers.
+ */
+ private static final Object sLock = new Object();
+
+ /**
+ * Ensures that the trust managers and certificate factory are initialized.
+ */
+ private static void ensureInitialized() throws CertificateException,
KeyStoreException, NoSuchAlgorithmException {
- if (sCertificateFactory == null) {
- sCertificateFactory = CertificateFactory.getInstance("X.509");
- }
- if (sDefaultTrustManager == null) {
- sDefaultTrustManager = X509Util.createDefaultTrustManager();
+ synchronized(sLock) {
+ if (sCertificateFactory == null) {
+ sCertificateFactory = CertificateFactory.getInstance("X.509");
+ }
+ if (sDefaultTrustManager == null) {
+ sDefaultTrustManager = X509Util.createTrustManager(null);
+ }
+ if (sTestKeyStore == null) {
+ sTestKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ try {
+ sTestKeyStore.load(null);
+ } catch(IOException e) {} // No IO operation is attempted.
+ }
+ if (sTestTrustManager == null) {
+ sTestTrustManager = X509Util.createTrustManager(sTestKeyStore);
+ }
}
}
/**
- * Creates a TrustManagerFactory and returns the X509TrustManager instance
- * if one can be found.
- *
- * @throws CertificateException,KeyStoreException,NoSuchAlgorithmException
- * on error initializing the TrustManager.
+ * Creates a X509TrustManager backed up by the given key store. When null is passed as a key
+ * store, system default trust store is used.
+ * @throws KeyStoreException, NoSuchAlgorithmException on error initializing the TrustManager.
*/
- private static X509TrustManager createDefaultTrustManager()
- throws KeyStoreException, NoSuchAlgorithmException {
+ private static X509TrustManager createTrustManager(KeyStore keyStore) throws KeyStoreException,
+ NoSuchAlgorithmException {
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
- tmf.init((KeyStore) null);
+ tmf.init(keyStore);
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
@@ -66,7 +86,15 @@ public class X509Util {
}
/**
- * Convert a DER encoded certificate to an X509Certificate
+ * After each modification of test key store, trust manager has to be generated again.
+ */
+ private static void reloadTestTrustManager() throws KeyStoreException,
+ NoSuchAlgorithmException {
+ sTestTrustManager = X509Util.createTrustManager(sTestKeyStore);
+ }
+
+ /**
+ * Convert a DER encoded certificate to an X509Certificate.
*/
public static X509Certificate createCertificateFromBytes(byte[] derBytes) throws
CertificateException, KeyStoreException, NoSuchAlgorithmException {
@@ -75,6 +103,28 @@ public class X509Util {
new ByteArrayInputStream(derBytes));
}
+ public static void addTestRootCertificate(byte[] rootCertBytes) throws CertificateException,
+ KeyStoreException, NoSuchAlgorithmException {
+ ensureInitialized();
+ X509Certificate rootCert = createCertificateFromBytes(rootCertBytes);
+ synchronized(sLock) {
+ sTestKeyStore.setCertificateEntry(
+ "root_cert_" + Integer.toString(sTestKeyStore.size()), rootCert);
+ reloadTestTrustManager();
+ }
+ }
+
+ public static void clearTestRootCertificates() throws NoSuchAlgorithmException,
+ CertificateException, KeyStoreException {
+ ensureInitialized();
+ synchronized(sLock) {
+ try {
+ sTestKeyStore.load(null);
+ reloadTestTrustManager();
+ } catch(IOException e) {} // No IO operation is attempted.
+ }
+ }
+
public static boolean verifyServerCertificates(byte[][] certChain, String authType)
throws CertificateException, KeyStoreException, NoSuchAlgorithmException {
if (certChain == null || certChain.length == 0 || certChain[0] == null) {
@@ -88,14 +138,24 @@ public class X509Util {
serverCertificates[i] = createCertificateFromBytes(certChain[i]);
}
- try {
- sDefaultTrustManager.checkServerTrusted(serverCertificates, authType);
- return true;
- } catch (CertificateException e) {
- Log.i(TAG, "failed to validate the certificate chain, error: " +
- e.getMessage());
+ synchronized (sLock) {
+ try {
+ sDefaultTrustManager.checkServerTrusted(serverCertificates, authType);
+ return true;
+ } catch (CertificateException eDefaultManager) {
+ try {
+ sTestTrustManager.checkServerTrusted(serverCertificates, authType);
+ return true;
+ } catch (CertificateException eTestManager) {
+ /*
+ * Neither of the trust managers confirms the validity of the certificate
+ * chain, we emit the error message returned by the system trust manager.
+ */
+ Log.i(TAG, "failed to validate the certificate chain, error: " +
+ eDefaultManager.getMessage());
+ }
+ }
}
return false;
}
-
-}
+} \ No newline at end of file
diff --git a/net/android/network_library.cc b/net/android/network_library.cc
index ed538a2..c1c4d5d 100644
--- a/net/android/network_library.cc
+++ b/net/android/network_library.cc
@@ -43,6 +43,18 @@ VerifyResult VerifyX509CertChain(const std::vector<std::string>& cert_chain,
return trusted ? VERIFY_OK : VERIFY_NO_TRUSTED_ROOT;
}
+void AddTestRootCertificate(const uint8* cert, size_t len) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jbyteArray> cert_array = ToJavaByteArray(env, cert, len);
+ DCHECK(!cert_array.is_null());
+ Java_AndroidNetworkLibrary_addTestRootCertificate(env, cert_array.obj());
+}
+
+void ClearTestRootCertificates() {
+ JNIEnv* env = AttachCurrentThread();
+ Java_AndroidNetworkLibrary_clearTestRootCertificates(env);
+}
+
bool StoreKeyPair(const uint8* public_key,
size_t public_len,
const uint8* private_key,
diff --git a/net/android/network_library.h b/net/android/network_library.h
index 955603d..9db3e0e 100644
--- a/net/android/network_library.h
+++ b/net/android/network_library.h
@@ -34,6 +34,13 @@ enum VerifyResult {
VerifyResult VerifyX509CertChain(const std::vector<std::string>& cert_chain,
const std::string& auth_type);
+// Adds a certificate as a root trust certificate to the trust manager.
+// |cert| is DER encoded certificate, |len| is its length in bytes.
+void AddTestRootCertificate(const uint8* cert, size_t len);
+
+// Removes all root certificates added by |AddTestRootCertificate| calls.
+void ClearTestRootCertificates();
+
// Helper for the <keygen> handler. Passes the DER-encoded key pair via
// JNI to the Credentials store. Note that the public key must be a DER
// encoded SubjectPublicKeyInfo (X.509), as returned by i2d_PUBKEY()