summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/android/pylib/gtest/filter/net_unittests_disabled3
-rw-r--r--net/android/cert_verify_result_android.h26
-rw-r--r--net/android/cert_verify_result_android_list.h27
-rw-r--r--net/android/java/CertVerifyResultAndroid.template10
-rw-r--r--net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java25
-rw-r--r--net/android/java/src/org/chromium/net/X509Util.java59
-rw-r--r--net/android/network_library.cc11
-rw-r--r--net/android/network_library.h17
-rw-r--r--net/base/cert_verify_proc_android.cc19
-rw-r--r--net/base/cert_verify_proc_unittest.cc2
-rw-r--r--net/net.gyp21
11 files changed, 160 insertions, 60 deletions
diff --git a/build/android/pylib/gtest/filter/net_unittests_disabled b/build/android/pylib/gtest/filter/net_unittests_disabled
index 4d097ac..95b465b 100644
--- a/build/android/pylib/gtest/filter/net_unittests_disabled
+++ b/build/android/pylib/gtest/filter/net_unittests_disabled
@@ -1,6 +1,4 @@
# List of suppressions.
-CertVerifyProcTest.ExtraneousMD5RootCert
-CertVerifyProcTest.IntermediateCARequireExplicitPolicy
CertVerifyProcTest.PublicKeyHashes
CertVerifyProcTest.RejectWeakKeys
CertVerifyProcTest.VerifyReturnChainBasic
@@ -40,6 +38,7 @@ VerifyRoot/CertVerifyProcWeakDigestTest.Verify/2
# Fail only on bots.
CertVerifyProcTest.TestKnownRoot
CertVerifyProcTest.WithoutRevocationChecking
+CertVerifyProcTest.InvalidKeyUsage
HttpCache.RangeGET_Cancel
HttpCache.RangeGET_Cancel2
HttpCache.RangeGET_OK
diff --git a/net/android/cert_verify_result_android.h b/net/android/cert_verify_result_android.h
new file mode 100644
index 0000000..ac18c21
--- /dev/null
+++ b/net/android/cert_verify_result_android.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_ANDROID_CERT_VERIFY_RESULT_ANDROID_H_
+#define NET_ANDROID_CERT_VERIFY_RESULT_ANDROID_H_
+
+#include "base/basictypes.h"
+#include "base/platform_file.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+namespace android {
+
+enum CertVerifyResultAndroid {
+#define CERT_VERIFY_RESULT_ANDROID(label, value) VERIFY_ ## label = value,
+#include "net/android/cert_verify_result_android_list.h"
+#undef CERT_VERIFY_RESULT_ANDROID
+};
+
+} // namespace android
+
+} // namespace net
+
+#endif // NET_ANDROID_CERT_VERIFY_RESULT_ANDROID_H_
diff --git a/net/android/cert_verify_result_android_list.h b/net/android/cert_verify_result_android_list.h
new file mode 100644
index 0000000..201ea5a
--- /dev/null
+++ b/net/android/cert_verify_result_android_list.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file intentionally does not have header guards, it's included
+// inside a macro to generate enum.
+
+// This file contains the list of certificate verification results returned
+// from Java side to the C++ side.
+
+// Certificate is trusted.
+CERT_VERIFY_RESULT_ANDROID(OK, 0)
+
+// Certificate verification could not be conducted.
+CERT_VERIFY_RESULT_ANDROID(FAILED, -1)
+
+// Certificate is not trusted due to non-trusted root of the certificate chain.
+CERT_VERIFY_RESULT_ANDROID(NO_TRUSTED_ROOT, -2)
+
+// Certificate is not trusted because it has expired.
+CERT_VERIFY_RESULT_ANDROID(EXPIRED, -3)
+
+// Certificate is not trusted because it is not valid yet.
+CERT_VERIFY_RESULT_ANDROID(NOT_YET_VALID, -4)
+
+// Certificate is not trusted because it could not be parsed.
+CERT_VERIFY_RESULT_ANDROID(UNABLE_TO_PARSE, -5)
diff --git a/net/android/java/CertVerifyResultAndroid.template b/net/android/java/CertVerifyResultAndroid.template
new file mode 100644
index 0000000..b19e937
--- /dev/null
+++ b/net/android/java/CertVerifyResultAndroid.template
@@ -0,0 +1,10 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net;
+
+public class CertVerifyResultAndroid {
+#define CERT_VERIFY_RESULT_ANDROID(name, value) public static final int VERIFY_##name = value;
+#include "net/android/cert_verify_result_android_list.h"
+}
diff --git a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
index 69a5722..a075685 100644
--- a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
+++ b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
@@ -10,9 +10,10 @@ import android.content.Intent;
import android.security.KeyChain;
import android.util.Log;
-import org.chromium.net.CertificateMimeType;
import org.chromium.base.CalledByNative;
import org.chromium.base.CalledByNativeUnchecked;
+import org.chromium.net.CertVerifyResultAndroid;
+import org.chromium.net.CertificateMimeType;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -66,7 +67,7 @@ class AndroidNetworkLibrary {
* PKCS#12 keychain) through the system's CertInstaller activity.
*
* @param context: current application context.
- * @param file_type: cryptographic file type. E.g. CertificateMimeType.X509_USER_CERT
+ * @param cert_type: cryptographic file type. E.g. CertificateMimeType.X509_USER_CERT
* @param data: certificate/keychain data bytes.
* @return true on success, false on failure.
*
@@ -196,15 +197,17 @@ class AndroidNetworkLibrary {
*
* @param certChain The ASN.1 DER encoded bytes for certificates.
* @param authType The key exchange algorithm name (e.g. RSA)
- * @return true if the server is trusted
- * @throws CertificateException,KeyStoreException,NoSuchAlgorithmException
- * on error initializing the TrustManager or reading the
- * certChain
+ * @return Android certificate verification result code.
*/
- @CalledByNativeUnchecked
- public static boolean verifyServerCertificates(byte[][] certChain, String authType)
- throws CertificateException, KeyStoreException, NoSuchAlgorithmException {
- return X509Util.verifyServerCertificates(certChain, authType);
+ @CalledByNative
+ public static int verifyServerCertificates(byte[][] certChain, String authType) {
+ try {
+ return X509Util.verifyServerCertificates(certChain, authType);
+ } catch (KeyStoreException e) {
+ return CertVerifyResultAndroid.VERIFY_FAILED;
+ } catch (NoSuchAlgorithmException e) {
+ return CertVerifyResultAndroid.VERIFY_FAILED;
+ }
}
/**
@@ -226,4 +229,4 @@ class AndroidNetworkLibrary {
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 cbd4f4cf..6bbf171 100644
--- a/net/android/java/src/org/chromium/net/X509Util.java
+++ b/net/android/java/src/org/chromium/net/X509Util.java
@@ -6,12 +6,16 @@ package org.chromium.net;
import android.util.Log;
+import org.chromium.net.CertVerifyResultAndroid;
+
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
@@ -107,7 +111,7 @@ public class X509Util {
KeyStoreException, NoSuchAlgorithmException {
ensureInitialized();
X509Certificate rootCert = createCertificateFromBytes(rootCertBytes);
- synchronized(sLock) {
+ synchronized (sLock) {
sTestKeyStore.setCertificateEntry(
"root_cert_" + Integer.toString(sTestKeyStore.size()), rootCert);
reloadTestTrustManager();
@@ -117,45 +121,64 @@ public class X509Util {
public static void clearTestRootCertificates() throws NoSuchAlgorithmException,
CertificateException, KeyStoreException {
ensureInitialized();
- synchronized(sLock) {
+ synchronized (sLock) {
try {
sTestKeyStore.load(null);
reloadTestTrustManager();
- } catch(IOException e) {} // No IO operation is attempted.
+ } catch (IOException e) {} // No IO operation is attempted.
}
}
- public static boolean verifyServerCertificates(byte[][] certChain, String authType)
- throws CertificateException, KeyStoreException, NoSuchAlgorithmException {
+ public static int verifyServerCertificates(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 " +
"chain passed as |certChain|. |certChain|=" + certChain);
}
- ensureInitialized();
+ try {
+ ensureInitialized();
+ } catch (CertificateException e) {
+ return CertVerifyResultAndroid.VERIFY_FAILED;
+ }
+
X509Certificate[] serverCertificates = new X509Certificate[certChain.length];
- for (int i = 0; i < certChain.length; ++i) {
- serverCertificates[i] = createCertificateFromBytes(certChain[i]);
+ try {
+ for (int i = 0; i < certChain.length; ++i) {
+ serverCertificates[i] = createCertificateFromBytes(certChain[i]);
+ }
+ } catch (CertificateException e) {
+ return CertVerifyResultAndroid.VERIFY_UNABLE_TO_PARSE;
+ }
+
+ // Expired and not yet valid certificates would be rejected by the trust managers, but the
+ // trust managers report all certificate errors using the general CertificateException. In
+ // order to get more granular error information, cert validity time range is being checked
+ // separately.
+ try {
+ serverCertificates[0].checkValidity();
+ } catch (CertificateExpiredException e) {
+ return CertVerifyResultAndroid.VERIFY_EXPIRED;
+ } catch (CertificateNotYetValidException e) {
+ return CertVerifyResultAndroid.VERIFY_NOT_YET_VALID;
}
synchronized (sLock) {
try {
sDefaultTrustManager.checkServerTrusted(serverCertificates, authType);
- return true;
+ return CertVerifyResultAndroid.VERIFY_OK;
} catch (CertificateException eDefaultManager) {
try {
sTestTrustManager.checkServerTrusted(serverCertificates, authType);
- return true;
+ return CertVerifyResultAndroid.VERIFY_OK;
} 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());
+ // Neither of the trust managers confirms the validity of the certificate chain,
+ // log the error message returned by the system trust manager.
+ Log.i(TAG, "Failed to validate the certificate chain, error: " +
+ eDefaultManager.getMessage());
+ return CertVerifyResultAndroid.VERIFY_NO_TRUSTED_ROOT;
}
}
}
- return false;
}
-} \ No newline at end of file
+}
diff --git a/net/android/network_library.cc b/net/android/network_library.cc
index c1c4d5d..2407100 100644
--- a/net/android/network_library.cc
+++ b/net/android/network_library.cc
@@ -23,8 +23,9 @@ using base::android::ToJavaByteArray;
namespace net {
namespace android {
-VerifyResult VerifyX509CertChain(const std::vector<std::string>& cert_chain,
- const std::string& auth_type) {
+CertVerifyResultAndroid VerifyX509CertChain(
+ const std::vector<std::string>& cert_chain,
+ const std::string& auth_type) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobjectArray> chain_byte_array =
@@ -35,12 +36,10 @@ VerifyResult VerifyX509CertChain(const std::vector<std::string>& cert_chain,
ConvertUTF8ToJavaString(env, auth_type);
DCHECK(!auth_string.is_null());
- jboolean trusted = Java_AndroidNetworkLibrary_verifyServerCertificates(
+ jint result = Java_AndroidNetworkLibrary_verifyServerCertificates(
env, chain_byte_array.obj(), auth_string.obj());
- if (ClearException(env))
- return VERIFY_INVOCATION_ERROR;
- return trusted ? VERIFY_OK : VERIFY_NO_TRUSTED_ROOT;
+ return static_cast<CertVerifyResultAndroid>(result);
}
void AddTestRootCertificate(const uint8* cert, size_t len) {
diff --git a/net/android/network_library.h b/net/android/network_library.h
index 9db3e0e..451834e 100644
--- a/net/android/network_library.h
+++ b/net/android/network_library.h
@@ -11,28 +11,19 @@
#include <vector>
#include "base/basictypes.h"
+#include "net/android/cert_verify_result_android.h"
#include "net/base/mime_util.h"
#include "net/base/net_export.h"
namespace net {
namespace android {
-enum VerifyResult {
- // Certificate verification was successful.
- VERIFY_OK,
- // Certificate verification was failed. There is no detail error information
- // given by Android API.
- VERIFY_NO_TRUSTED_ROOT,
- // Error occurs when invoke JNI methods.
- VERIFY_INVOCATION_ERROR,
-};
-
// |cert_chain| is DER encoded chain of certificates, with the server's own
// certificate listed first.
// |auth_type| is as per the Java X509Certificate.checkServerTrusted method.
-
-VerifyResult VerifyX509CertChain(const std::vector<std::string>& cert_chain,
- const std::string& auth_type);
+CertVerifyResultAndroid 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.
diff --git a/net/base/cert_verify_proc_android.cc b/net/base/cert_verify_proc_android.cc
index a7b17e6..cbf9e29 100644
--- a/net/base/cert_verify_proc_android.cc
+++ b/net/base/cert_verify_proc_android.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/logging.h"
+#include "net/android/cert_verify_result_android.h"
#include "net/android/network_library.h"
#include "net/base/cert_status_flags.h"
#include "net/base/cert_verify_result.h"
@@ -23,23 +24,29 @@ namespace {
bool VerifyFromAndroidTrustManager(const std::vector<std::string>& cert_bytes,
CertVerifyResult* verify_result) {
// TODO(joth): Fetch the authentication type from SSL rather than hardcode.
- bool verified = true;
- android::VerifyResult result =
+ android::CertVerifyResultAndroid android_result =
android::VerifyX509CertChain(cert_bytes, "RSA");
- switch (result) {
+ switch (android_result) {
+ case android::VERIFY_FAILED:
+ return false;
case android::VERIFY_OK:
break;
case android::VERIFY_NO_TRUSTED_ROOT:
verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
break;
- case android::VERIFY_INVOCATION_ERROR:
- verified = false;
+ case android::VERIFY_EXPIRED:
+ case android::VERIFY_NOT_YET_VALID:
+ verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
+ break;
+ case android::VERIFY_UNABLE_TO_PARSE:
+ verify_result->cert_status |= CERT_STATUS_INVALID;
break;
default:
+ NOTREACHED();
verify_result->cert_status |= CERT_STATUS_INVALID;
break;
}
- return verified;
+ return true;
}
bool GetChainDEREncodedBytes(X509Certificate* cert,
diff --git a/net/base/cert_verify_proc_unittest.cc b/net/base/cert_verify_proc_unittest.cc
index 9dae0b2..e440563 100644
--- a/net/base/cert_verify_proc_unittest.cc
+++ b/net/base/cert_verify_proc_unittest.cc
@@ -131,7 +131,7 @@ TEST_F(CertVerifyProcTest, PaypalNullCertParsing) {
CertVerifyResult verify_result;
int error = Verify(paypal_null_cert, "www.paypal.com", flags, NULL,
&verify_result);
-#if defined(USE_NSS) || defined(OS_IOS)
+#if defined(USE_NSS) || defined(OS_IOS) || defined(OS_ANDROID)
EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error);
#else
// TOOD(bulach): investigate why macosx and win aren't returning
diff --git a/net/net.gyp b/net/net.gyp
index 9fad87b..6e15215 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -56,12 +56,14 @@
'net_resources',
],
'sources': [
+ 'android/cert_verify_result_android.h',
+ 'android/cert_verify_result_android_list.h',
+ 'android/gurl_utils.cc',
+ 'android/gurl_utils.h',
'android/keystore.cc',
'android/keystore.h',
'android/keystore_openssl.cc',
'android/keystore_openssl.h',
- 'android/gurl_utils.cc',
- 'android/gurl_utils.h',
'android/net_jni_registrar.cc',
'android/net_jni_registrar.h',
'android/network_change_notifier_android.cc',
@@ -2383,8 +2385,9 @@
},
'dependencies': [
'../base/base.gyp:base',
- 'net_errors_java',
+ 'cert_verify_result_android_java',
'certificate_mime_types_java',
+ 'net_errors_java',
'private_key_types_java',
],
'includes': [ '../build/java.gypi' ],
@@ -2437,6 +2440,18 @@
'includes': [ '../build/android/java_cpp_template.gypi' ],
},
{
+ 'target_name': 'cert_verify_result_android_java',
+ 'type': 'none',
+ 'sources': [
+ 'android/java/CertVerifyResultAndroid.template',
+ ],
+ 'variables': {
+ 'package_name': 'org.chromium.net',
+ 'template_deps': ['android/cert_verify_result_android_list.h'],
+ },
+ 'includes': [ '../build/android/java_cpp_template.gypi' ],
+ },
+ {
'target_name': 'private_key_types_java',
'type': 'none',
'sources': [