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

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: Fix ChromeOS Test 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
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 // Setup a callback to call into CheckChainRevocationWithCRLSet with the
873 // current CRLSet. If the CRLSet revokes a given chain, |was_revoked|
874 // will be set to true.
875 // The same callback and args are used for every invocation of
876 // PKIXVerifyCert, as CheckChainRevocationWithCRLSet handles resetting
877 // |was_revoked| as necessary.
878 CheckChainRevocationArgs check_chain_revocation_args;
879 check_chain_revocation_args.crl_set = crl_set;
880 check_chain_revocation_args.next_callback = chain_verify_callback;
881
882 CERTChainVerifyCallback crlset_callback;
883 memset(&crlset_callback, 0, sizeof(crlset_callback));
884 crlset_callback.isChainValid = &CheckChainRevocationWithCRLSet;
885 crlset_callback.isChainValidArg =
886 static_cast<void*>(&check_chain_revocation_args);
887
828 // Make sure that the cert is valid now. 888 // Make sure that the cert is valid now.
829 SECCertTimeValidity validity = CERT_CheckCertValidTimes( 889 SECCertTimeValidity validity = CERT_CheckCertValidTimes(
830 cert_handle, PR_Now(), PR_TRUE); 890 cert_handle, PR_Now(), PR_TRUE);
831 if (validity != secCertTimeValid) 891 if (validity != secCertTimeValid)
832 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 892 verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
833 893
834 CERTValOutParam cvout[3]; 894 CERTValOutParam cvout[3];
835 int cvout_index = 0; 895 int cvout_index = 0;
836 cvout[cvout_index].type = cert_po_certList; 896 cvout[cvout_index].type = cert_po_certList;
837 cvout[cvout_index].value.pointer.chain = NULL; 897 cvout[cvout_index].value.pointer.chain = NULL;
(...skipping 17 matching lines...) Expand all
855 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); 915 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED);
856 if (check_revocation) 916 if (check_revocation)
857 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 917 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
858 918
859 ScopedCERTCertList trust_anchors; 919 ScopedCERTCertList trust_anchors;
860 if (!additional_trust_anchors.empty()) { 920 if (!additional_trust_anchors.empty()) {
861 trust_anchors.reset( 921 trust_anchors.reset(
862 CertificateListToCERTCertList(additional_trust_anchors)); 922 CertificateListToCERTCertList(additional_trust_anchors));
863 } 923 }
864 924
865 SECStatus status = PKIXVerifyCert(cert_handle, 925 SECStatus status =
866 check_revocation, 926 PKIXVerifyCert(cert_handle, check_revocation, false, cert_io_enabled,
867 false, 927 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 928
875 if (status == SECSuccess && 929 if (status == SECSuccess &&
876 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && 930 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) &&
877 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) { 931 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) {
878 // TODO(rsleevi): Optimize this by supplying the constructed chain to 932 // TODO(rsleevi): Optimize this by supplying the constructed chain to
879 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream 933 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream
880 // NSS tests for that feature. 934 // NSS tests for that feature.
881 scoped_cvout.Clear(); 935 scoped_cvout.Clear();
882 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 936 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
883 status = PKIXVerifyCert(cert_handle, 937 status = PKIXVerifyCert(cert_handle, true, true, cert_io_enabled, NULL, 0,
884 true, 938 trust_anchors.get(), &crlset_callback, cvout);
885 true,
886 cert_io_enabled,
887 NULL,
888 0,
889 trust_anchors.get(),
890 chain_verify_callback,
891 cvout);
892 } 939 }
893 940
894 if (status == SECSuccess) { 941 if (status == SECSuccess) {
895 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, 942 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain,
896 cvout[cvout_trust_anchor_index].value.pointer.cert, 943 cvout[cvout_trust_anchor_index].value.pointer.cert,
897 &verify_result->public_key_hashes); 944 &verify_result->public_key_hashes);
898 945
899 verify_result->is_issued_by_known_root = 946 verify_result->is_issued_by_known_root =
900 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); 947 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert);
901 verify_result->is_issued_by_additional_trust_anchor = 948 verify_result->is_issued_by_additional_trust_anchor =
902 IsAdditionalTrustAnchor( 949 IsAdditionalTrustAnchor(
903 trust_anchors.get(), 950 trust_anchors.get(),
904 cvout[cvout_trust_anchor_index].value.pointer.cert); 951 cvout[cvout_trust_anchor_index].value.pointer.cert);
905 952
906 GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain, 953 GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain,
907 cvout[cvout_trust_anchor_index].value.pointer.cert, 954 cvout[cvout_trust_anchor_index].value.pointer.cert,
908 verify_result); 955 verify_result);
909 } 956 }
910 957
911 CRLSetResult crl_set_result = kCRLSetUnknown; 958 CRLSetResult crl_set_result = kCRLSetUnknown;
912 if (crl_set) { 959 if (crl_set) {
913 crl_set_result = CheckRevocationWithCRLSet( 960 if (status == SECSuccess) {
914 cvout[cvout_cert_list_index].value.pointer.chain, 961 // Reverify the returned chain; NSS should have already called
915 cvout[cvout_trust_anchor_index].value.pointer.cert, 962 // CheckChainRevocationWithCRLSet prior to returning, but given the
916 crl_set); 963 // edge cases (self-signed certs that are trusted; cached chains;
917 if (crl_set_result == kCRLSetRevoked) { 964 // unreadable code), this is more about defense in depth than
965 // functional necessity.
966 crl_set_result = CheckRevocationWithCRLSet(
967 cvout[cvout_cert_list_index].value.pointer.chain,
968 cvout[cvout_trust_anchor_index].value.pointer.cert, crl_set);
969 if (crl_set_result == kCRLSetRevoked) {
970 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
971 status = SECFailure;
972 }
973 } else if (PORT_GetError() == SEC_ERROR_APPLICATION_CALLBACK_ERROR &&
974 check_chain_revocation_args.was_revoked) {
975 // If a CRLSet was supplied, and the error was an application callback
976 // error, then it was directed through the CRLSet code and that
977 // particular chain was revoked.
918 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); 978 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
919 status = SECFailure;
920 } 979 }
921 } 980 }
922 981
923 if (status != SECSuccess) { 982 if (status != SECSuccess) {
924 int err = PORT_GetError(); 983 int err = PORT_GetError();
925 LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname 984 LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname
926 << " failed err=" << err; 985 << " failed err=" << err;
927 // CERT_PKIXVerifyCert rerports the wrong error code for 986 // CERT_PKIXVerifyCert rerports the wrong error code for
928 // expired certificates (NSS bug 491174) 987 // expired certificates (NSS bug 491174)
929 if (err == SEC_ERROR_CERT_NOT_VALID && 988 if (err == SEC_ERROR_CERT_NOT_VALID &&
(...skipping 12 matching lines...) Expand all
942 return MapCertStatusToNetError(verify_result->cert_status); 1001 return MapCertStatusToNetError(verify_result->cert_status);
943 1002
944 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { 1003 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) {
945 check_revocation |= 1004 check_revocation |=
946 crl_set_result != kCRLSetOk && 1005 crl_set_result != kCRLSetOk &&
947 cert_io_enabled && 1006 cert_io_enabled &&
948 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); 1007 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY);
949 if (check_revocation) 1008 if (check_revocation)
950 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 1009 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
951 1010
952 if (VerifyEV(cert_handle, 1011 if (VerifyEV(cert_handle, flags, crl_set, check_revocation, metadata,
953 flags, 1012 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; 1013 verify_result->cert_status |= CERT_STATUS_IS_EV;
961 } 1014 }
962 } 1015 }
963 1016
964 return OK; 1017 return OK;
965 } 1018 }
966 1019
967 int CertVerifyProcNSS::VerifyInternal( 1020 int CertVerifyProcNSS::VerifyInternal(
968 X509Certificate* cert, 1021 X509Certificate* cert,
969 const std::string& hostname, 1022 const std::string& hostname,
970 const std::string& ocsp_response, 1023 const std::string& ocsp_response,
971 int flags, 1024 int flags,
972 CRLSet* crl_set, 1025 CRLSet* crl_set,
973 const CertificateList& additional_trust_anchors, 1026 const CertificateList& additional_trust_anchors,
974 CertVerifyResult* verify_result) { 1027 CertVerifyResult* verify_result) {
975 return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set, 1028 return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set,
976 additional_trust_anchors, 1029 additional_trust_anchors,
977 NULL, // chain_verify_callback 1030 NULL, // chain_verify_callback
978 verify_result); 1031 verify_result);
979 } 1032 }
980 1033
981 } // namespace net 1034 } // namespace net
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc ('k') | net/cert/cert_verify_proc_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698