| 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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 return ERR_CERT_AUTHORITY_INVALID; | 111 return ERR_CERT_AUTHORITY_INVALID; |
| 112 // TODO(port): map ERR_CERT_NO_REVOCATION_MECHANISM. | 112 // TODO(port): map ERR_CERT_NO_REVOCATION_MECHANISM. |
| 113 case SEC_ERROR_OCSP_BAD_HTTP_RESPONSE: | 113 case SEC_ERROR_OCSP_BAD_HTTP_RESPONSE: |
| 114 case SEC_ERROR_OCSP_SERVER_ERROR: | 114 case SEC_ERROR_OCSP_SERVER_ERROR: |
| 115 return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; | 115 return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; |
| 116 case SEC_ERROR_REVOKED_CERTIFICATE: | 116 case SEC_ERROR_REVOKED_CERTIFICATE: |
| 117 case SEC_ERROR_UNTRUSTED_CERT: // Treat as revoked. | 117 case SEC_ERROR_UNTRUSTED_CERT: // Treat as revoked. |
| 118 case SEC_ERROR_APPLICATION_CALLBACK_ERROR: // Rejected by |
| 119 // chain_verify_callback. |
| 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; |
| 121 case SEC_ERROR_BAD_DER: | 123 case SEC_ERROR_BAD_DER: |
| 122 case SEC_ERROR_BAD_SIGNATURE: | 124 case SEC_ERROR_BAD_SIGNATURE: |
| 123 case SEC_ERROR_CERT_NOT_VALID: | 125 case SEC_ERROR_CERT_NOT_VALID: |
| 124 // TODO(port): add an ERR_CERT_WRONG_USAGE error code. | 126 // TODO(port): add an ERR_CERT_WRONG_USAGE error code. |
| 125 case SEC_ERROR_CERT_USAGES_INVALID: | 127 case SEC_ERROR_CERT_USAGES_INVALID: |
| 126 case SEC_ERROR_INADEQUATE_KEY_USAGE: // Key usage. | 128 case SEC_ERROR_INADEQUATE_KEY_USAGE: // Key usage. |
| 127 case SEC_ERROR_INADEQUATE_CERT_TYPE: // Extended key usage and whether | 129 case SEC_ERROR_INADEQUATE_CERT_TYPE: // Extended key usage and whether |
| (...skipping 214 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 28 matching lines...) Expand all Loading... |
| 721 #else | 731 #else |
| 722 CERTCertificate* cert = list[i]->os_cert_handle(); | 732 CERTCertificate* cert = list[i]->os_cert_handle(); |
| 723 #endif | 733 #endif |
| 724 CERT_AddCertToListTail(result, CERT_DupCertificate(cert)); | 734 CERT_AddCertToListTail(result, CERT_DupCertificate(cert)); |
| 725 } | 735 } |
| 726 return result; | 736 return result; |
| 727 } | 737 } |
| 728 | 738 |
| 729 } // namespace | 739 } // namespace |
| 730 | 740 |
| 731 CertVerifyProcNSS::CertVerifyProcNSS() {} | 741 CertVerifyProcNSS::CertVerifyProcNSS() : chain_verify_callback_(NULL) {} |
| 742 |
| 743 CertVerifyProcNSS::CertVerifyProcNSS( |
| 744 CERTChainVerifyCallback* chain_verify_callback) |
| 745 : chain_verify_callback_(chain_verify_callback) {} |
| 732 | 746 |
| 733 CertVerifyProcNSS::~CertVerifyProcNSS() {} | 747 CertVerifyProcNSS::~CertVerifyProcNSS() {} |
| 734 | 748 |
| 735 bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { | 749 bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { |
| 736 return true; | 750 return true; |
| 737 } | 751 } |
| 738 | 752 |
| 739 int CertVerifyProcNSS::VerifyInternal( | 753 int CertVerifyProcNSS::VerifyInternal( |
| 740 X509Certificate* cert, | 754 X509Certificate* cert, |
| 741 const std::string& hostname, | 755 const std::string& hostname, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); | 801 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); |
| 788 if (check_revocation) | 802 if (check_revocation) |
| 789 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 803 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
| 790 | 804 |
| 791 ScopedCERTCertList trust_anchors; | 805 ScopedCERTCertList trust_anchors; |
| 792 if (!additional_trust_anchors.empty()) { | 806 if (!additional_trust_anchors.empty()) { |
| 793 trust_anchors.reset( | 807 trust_anchors.reset( |
| 794 CertificateListToCERTCertList(additional_trust_anchors)); | 808 CertificateListToCERTCertList(additional_trust_anchors)); |
| 795 } | 809 } |
| 796 | 810 |
| 797 SECStatus status = PKIXVerifyCert(cert_handle, check_revocation, false, | 811 SECStatus status = PKIXVerifyCert(cert_handle, |
| 798 cert_io_enabled, NULL, 0, | 812 check_revocation, |
| 799 trust_anchors.get(), cvout); | 813 false, |
| 814 cert_io_enabled, |
| 815 NULL, |
| 816 0, |
| 817 trust_anchors.get(), |
| 818 chain_verify_callback_, |
| 819 cvout); |
| 800 | 820 |
| 801 if (status == SECSuccess && | 821 if (status == SECSuccess && |
| 802 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && | 822 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && |
| 803 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) { | 823 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) { |
| 804 // TODO(rsleevi): Optimize this by supplying the constructed chain to | 824 // TODO(rsleevi): Optimize this by supplying the constructed chain to |
| 805 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream | 825 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream |
| 806 // NSS tests for that feature. | 826 // NSS tests for that feature. |
| 807 scoped_cvout.Clear(); | 827 scoped_cvout.Clear(); |
| 808 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 828 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
| 809 status = PKIXVerifyCert(cert_handle, true, true, | 829 status = PKIXVerifyCert(cert_handle, |
| 810 cert_io_enabled, NULL, 0, trust_anchors.get(), | 830 true, |
| 831 true, |
| 832 cert_io_enabled, |
| 833 NULL, |
| 834 0, |
| 835 trust_anchors.get(), |
| 836 chain_verify_callback_, |
| 811 cvout); | 837 cvout); |
| 812 } | 838 } |
| 813 | 839 |
| 814 if (status == SECSuccess) { | 840 if (status == SECSuccess) { |
| 815 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, | 841 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, |
| 816 cvout[cvout_trust_anchor_index].value.pointer.cert, | 842 cvout[cvout_trust_anchor_index].value.pointer.cert, |
| 817 &verify_result->public_key_hashes); | 843 &verify_result->public_key_hashes); |
| 818 | 844 |
| 819 verify_result->is_issued_by_known_root = | 845 verify_result->is_issued_by_known_root = |
| 820 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); | 846 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 | 889 |
| 864 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { | 890 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { |
| 865 check_revocation |= | 891 check_revocation |= |
| 866 crl_set_result != kCRLSetOk && | 892 crl_set_result != kCRLSetOk && |
| 867 cert_io_enabled && | 893 cert_io_enabled && |
| 868 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); | 894 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); |
| 869 if (check_revocation) | 895 if (check_revocation) |
| 870 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 896 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
| 871 | 897 |
| 872 if (VerifyEV(cert_handle, flags, crl_set, check_revocation, metadata, | 898 if (VerifyEV(cert_handle, flags, crl_set, check_revocation, metadata, |
| 873 ev_policy_oid, trust_anchors.get())) { | 899 ev_policy_oid, trust_anchors.get(), chain_verify_callback_)) { |
| 874 verify_result->cert_status |= CERT_STATUS_IS_EV; | 900 verify_result->cert_status |= CERT_STATUS_IS_EV; |
| 875 } | 901 } |
| 876 } | 902 } |
| 877 | 903 |
| 878 return OK; | 904 return OK; |
| 879 } | 905 } |
| 880 | 906 |
| 881 } // namespace net | 907 } // namespace net |
| OLD | NEW |