Chromium Code Reviews| 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}) { |
| 612 ScopedCFTypeRef<SecTrustRef> temp_ref; | 619 ScopedCFTypeRef<CFArrayRef> scoped_alternate_keychain_search_list; |
| 613 SecTrustResultType temp_trust_result = kSecTrustResultDeny; | 620 if (try_reordered_keychain) { |
| 614 ScopedCFTypeRef<CFArrayRef> temp_chain; | 621 CFArrayRef keychain_search_list; |
| 615 CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL; | 622 if (TestKeychainSearchList::HasInstance()) |
| 623 status = TestKeychainSearchList::GetInstance()->CopySearchList( | |
| 624 &keychain_search_list); | |
| 625 else | |
| 626 status = SecKeychainCopySearchList(&keychain_search_list); | |
| 627 if (status) | |
| 628 return NetErrorFromOSStatus(status); | |
| 629 ScopedCFTypeRef<CFArrayRef> scoped_keychain_search_list( | |
| 630 keychain_search_list); | |
| 616 | 631 |
| 617 int rv = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, flags, | 632 CFMutableArrayRef mutable_keychain_search_list = CFArrayCreateMutableCopy( |
| 618 &temp_ref, &temp_trust_result, | 633 kCFAllocatorDefault, CFArrayGetCount(keychain_search_list) + 1, |
| 619 &temp_chain, &temp_chain_info); | 634 keychain_search_list); |
| 620 if (rv != OK) | 635 if (!mutable_keychain_search_list) |
| 621 return rv; | 636 return ERR_OUT_OF_MEMORY; |
| 637 scoped_alternate_keychain_search_list.reset(mutable_keychain_search_list); | |
| 622 | 638 |
| 623 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified && | 639 SecKeychainRef keychain; |
| 624 temp_trust_result != kSecTrustResultProceed); | 640 // Get a reference to the System Roots keychain. This is a gross hack, |
| 625 bool weak_chain = false; | 641 // but the path is known to be valid on OS X 10.9-10.11. |
| 626 if (CFArrayGetCount(temp_chain) == 0) { | 642 status = SecKeychainOpen( |
| 627 // If the chain is empty, it cannot be trusted or have recoverable | 643 "/System/Library/Keychains/SystemRootCertificates.keychain", |
| 628 // errors. | 644 &keychain); |
|
Ryan Sleevi
2016/06/30 01:49:16
Can we not just use the last keychain? Or the name
mattm
2016/06/30 03:20:51
Unfortunately, SystemRootCertificates is not part
| |
| 629 DCHECK(untrusted); | 645 if (status) |
| 630 DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result); | 646 return NetErrorFromOSStatus(status); |
| 631 } else { | 647 ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain); |
| 632 CertVerifyResult temp_verify_result; | 648 |
| 633 bool leaf_is_weak = false; | 649 CFArrayInsertValueAtIndex(mutable_keychain_search_list, 0, keychain); |
| 634 GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result, | 650 } else if (TestKeychainSearchList::HasInstance()) { |
| 635 &leaf_is_weak); | 651 CFArrayRef keychain_search_list; |
| 636 weak_chain = !leaf_is_weak && | 652 status = TestKeychainSearchList::GetInstance()->CopySearchList( |
| 637 (temp_verify_result.has_md2 || temp_verify_result.has_md4 || | 653 &keychain_search_list); |
| 638 temp_verify_result.has_md5 || temp_verify_result.has_sha1); | 654 scoped_alternate_keychain_search_list.reset(keychain_search_list); |
| 639 } | 655 } |
|
Ryan Sleevi
2016/06/30 01:49:16
Suggestion: Re-order this before the conditional,
mattm
2016/06/30 03:20:52
Done.
| |
| 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 // Create and configure a SecTrustRef, which takes our certificate(s) |
| 663 candidate_weak = weak_chain; | 658 // and our SSL SecPolicyRef. SecTrustCreateWithCertificates() takes an |
| 659 // array of certificates, the first of which is the certificate we're | |
| 660 // verifying, and the subsequent (optional) certificates are used for | |
| 661 // chain building. | |
|
Ryan Sleevi
2016/06/30 01:49:16
I actually think we can nuke all of this (657-661)
mattm
2016/06/30 03:20:51
Done.
| |
| 662 ScopedCFTypeRef<CFMutableArrayRef> cert_array( | |
| 663 cert->CreateOSCertChainForCert()); | |
| 664 | |
| 665 while (CFArrayGetCount(cert_array) > 0) { | |
| 666 ScopedCFTypeRef<SecTrustRef> temp_ref; | |
| 667 SecTrustResultType temp_trust_result = kSecTrustResultDeny; | |
| 668 ScopedCFTypeRef<CFArrayRef> temp_chain; | |
| 669 CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL; | |
| 670 | |
| 671 int rv = BuildAndEvaluateSecTrustRef( | |
| 672 cert_array, trust_policies, flags, | |
| 673 scoped_alternate_keychain_search_list.get(), &temp_ref, | |
| 674 &temp_trust_result, &temp_chain, &temp_chain_info); | |
| 675 if (rv != OK) | |
| 676 return rv; | |
| 677 | |
| 678 bool revoked = | |
| 679 (crl_set && !CheckRevocationWithCRLSet(temp_chain, crl_set)); | |
| 680 bool untrusted = (temp_trust_result != kSecTrustResultUnspecified && | |
| 681 temp_trust_result != kSecTrustResultProceed) || | |
| 682 revoked; | |
| 683 bool weak_chain = false; | |
| 684 if (CFArrayGetCount(temp_chain) == 0) { | |
| 685 // If the chain is empty, it cannot be trusted or have recoverable | |
| 686 // errors. | |
| 687 DCHECK(untrusted); | |
| 688 DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result); | |
| 689 } else { | |
| 690 CertVerifyResult temp_verify_result; | |
| 691 bool leaf_is_weak = false; | |
| 692 GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result, | |
| 693 &leaf_is_weak); | |
| 694 weak_chain = | |
| 695 !leaf_is_weak && | |
| 696 (temp_verify_result.has_md2 || temp_verify_result.has_md4 || | |
| 697 temp_verify_result.has_md5 || temp_verify_result.has_sha1); | |
| 698 } | |
| 699 // Set the result to the current chain if: | |
| 700 // - This is the first verification attempt. This ensures that if | |
| 701 // everything is awful (e.g. it may just be an untrusted cert), that | |
| 702 // what is reported is exactly what was sent by the server | |
| 703 // - If the current chain is trusted, and the old chain was not trusted, | |
| 704 // then prefer this chain. This ensures that if there is at least a | |
| 705 // valid path to a trust anchor, it's preferred over reporting an error. | |
| 706 // - If the current chain is trusted, and the old chain is trusted, but | |
| 707 // the old chain contained weak algorithms while the current chain only | |
| 708 // contains strong algorithms, then prefer the current chain over the | |
| 709 // old chain. | |
| 710 // | |
| 711 // Note: If the leaf certificate itself is weak, then the only | |
| 712 // consideration is whether or not there is a trusted chain. That's | |
| 713 // because no amount of path discovery will fix a weak leaf. | |
| 714 if (!trust_ref || (!untrusted && (candidate_untrusted || | |
| 715 (candidate_weak && !weak_chain)))) { | |
| 716 trust_ref = temp_ref; | |
| 717 trust_result = temp_trust_result; | |
| 718 completed_chain = temp_chain; | |
| 719 completed_chain_revoked = revoked; | |
| 720 chain_info = temp_chain_info; | |
| 721 | |
| 722 candidate_untrusted = untrusted; | |
| 723 candidate_weak = weak_chain; | |
| 724 } | |
| 725 // Short-circuit when a current, trusted chain is found. | |
| 726 if (!untrusted && !weak_chain) | |
| 727 break; | |
| 728 CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1); | |
| 664 } | 729 } |
| 665 // Short-circuit when a current, trusted chain is found. | 730 // Short-circuit when a current, trusted chain is found. |
| 666 if (!untrusted && !weak_chain) | 731 if (!candidate_untrusted && !candidate_weak) |
| 667 break; | 732 break; |
| 668 CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1); | |
| 669 } | 733 } |
| 670 | 734 |
| 671 if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) | 735 if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) |
| 672 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 736 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
| 673 | 737 |
| 674 if (crl_set && !CheckRevocationWithCRLSet(completed_chain, crl_set)) | 738 if (completed_chain_revoked) |
| 675 verify_result->cert_status |= CERT_STATUS_REVOKED; | 739 verify_result->cert_status |= CERT_STATUS_REVOKED; |
| 676 | 740 |
| 677 if (CFArrayGetCount(completed_chain) > 0) { | 741 if (CFArrayGetCount(completed_chain) > 0) { |
| 678 bool leaf_is_weak_unused = false; | 742 bool leaf_is_weak_unused = false; |
| 679 GetCertChainInfo(completed_chain, chain_info, verify_result, | 743 GetCertChainInfo(completed_chain, chain_info, verify_result, |
| 680 &leaf_is_weak_unused); | 744 &leaf_is_weak_unused); |
| 681 } | 745 } |
| 682 | 746 |
| 683 // As of Security Update 2012-002/OS X 10.7.4, when an RSA key < 1024 bits | 747 // 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 | 748 // 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 } | 899 } |
| 836 } | 900 } |
| 837 } | 901 } |
| 838 | 902 |
| 839 return OK; | 903 return OK; |
| 840 } | 904 } |
| 841 | 905 |
| 842 } // namespace net | 906 } // namespace net |
| 843 | 907 |
| 844 #pragma clang diagnostic pop // "-Wdeprecated-declarations" | 908 #pragma clang diagnostic pop // "-Wdeprecated-declarations" |
| OLD | NEW |