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_nss.h" | 5 #include "net/cert/cert_verify_proc_nss.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include <cert.h> | 10 #include <cert.h> |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 return ERR_INVALID_ARGUMENT; | 101 return ERR_INVALID_ARGUMENT; |
102 case SSL_ERROR_BAD_CERT_DOMAIN: | 102 case SSL_ERROR_BAD_CERT_DOMAIN: |
103 return ERR_CERT_COMMON_NAME_INVALID; | 103 return ERR_CERT_COMMON_NAME_INVALID; |
104 case SEC_ERROR_INVALID_TIME: | 104 case SEC_ERROR_INVALID_TIME: |
105 case SEC_ERROR_EXPIRED_CERTIFICATE: | 105 case SEC_ERROR_EXPIRED_CERTIFICATE: |
106 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: | 106 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: |
107 return ERR_CERT_DATE_INVALID; | 107 return ERR_CERT_DATE_INVALID; |
108 case SEC_ERROR_UNKNOWN_ISSUER: | 108 case SEC_ERROR_UNKNOWN_ISSUER: |
109 case SEC_ERROR_UNTRUSTED_ISSUER: | 109 case SEC_ERROR_UNTRUSTED_ISSUER: |
110 case SEC_ERROR_CA_CERT_INVALID: | 110 case SEC_ERROR_CA_CERT_INVALID: |
| 111 case SEC_ERROR_APPLICATION_CALLBACK_ERROR: // Rejected by |
| 112 // chain_verify_callback. |
111 return ERR_CERT_AUTHORITY_INVALID; | 113 return ERR_CERT_AUTHORITY_INVALID; |
112 // TODO(port): map ERR_CERT_NO_REVOCATION_MECHANISM. | 114 // TODO(port): map ERR_CERT_NO_REVOCATION_MECHANISM. |
113 case SEC_ERROR_OCSP_BAD_HTTP_RESPONSE: | 115 case SEC_ERROR_OCSP_BAD_HTTP_RESPONSE: |
114 case SEC_ERROR_OCSP_SERVER_ERROR: | 116 case SEC_ERROR_OCSP_SERVER_ERROR: |
115 return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; | 117 return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; |
116 case SEC_ERROR_REVOKED_CERTIFICATE: | 118 case SEC_ERROR_REVOKED_CERTIFICATE: |
117 case SEC_ERROR_UNTRUSTED_CERT: // Treat as revoked. | 119 case SEC_ERROR_UNTRUSTED_CERT: // Treat as revoked. |
118 return ERR_CERT_REVOKED; | 120 return ERR_CERT_REVOKED; |
119 case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: | 121 case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: |
120 return ERR_CERT_NAME_CONSTRAINT_VIOLATION; | 122 return ERR_CERT_NAME_CONSTRAINT_VIOLATION; |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 // additional_trust_anchors is an optional list of certificates that can be | 344 // additional_trust_anchors is an optional list of certificates that can be |
343 // trusted as anchors when building a certificate chain. | 345 // trusted as anchors when building a certificate chain. |
344 // Caller must initialize cvout before calling this function. | 346 // Caller must initialize cvout before calling this function. |
345 SECStatus PKIXVerifyCert(CERTCertificate* cert_handle, | 347 SECStatus PKIXVerifyCert(CERTCertificate* cert_handle, |
346 bool check_revocation, | 348 bool check_revocation, |
347 bool hard_fail, | 349 bool hard_fail, |
348 bool cert_io_enabled, | 350 bool cert_io_enabled, |
349 const SECOidTag* policy_oids, | 351 const SECOidTag* policy_oids, |
350 int num_policy_oids, | 352 int num_policy_oids, |
351 CERTCertList* additional_trust_anchors, | 353 CERTCertList* additional_trust_anchors, |
| 354 CERTChainVerifyCallback* chain_verify_callback, |
352 CERTValOutParam* cvout) { | 355 CERTValOutParam* cvout) { |
353 bool use_crl = check_revocation; | 356 bool use_crl = check_revocation; |
354 bool use_ocsp = check_revocation; | 357 bool use_ocsp = check_revocation; |
355 | 358 |
356 PRUint64 revocation_method_flags = | 359 PRUint64 revocation_method_flags = |
357 CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD | | 360 CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD | |
358 CERT_REV_M_ALLOW_NETWORK_FETCHING | | 361 CERT_REV_M_ALLOW_NETWORK_FETCHING | |
359 CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE | | 362 CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE | |
360 CERT_REV_M_IGNORE_MISSING_FRESH_INFO | | 363 CERT_REV_M_IGNORE_MISSING_FRESH_INFO | |
361 CERT_REV_M_STOP_TESTING_ON_FRESH_INFO; | 364 CERT_REV_M_STOP_TESTING_ON_FRESH_INFO; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 cvin.push_back(in_param); | 434 cvin.push_back(in_param); |
432 } | 435 } |
433 if (additional_trust_anchors) { | 436 if (additional_trust_anchors) { |
434 in_param.type = cert_pi_trustAnchors; | 437 in_param.type = cert_pi_trustAnchors; |
435 in_param.value.pointer.chain = additional_trust_anchors; | 438 in_param.value.pointer.chain = additional_trust_anchors; |
436 cvin.push_back(in_param); | 439 cvin.push_back(in_param); |
437 in_param.type = cert_pi_useOnlyTrustAnchors; | 440 in_param.type = cert_pi_useOnlyTrustAnchors; |
438 in_param.value.scalar.b = PR_FALSE; | 441 in_param.value.scalar.b = PR_FALSE; |
439 cvin.push_back(in_param); | 442 cvin.push_back(in_param); |
440 } | 443 } |
| 444 if (chain_verify_callback) { |
| 445 in_param.type = cert_pi_chainVerifyCallback; |
| 446 in_param.value.pointer.chainVerifyCallback = chain_verify_callback; |
| 447 cvin.push_back(in_param); |
| 448 } |
441 in_param.type = cert_pi_end; | 449 in_param.type = cert_pi_end; |
442 cvin.push_back(in_param); | 450 cvin.push_back(in_param); |
443 | 451 |
444 SECStatus rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, | 452 SECStatus rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, |
445 &cvin[0], cvout, NULL); | 453 &cvin[0], cvout, NULL); |
446 if (rv != SECSuccess) { | 454 if (rv != SECSuccess) { |
447 rv = RetryPKIXVerifyCertWithWorkarounds(cert_handle, num_policy_oids, | 455 rv = RetryPKIXVerifyCertWithWorkarounds(cert_handle, num_policy_oids, |
448 cert_io_enabled, &cvin, cvout); | 456 cert_io_enabled, &cvin, cvout); |
449 } | 457 } |
450 return rv; | 458 return rv; |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 // the first PKIXVerifyCert call. We look up the EV policy for the trust | 659 // the first PKIXVerifyCert call. We look up the EV policy for the trust |
652 // anchor. If the trust anchor has no EV policy, we know the cert isn't EV. | 660 // anchor. If the trust anchor has no EV policy, we know the cert isn't EV. |
653 // Otherwise, we pass just that EV policy (as opposed to all the EV policies) | 661 // Otherwise, we pass just that EV policy (as opposed to all the EV policies) |
654 // to the second PKIXVerifyCert call. | 662 // to the second PKIXVerifyCert call. |
655 bool VerifyEV(CERTCertificate* cert_handle, | 663 bool VerifyEV(CERTCertificate* cert_handle, |
656 int flags, | 664 int flags, |
657 CRLSet* crl_set, | 665 CRLSet* crl_set, |
658 bool rev_checking_enabled, | 666 bool rev_checking_enabled, |
659 EVRootCAMetadata* metadata, | 667 EVRootCAMetadata* metadata, |
660 SECOidTag ev_policy_oid, | 668 SECOidTag ev_policy_oid, |
661 CERTCertList* additional_trust_anchors) { | 669 CERTCertList* additional_trust_anchors, |
| 670 CERTChainVerifyCallback* chain_verify_callback) { |
662 CERTValOutParam cvout[3]; | 671 CERTValOutParam cvout[3]; |
663 int cvout_index = 0; | 672 int cvout_index = 0; |
664 cvout[cvout_index].type = cert_po_certList; | 673 cvout[cvout_index].type = cert_po_certList; |
665 cvout[cvout_index].value.pointer.chain = NULL; | 674 cvout[cvout_index].value.pointer.chain = NULL; |
666 int cvout_cert_list_index = cvout_index; | 675 int cvout_cert_list_index = cvout_index; |
667 cvout_index++; | 676 cvout_index++; |
668 cvout[cvout_index].type = cert_po_trustAnchor; | 677 cvout[cvout_index].type = cert_po_trustAnchor; |
669 cvout[cvout_index].value.pointer.cert = NULL; | 678 cvout[cvout_index].value.pointer.cert = NULL; |
670 int cvout_trust_anchor_index = cvout_index; | 679 int cvout_trust_anchor_index = cvout_index; |
671 cvout_index++; | 680 cvout_index++; |
672 cvout[cvout_index].type = cert_po_end; | 681 cvout[cvout_index].type = cert_po_end; |
673 ScopedCERTValOutParam scoped_cvout(cvout); | 682 ScopedCERTValOutParam scoped_cvout(cvout); |
674 | 683 |
675 SECStatus status = PKIXVerifyCert( | 684 SECStatus status = PKIXVerifyCert( |
676 cert_handle, | 685 cert_handle, |
677 rev_checking_enabled, | 686 rev_checking_enabled, |
678 true, /* hard fail is implied in EV. */ | 687 true, /* hard fail is implied in EV. */ |
679 flags & CertVerifier::VERIFY_CERT_IO_ENABLED, | 688 flags & CertVerifier::VERIFY_CERT_IO_ENABLED, |
680 &ev_policy_oid, | 689 &ev_policy_oid, |
681 1, | 690 1, |
682 additional_trust_anchors, | 691 additional_trust_anchors, |
| 692 chain_verify_callback, |
683 cvout); | 693 cvout); |
684 if (status != SECSuccess) | 694 if (status != SECSuccess) |
685 return false; | 695 return false; |
686 | 696 |
687 CERTCertificate* root_ca = | 697 CERTCertificate* root_ca = |
688 cvout[cvout_trust_anchor_index].value.pointer.cert; | 698 cvout[cvout_trust_anchor_index].value.pointer.cert; |
689 if (root_ca == NULL) | 699 if (root_ca == NULL) |
690 return false; | 700 return false; |
691 | 701 |
692 // This second PKIXVerifyCert call could have found a different certification | 702 // This second PKIXVerifyCert call could have found a different certification |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 } // namespace | 739 } // namespace |
730 | 740 |
731 CertVerifyProcNSS::CertVerifyProcNSS() {} | 741 CertVerifyProcNSS::CertVerifyProcNSS() {} |
732 | 742 |
733 CertVerifyProcNSS::~CertVerifyProcNSS() {} | 743 CertVerifyProcNSS::~CertVerifyProcNSS() {} |
734 | 744 |
735 bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { | 745 bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { |
736 return true; | 746 return true; |
737 } | 747 } |
738 | 748 |
739 int CertVerifyProcNSS::VerifyInternal( | 749 int CertVerifyProcNSS::VerifyInternalImpl( |
740 X509Certificate* cert, | 750 X509Certificate* cert, |
741 const std::string& hostname, | 751 const std::string& hostname, |
742 int flags, | 752 int flags, |
743 CRLSet* crl_set, | 753 CRLSet* crl_set, |
744 const CertificateList& additional_trust_anchors, | 754 const CertificateList& additional_trust_anchors, |
| 755 CERTChainVerifyCallback* chain_verify_callback, |
745 CertVerifyResult* verify_result) { | 756 CertVerifyResult* verify_result) { |
746 #if defined(OS_IOS) | 757 #if defined(OS_IOS) |
747 // For iOS, the entire chain must be loaded into NSS's in-memory certificate | 758 // For iOS, the entire chain must be loaded into NSS's in-memory certificate |
748 // store. | 759 // store. |
749 x509_util_ios::NSSCertChain scoped_chain(cert); | 760 x509_util_ios::NSSCertChain scoped_chain(cert); |
750 CERTCertificate* cert_handle = scoped_chain.cert_handle(); | 761 CERTCertificate* cert_handle = scoped_chain.cert_handle(); |
751 #else | 762 #else |
752 CERTCertificate* cert_handle = cert->os_cert_handle(); | 763 CERTCertificate* cert_handle = cert->os_cert_handle(); |
753 #endif // defined(OS_IOS) | 764 #endif // defined(OS_IOS) |
754 | 765 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); | 798 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); |
788 if (check_revocation) | 799 if (check_revocation) |
789 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 800 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
790 | 801 |
791 ScopedCERTCertList trust_anchors; | 802 ScopedCERTCertList trust_anchors; |
792 if (!additional_trust_anchors.empty()) { | 803 if (!additional_trust_anchors.empty()) { |
793 trust_anchors.reset( | 804 trust_anchors.reset( |
794 CertificateListToCERTCertList(additional_trust_anchors)); | 805 CertificateListToCERTCertList(additional_trust_anchors)); |
795 } | 806 } |
796 | 807 |
797 SECStatus status = PKIXVerifyCert(cert_handle, check_revocation, false, | 808 SECStatus status = PKIXVerifyCert(cert_handle, |
798 cert_io_enabled, NULL, 0, | 809 check_revocation, |
799 trust_anchors.get(), cvout); | 810 false, |
| 811 cert_io_enabled, |
| 812 NULL, |
| 813 0, |
| 814 trust_anchors.get(), |
| 815 chain_verify_callback, |
| 816 cvout); |
800 | 817 |
801 if (status == SECSuccess && | 818 if (status == SECSuccess && |
802 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && | 819 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && |
803 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) { | 820 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) { |
804 // TODO(rsleevi): Optimize this by supplying the constructed chain to | 821 // TODO(rsleevi): Optimize this by supplying the constructed chain to |
805 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream | 822 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream |
806 // NSS tests for that feature. | 823 // NSS tests for that feature. |
807 scoped_cvout.Clear(); | 824 scoped_cvout.Clear(); |
808 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 825 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
809 status = PKIXVerifyCert(cert_handle, true, true, | 826 status = PKIXVerifyCert(cert_handle, |
810 cert_io_enabled, NULL, 0, trust_anchors.get(), | 827 true, |
| 828 true, |
| 829 cert_io_enabled, |
| 830 NULL, |
| 831 0, |
| 832 trust_anchors.get(), |
| 833 chain_verify_callback, |
811 cvout); | 834 cvout); |
812 } | 835 } |
813 | 836 |
814 if (status == SECSuccess) { | 837 if (status == SECSuccess) { |
815 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, | 838 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, |
816 cvout[cvout_trust_anchor_index].value.pointer.cert, | 839 cvout[cvout_trust_anchor_index].value.pointer.cert, |
817 &verify_result->public_key_hashes); | 840 &verify_result->public_key_hashes); |
818 | 841 |
819 verify_result->is_issued_by_known_root = | 842 verify_result->is_issued_by_known_root = |
820 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); | 843 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
862 return MapCertStatusToNetError(verify_result->cert_status); | 885 return MapCertStatusToNetError(verify_result->cert_status); |
863 | 886 |
864 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { | 887 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { |
865 check_revocation |= | 888 check_revocation |= |
866 crl_set_result != kCRLSetOk && | 889 crl_set_result != kCRLSetOk && |
867 cert_io_enabled && | 890 cert_io_enabled && |
868 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); | 891 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); |
869 if (check_revocation) | 892 if (check_revocation) |
870 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 893 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
871 | 894 |
872 if (VerifyEV(cert_handle, flags, crl_set, check_revocation, metadata, | 895 if (VerifyEV(cert_handle, |
873 ev_policy_oid, trust_anchors.get())) { | 896 flags, |
| 897 crl_set, |
| 898 check_revocation, |
| 899 metadata, |
| 900 ev_policy_oid, |
| 901 trust_anchors.get(), |
| 902 chain_verify_callback)) { |
874 verify_result->cert_status |= CERT_STATUS_IS_EV; | 903 verify_result->cert_status |= CERT_STATUS_IS_EV; |
875 } | 904 } |
876 } | 905 } |
877 | 906 |
878 return OK; | 907 return OK; |
879 } | 908 } |
880 | 909 |
| 910 int CertVerifyProcNSS::VerifyInternal( |
| 911 X509Certificate* cert, |
| 912 const std::string& hostname, |
| 913 int flags, |
| 914 CRLSet* crl_set, |
| 915 const CertificateList& additional_trust_anchors, |
| 916 CertVerifyResult* verify_result) { |
| 917 return VerifyInternalImpl(cert, |
| 918 hostname, |
| 919 flags, |
| 920 crl_set, |
| 921 additional_trust_anchors, |
| 922 NULL, // chain_verify_callback |
| 923 verify_result); |
| 924 } |
| 925 |
881 } // namespace net | 926 } // namespace net |
OLD | NEW |