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

Side by Side Diff: net/base/cert_verify_proc_nss.cc

Issue 10857020: Do not perform online revocation checking when the user has explicitly disabled it, except for when… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « net/base/cert_verify_proc.cc ('k') | net/base/cert_verify_proc_win.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/base/cert_verify_proc_nss.h" 5 #include "net/base/cert_verify_proc_nss.h"
6 6
7 #include <cert.h> 7 #include <cert.h>
8 #include <nss.h> 8 #include <nss.h>
9 #include <prerror.h> 9 #include <prerror.h>
10 #include <secerr.h> 10 #include <secerr.h>
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 od.offset = SEC_OID_UNKNOWN; 569 od.offset = SEC_OID_UNKNOWN;
570 // NSS doesn't allow us to pass an empty description, so I use a hardcoded, 570 // NSS doesn't allow us to pass an empty description, so I use a hardcoded,
571 // default description here. The description doesn't need to be unique for 571 // default description here. The description doesn't need to be unique for
572 // each OID. 572 // each OID.
573 od.desc = "a certificate policy"; 573 od.desc = "a certificate policy";
574 od.mechanism = CKM_INVALID_MECHANISM; 574 od.mechanism = CKM_INVALID_MECHANISM;
575 od.supportedExtension = INVALID_CERT_EXTENSION; 575 od.supportedExtension = INVALID_CERT_EXTENSION;
576 return SECOID_AddEntry(&od); 576 return SECOID_AddEntry(&od);
577 } 577 }
578 578
579 bool CheckCertPolicies(X509Certificate::OSCertHandle cert_handle,
580 SECOidTag ev_policy_tag) {
581 CERTCertificatePolicies* policies = DecodeCertPolicies(cert_handle);
582 if (!policies) {
583 LOG(ERROR) << "Cert has no policies extension or extension couldn't be "
584 "decoded.";
585 return false;
586 }
587 ScopedCERTCertificatePolicies scoped_policies(policies);
588 CERTPolicyInfo** policy_infos = policies->policyInfos;
589 while (*policy_infos != NULL) {
590 CERTPolicyInfo* policy_info = *policy_infos++;
591 SECOidTag oid_tag = policy_info->oid;
592 if (oid_tag == SEC_OID_UNKNOWN)
593 continue;
594 if (oid_tag == ev_policy_tag)
595 return true;
596 }
597 return false;
598 }
599
600 SHA1Fingerprint CertPublicKeyHash(CERTCertificate* cert) { 579 SHA1Fingerprint CertPublicKeyHash(CERTCertificate* cert) {
601 SHA1Fingerprint hash; 580 SHA1Fingerprint hash;
602 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data, 581 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data,
603 cert->derPublicKey.data, cert->derPublicKey.len); 582 cert->derPublicKey.data, cert->derPublicKey.len);
604 DCHECK_EQ(rv, SECSuccess); 583 DCHECK_EQ(rv, SECSuccess);
605 return hash; 584 return hash;
606 } 585 }
607 586
608 void AppendPublicKeyHashes(CERTCertList* cert_list, 587 void AppendPublicKeyHashes(CERTCertList* cert_list,
609 CERTCertificate* root_cert, 588 CERTCertificate* root_cert,
610 std::vector<SHA1Fingerprint>* hashes) { 589 std::vector<SHA1Fingerprint>* hashes) {
611 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 590 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
612 !CERT_LIST_END(node, cert_list); 591 !CERT_LIST_END(node, cert_list);
613 node = CERT_LIST_NEXT(node)) { 592 node = CERT_LIST_NEXT(node)) {
614 hashes->push_back(CertPublicKeyHash(node->cert)); 593 hashes->push_back(CertPublicKeyHash(node->cert));
615 } 594 }
616 if (root_cert) 595 if (root_cert)
617 hashes->push_back(CertPublicKeyHash(root_cert)); 596 hashes->push_back(CertPublicKeyHash(root_cert));
618 } 597 }
619 598
599 // Returns true if |cert_handle| contains a policy OID that is an EV policy
600 // OID according to |metadata|, storing the resulting policy OID in
601 // |*ev_policy_oid|. A true return is not sufficient to establish that a
602 // certificate is EV, but a false return is sufficient to establish the
603 // certificate cannot be EV.
604 bool IsEVCandidate(EVRootCAMetadata* metadata,
agl 2012/08/15 22:57:53 Is the assumption that there'll only be one EV OID
Ryan Sleevi 2012/08/15 23:04:58 That's what I'm not sure about. That's certainly t
605 CERTCertificate* cert_handle,
606 SECOidTag* ev_policy_oid) {
607 DCHECK(cert_handle);
608 ScopedCERTCertificatePolicies policies(DecodeCertPolicies(cert_handle));
609 if (!policies.get())
610 return false;
611
612 CERTPolicyInfo** policy_infos = policies->policyInfos;
613 while (*policy_infos != NULL) {
614 CERTPolicyInfo* policy_info = *policy_infos++;
615 // If the Policy OID is unknown, that implicitly means it has not been
616 // registered as an EV policy.
617 if (policy_info->oid == SEC_OID_UNKNOWN)
618 continue;
619 if (metadata->IsEVPolicyOID(policy_info->oid)) {
620 *ev_policy_oid = policy_info->oid;
621 return true;
622 }
623 }
624
625 return false;
626 }
627
620 // Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp 628 // Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp
621 // and nsNSSCertHelper.cpp) to learn how to verify EV certificate. 629 // and nsNSSCertHelper.cpp) to learn how to verify EV certificate.
622 // TODO(wtc): A possible optimization is that we get the trust anchor from 630 // TODO(wtc): A possible optimization is that we get the trust anchor from
623 // the first PKIXVerifyCert call. We look up the EV policy for the trust 631 // the first PKIXVerifyCert call. We look up the EV policy for the trust
624 // anchor. If the trust anchor has no EV policy, we know the cert isn't EV. 632 // anchor. If the trust anchor has no EV policy, we know the cert isn't EV.
625 // Otherwise, we pass just that EV policy (as opposed to all the EV policies) 633 // Otherwise, we pass just that EV policy (as opposed to all the EV policies)
626 // to the second PKIXVerifyCert call. 634 // to the second PKIXVerifyCert call.
627 bool VerifyEV(CERTCertificate* cert_handle, int flags, CRLSet* crl_set) { 635 bool VerifyEV(CERTCertificate* cert_handle, int flags, CRLSet* crl_set) {
628 EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); 636 EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
629 637
638 SECOidTag ev_policy_oid = SEC_OID_UNKNOWN;
639 bool is_ev_candidate = IsEVCandidate(metadata, cert_handle, &ev_policy_oid);
640 if (!is_ev_candidate)
641 return false;
642
630 CERTValOutParam cvout[3]; 643 CERTValOutParam cvout[3];
631 int cvout_index = 0; 644 int cvout_index = 0;
632 cvout[cvout_index].type = cert_po_certList; 645 cvout[cvout_index].type = cert_po_certList;
633 cvout[cvout_index].value.pointer.chain = NULL; 646 cvout[cvout_index].value.pointer.chain = NULL;
634 int cvout_cert_list_index = cvout_index; 647 int cvout_cert_list_index = cvout_index;
635 cvout_index++; 648 cvout_index++;
636 cvout[cvout_index].type = cert_po_trustAnchor; 649 cvout[cvout_index].type = cert_po_trustAnchor;
637 cvout[cvout_index].value.pointer.cert = NULL; 650 cvout[cvout_index].value.pointer.cert = NULL;
638 int cvout_trust_anchor_index = cvout_index; 651 int cvout_trust_anchor_index = cvout_index;
639 cvout_index++; 652 cvout_index++;
640 cvout[cvout_index].type = cert_po_end; 653 cvout[cvout_index].type = cert_po_end;
641 ScopedCERTValOutParam scoped_cvout(cvout); 654 ScopedCERTValOutParam scoped_cvout(cvout);
642 655
656 bool rev_checking_enabled =
657 (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) ||
658 (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED_EV_ONLY);
659
643 SECStatus status = PKIXVerifyCert( 660 SECStatus status = PKIXVerifyCert(
644 cert_handle, 661 cert_handle,
645 flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED, 662 rev_checking_enabled,
646 flags & X509Certificate::VERIFY_CERT_IO_ENABLED, 663 flags & X509Certificate::VERIFY_CERT_IO_ENABLED,
647 metadata->GetPolicyOIDs(), 664 &ev_policy_oid,
648 metadata->NumPolicyOIDs(), 665 1,
649 cvout); 666 cvout);
650 if (status != SECSuccess) 667 if (status != SECSuccess)
651 return false; 668 return false;
652 669
653 CERTCertificate* root_ca = 670 CERTCertificate* root_ca =
654 cvout[cvout_trust_anchor_index].value.pointer.cert; 671 cvout[cvout_trust_anchor_index].value.pointer.cert;
655 if (root_ca == NULL) 672 if (root_ca == NULL)
656 return false; 673 return false;
657 674
658 // This second PKIXVerifyCert call could have found a different certification 675 // This second PKIXVerifyCert call could have found a different certification
659 // path and one or more of the certificates on this new path, that weren't on 676 // path and one or more of the certificates on this new path, that weren't on
660 // the old path, might have been revoked. 677 // the old path, might have been revoked.
661 if (crl_set) { 678 if (crl_set) {
662 CRLSetResult crl_set_result = CheckRevocationWithCRLSet( 679 CRLSetResult crl_set_result = CheckRevocationWithCRLSet(
663 cvout[cvout_cert_list_index].value.pointer.chain, 680 cvout[cvout_cert_list_index].value.pointer.chain,
664 cvout[cvout_trust_anchor_index].value.pointer.cert, 681 cvout[cvout_trust_anchor_index].value.pointer.cert,
665 crl_set); 682 crl_set);
666 if (crl_set_result == kCRLSetRevoked) 683 if (crl_set_result == kCRLSetRevoked)
667 return false; 684 return false;
668 } 685 }
669 686
670 SHA1Fingerprint fingerprint = 687 SHA1Fingerprint fingerprint =
671 X509Certificate::CalculateFingerprint(root_ca); 688 X509Certificate::CalculateFingerprint(root_ca);
672 std::vector<SECOidTag> ev_policy_tags; 689 return metadata->HasEVPolicyOID(fingerprint, ev_policy_oid);
673 if (!metadata->GetPolicyOIDsForCA(fingerprint, &ev_policy_tags))
674 return false;
675 DCHECK(!ev_policy_tags.empty());
676
677 for (std::vector<SECOidTag>::const_iterator
678 i = ev_policy_tags.begin(); i != ev_policy_tags.end(); ++i) {
679 if (CheckCertPolicies(cert_handle, *i))
680 return true;
681 }
682 return false;
683 } 690 }
684 691
685 } // namespace 692 } // namespace
686 693
687 CertVerifyProcNSS::CertVerifyProcNSS() {} 694 CertVerifyProcNSS::CertVerifyProcNSS() {}
688 695
689 CertVerifyProcNSS::~CertVerifyProcNSS() {} 696 CertVerifyProcNSS::~CertVerifyProcNSS() {}
690 697
691 int CertVerifyProcNSS::VerifyInternal(X509Certificate* cert, 698 int CertVerifyProcNSS::VerifyInternal(X509Certificate* cert,
692 const std::string& hostname, 699 const std::string& hostname,
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
766 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, 773 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain,
767 cvout[cvout_trust_anchor_index].value.pointer.cert, 774 cvout[cvout_trust_anchor_index].value.pointer.cert,
768 &verify_result->public_key_hashes); 775 &verify_result->public_key_hashes);
769 776
770 verify_result->is_issued_by_known_root = 777 verify_result->is_issued_by_known_root =
771 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); 778 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert);
772 779
773 if ((flags & X509Certificate::VERIFY_EV_CERT) && 780 if ((flags & X509Certificate::VERIFY_EV_CERT) &&
774 VerifyEV(cert_handle, flags, crl_set)) { 781 VerifyEV(cert_handle, flags, crl_set)) {
775 verify_result->cert_status |= CERT_STATUS_IS_EV; 782 verify_result->cert_status |= CERT_STATUS_IS_EV;
783 if (cert_io_enabled &&
784 (flags & (X509Certificate::VERIFY_REV_CHECKING_ENABLED |
785 X509Certificate::VERIFY_REV_CHECKING_ENABLED_EV_ONLY)) {
786 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
787 }
776 } 788 }
777 789
778 return OK; 790 return OK;
779 } 791 }
780 792
781 } // namespace net 793 } // namespace net
OLDNEW
« no previous file with comments | « net/base/cert_verify_proc.cc ('k') | net/base/cert_verify_proc_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698