Index: net/base/x509_certificate_mac.cc |
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc |
index 44acddf78167f84f1a5b912954ccd172c5bf6d0f..93bf74b80232bf39b10438f1c33997fd9a880dea 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; |