| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/cert/cert_verify_proc_mac.h" | 5 #include "net/cert/cert_verify_proc_mac.h" |
| 6 | 6 |
| 7 #include <CommonCrypto/CommonDigest.h> | 7 #include <CommonCrypto/CommonDigest.h> |
| 8 #include <CoreServices/CoreServices.h> | 8 #include <CoreServices/CoreServices.h> |
| 9 #include <Security/Security.h> | 9 #include <Security/Security.h> |
| 10 | 10 |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 } | 508 } |
| 509 | 509 |
| 510 ~OSXKnownRootHelper() {} | 510 ~OSXKnownRootHelper() {} |
| 511 | 511 |
| 512 std::set<SHA256HashValue, SHA256HashValueLessThan> known_roots_; | 512 std::set<SHA256HashValue, SHA256HashValueLessThan> known_roots_; |
| 513 }; | 513 }; |
| 514 | 514 |
| 515 base::LazyInstance<OSXKnownRootHelper>::Leaky g_known_roots = | 515 base::LazyInstance<OSXKnownRootHelper>::Leaky g_known_roots = |
| 516 LAZY_INSTANCE_INITIALIZER; | 516 LAZY_INSTANCE_INITIALIZER; |
| 517 | 517 |
| 518 void log_cert(const void* value, void* context) { |
| 519 SecCertificateRef cert_ref = |
| 520 reinterpret_cast<SecCertificateRef>(const_cast<void*>(value)); |
| 521 // SHA256HashValue hash = X509Certificate::CalculateFingerprint256(cert_ref); |
| 522 scoped_refptr<X509Certificate> cert = |
| 523 X509Certificate::CreateFromHandle(cert_ref, {}); |
| 524 LOG(INFO) << cert->subject().GetDisplayName(); |
| 525 } |
| 526 |
| 527 void LogChain(CFArrayRef chain) { |
| 528 CFRange range = {0, CFArrayGetCount(chain)}; |
| 529 CFArrayApplyFunction(chain, range, log_cert, NULL); |
| 530 } |
| 531 |
| 518 } // namespace | 532 } // namespace |
| 519 | 533 |
| 520 CertVerifyProcMac::CertVerifyProcMac() {} | 534 CertVerifyProcMac::CertVerifyProcMac() {} |
| 521 | 535 |
| 522 CertVerifyProcMac::~CertVerifyProcMac() {} | 536 CertVerifyProcMac::~CertVerifyProcMac() {} |
| 523 | 537 |
| 524 bool CertVerifyProcMac::SupportsAdditionalTrustAnchors() const { | 538 bool CertVerifyProcMac::SupportsAdditionalTrustAnchors() const { |
| 525 return false; | 539 return false; |
| 526 } | 540 } |
| 527 | 541 |
| 528 bool CertVerifyProcMac::SupportsOCSPStapling() const { | 542 bool CertVerifyProcMac::SupportsOCSPStapling() const { |
| 529 // TODO(rsleevi): Plumb an OCSP response into the Mac system library. | 543 // TODO(rsleevi): Plumb an OCSP response into the Mac system library. |
| 530 // https://crbug.com/430714 | 544 // https://crbug.com/430714 |
| 531 return false; | 545 return false; |
| 532 } | 546 } |
| 533 | 547 |
| 534 int CertVerifyProcMac::VerifyInternal( | 548 int CertVerifyProcMac::VerifyInternal( |
| 535 X509Certificate* cert, | 549 X509Certificate* cert, |
| 536 const std::string& hostname, | 550 const std::string& hostname, |
| 537 const std::string& ocsp_response, | 551 const std::string& ocsp_response, |
| 538 int flags, | 552 int flags, |
| 539 CRLSet* crl_set, | 553 CRLSet* crl_set, |
| 540 const CertificateList& additional_trust_anchors, | 554 const CertificateList& additional_trust_anchors, |
| 541 CertVerifyResult* verify_result) { | 555 CertVerifyResult* verify_result) { |
| 556 LOG(INFO) << "CertVerifyProcMac::VerifyInternal starting for " << hostname; |
| 542 ScopedCFTypeRef<CFArrayRef> trust_policies; | 557 ScopedCFTypeRef<CFArrayRef> trust_policies; |
| 543 OSStatus status = CreateTrustPolicies(hostname, flags, &trust_policies); | 558 OSStatus status = CreateTrustPolicies(hostname, flags, &trust_policies); |
| 544 if (status) | 559 if (status) |
| 545 return NetErrorFromOSStatus(status); | 560 return NetErrorFromOSStatus(status); |
| 546 | 561 |
| 547 // Create and configure a SecTrustRef, which takes our certificate(s) | 562 // Create and configure a SecTrustRef, which takes our certificate(s) |
| 548 // and our SSL SecPolicyRef. SecTrustCreateWithCertificates() takes an | 563 // and our SSL SecPolicyRef. SecTrustCreateWithCertificates() takes an |
| 549 // array of certificates, the first of which is the certificate we're | 564 // array of certificates, the first of which is the certificate we're |
| 550 // verifying, and the subsequent (optional) certificates are used for | 565 // verifying, and the subsequent (optional) certificates are used for |
| 551 // chain building. | 566 // chain building. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 // | 622 // |
| 608 // This does cause a performance hit for these users, but only in cases where | 623 // This does cause a performance hit for these users, but only in cases where |
| 609 // OS X is building weaker chains than desired, or when it would otherwise | 624 // OS X is building weaker chains than desired, or when it would otherwise |
| 610 // fail the connection. | 625 // fail the connection. |
| 611 while (CFArrayGetCount(cert_array) > 0) { | 626 while (CFArrayGetCount(cert_array) > 0) { |
| 612 ScopedCFTypeRef<SecTrustRef> temp_ref; | 627 ScopedCFTypeRef<SecTrustRef> temp_ref; |
| 613 SecTrustResultType temp_trust_result = kSecTrustResultDeny; | 628 SecTrustResultType temp_trust_result = kSecTrustResultDeny; |
| 614 ScopedCFTypeRef<CFArrayRef> temp_chain; | 629 ScopedCFTypeRef<CFArrayRef> temp_chain; |
| 615 CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL; | 630 CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL; |
| 616 | 631 |
| 632 LOG(INFO) << "Trying chain of " << CFArrayGetCount(cert_array) << " certs:"; |
| 633 LogChain(cert_array); |
| 617 int rv = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, flags, | 634 int rv = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, flags, |
| 618 &temp_ref, &temp_trust_result, | 635 &temp_ref, &temp_trust_result, |
| 619 &temp_chain, &temp_chain_info); | 636 &temp_chain, &temp_chain_info); |
| 637 LOG(INFO) << "rv = " << rv; |
| 620 if (rv != OK) | 638 if (rv != OK) |
| 621 return rv; | 639 return rv; |
| 622 | 640 |
| 623 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified && | 641 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified && |
| 624 temp_trust_result != kSecTrustResultProceed); | 642 temp_trust_result != kSecTrustResultProceed); |
| 625 bool weak_chain = false; | 643 bool weak_chain = false; |
| 626 if (CFArrayGetCount(temp_chain) == 0) { | 644 if (CFArrayGetCount(temp_chain) == 0) { |
| 627 // If the chain is empty, it cannot be trusted or have recoverable | 645 // If the chain is empty, it cannot be trusted or have recoverable |
| 628 // errors. | 646 // errors. |
| 629 DCHECK(untrusted); | 647 DCHECK(untrusted); |
| 630 DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result); | 648 DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result); |
| 631 } else { | 649 } else { |
| 632 CertVerifyResult temp_verify_result; | 650 CertVerifyResult temp_verify_result; |
| 633 bool leaf_is_weak = false; | 651 bool leaf_is_weak = false; |
| 634 GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result, | 652 GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result, |
| 635 &leaf_is_weak); | 653 &leaf_is_weak); |
| 636 weak_chain = !leaf_is_weak && | 654 weak_chain = !leaf_is_weak && |
| 637 (temp_verify_result.has_md2 || temp_verify_result.has_md4 || | 655 (temp_verify_result.has_md2 || temp_verify_result.has_md4 || |
| 638 temp_verify_result.has_md5 || temp_verify_result.has_sha1); | 656 temp_verify_result.has_md5 || temp_verify_result.has_sha1); |
| 657 LOG(INFO) << "verified chain:"; |
| 658 LogChain(temp_chain); |
| 639 } | 659 } |
| 660 LOG(INFO) << "untrusted = " << untrusted << " weak_chain = " << weak_chain; |
| 640 // Set the result to the current chain if: | 661 // Set the result to the current chain if: |
| 641 // - This is the first verification attempt. This ensures that if | 662 // - This is the first verification attempt. This ensures that if |
| 642 // everything is awful (e.g. it may just be an untrusted cert), that | 663 // everything is awful (e.g. it may just be an untrusted cert), that |
| 643 // what is reported is exactly what was sent by the server | 664 // what is reported is exactly what was sent by the server |
| 644 // - If the current chain is trusted, and the old chain was not trusted, | 665 // - If the current chain is trusted, and the old chain was not trusted, |
| 645 // then prefer this chain. This ensures that if there is at least a | 666 // then prefer this chain. This ensures that if there is at least a |
| 646 // valid path to a trust anchor, it's preferred over reporting an error. | 667 // valid path to a trust anchor, it's preferred over reporting an error. |
| 647 // - If the current chain is trusted, and the old chain is trusted, but | 668 // - If the current chain is trusted, and the old chain is trusted, but |
| 648 // the old chain contained weak algorithms while the current chain only | 669 // the old chain contained weak algorithms while the current chain only |
| 649 // contains strong algorithms, then prefer the current chain over the | 670 // contains strong algorithms, then prefer the current chain over the |
| 650 // old chain. | 671 // old chain. |
| 651 // | 672 // |
| 652 // Note: If the leaf certificate itself is weak, then the only | 673 // Note: If the leaf certificate itself is weak, then the only |
| 653 // consideration is whether or not there is a trusted chain. That's | 674 // consideration is whether or not there is a trusted chain. That's |
| 654 // because no amount of path discovery will fix a weak leaf. | 675 // because no amount of path discovery will fix a weak leaf. |
| 655 if (!trust_ref || (!untrusted && (candidate_untrusted || | 676 if (!trust_ref || (!untrusted && (candidate_untrusted || |
| 656 (candidate_weak && !weak_chain)))) { | 677 (candidate_weak && !weak_chain)))) { |
| 657 trust_ref = temp_ref; | 678 trust_ref = temp_ref; |
| 658 trust_result = temp_trust_result; | 679 trust_result = temp_trust_result; |
| 659 completed_chain = temp_chain; | 680 completed_chain = temp_chain; |
| 660 chain_info = temp_chain_info; | 681 chain_info = temp_chain_info; |
| 661 | 682 |
| 662 candidate_untrusted = untrusted; | 683 candidate_untrusted = untrusted; |
| 663 candidate_weak = weak_chain; | 684 candidate_weak = weak_chain; |
| 664 } | 685 } |
| 665 // Short-circuit when a current, trusted chain is found. | 686 // Short-circuit when a current, trusted chain is found. |
| 666 if (!untrusted && !weak_chain) | 687 if (!untrusted && !weak_chain) { |
| 688 LOG(INFO) << "found a trusted, non-weak chain"; |
| 667 break; | 689 break; |
| 690 } |
| 668 CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1); | 691 CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1); |
| 669 } | 692 } |
| 670 | 693 |
| 671 if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) | 694 if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) |
| 672 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 695 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
| 673 | 696 |
| 674 if (crl_set && !CheckRevocationWithCRLSet(completed_chain, crl_set)) | 697 if (crl_set && !CheckRevocationWithCRLSet(completed_chain, crl_set)) |
| 675 verify_result->cert_status |= CERT_STATUS_REVOKED; | 698 verify_result->cert_status |= CERT_STATUS_REVOKED; |
| 676 | 699 |
| 677 if (CFArrayGetCount(completed_chain) > 0) { | 700 if (CFArrayGetCount(completed_chain) > 0) { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 } | 858 } |
| 836 } | 859 } |
| 837 } | 860 } |
| 838 | 861 |
| 839 return OK; | 862 return OK; |
| 840 } | 863 } |
| 841 | 864 |
| 842 } // namespace net | 865 } // namespace net |
| 843 | 866 |
| 844 #pragma clang diagnostic pop // "-Wdeprecated-declarations" | 867 #pragma clang diagnostic pop // "-Wdeprecated-declarations" |
| OLD | NEW |