| 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 |
| 11 #include <set> | |
| 12 #include <string> | 11 #include <string> |
| 13 #include <vector> | 12 #include <vector> |
| 14 | 13 |
| 15 #include "base/lazy_instance.h" | |
| 16 #include "base/logging.h" | 14 #include "base/logging.h" |
| 17 #include "base/mac/mac_logging.h" | 15 #include "base/mac/mac_logging.h" |
| 18 #include "base/mac/mac_util.h" | 16 #include "base/mac/mac_util.h" |
| 19 #include "base/mac/scoped_cftyperef.h" | 17 #include "base/mac/scoped_cftyperef.h" |
| 20 #include "base/sha1.h" | 18 #include "base/sha1.h" |
| 21 #include "base/strings/string_piece.h" | 19 #include "base/strings/string_piece.h" |
| 22 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
| 23 #include "crypto/mac_security_services_lock.h" | 21 #include "crypto/mac_security_services_lock.h" |
| 24 #include "crypto/sha2.h" | 22 #include "crypto/sha2.h" |
| 25 #include "net/base/hash_value.h" | 23 #include "net/base/hash_value.h" |
| 26 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
| 27 #include "net/cert/asn1_util.h" | 25 #include "net/cert/asn1_util.h" |
| 28 #include "net/cert/cert_status_flags.h" | 26 #include "net/cert/cert_status_flags.h" |
| 29 #include "net/cert/cert_verifier.h" | 27 #include "net/cert/cert_verifier.h" |
| 30 #include "net/cert/cert_verify_result.h" | 28 #include "net/cert/cert_verify_result.h" |
| 31 #include "net/cert/crl_set.h" | 29 #include "net/cert/crl_set.h" |
| 32 #include "net/cert/ev_root_ca_metadata.h" | 30 #include "net/cert/ev_root_ca_metadata.h" |
| 33 #include "net/cert/internal/certificate_policies.h" | 31 #include "net/cert/internal/certificate_policies.h" |
| 34 #include "net/cert/internal/parsed_certificate.h" | 32 #include "net/cert/internal/parsed_certificate.h" |
| 33 #include "net/cert/known_roots_mac.h" |
| 35 #include "net/cert/test_keychain_search_list_mac.h" | 34 #include "net/cert/test_keychain_search_list_mac.h" |
| 36 #include "net/cert/test_root_certs.h" | 35 #include "net/cert/test_root_certs.h" |
| 37 #include "net/cert/x509_certificate.h" | 36 #include "net/cert/x509_certificate.h" |
| 38 #include "net/cert/x509_util.h" | 37 #include "net/cert/x509_util.h" |
| 39 #include "net/cert/x509_util_mac.h" | 38 #include "net/cert/x509_util_mac.h" |
| 40 | 39 |
| 41 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. | 40 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. |
| 42 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 | 41 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 |
| 43 #pragma clang diagnostic push | 42 #pragma clang diagnostic push |
| 44 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 43 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| (...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 return NetErrorFromOSStatus(status); | 588 return NetErrorFromOSStatus(status); |
| 590 | 589 |
| 591 trust_ref->swap(scoped_tmp_trust); | 590 trust_ref->swap(scoped_tmp_trust); |
| 592 *trust_result = tmp_trust_result; | 591 *trust_result = tmp_trust_result; |
| 593 verified_chain->reset(tmp_verified_chain); | 592 verified_chain->reset(tmp_verified_chain); |
| 594 *chain_info = tmp_chain_info; | 593 *chain_info = tmp_chain_info; |
| 595 | 594 |
| 596 return OK; | 595 return OK; |
| 597 } | 596 } |
| 598 | 597 |
| 599 // Helper class for managing the set of OS X Known Roots. This is only safe | 598 // IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA |
| 600 // to initialize while the crypto::GetMacSecurityServicesLock() is held, due | 599 // that we recognise as a standard root. |
| 601 // to calling into Security.framework functions; however, once initialized, | 600 bool IsIssuedByKnownRoot(CFArrayRef chain) { |
| 602 // it can be called at any time. | 601 CFIndex n = CFArrayGetCount(chain); |
| 603 // In practice, due to lazy initialization, it's best to just always guard | 602 if (n < 1) |
| 604 // accesses with the lock. | 603 return false; |
| 605 class OSXKnownRootHelper { | 604 SecCertificateRef root_ref = reinterpret_cast<SecCertificateRef>( |
| 606 public: | 605 const_cast<void*>(CFArrayGetValueAtIndex(chain, n - 1))); |
| 607 // IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA | 606 return IsKnownRoot(root_ref); |
| 608 // that we recognise as a standard root. | 607 } |
| 609 bool IsIssuedByKnownRoot(CFArrayRef chain) { | |
| 610 // If there are no known roots, then an API failure occurred. For safety, | |
| 611 // assume that all certificates are issued by known roots. | |
| 612 if (known_roots_.empty()) | |
| 613 return true; | |
| 614 | |
| 615 CFIndex n = CFArrayGetCount(chain); | |
| 616 if (n < 1) | |
| 617 return false; | |
| 618 SecCertificateRef root_ref = reinterpret_cast<SecCertificateRef>( | |
| 619 const_cast<void*>(CFArrayGetValueAtIndex(chain, n - 1))); | |
| 620 SHA256HashValue hash = x509_util::CalculateFingerprint256(root_ref); | |
| 621 return known_roots_.find(hash) != known_roots_.end(); | |
| 622 } | |
| 623 | |
| 624 private: | |
| 625 friend struct base::LazyInstanceTraitsBase<OSXKnownRootHelper>; | |
| 626 | |
| 627 OSXKnownRootHelper() { | |
| 628 CFArrayRef cert_array = NULL; | |
| 629 OSStatus rv = SecTrustSettingsCopyCertificates( | |
| 630 kSecTrustSettingsDomainSystem, &cert_array); | |
| 631 if (rv != noErr) { | |
| 632 LOG(ERROR) << "Unable to determine trusted roots; assuming all roots are " | |
| 633 << "trusted! Error " << rv; | |
| 634 return; | |
| 635 } | |
| 636 base::ScopedCFTypeRef<CFArrayRef> scoped_array(cert_array); | |
| 637 for (CFIndex i = 0, size = CFArrayGetCount(cert_array); i < size; ++i) { | |
| 638 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>( | |
| 639 const_cast<void*>(CFArrayGetValueAtIndex(cert_array, i))); | |
| 640 known_roots_.insert(x509_util::CalculateFingerprint256(cert)); | |
| 641 } | |
| 642 } | |
| 643 | |
| 644 ~OSXKnownRootHelper() {} | |
| 645 | |
| 646 std::set<SHA256HashValue, SHA256HashValueLessThan> known_roots_; | |
| 647 }; | |
| 648 | |
| 649 base::LazyInstance<OSXKnownRootHelper>::Leaky g_known_roots = | |
| 650 LAZY_INSTANCE_INITIALIZER; | |
| 651 | 608 |
| 652 // Runs path building & verification loop for |cert|, given |flags|. This is | 609 // Runs path building & verification loop for |cert|, given |flags|. This is |
| 653 // split into a separate function so verification can be repeated with different | 610 // split into a separate function so verification can be repeated with different |
| 654 // flags. This function does not handle EV. | 611 // flags. This function does not handle EV. |
| 655 int VerifyWithGivenFlags(X509Certificate* cert, | 612 int VerifyWithGivenFlags(X509Certificate* cert, |
| 656 const std::string& hostname, | 613 const std::string& hostname, |
| 657 const int flags, | 614 const int flags, |
| 658 CRLSet* crl_set, | 615 CRLSet* crl_set, |
| 659 CertVerifyResult* verify_result, | 616 CertVerifyResult* verify_result, |
| 660 CRLSetResult* completed_chain_crl_result) { | 617 CRLSetResult* completed_chain_crl_result) { |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 // Hostname validation is handled by CertVerifyProc, so mask off any errors | 956 // Hostname validation is handled by CertVerifyProc, so mask off any errors |
| 1000 // that SecTrustEvaluate may have set, as its results are not used. | 957 // that SecTrustEvaluate may have set, as its results are not used. |
| 1001 verify_result->cert_status &= ~CERT_STATUS_COMMON_NAME_INVALID; | 958 verify_result->cert_status &= ~CERT_STATUS_COMMON_NAME_INVALID; |
| 1002 | 959 |
| 1003 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be | 960 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be |
| 1004 // compatible with Windows, which in turn implements this behavior to be | 961 // compatible with Windows, which in turn implements this behavior to be |
| 1005 // compatible with WinHTTP, which doesn't report this error (bug 3004). | 962 // compatible with WinHTTP, which doesn't report this error (bug 3004). |
| 1006 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; | 963 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; |
| 1007 | 964 |
| 1008 AppendPublicKeyHashes(completed_chain, &verify_result->public_key_hashes); | 965 AppendPublicKeyHashes(completed_chain, &verify_result->public_key_hashes); |
| 1009 verify_result->is_issued_by_known_root = | 966 verify_result->is_issued_by_known_root = IsIssuedByKnownRoot(completed_chain); |
| 1010 g_known_roots.Get().IsIssuedByKnownRoot(completed_chain); | |
| 1011 | 967 |
| 1012 if (IsCertStatusError(verify_result->cert_status)) | 968 if (IsCertStatusError(verify_result->cert_status)) |
| 1013 return MapCertStatusToNetError(verify_result->cert_status); | 969 return MapCertStatusToNetError(verify_result->cert_status); |
| 1014 | 970 |
| 1015 return OK; | 971 return OK; |
| 1016 } | 972 } |
| 1017 | 973 |
| 1018 } // namespace | 974 } // namespace |
| 1019 | 975 |
| 1020 CertVerifyProcMac::CertVerifyProcMac() {} | 976 CertVerifyProcMac::CertVerifyProcMac() {} |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 // EV cert and it was covered by CRLSets or revocation checking passed. | 1037 // EV cert and it was covered by CRLSets or revocation checking passed. |
| 1082 verify_result->cert_status |= CERT_STATUS_IS_EV; | 1038 verify_result->cert_status |= CERT_STATUS_IS_EV; |
| 1083 } | 1039 } |
| 1084 | 1040 |
| 1085 return OK; | 1041 return OK; |
| 1086 } | 1042 } |
| 1087 | 1043 |
| 1088 } // namespace net | 1044 } // namespace net |
| 1089 | 1045 |
| 1090 #pragma clang diagnostic pop // "-Wdeprecated-declarations" | 1046 #pragma clang diagnostic pop // "-Wdeprecated-declarations" |
| OLD | NEW |