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

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

Issue 1724413002: Perform CRLSet evaluation during Path Building on NSS (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Review feedback Created 4 years, 9 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
« no previous file with comments | « no previous file | net/cert/cert_verify_proc_unittest.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/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 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 // kCRLSetRevoked: if any element of the chain is known to have been revoked. 272 // kCRLSetRevoked: if any element of the chain is known to have been revoked.
273 // kCRLSetUnknown: if there is no fresh information about the leaf 273 // kCRLSetUnknown: if there is no fresh information about the leaf
274 // certificate in the chain or if the CRLSet has expired. 274 // certificate in the chain or if the CRLSet has expired.
275 // 275 //
276 // Only the leaf certificate is considered for coverage because some 276 // Only the leaf certificate is considered for coverage because some
277 // intermediates have CRLs with no revocations (after filtering) and 277 // intermediates have CRLs with no revocations (after filtering) and
278 // those CRLs are pruned from the CRLSet at generation time. This means 278 // those CRLs are pruned from the CRLSet at generation time. This means
279 // that some EV sites would otherwise take the hit of an OCSP lookup for 279 // that some EV sites would otherwise take the hit of an OCSP lookup for
280 // no reason. 280 // no reason.
281 // kCRLSetOk: otherwise. 281 // kCRLSetOk: otherwise.
282 CRLSetResult CheckRevocationWithCRLSet(CERTCertList* cert_list, 282 CRLSetResult CheckRevocationWithCRLSet(const CERTCertList* cert_list,
283 CERTCertificate* root, 283 CERTCertificate* root,
284 CRLSet* crl_set) { 284 CRLSet* crl_set) {
285 std::vector<CERTCertificate*> certs; 285 std::vector<CERTCertificate*> certs;
286 286
287 if (cert_list) { 287 if (cert_list) {
288 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 288 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
289 !CERT_LIST_END(node, cert_list); 289 !CERT_LIST_END(node, cert_list);
290 node = CERT_LIST_NEXT(node)) { 290 node = CERT_LIST_NEXT(node)) {
291 certs.push_back(node->cert); 291 certs.push_back(node->cert);
292 } 292 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 error = true; 345 error = true;
346 continue; 346 continue;
347 } 347 }
348 } 348 }
349 349
350 if (error || !last_covered || crl_set->IsExpired()) 350 if (error || !last_covered || crl_set->IsExpired())
351 return kCRLSetUnknown; 351 return kCRLSetUnknown;
352 return kCRLSetOk; 352 return kCRLSetOk;
353 } 353 }
354 354
355 // Arguments for CheckChainRevocationWithCRLSet that are curried within the
356 // CERTChainVerifyCallback's isChainValidArg.
357 struct CheckChainRevocationArgs {
358 // The CRLSet to evaluate against.
359 CRLSet* crl_set = nullptr;
360
361 // The next callback to invoke, if the CRLSet does not report any errors.
362 CERTChainVerifyCallback* next_callback = nullptr;
363
364 // Indicates that the application callback failure was due to a CRLSet
365 // revocation, rather than due to |next_callback| rejecting it. This is
366 // used to map the error back to the proper caller-visible error code.
367 bool was_revoked = false;
368 };
369
370 SECStatus CheckChainRevocationWithCRLSet(void* is_chain_valid_arg,
371 const CERTCertList* current_chain,
372 PRBool* chain_ok) {
373 CHECK(is_chain_valid_arg);
374
375 CheckChainRevocationArgs* args =
376 static_cast<CheckChainRevocationArgs*>(is_chain_valid_arg);
377
378 CRLSetResult crlset_result = kCRLSetUnknown;
379 if (args->crl_set) {
380 crlset_result =
381 CheckRevocationWithCRLSet(current_chain, nullptr, args->crl_set);
382 }
383
384 if (crlset_result == kCRLSetRevoked) {
385 args->was_revoked = true;
386 *chain_ok = PR_FALSE;
387 return SECSuccess;
388 }
389 args->was_revoked = false;
390
391 *chain_ok = PR_TRUE;
392 if (!args->next_callback || !args->next_callback->isChainValid)
393 return SECSuccess;
394
395 return (*args->next_callback->isChainValid)(
396 args->next_callback->isChainValidArg, current_chain, chain_ok);
397 }
398
355 // Forward declarations. 399 // Forward declarations.
356 SECStatus RetryPKIXVerifyCertWithWorkarounds( 400 SECStatus RetryPKIXVerifyCertWithWorkarounds(
357 CERTCertificate* cert_handle, int num_policy_oids, 401 CERTCertificate* cert_handle, int num_policy_oids,
358 bool cert_io_enabled, std::vector<CERTValInParam>* cvin, 402 bool cert_io_enabled, std::vector<CERTValInParam>* cvin,
359 CERTValOutParam* cvout); 403 CERTValOutParam* cvout);
360 SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle); 404 SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle);
361 405
362 // Call CERT_PKIXVerifyCert for the cert_handle. 406 // Call CERT_PKIXVerifyCert for the cert_handle.
363 // Verification results are stored in an array of CERTValOutParam. 407 // Verification results are stored in an array of CERTValOutParam.
364 // If |hard_fail| is true, and no policy_oids are supplied (eg: EV is NOT being 408 // If |hard_fail| is true, and no policy_oids are supplied (eg: EV is NOT being
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 cache_ocsp_response_from_side_channel_(CERT_GetDefaultCertDB(), cert_handle, 862 cache_ocsp_response_from_side_channel_(CERT_GetDefaultCertDB(), cert_handle,
819 PR_Now(), &ocsp_response_item, 863 PR_Now(), &ocsp_response_item,
820 nullptr); 864 nullptr);
821 } 865 }
822 866
823 if (!cert->VerifyNameMatch(hostname, 867 if (!cert->VerifyNameMatch(hostname,
824 &verify_result->common_name_fallback_used)) { 868 &verify_result->common_name_fallback_used)) {
825 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 869 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
826 } 870 }
827 871
872 CheckChainRevocationArgs check_chain_revocation_args;
873 CERTChainVerifyCallback crlset_callback;
874 memset(&crlset_callback, 0, sizeof(crlset_callback));
875 crlset_callback.isChainValid = &CheckChainRevocationWithCRLSet;
876 crlset_callback.isChainValidArg =
877 static_cast<void*>(&check_chain_revocation_args);
878
828 // Make sure that the cert is valid now. 879 // Make sure that the cert is valid now.
829 SECCertTimeValidity validity = CERT_CheckCertValidTimes( 880 SECCertTimeValidity validity = CERT_CheckCertValidTimes(
830 cert_handle, PR_Now(), PR_TRUE); 881 cert_handle, PR_Now(), PR_TRUE);
831 if (validity != secCertTimeValid) 882 if (validity != secCertTimeValid)
832 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 883 verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
833 884
834 CERTValOutParam cvout[3]; 885 CERTValOutParam cvout[3];
835 int cvout_index = 0; 886 int cvout_index = 0;
836 cvout[cvout_index].type = cert_po_certList; 887 cvout[cvout_index].type = cert_po_certList;
837 cvout[cvout_index].value.pointer.chain = NULL; 888 cvout[cvout_index].value.pointer.chain = NULL;
(...skipping 17 matching lines...) Expand all
855 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); 906 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED);
856 if (check_revocation) 907 if (check_revocation)
857 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 908 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
858 909
859 ScopedCERTCertList trust_anchors; 910 ScopedCERTCertList trust_anchors;
860 if (!additional_trust_anchors.empty()) { 911 if (!additional_trust_anchors.empty()) {
861 trust_anchors.reset( 912 trust_anchors.reset(
862 CertificateListToCERTCertList(additional_trust_anchors)); 913 CertificateListToCERTCertList(additional_trust_anchors));
863 } 914 }
864 915
865 SECStatus status = PKIXVerifyCert(cert_handle, 916 SECStatus status =
866 check_revocation, 917 PKIXVerifyCert(cert_handle, check_revocation, false, cert_io_enabled,
867 false, 918 NULL, 0, trust_anchors.get(), &crlset_callback, cvout);
868 cert_io_enabled,
869 NULL,
870 0,
871 trust_anchors.get(),
872 chain_verify_callback,
873 cvout);
874 919
875 if (status == SECSuccess && 920 if (status == SECSuccess &&
876 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && 921 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) &&
877 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) { 922 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) {
878 // TODO(rsleevi): Optimize this by supplying the constructed chain to 923 // TODO(rsleevi): Optimize this by supplying the constructed chain to
879 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream 924 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream
880 // NSS tests for that feature. 925 // NSS tests for that feature.
881 scoped_cvout.Clear(); 926 scoped_cvout.Clear();
882 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 927 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
883 status = PKIXVerifyCert(cert_handle, 928 status = PKIXVerifyCert(cert_handle, true, true, cert_io_enabled, NULL, 0,
884 true, 929 trust_anchors.get(), &crlset_callback, cvout);
eroman 2016/03/02 00:05:07 I think it would be better to explicitly reset |ch
885 true,
886 cert_io_enabled,
887 NULL,
888 0,
889 trust_anchors.get(),
890 chain_verify_callback,
891 cvout);
892 } 930 }
893 931
894 if (status == SECSuccess) { 932 if (status == SECSuccess) {
895 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, 933 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain,
896 cvout[cvout_trust_anchor_index].value.pointer.cert, 934 cvout[cvout_trust_anchor_index].value.pointer.cert,
897 &verify_result->public_key_hashes); 935 &verify_result->public_key_hashes);
898 936
899 verify_result->is_issued_by_known_root = 937 verify_result->is_issued_by_known_root =
900 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); 938 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert);
901 verify_result->is_issued_by_additional_trust_anchor = 939 verify_result->is_issued_by_additional_trust_anchor =
902 IsAdditionalTrustAnchor( 940 IsAdditionalTrustAnchor(
903 trust_anchors.get(), 941 trust_anchors.get(),
904 cvout[cvout_trust_anchor_index].value.pointer.cert); 942 cvout[cvout_trust_anchor_index].value.pointer.cert);
905 943
906 GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain, 944 GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain,
907 cvout[cvout_trust_anchor_index].value.pointer.cert, 945 cvout[cvout_trust_anchor_index].value.pointer.cert,
908 verify_result); 946 verify_result);
909 } 947 }
910 948
911 CRLSetResult crl_set_result = kCRLSetUnknown; 949 CRLSetResult crl_set_result = kCRLSetUnknown;
912 if (crl_set) { 950 if (crl_set) {
913 crl_set_result = CheckRevocationWithCRLSet( 951 if (status == SECSuccess) {
914 cvout[cvout_cert_list_index].value.pointer.chain, 952 crl_set_result = CheckRevocationWithCRLSet(
915 cvout[cvout_trust_anchor_index].value.pointer.cert, 953 cvout[cvout_cert_list_index].value.pointer.chain,
916 crl_set); 954 cvout[cvout_trust_anchor_index].value.pointer.cert, crl_set);
917 if (crl_set_result == kCRLSetRevoked) { 955 if (crl_set_result == kCRLSetRevoked) {
956 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
957 status = SECFailure;
958 }
959 } else if (PORT_GetError() == SEC_ERROR_APPLICATION_CALLBACK_ERROR &&
960 check_chain_revocation_args.was_revoked) {
961 // If a CRLSet was supplied, and the error was an application callback
962 // error, then it was directed through the CRLSet code and that
963 // particular chain was revoked.
918 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); 964 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
919 status = SECFailure;
920 } 965 }
921 } 966 }
922 967
923 if (status != SECSuccess) { 968 if (status != SECSuccess) {
924 int err = PORT_GetError(); 969 int err = PORT_GetError();
925 LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname 970 LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname
926 << " failed err=" << err; 971 << " failed err=" << err;
927 // CERT_PKIXVerifyCert rerports the wrong error code for 972 // CERT_PKIXVerifyCert rerports the wrong error code for
928 // expired certificates (NSS bug 491174) 973 // expired certificates (NSS bug 491174)
929 if (err == SEC_ERROR_CERT_NOT_VALID && 974 if (err == SEC_ERROR_CERT_NOT_VALID &&
(...skipping 12 matching lines...) Expand all
942 return MapCertStatusToNetError(verify_result->cert_status); 987 return MapCertStatusToNetError(verify_result->cert_status);
943 988
944 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { 989 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) {
945 check_revocation |= 990 check_revocation |=
946 crl_set_result != kCRLSetOk && 991 crl_set_result != kCRLSetOk &&
947 cert_io_enabled && 992 cert_io_enabled &&
948 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); 993 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY);
949 if (check_revocation) 994 if (check_revocation)
950 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 995 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
951 996
952 if (VerifyEV(cert_handle, 997 if (VerifyEV(cert_handle, flags, crl_set, check_revocation, metadata,
953 flags, 998 ev_policy_oid, trust_anchors.get(), &crlset_callback)) {
954 crl_set,
955 check_revocation,
956 metadata,
957 ev_policy_oid,
958 trust_anchors.get(),
959 chain_verify_callback)) {
960 verify_result->cert_status |= CERT_STATUS_IS_EV; 999 verify_result->cert_status |= CERT_STATUS_IS_EV;
961 } 1000 }
962 } 1001 }
963 1002
964 return OK; 1003 return OK;
965 } 1004 }
966 1005
967 int CertVerifyProcNSS::VerifyInternal( 1006 int CertVerifyProcNSS::VerifyInternal(
968 X509Certificate* cert, 1007 X509Certificate* cert,
969 const std::string& hostname, 1008 const std::string& hostname,
970 const std::string& ocsp_response, 1009 const std::string& ocsp_response,
971 int flags, 1010 int flags,
972 CRLSet* crl_set, 1011 CRLSet* crl_set,
973 const CertificateList& additional_trust_anchors, 1012 const CertificateList& additional_trust_anchors,
974 CertVerifyResult* verify_result) { 1013 CertVerifyResult* verify_result) {
975 return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set, 1014 return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set,
976 additional_trust_anchors, 1015 additional_trust_anchors,
977 NULL, // chain_verify_callback 1016 NULL, // chain_verify_callback
978 verify_result); 1017 verify_result);
979 } 1018 }
980 1019
981 } // namespace net 1020 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/cert/cert_verify_proc_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698