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 10 matching lines...) Expand all Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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}) { |
Ryan Sleevi
2016/08/12 19:50:17
NICE! :)
| |
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 CFArrayRef keychain_search_list; |
615 CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL; | 622 status = TestKeychainSearchList::GetInstance()->CopySearchList( |
623 &keychain_search_list); | |
624 if (status) | |
625 return NetErrorFromOSStatus(status); | |
626 scoped_alternate_keychain_search_list.reset(keychain_search_list); | |
627 } | |
Ryan Sleevi
2016/08/12 19:50:17
Could you add some additional documentation here e
mattm
2016/08/16 01:41:34
Done.
| |
628 if (try_reordered_keychain) { | |
629 if (!scoped_alternate_keychain_search_list) { | |
630 CFArrayRef keychain_search_list; | |
631 status = SecKeychainCopySearchList(&keychain_search_list); | |
632 if (status) | |
633 return NetErrorFromOSStatus(status); | |
634 scoped_alternate_keychain_search_list.reset(keychain_search_list); | |
635 } | |
636 CFMutableArrayRef mutable_keychain_search_list = CFArrayCreateMutableCopy( | |
637 kCFAllocatorDefault, | |
638 CFArrayGetCount(scoped_alternate_keychain_search_list.get()) + 1, | |
639 scoped_alternate_keychain_search_list.get()); | |
640 if (!mutable_keychain_search_list) | |
641 return ERR_OUT_OF_MEMORY; | |
642 scoped_alternate_keychain_search_list.reset(mutable_keychain_search_list); | |
616 | 643 |
617 int rv = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, flags, | 644 SecKeychainRef keychain; |
618 &temp_ref, &temp_trust_result, | 645 // Get a reference to the System Roots keychain. This is a gross hack, |
619 &temp_chain, &temp_chain_info); | 646 // but the path is known to be valid on OS X 10.9-10.11. |
620 if (rv != OK) | 647 status = SecKeychainOpen( |
621 return rv; | 648 "/System/Library/Keychains/SystemRootCertificates.keychain", |
649 &keychain); | |
Ryan Sleevi
2016/08/12 19:50:17
DESIGN: Is it worth adding a unit test for this ca
mattm
2016/08/16 01:41:34
Done.
| |
650 if (status) | |
651 return NetErrorFromOSStatus(status); | |
652 ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain); | |
622 | 653 |
623 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified && | 654 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 } | 655 } |
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 | 656 |
662 candidate_untrusted = untrusted; | 657 ScopedCFTypeRef<CFMutableArrayRef> cert_array( |
663 candidate_weak = weak_chain; | 658 cert->CreateOSCertChainForCert()); |
659 | |
660 while (CFArrayGetCount(cert_array) > 0) { | |
Ryan Sleevi
2016/08/12 19:50:17
I'm a little nervous that this is moved far away f
mattm
2016/08/16 01:41:34
Done.
| |
661 ScopedCFTypeRef<SecTrustRef> temp_ref; | |
662 SecTrustResultType temp_trust_result = kSecTrustResultDeny; | |
663 ScopedCFTypeRef<CFArrayRef> temp_chain; | |
664 CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL; | |
665 | |
666 int rv = BuildAndEvaluateSecTrustRef( | |
667 cert_array, trust_policies, flags, | |
668 scoped_alternate_keychain_search_list.get(), &temp_ref, | |
669 &temp_trust_result, &temp_chain, &temp_chain_info); | |
670 if (rv != OK) | |
671 return rv; | |
672 | |
673 bool revoked = | |
674 (crl_set && !CheckRevocationWithCRLSet(temp_chain, crl_set)); | |
Ryan Sleevi
2016/08/12 19:50:17
I suspect we should do with some documentation her
mattm
2016/08/16 01:41:34
That would be great since I'm not sure what the nu
Ryan Sleevi
2016/08/17 02:28:12
// Check to see if the path |temp_chain| has been
mattm
2016/08/17 03:50:57
Ah, that. Done.
| |
675 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified && | |
676 temp_trust_result != kSecTrustResultProceed) || | |
677 revoked; | |
678 bool weak_chain = false; | |
679 if (CFArrayGetCount(temp_chain) == 0) { | |
680 // If the chain is empty, it cannot be trusted or have recoverable | |
681 // errors. | |
682 DCHECK(untrusted); | |
683 DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result); | |
684 } else { | |
685 CertVerifyResult temp_verify_result; | |
686 bool leaf_is_weak = false; | |
687 GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result, | |
688 &leaf_is_weak); | |
689 weak_chain = | |
690 !leaf_is_weak && | |
691 (temp_verify_result.has_md2 || temp_verify_result.has_md4 || | |
692 temp_verify_result.has_md5 || temp_verify_result.has_sha1); | |
693 } | |
694 // Set the result to the current chain if: | |
695 // - This is the first verification attempt. This ensures that if | |
696 // everything is awful (e.g. it may just be an untrusted cert), that | |
697 // what is reported is exactly what was sent by the server | |
698 // - If the current chain is trusted, and the old chain was not trusted, | |
699 // then prefer this chain. This ensures that if there is at least a | |
700 // valid path to a trust anchor, it's preferred over reporting an error. | |
701 // - If the current chain is trusted, and the old chain is trusted, but | |
702 // the old chain contained weak algorithms while the current chain only | |
703 // contains strong algorithms, then prefer the current chain over the | |
704 // old chain. | |
705 // | |
706 // Note: If the leaf certificate itself is weak, then the only | |
707 // consideration is whether or not there is a trusted chain. That's | |
708 // because no amount of path discovery will fix a weak leaf. | |
709 if (!trust_ref || (!untrusted && (candidate_untrusted || | |
710 (candidate_weak && !weak_chain)))) { | |
711 trust_ref = temp_ref; | |
712 trust_result = temp_trust_result; | |
713 completed_chain = temp_chain; | |
714 completed_chain_revoked = revoked; | |
715 chain_info = temp_chain_info; | |
716 | |
717 candidate_untrusted = untrusted; | |
718 candidate_weak = weak_chain; | |
719 } | |
720 // Short-circuit when a current, trusted chain is found. | |
721 if (!untrusted && !weak_chain) | |
722 break; | |
723 CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1); | |
664 } | 724 } |
665 // Short-circuit when a current, trusted chain is found. | 725 // Short-circuit when a current, trusted chain is found. |
666 if (!untrusted && !weak_chain) | 726 if (!candidate_untrusted && !candidate_weak) |
667 break; | 727 break; |
668 CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1); | |
669 } | 728 } |
670 | 729 |
671 if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) | 730 if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) |
672 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 731 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
673 | 732 |
674 if (crl_set && !CheckRevocationWithCRLSet(completed_chain, crl_set)) | 733 if (completed_chain_revoked) |
675 verify_result->cert_status |= CERT_STATUS_REVOKED; | 734 verify_result->cert_status |= CERT_STATUS_REVOKED; |
676 | 735 |
677 if (CFArrayGetCount(completed_chain) > 0) { | 736 if (CFArrayGetCount(completed_chain) > 0) { |
678 bool leaf_is_weak_unused = false; | 737 bool leaf_is_weak_unused = false; |
679 GetCertChainInfo(completed_chain, chain_info, verify_result, | 738 GetCertChainInfo(completed_chain, chain_info, verify_result, |
680 &leaf_is_weak_unused); | 739 &leaf_is_weak_unused); |
681 } | 740 } |
682 | 741 |
683 // As of Security Update 2012-002/OS X 10.7.4, when an RSA key < 1024 bits | 742 // 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 | 743 // is encountered, CSSM returns CSSMERR_TP_VERIFY_ACTION_FAILED and adds |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
835 } | 894 } |
836 } | 895 } |
837 } | 896 } |
838 | 897 |
839 return OK; | 898 return OK; |
840 } | 899 } |
841 | 900 |
842 } // namespace net | 901 } // namespace net |
843 | 902 |
844 #pragma clang diagnostic pop // "-Wdeprecated-declarations" | 903 #pragma clang diagnostic pop // "-Wdeprecated-declarations" |
OLD | NEW |