summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-02 17:09:25 +0000
committerrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-02 17:09:25 +0000
commit3154f968c3bb1cc35a33faa7b6d3fd80677b3583 (patch)
tree6871baf94836d91ebb940879c0df794e6838e4e5 /net
parente876c27118d298051d2245d67f05aacee88adc48 (diff)
downloadchromium_src-3154f968c3bb1cc35a33faa7b6d3fd80677b3583.zip
chromium_src-3154f968c3bb1cc35a33faa7b6d3fd80677b3583.tar.gz
chromium_src-3154f968c3bb1cc35a33faa7b6d3fd80677b3583.tar.bz2
Record when certificates signed with md[2,4,5] are encountered on OS X.
R=wtc@chromium.org BUG=101123 Review URL: http://codereview.chromium.org/8374019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108308 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/x509_certificate_mac.cc88
-rw-r--r--net/base/x509_certificate_unittest.cc26
-rw-r--r--net/base/x509_certificate_win.cc6
3 files changed, 93 insertions, 27 deletions
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
index 44acddf..93bf74b 100644
--- a/net/base/x509_certificate_mac.cc
+++ b/net/base/x509_certificate_mac.cc
@@ -286,6 +286,77 @@ OSStatus CreateTrustPolicies(const std::string& hostname,
return noErr;
}
+// Saves some information about the certificate chain |cert_chain| in
+// |*verify_result|. The caller MUST initialize |*verify_result| before
+// calling this function.
+void GetCertChainInfo(CFArrayRef cert_chain,
+ CSSM_TP_APPLE_EVIDENCE_INFO* chain_info,
+ CertVerifyResult* verify_result) {
+ SecCertificateRef verified_cert = NULL;
+ std::vector<SecCertificateRef> verified_chain;
+ for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
+ SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>(
+ const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
+ if (i == 0) {
+ verified_cert = chain_cert;
+ } else {
+ verified_chain.push_back(chain_cert);
+ }
+
+ if ((chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_IN_ANCHORS) ||
+ (chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_ROOT)) {
+ // The current certificate is either in the user's trusted store or is
+ // a root (self-signed) certificate. Ignore the signature algorithm for
+ // these certificates, as it is meaningless for security. We allow
+ // self-signed certificates (i == 0 & IS_ROOT), since we accept that
+ // any security assertions by such a cert are inherently meaningless.
+ continue;
+ }
+
+ CSSMFields cssm_fields;
+ OSStatus status = GetCertFields(chain_cert, &cssm_fields);
+ if (status)
+ continue;
+ CSSM_FIELD_PTR fields = cssm_fields.fields;
+ for (size_t field = 0; field < cssm_fields.num_of_fields; ++field) {
+ if (!CSSMOIDEqual(&fields[field].FieldOid,
+ &CSSMOID_X509V1SignatureAlgorithm)) {
+ continue;
+ }
+
+ CSSM_X509_ALGORITHM_IDENTIFIER* signature_algorithm =
+ reinterpret_cast<CSSM_X509_ALGORITHM_IDENTIFIER*>(
+ fields[field].FieldValue.Data);
+ // Match the behaviour of OS X system tools and defensively check that
+ // sizes are appropriate. This would indicate a critical failure of the
+ // OS X certificate library, but based on history, it is best to play it
+ // safe.
+ if (!signature_algorithm || (fields[field].FieldValue.Length !=
+ sizeof(CSSM_X509_ALGORITHM_IDENTIFIER))) {
+ break;
+ }
+ CSSM_OID_PTR alg_oid = &signature_algorithm->algorithm;
+ if (CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA)) {
+ verify_result->has_md2 = true;
+ if (i != 0)
+ verify_result->has_md2_ca = true;
+ } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA)) {
+ verify_result->has_md4 = true;
+ } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA)) {
+ verify_result->has_md5 = true;
+ if (i != 0)
+ verify_result->has_md5_ca = true;
+ }
+ break;
+ }
+ }
+ if (!verified_cert)
+ return;
+
+ verify_result->verified_cert =
+ X509Certificate::CreateFromHandle(verified_cert, verified_chain);
+}
+
// Gets the issuer for a given cert, starting with the cert itself and
// including the intermediate and finally root certificates (if any).
// This function calls SecTrust but doesn't actually pay attention to the trust
@@ -830,22 +901,7 @@ int X509Certificate::VerifyInternal(const std::string& hostname,
return NetErrorFromOSStatus(status);
ScopedCFTypeRef<CFArrayRef> scoped_completed_chain(completed_chain);
- SecCertificateRef verified_cert = NULL;
- std::vector<SecCertificateRef> verified_chain;
- for (CFIndex i = 0, count = CFArrayGetCount(completed_chain);
- i < count; ++i) {
- SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>(
- const_cast<void*>(CFArrayGetValueAtIndex(completed_chain, i)));
- if (i == 0) {
- verified_cert = chain_cert;
- } else {
- verified_chain.push_back(chain_cert);
- }
- }
- if (verified_cert) {
- verify_result->verified_cert = CreateFromHandle(verified_cert,
- verified_chain);
- }
+ GetCertChainInfo(scoped_completed_chain.get(), chain_info, verify_result);
// Evaluate the results
OSStatus cssm_result;
diff --git a/net/base/x509_certificate_unittest.cc b/net/base/x509_certificate_unittest.cc
index c0240ea..21416b1 100644
--- a/net/base/x509_certificate_unittest.cc
+++ b/net/base/x509_certificate_unittest.cc
@@ -1489,8 +1489,8 @@ TEST_P(X509CertificateNameVerifyTest, VerifyHostname) {
INSTANTIATE_TEST_CASE_P(, X509CertificateNameVerifyTest,
testing::ValuesIn(kNameVerifyTestData));
-// Not implemented on Mac or OpenSSL - http://crbug.com/101123
-#if defined(USE_NSS) || defined(OS_WIN)
+// Not implemented on OpenSSL - http://crbug.com/101123
+#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
struct WeakDigestTestData {
const char* root_cert_filename;
@@ -1574,8 +1574,10 @@ TEST_P(X509CertificateWeakDigestTest, Verify) {
const WeakDigestTestData kVerifyRootCATestData[] = {
{ "weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_sha1_ee.pem", false, false, false, false, false },
+#if !defined(OS_MACOSX) // MD4 is not supported.
{ "weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_sha1_ee.pem", false, false, false, false, false },
+#endif
{ "weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_sha1_ee.pem", false, false, false, false, false },
};
@@ -1586,10 +1588,11 @@ INSTANTIATE_TEST_CASE_P(VerifyRoot, X509CertificateWeakDigestTest,
const WeakDigestTestData kVerifyIntermediateCATestData[] = {
{ "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem",
"weak_digest_sha1_ee.pem", true, false, false, true, false },
-// NSS does not support MD4 and does not enable MD2 by policy.
-#if !defined(USE_NSS)
+#if !defined(USE_NSS) && !defined(OS_MACOSX) // MD4 is not supported.
{ "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
"weak_digest_sha1_ee.pem", false, true, false, false, false },
+#endif
+#if !defined(USE_NSS) // MD2 is disabled by default.
{ "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem",
"weak_digest_sha1_ee.pem", false, false, true, false, true },
#endif
@@ -1601,10 +1604,11 @@ INSTANTIATE_TEST_CASE_P(VerifyIntermediate, X509CertificateWeakDigestTest,
const WeakDigestTestData kVerifyEndEntityTestData[] = {
{ "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_md5_ee.pem", true, false, false, false, false },
-// NSS does not support MD4 and does not enable MD2 by policy.
-#if !defined(USE_NSS)
+#if !defined(USE_NSS) && !defined(OS_MACOSX) // MD4 is not supported.
{ "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_md4_ee.pem", false, true, false, false, false },
+#endif
+#if !defined(USE_NSS) // MD2 is disabled by default.
{ "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
"weak_digest_md2_ee.pem", false, false, true, false, false },
#endif
@@ -1625,8 +1629,10 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(MAYBE_VerifyEndEntity,
const WeakDigestTestData kVerifyIncompleteIntermediateTestData[] = {
{ NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem",
true, false, false, true, false },
+#if !defined(OS_MACOSX) // MD4 is not supported.
{ NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem",
false, true, false, false, false },
+#endif
{ NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem",
false, false, true, false, true },
};
@@ -1647,8 +1653,10 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(
const WeakDigestTestData kVerifyIncompleteEETestData[] = {
{ NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md5_ee.pem",
true, false, false, false, false },
+#if !defined(OS_MACOSX) // MD4 is not supported.
{ NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md4_ee.pem",
false, true, false, false, false },
+#endif
{ NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md2_ee.pem",
false, false, true, false, false },
};
@@ -1671,10 +1679,12 @@ const WeakDigestTestData kVerifyMixedTestData[] = {
"weak_digest_md2_ee.pem", true, false, true, true, false },
{ "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem",
"weak_digest_md5_ee.pem", true, false, true, false, true },
+#if !defined(OS_MACOSX) // MD4 is not supported.
{ "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
"weak_digest_md2_ee.pem", false, true, true, false, false },
+#endif
};
-// NSS does not support MD4 and does not enable MD2 by policy, making all
+// NSS does not support MD4 and does not enable MD2 by default, making all
// permutations invalid.
#if defined(USE_NSS)
#define MAYBE_VerifyMixed DISABLED_VerifyMixed
@@ -1686,6 +1696,6 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(
X509CertificateWeakDigestTest,
testing::ValuesIn(kVerifyMixedTestData));
-#endif // defined(USE_NSS) || defined(OS_WIN)
+#endif // defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
} // namespace net
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc
index 4f0d40c..4905b0b 100644
--- a/net/base/x509_certificate_win.cc
+++ b/net/base/x509_certificate_win.cc
@@ -315,9 +315,9 @@ bool CertSubjectCommonNameHasNull(PCCERT_CONTEXT cert) {
return false;
}
-// Saves some information about the certificate chain chain_context in
-// *verify_result. The caller MUST initialize *verify_result before calling
-// this function.
+// Saves some information about the certificate chain |chain_context| in
+// |*verify_result|. The caller MUST initialize |*verify_result| before
+// calling this function.
void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,
CertVerifyResult* verify_result) {
if (chain_context->cChain == 0)