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

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: Created 4 years, 10 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 scoped_refptr<X509Certificate> CreateCertFromCERTList(
356 const CERTCertList* cert_list) {
357 X509Certificate::OSCertHandles intermediates;
358 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
359 !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) {
360 intermediates.push_back(node->cert);
361 }
362 if (intermediates.empty())
363 return nullptr;
364
365 X509Certificate::OSCertHandle leaf = intermediates.front();
366 intermediates.erase(intermediates.begin());
eroman 2016/02/25 03:12:02 Could have avoided the erase().
Ryan Sleevi 2016/03/01 22:44:57 I'm not sure your remark here, or what you're sugg
eroman 2016/03/02 00:05:07 In the construction of intermediates vector above,
367 #if defined(OS_IOS)
368 return x509_util_ios::CreateCertFromNSSHandles(leaf, intermediates);
369 #else
370 return X509Certificate::CreateFromHandle(leaf, intermediates);
371 #endif
372 }
373
374 // Arguments for CheckChainRevocationWithCRLSet that are curried within the
375 // CERTChainVerifyCallback's isChainValidArg.
376 struct CheckChainRevocationArgs {
377 CRLSet* crl_set;
378 CERTChainVerifyCallback* next_callback;
379 scoped_refptr<X509Certificate> revoked_chain;
380 };
381
382 SECStatus CheckChainRevocationWithCRLSet(void* is_chain_valid_arg,
383 const CERTCertList* current_chain,
384 PRBool* chain_ok) {
385 if (!is_chain_valid_arg) {
eroman 2016/02/25 03:12:02 Is this actually reachable?
Ryan Sleevi 2016/03/01 22:44:57 It's NSS; the guarantees the API provides are undo
386 *chain_ok = PR_FALSE;
387 return SECFailure;
388 }
389
390 CheckChainRevocationArgs* args =
391 static_cast<CheckChainRevocationArgs*>(is_chain_valid_arg);
392
393 CRLSetResult crlset_result = kCRLSetUnknown;
394 if (args->crl_set)
eroman 2016/02/25 03:12:01 curlies
395 crlset_result =
396 CheckRevocationWithCRLSet(current_chain, nullptr, args->crl_set);
397
398 if (crlset_result == kCRLSetRevoked) {
399 args->revoked_chain = CreateCertFromCERTList(current_chain);
400 *chain_ok = PR_FALSE;
401 return SECSuccess;
402 }
403 args->revoked_chain = nullptr;
404
405 *chain_ok = PR_TRUE;
406 if (!args->next_callback || !args->next_callback->isChainValid)
eroman 2016/02/25 03:12:02 Is it expected that isChainValid can be NULL, or i
Ryan Sleevi 2016/03/01 22:44:57 Yes, it is; this matches the internal checks of NS
407 return SECSuccess;
408
409 return (*args->next_callback->isChainValid)(
410 args->next_callback->isChainValidArg, current_chain, chain_ok);
411 }
412
355 // Forward declarations. 413 // Forward declarations.
356 SECStatus RetryPKIXVerifyCertWithWorkarounds( 414 SECStatus RetryPKIXVerifyCertWithWorkarounds(
357 CERTCertificate* cert_handle, int num_policy_oids, 415 CERTCertificate* cert_handle, int num_policy_oids,
358 bool cert_io_enabled, std::vector<CERTValInParam>* cvin, 416 bool cert_io_enabled, std::vector<CERTValInParam>* cvin,
359 CERTValOutParam* cvout); 417 CERTValOutParam* cvout);
360 SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle); 418 SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle);
361 419
362 // Call CERT_PKIXVerifyCert for the cert_handle. 420 // Call CERT_PKIXVerifyCert for the cert_handle.
363 // Verification results are stored in an array of CERTValOutParam. 421 // 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 422 // 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, 876 cache_ocsp_response_from_side_channel_(CERT_GetDefaultCertDB(), cert_handle,
819 PR_Now(), &ocsp_response_item, 877 PR_Now(), &ocsp_response_item,
820 nullptr); 878 nullptr);
821 } 879 }
822 880
823 if (!cert->VerifyNameMatch(hostname, 881 if (!cert->VerifyNameMatch(hostname,
824 &verify_result->common_name_fallback_used)) { 882 &verify_result->common_name_fallback_used)) {
825 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 883 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
826 } 884 }
827 885
886 CheckChainRevocationArgs check_chain_revocation_args;
887 check_chain_revocation_args.crl_set = crl_set;
888 check_chain_revocation_args.next_callback = chain_verify_callback;
889 check_chain_revocation_args.revoked_chain = nullptr;
eroman 2016/02/25 03:12:01 could have omitted this unless you are trying to b
Ryan Sleevi 2016/03/01 22:44:58 crl_set and next_callback are pointer types; they
eroman 2016/03/02 00:05:07 I was referring to revoked_chain, which is a scope
890
891 CERTChainVerifyCallback crlset_callback;
892 memset(&crlset_callback, 0, sizeof(crlset_callback));
893 crlset_callback.isChainValid = &CheckChainRevocationWithCRLSet;
894 crlset_callback.isChainValidArg =
895 static_cast<void*>(&check_chain_revocation_args);
896
828 // Make sure that the cert is valid now. 897 // Make sure that the cert is valid now.
829 SECCertTimeValidity validity = CERT_CheckCertValidTimes( 898 SECCertTimeValidity validity = CERT_CheckCertValidTimes(
830 cert_handle, PR_Now(), PR_TRUE); 899 cert_handle, PR_Now(), PR_TRUE);
831 if (validity != secCertTimeValid) 900 if (validity != secCertTimeValid)
832 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 901 verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
833 902
834 CERTValOutParam cvout[3]; 903 CERTValOutParam cvout[3];
835 int cvout_index = 0; 904 int cvout_index = 0;
836 cvout[cvout_index].type = cert_po_certList; 905 cvout[cvout_index].type = cert_po_certList;
837 cvout[cvout_index].value.pointer.chain = NULL; 906 cvout[cvout_index].value.pointer.chain = NULL;
(...skipping 17 matching lines...) Expand all
855 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); 924 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED);
856 if (check_revocation) 925 if (check_revocation)
857 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 926 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
858 927
859 ScopedCERTCertList trust_anchors; 928 ScopedCERTCertList trust_anchors;
860 if (!additional_trust_anchors.empty()) { 929 if (!additional_trust_anchors.empty()) {
861 trust_anchors.reset( 930 trust_anchors.reset(
862 CertificateListToCERTCertList(additional_trust_anchors)); 931 CertificateListToCERTCertList(additional_trust_anchors));
863 } 932 }
864 933
865 SECStatus status = PKIXVerifyCert(cert_handle, 934 SECStatus status =
866 check_revocation, 935 PKIXVerifyCert(cert_handle, check_revocation, false, cert_io_enabled,
867 false, 936 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 937
875 if (status == SECSuccess && 938 if (status == SECSuccess &&
876 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && 939 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) &&
877 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) { 940 !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) {
878 // TODO(rsleevi): Optimize this by supplying the constructed chain to 941 // TODO(rsleevi): Optimize this by supplying the constructed chain to
879 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream 942 // libpkix via cvin. Omitting for now, due to lack of coverage in upstream
880 // NSS tests for that feature. 943 // NSS tests for that feature.
881 scoped_cvout.Clear(); 944 scoped_cvout.Clear();
882 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 945 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
883 status = PKIXVerifyCert(cert_handle, 946 status = PKIXVerifyCert(cert_handle, true, true, cert_io_enabled, NULL, 0,
884 true, 947 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 } 948 }
893 949
894 if (status == SECSuccess) { 950 if (status == SECSuccess) {
895 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, 951 AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain,
896 cvout[cvout_trust_anchor_index].value.pointer.cert, 952 cvout[cvout_trust_anchor_index].value.pointer.cert,
897 &verify_result->public_key_hashes); 953 &verify_result->public_key_hashes);
898 954
899 verify_result->is_issued_by_known_root = 955 verify_result->is_issued_by_known_root =
900 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); 956 IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert);
901 verify_result->is_issued_by_additional_trust_anchor = 957 verify_result->is_issued_by_additional_trust_anchor =
902 IsAdditionalTrustAnchor( 958 IsAdditionalTrustAnchor(
903 trust_anchors.get(), 959 trust_anchors.get(),
904 cvout[cvout_trust_anchor_index].value.pointer.cert); 960 cvout[cvout_trust_anchor_index].value.pointer.cert);
905 961
906 GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain, 962 GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain,
907 cvout[cvout_trust_anchor_index].value.pointer.cert, 963 cvout[cvout_trust_anchor_index].value.pointer.cert,
908 verify_result); 964 verify_result);
909 } 965 }
910 966
911 CRLSetResult crl_set_result = kCRLSetUnknown; 967 CRLSetResult crl_set_result = kCRLSetUnknown;
912 if (crl_set) { 968 if (crl_set) {
913 crl_set_result = CheckRevocationWithCRLSet( 969 if (status == SECSuccess) {
914 cvout[cvout_cert_list_index].value.pointer.chain, 970 crl_set_result = CheckRevocationWithCRLSet(
eroman 2016/02/25 03:12:02 Wasn't this already called by PKIXVerifyCert() on
Ryan Sleevi 2016/03/01 22:44:57 As with the Windows code, we're taking a defense i
915 cvout[cvout_trust_anchor_index].value.pointer.cert, 971 cvout[cvout_cert_list_index].value.pointer.chain,
916 crl_set); 972 cvout[cvout_trust_anchor_index].value.pointer.cert, crl_set);
917 if (crl_set_result == kCRLSetRevoked) { 973 if (crl_set_result == kCRLSetRevoked) {
974 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
975 status = SECFailure;
976 }
977 } else if (PORT_GetError() == SEC_ERROR_APPLICATION_CALLBACK_ERROR &&
978 check_chain_revocation_args.revoked_chain) {
eroman 2016/02/25 03:12:02 It doesn't look like the revoked_chain is every co
Ryan Sleevi 2016/03/01 22:44:58 You're right; I was originally going to sub in the
979 // If a CRLSet was supplied, and the error was an application callback
980 // error, then it was directed through the CRLSet code and that
981 // particular chain was revoked.
918 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); 982 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
919 status = SECFailure;
920 } 983 }
921 } 984 }
922 985
923 if (status != SECSuccess) { 986 if (status != SECSuccess) {
924 int err = PORT_GetError(); 987 int err = PORT_GetError();
925 LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname 988 LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname
926 << " failed err=" << err; 989 << " failed err=" << err;
927 // CERT_PKIXVerifyCert rerports the wrong error code for 990 // CERT_PKIXVerifyCert rerports the wrong error code for
928 // expired certificates (NSS bug 491174) 991 // expired certificates (NSS bug 491174)
929 if (err == SEC_ERROR_CERT_NOT_VALID && 992 if (err == SEC_ERROR_CERT_NOT_VALID &&
(...skipping 12 matching lines...) Expand all
942 return MapCertStatusToNetError(verify_result->cert_status); 1005 return MapCertStatusToNetError(verify_result->cert_status);
943 1006
944 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { 1007 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) {
945 check_revocation |= 1008 check_revocation |=
946 crl_set_result != kCRLSetOk && 1009 crl_set_result != kCRLSetOk &&
947 cert_io_enabled && 1010 cert_io_enabled &&
948 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); 1011 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY);
949 if (check_revocation) 1012 if (check_revocation)
950 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 1013 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
951 1014
952 if (VerifyEV(cert_handle, 1015 if (VerifyEV(cert_handle, flags, crl_set, check_revocation, metadata,
953 flags, 1016 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; 1017 verify_result->cert_status |= CERT_STATUS_IS_EV;
961 } 1018 }
962 } 1019 }
963 1020
964 return OK; 1021 return OK;
965 } 1022 }
966 1023
967 int CertVerifyProcNSS::VerifyInternal( 1024 int CertVerifyProcNSS::VerifyInternal(
968 X509Certificate* cert, 1025 X509Certificate* cert,
969 const std::string& hostname, 1026 const std::string& hostname,
970 const std::string& ocsp_response, 1027 const std::string& ocsp_response,
971 int flags, 1028 int flags,
972 CRLSet* crl_set, 1029 CRLSet* crl_set,
973 const CertificateList& additional_trust_anchors, 1030 const CertificateList& additional_trust_anchors,
974 CertVerifyResult* verify_result) { 1031 CertVerifyResult* verify_result) {
975 return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set, 1032 return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set,
976 additional_trust_anchors, 1033 additional_trust_anchors,
977 NULL, // chain_verify_callback 1034 NULL, // chain_verify_callback
978 verify_result); 1035 verify_result);
979 } 1036 }
980 1037
981 } // namespace net 1038 } // 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