diff options
author | rsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-02 17:09:25 +0000 |
---|---|---|
committer | rsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-02 17:09:25 +0000 |
commit | 3154f968c3bb1cc35a33faa7b6d3fd80677b3583 (patch) | |
tree | 6871baf94836d91ebb940879c0df794e6838e4e5 /net | |
parent | e876c27118d298051d2245d67f05aacee88adc48 (diff) | |
download | chromium_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.cc | 88 | ||||
-rw-r--r-- | net/base/x509_certificate_unittest.cc | 26 | ||||
-rw-r--r-- | net/base/x509_certificate_win.cc | 6 |
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) |