Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: net/cert/cert_verify_proc_mac.cc

Issue 2101303005: CertVerifyProcMac: Add Keychain re-ordering hack, check CRLsets in path pruning loop. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/BUILD.gn ('k') | net/cert/cert_verify_proc_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 10 matching lines...) Expand all
21 #include "base/synchronization/lock.h" 21 #include "base/synchronization/lock.h"
22 #include "crypto/mac_security_services_lock.h" 22 #include "crypto/mac_security_services_lock.h"
23 #include "crypto/sha2.h" 23 #include "crypto/sha2.h"
24 #include "net/base/hash_value.h" 24 #include "net/base/hash_value.h"
25 #include "net/base/net_errors.h" 25 #include "net/base/net_errors.h"
26 #include "net/cert/asn1_util.h" 26 #include "net/cert/asn1_util.h"
27 #include "net/cert/cert_status_flags.h" 27 #include "net/cert/cert_status_flags.h"
28 #include "net/cert/cert_verifier.h" 28 #include "net/cert/cert_verifier.h"
29 #include "net/cert/cert_verify_result.h" 29 #include "net/cert/cert_verify_result.h"
30 #include "net/cert/crl_set.h" 30 #include "net/cert/crl_set.h"
31 #include "net/cert/test_keychain_search_list_mac.h"
31 #include "net/cert/test_root_certs.h" 32 #include "net/cert/test_root_certs.h"
32 #include "net/cert/x509_certificate.h" 33 #include "net/cert/x509_certificate.h"
33 #include "net/cert/x509_util_mac.h" 34 #include "net/cert/x509_util_mac.h"
34 35
35 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. 36 // CSSM functions are deprecated as of OSX 10.7, but have no replacement.
36 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 37 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1
37 #pragma clang diagnostic push 38 #pragma clang diagnostic push
38 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 39 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
39 40
40 // From 10.7.2 libsecurity_keychain-55035/lib/SecTrustPriv.h, for use with 41 // From 10.7.2 libsecurity_keychain-55035/lib/SecTrustPriv.h, for use with
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 // specific status for (such as basic constraints violation, or 142 // specific status for (such as basic constraints violation, or
142 // unknown critical extension) 143 // unknown critical extension)
143 OSSTATUS_LOG(WARNING, status) 144 OSSTATUS_LOG(WARNING, status)
144 << "Unknown error mapped to CERT_STATUS_INVALID"; 145 << "Unknown error mapped to CERT_STATUS_INVALID";
145 return CERT_STATUS_INVALID; 146 return CERT_STATUS_INVALID;
146 } 147 }
147 } 148 }
148 } 149 }
149 150
150 // Creates a series of SecPolicyRefs to be added to a SecTrustRef used to 151 // Creates a series of SecPolicyRefs to be added to a SecTrustRef used to
151 // validate a certificate for an SSL server. |hostname| contains the name of 152 // validate a certificate for an SSL server. |flags| is a bitwise-OR of
152 // the SSL server that the certificate should be verified against. |flags| is 153 // VerifyFlags that can further alter how trust is validated, such as how
153 // a bitwise-OR of VerifyFlags that can further alter how trust is validated, 154 // revocation is checked. If successful, returns noErr, and stores the
154 // such as how revocation is checked. If successful, returns noErr, and 155 // resultant array of SecPolicyRefs in |policies|.
155 // stores the resultant array of SecPolicyRefs in |policies|. 156 OSStatus CreateTrustPolicies(int flags, ScopedCFTypeRef<CFArrayRef>* policies) {
156 OSStatus CreateTrustPolicies(const std::string& hostname,
157 int flags,
158 ScopedCFTypeRef<CFArrayRef>* policies) {
159 ScopedCFTypeRef<CFMutableArrayRef> local_policies( 157 ScopedCFTypeRef<CFMutableArrayRef> local_policies(
160 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); 158 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
161 if (!local_policies) 159 if (!local_policies)
162 return memFullErr; 160 return memFullErr;
163 161
164 SecPolicyRef ssl_policy; 162 SecPolicyRef ssl_policy;
165 OSStatus status = x509_util::CreateSSLServerPolicy(hostname, &ssl_policy); 163 OSStatus status =
164 x509_util::CreateSSLServerPolicy(std::string(), &ssl_policy);
166 if (status) 165 if (status)
167 return status; 166 return status;
168 CFArrayAppendValue(local_policies, ssl_policy); 167 CFArrayAppendValue(local_policies, ssl_policy);
169 CFRelease(ssl_policy); 168 CFRelease(ssl_policy);
170 169
171 // Explicitly add revocation policies, in order to override system 170 // Explicitly add revocation policies, in order to override system
172 // revocation checking policies and instead respect the application-level 171 // revocation checking policies and instead respect the application-level
173 // revocation preference. 172 // revocation preference.
174 status = x509_util::CreateRevocationPolicies( 173 status = x509_util::CreateRevocationPolicies(
175 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED), 174 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED),
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 // failure, no output parameters are modified. 369 // failure, no output parameters are modified.
371 // 370 //
372 // Note: An OK return does not mean that |cert_array| is trusted, merely that 371 // Note: An OK return does not mean that |cert_array| is trusted, merely that
373 // verification was performed successfully. 372 // verification was performed successfully.
374 // 373 //
375 // This function should only be called while the Mac Security Services lock is 374 // This function should only be called while the Mac Security Services lock is
376 // held. 375 // held.
377 int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array, 376 int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array,
378 CFArrayRef trust_policies, 377 CFArrayRef trust_policies,
379 int flags, 378 int flags,
379 CFArrayRef keychain_search_list,
380 ScopedCFTypeRef<SecTrustRef>* trust_ref, 380 ScopedCFTypeRef<SecTrustRef>* trust_ref,
381 SecTrustResultType* trust_result, 381 SecTrustResultType* trust_result,
382 ScopedCFTypeRef<CFArrayRef>* verified_chain, 382 ScopedCFTypeRef<CFArrayRef>* verified_chain,
383 CSSM_TP_APPLE_EVIDENCE_INFO** chain_info) { 383 CSSM_TP_APPLE_EVIDENCE_INFO** chain_info) {
384 SecTrustRef tmp_trust = NULL; 384 SecTrustRef tmp_trust = NULL;
385 OSStatus status = SecTrustCreateWithCertificates(cert_array, trust_policies, 385 OSStatus status = SecTrustCreateWithCertificates(cert_array, trust_policies,
386 &tmp_trust); 386 &tmp_trust);
387 if (status) 387 if (status)
388 return NetErrorFromOSStatus(status); 388 return NetErrorFromOSStatus(status);
389 ScopedCFTypeRef<SecTrustRef> scoped_tmp_trust(tmp_trust); 389 ScopedCFTypeRef<SecTrustRef> scoped_tmp_trust(tmp_trust);
390 390
391 if (TestRootCerts::HasInstance()) { 391 if (TestRootCerts::HasInstance()) {
392 status = TestRootCerts::GetInstance()->FixupSecTrustRef(tmp_trust); 392 status = TestRootCerts::GetInstance()->FixupSecTrustRef(tmp_trust);
393 if (status) 393 if (status)
394 return NetErrorFromOSStatus(status); 394 return NetErrorFromOSStatus(status);
395 } 395 }
396 396
397 if (keychain_search_list) {
398 status = SecTrustSetKeychains(tmp_trust, keychain_search_list);
399 if (status)
400 return NetErrorFromOSStatus(status);
401 }
402
397 CSSM_APPLE_TP_ACTION_DATA tp_action_data; 403 CSSM_APPLE_TP_ACTION_DATA tp_action_data;
398 memset(&tp_action_data, 0, sizeof(tp_action_data)); 404 memset(&tp_action_data, 0, sizeof(tp_action_data));
399 tp_action_data.Version = CSSM_APPLE_TP_ACTION_VERSION; 405 tp_action_data.Version = CSSM_APPLE_TP_ACTION_VERSION;
400 // Allow CSSM to download any missing intermediate certificates if an 406 // Allow CSSM to download any missing intermediate certificates if an
401 // authorityInfoAccess extension or issuerAltName extension is present. 407 // authorityInfoAccess extension or issuerAltName extension is present.
402 tp_action_data.ActionFlags = CSSM_TP_ACTION_FETCH_CERT_FROM_NET | 408 tp_action_data.ActionFlags = CSSM_TP_ACTION_FETCH_CERT_FROM_NET |
403 CSSM_TP_ACTION_TRUST_SETTINGS; 409 CSSM_TP_ACTION_TRUST_SETTINGS;
404 410
405 // Note: For EV certificates, the Apple TP will handle setting these flags 411 // Note: For EV certificates, the Apple TP will handle setting these flags
406 // as part of EV evaluation. 412 // as part of EV evaluation.
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 539
534 int CertVerifyProcMac::VerifyInternal( 540 int CertVerifyProcMac::VerifyInternal(
535 X509Certificate* cert, 541 X509Certificate* cert,
536 const std::string& hostname, 542 const std::string& hostname,
537 const std::string& ocsp_response, 543 const std::string& ocsp_response,
538 int flags, 544 int flags,
539 CRLSet* crl_set, 545 CRLSet* crl_set,
540 const CertificateList& additional_trust_anchors, 546 const CertificateList& additional_trust_anchors,
541 CertVerifyResult* verify_result) { 547 CertVerifyResult* verify_result) {
542 ScopedCFTypeRef<CFArrayRef> trust_policies; 548 ScopedCFTypeRef<CFArrayRef> trust_policies;
543 OSStatus status = CreateTrustPolicies(hostname, flags, &trust_policies); 549 OSStatus status = CreateTrustPolicies(flags, &trust_policies);
544 if (status) 550 if (status)
545 return NetErrorFromOSStatus(status); 551 return NetErrorFromOSStatus(status);
546 552
547 // Create and configure a SecTrustRef, which takes our certificate(s)
548 // and our SSL SecPolicyRef. SecTrustCreateWithCertificates() takes an
549 // array of certificates, the first of which is the certificate we're
550 // verifying, and the subsequent (optional) certificates are used for
551 // chain building.
552 ScopedCFTypeRef<CFMutableArrayRef> cert_array(
553 cert->CreateOSCertChainForCert());
554
555 // Serialize all calls that may use the Keychain, to work around various 553 // Serialize all calls that may use the Keychain, to work around various
556 // issues in OS X 10.6+ with multi-threaded access to Security.framework. 554 // issues in OS X 10.6+ with multi-threaded access to Security.framework.
557 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); 555 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
558 556
559 ScopedCFTypeRef<SecTrustRef> trust_ref; 557 ScopedCFTypeRef<SecTrustRef> trust_ref;
560 SecTrustResultType trust_result = kSecTrustResultDeny; 558 SecTrustResultType trust_result = kSecTrustResultDeny;
561 ScopedCFTypeRef<CFArrayRef> completed_chain; 559 ScopedCFTypeRef<CFArrayRef> completed_chain;
562 CSSM_TP_APPLE_EVIDENCE_INFO* chain_info = NULL; 560 CSSM_TP_APPLE_EVIDENCE_INFO* chain_info = NULL;
563 bool candidate_untrusted = true; 561 bool candidate_untrusted = true;
564 bool candidate_weak = false; 562 bool candidate_weak = false;
563 bool completed_chain_revoked = false;
565 564
566 // OS X lacks proper path discovery; it will take the input certs and never 565 // OS X lacks proper path discovery; it will take the input certs and never
567 // backtrack the graph attempting to discover valid paths. 566 // backtrack the graph attempting to discover valid paths.
568 // This can create issues in some situations: 567 // This can create issues in some situations:
569 // - When OS X changes the trust store, there may be a chain 568 // - When OS X changes the trust store, there may be a chain
570 // A -> B -> C -> D 569 // A -> B -> C -> D
571 // where OS X trusts D (on some versions) and trusts C (on some versions). 570 // where OS X trusts D (on some versions) and trusts C (on some versions).
572 // If a server supplies a chain A, B, C (cross-signed by D), then this chain 571 // If a server supplies a chain A, B, C (cross-signed by D), then this chain
573 // will successfully validate on systems that trust D, but fail for systems 572 // will successfully validate on systems that trust D, but fail for systems
574 // that trust C. If the server supplies a chain of A -> B, then it forces 573 // that trust C. If the server supplies a chain of A -> B, then it forces
(...skipping 15 matching lines...) Expand all
590 // version of C signed by D is signed using a weak algorithm (e.g. SHA-1), 589 // version of C signed by D is signed using a weak algorithm (e.g. SHA-1),
591 // while the version of C in the trust store's signature doesn't matter. 590 // while the version of C in the trust store's signature doesn't matter.
592 // Since a 'strong' chain exists, it would be desirable to prefer this 591 // Since a 'strong' chain exists, it would be desirable to prefer this
593 // chain. 592 // chain.
594 // 593 //
595 // - A variant of the above example, it may be that the version of B sent by 594 // - A variant of the above example, it may be that the version of B sent by
596 // the server is signed using a weak algorithm, but the version of B 595 // the server is signed using a weak algorithm, but the version of B
597 // present in the AIA of A is signed using a strong algorithm. Since a 596 // present in the AIA of A is signed using a strong algorithm. Since a
598 // 'strong' chain exists, it would be desirable to prefer this chain. 597 // 'strong' chain exists, it would be desirable to prefer this chain.
599 // 598 //
599 // - A user keychain may contain a less desirable intermediate or root.
600 // OS X gives the user keychains higher priority than the system keychain,
601 // so it may build a weak chain.
602 //
600 // Because of this, the code below first attempts to validate the peer's 603 // Because of this, the code below first attempts to validate the peer's
601 // identity using the supplied chain. If it is not trusted (e.g. the OS only 604 // identity using the supplied chain. If it is not trusted (e.g. the OS only
602 // trusts C, but the version of C signed by D was sent, and D is not trusted), 605 // trusts C, but the version of C signed by D was sent, and D is not trusted),
603 // or if it contains a weak chain, it will begin lopping off certificates 606 // or if it contains a weak chain, it will begin lopping off certificates
604 // from the end of the chain and attempting to verify. If a stronger, trusted 607 // from the end of the chain and attempting to verify. If a stronger, trusted
605 // chain is found, it is used, otherwise, the algorithm continues until only 608 // chain is found, it is used, otherwise, the algorithm continues until only
606 // the peer's certificate remains. 609 // the peer's certificate remains.
607 // 610 //
611 // If the loop does not find a trusted chain, the loop will be repeated with
612 // the keychain search order altered to give priority to the System Roots
613 // keychain.
614 //
608 // This does cause a performance hit for these users, but only in cases where 615 // 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 616 // OS X is building weaker chains than desired, or when it would otherwise
610 // fail the connection. 617 // fail the connection.
611 while (CFArrayGetCount(cert_array) > 0) { 618 for (bool try_reordered_keychain : {false, true}) {
612 ScopedCFTypeRef<SecTrustRef> temp_ref; 619 ScopedCFTypeRef<CFArrayRef> scoped_alternate_keychain_search_list;
613 SecTrustResultType temp_trust_result = kSecTrustResultDeny; 620 if (TestKeychainSearchList::HasInstance()) {
614 ScopedCFTypeRef<CFArrayRef> temp_chain; 621 // Unit tests need to be able to hermetically simulate situations where a
615 CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL; 622 // user has an undesirable certificate in a per-user keychain.
623 // Adding/Removing a Keychain using SecKeychainCreate/SecKeychainDelete
624 // has global side effects, which would break other tests and processes
625 // running on the same machine, so instead tests may load pre-created
626 // keychains using SecKeychainOpen and then inject them through
627 // TestKeychainSearchList.
628 CFArrayRef keychain_search_list;
629 status = TestKeychainSearchList::GetInstance()->CopySearchList(
630 &keychain_search_list);
631 if (status)
632 return NetErrorFromOSStatus(status);
633 scoped_alternate_keychain_search_list.reset(keychain_search_list);
634 }
635 if (try_reordered_keychain) {
636 // If a TestKeychainSearchList is present, it will have already set
637 // |scoped_alternate_keychain_search_list|, which will be used as the
638 // basis for reordering the keychain. Otherwise, get the current keychain
639 // search list and use that.
640 if (!scoped_alternate_keychain_search_list) {
641 CFArrayRef keychain_search_list;
642 status = SecKeychainCopySearchList(&keychain_search_list);
643 if (status)
644 return NetErrorFromOSStatus(status);
645 scoped_alternate_keychain_search_list.reset(keychain_search_list);
646 }
647 CFMutableArrayRef mutable_keychain_search_list = CFArrayCreateMutableCopy(
648 kCFAllocatorDefault,
649 CFArrayGetCount(scoped_alternate_keychain_search_list.get()) + 1,
650 scoped_alternate_keychain_search_list.get());
651 if (!mutable_keychain_search_list)
652 return ERR_OUT_OF_MEMORY;
653 scoped_alternate_keychain_search_list.reset(mutable_keychain_search_list);
616 654
617 int rv = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, flags, 655 SecKeychainRef keychain;
618 &temp_ref, &temp_trust_result, 656 // Get a reference to the System Roots keychain. The System Roots
619 &temp_chain, &temp_chain_info); 657 // keychain is not normally present in the keychain search list, but is
620 if (rv != OK) 658 // implicitly checked after the keychains in the search list. By
621 return rv; 659 // including it directly, force it to be checked first. This is a gross
660 // hack, but the path is known to be valid on OS X 10.9-10.11.
661 status = SecKeychainOpen(
662 "/System/Library/Keychains/SystemRootCertificates.keychain",
663 &keychain);
664 if (status)
665 return NetErrorFromOSStatus(status);
666 ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain);
622 667
623 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified && 668 CFArrayInsertValueAtIndex(mutable_keychain_search_list, 0, keychain);
624 temp_trust_result != kSecTrustResultProceed);
625 bool weak_chain = false;
626 if (CFArrayGetCount(temp_chain) == 0) {
627 // If the chain is empty, it cannot be trusted or have recoverable
628 // errors.
629 DCHECK(untrusted);
630 DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result);
631 } else {
632 CertVerifyResult temp_verify_result;
633 bool leaf_is_weak = false;
634 GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result,
635 &leaf_is_weak);
636 weak_chain = !leaf_is_weak &&
637 (temp_verify_result.has_md2 || temp_verify_result.has_md4 ||
638 temp_verify_result.has_md5 || temp_verify_result.has_sha1);
639 } 669 }
640 // Set the result to the current chain if:
641 // - This is the first verification attempt. This ensures that if
642 // 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
644 // - 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
646 // 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
648 // the old chain contained weak algorithms while the current chain only
649 // contains strong algorithms, then prefer the current chain over the
650 // old chain.
651 //
652 // Note: If the leaf certificate itself is weak, then the only
653 // consideration is whether or not there is a trusted chain. That's
654 // because no amount of path discovery will fix a weak leaf.
655 if (!trust_ref || (!untrusted && (candidate_untrusted ||
656 (candidate_weak && !weak_chain)))) {
657 trust_ref = temp_ref;
658 trust_result = temp_trust_result;
659 completed_chain = temp_chain;
660 chain_info = temp_chain_info;
661 670
662 candidate_untrusted = untrusted; 671 ScopedCFTypeRef<CFMutableArrayRef> cert_array(
663 candidate_weak = weak_chain; 672 cert->CreateOSCertChainForCert());
673
674 // Beginning with the certificate chain as supplied by the server, attempt
675 // to verify the chain. If a failure is encountered, trim a certificate
676 // from the end (so long as one remains) and retry, in the hope of forcing
677 // OS X to find a better path.
678 while (CFArrayGetCount(cert_array) > 0) {
679 ScopedCFTypeRef<SecTrustRef> temp_ref;
680 SecTrustResultType temp_trust_result = kSecTrustResultDeny;
681 ScopedCFTypeRef<CFArrayRef> temp_chain;
682 CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL;
683
684 int rv = BuildAndEvaluateSecTrustRef(
685 cert_array, trust_policies, flags,
686 scoped_alternate_keychain_search_list.get(), &temp_ref,
687 &temp_trust_result, &temp_chain, &temp_chain_info);
688 if (rv != OK)
689 return rv;
690
691 // Check to see if the path |temp_chain| has been revoked. This is less
692 // than ideal to perform after path building, rather than during, because
693 // there may be multiple paths to trust anchors, and only some of them
694 // are revoked. Ideally, CRLSets would be part of path building, which
695 // they are when using NSS (Linux) or CryptoAPI (Windows).
696 //
697 // The CRLSet checking is performed inside the loop in the hope that if a
698 // path is revoked, it's an older path, and the only reason it was built
699 // is because the server forced it (by supplying an older or less
700 // desirable intermediate) or because the user had installed a
701 // certificate in their Keychain forcing this path. However, this means
702 // its still possible for a CRLSet block of an intermediate to prevent
703 // access, even when there is a 'good' chain. To fully remedy this, a
704 // solution might be to have CRLSets contain enough knowledge about what
705 // the 'desired' path might be, but for the time being, the
706 // implementation is kept as 'simple' as it can be.
707 bool revoked =
708 (crl_set && !CheckRevocationWithCRLSet(temp_chain, crl_set));
709 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified &&
710 temp_trust_result != kSecTrustResultProceed) ||
711 revoked;
712 bool weak_chain = false;
713 if (CFArrayGetCount(temp_chain) == 0) {
714 // If the chain is empty, it cannot be trusted or have recoverable
715 // errors.
716 DCHECK(untrusted);
717 DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result);
718 } else {
719 CertVerifyResult temp_verify_result;
720 bool leaf_is_weak = false;
721 GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result,
722 &leaf_is_weak);
723 weak_chain =
724 !leaf_is_weak &&
725 (temp_verify_result.has_md2 || temp_verify_result.has_md4 ||
726 temp_verify_result.has_md5 || temp_verify_result.has_sha1);
727 }
728 // Set the result to the current chain if:
729 // - This is the first verification attempt. This ensures that if
730 // everything is awful (e.g. it may just be an untrusted cert), that
731 // what is reported is exactly what was sent by the server
732 // - If the current chain is trusted, and the old chain was not trusted,
733 // then prefer this chain. This ensures that if there is at least a
734 // valid path to a trust anchor, it's preferred over reporting an error.
735 // - If the current chain is trusted, and the old chain is trusted, but
736 // the old chain contained weak algorithms while the current chain only
737 // contains strong algorithms, then prefer the current chain over the
738 // old chain.
739 //
740 // Note: If the leaf certificate itself is weak, then the only
741 // consideration is whether or not there is a trusted chain. That's
742 // because no amount of path discovery will fix a weak leaf.
743 if (!trust_ref || (!untrusted && (candidate_untrusted ||
744 (candidate_weak && !weak_chain)))) {
745 trust_ref = temp_ref;
746 trust_result = temp_trust_result;
747 completed_chain = temp_chain;
748 completed_chain_revoked = revoked;
749 chain_info = temp_chain_info;
750
751 candidate_untrusted = untrusted;
752 candidate_weak = weak_chain;
753 }
754 // Short-circuit when a current, trusted chain is found.
755 if (!untrusted && !weak_chain)
756 break;
757 CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1);
664 } 758 }
665 // Short-circuit when a current, trusted chain is found. 759 // Short-circuit when a current, trusted chain is found.
666 if (!untrusted && !weak_chain) 760 if (!candidate_untrusted && !candidate_weak)
667 break; 761 break;
668 CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1);
669 } 762 }
670 763
671 if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) 764 if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED)
672 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 765 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
673 766
674 if (crl_set && !CheckRevocationWithCRLSet(completed_chain, crl_set)) 767 if (completed_chain_revoked)
675 verify_result->cert_status |= CERT_STATUS_REVOKED; 768 verify_result->cert_status |= CERT_STATUS_REVOKED;
676 769
677 if (CFArrayGetCount(completed_chain) > 0) { 770 if (CFArrayGetCount(completed_chain) > 0) {
678 bool leaf_is_weak_unused = false; 771 bool leaf_is_weak_unused = false;
679 GetCertChainInfo(completed_chain, chain_info, verify_result, 772 GetCertChainInfo(completed_chain, chain_info, verify_result,
680 &leaf_is_weak_unused); 773 &leaf_is_weak_unused);
681 } 774 }
682 775
683 // As of Security Update 2012-002/OS X 10.7.4, when an RSA key < 1024 bits 776 // As of Security Update 2012-002/OS X 10.7.4, when an RSA key < 1024 bits
684 // is encountered, CSSM returns CSSMERR_TP_VERIFY_ACTION_FAILED and adds 777 // is encountered, CSSM returns CSSMERR_TP_VERIFY_ACTION_FAILED and adds
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 } 928 }
836 } 929 }
837 } 930 }
838 931
839 return OK; 932 return OK;
840 } 933 }
841 934
842 } // namespace net 935 } // namespace net
843 936
844 #pragma clang diagnostic pop // "-Wdeprecated-declarations" 937 #pragma clang diagnostic pop // "-Wdeprecated-declarations"
OLDNEW
« no previous file with comments | « net/BUILD.gn ('k') | net/cert/cert_verify_proc_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698