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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: net/cert/cert_verify_proc_nss.cc
diff --git a/net/cert/cert_verify_proc_nss.cc b/net/cert/cert_verify_proc_nss.cc
index ca8e8116f0ef521f61539386abbc59dd57da2f21..cad20b9fa95fcc789159eba4fc947107269f383a 100644
--- a/net/cert/cert_verify_proc_nss.cc
+++ b/net/cert/cert_verify_proc_nss.cc
@@ -279,7 +279,7 @@ enum CRLSetResult {
// that some EV sites would otherwise take the hit of an OCSP lookup for
// no reason.
// kCRLSetOk: otherwise.
-CRLSetResult CheckRevocationWithCRLSet(CERTCertList* cert_list,
+CRLSetResult CheckRevocationWithCRLSet(const CERTCertList* cert_list,
CERTCertificate* root,
CRLSet* crl_set) {
std::vector<CERTCertificate*> certs;
@@ -352,6 +352,50 @@ CRLSetResult CheckRevocationWithCRLSet(CERTCertList* cert_list,
return kCRLSetOk;
}
+// Arguments for CheckChainRevocationWithCRLSet that are curried within the
+// CERTChainVerifyCallback's isChainValidArg.
+struct CheckChainRevocationArgs {
+ // The CRLSet to evaluate against.
+ CRLSet* crl_set = nullptr;
+
+ // The next callback to invoke, if the CRLSet does not report any errors.
+ CERTChainVerifyCallback* next_callback = nullptr;
+
+ // Indicates that the application callback failure was due to a CRLSet
+ // revocation, rather than due to |next_callback| rejecting it. This is
+ // used to map the error back to the proper caller-visible error code.
+ bool was_revoked = false;
+};
+
+SECStatus CheckChainRevocationWithCRLSet(void* is_chain_valid_arg,
+ const CERTCertList* current_chain,
+ PRBool* chain_ok) {
+ CHECK(is_chain_valid_arg);
+
+ CheckChainRevocationArgs* args =
+ static_cast<CheckChainRevocationArgs*>(is_chain_valid_arg);
+
+ CRLSetResult crlset_result = kCRLSetUnknown;
+ if (args->crl_set) {
+ crlset_result =
+ CheckRevocationWithCRLSet(current_chain, nullptr, args->crl_set);
+ }
+
+ if (crlset_result == kCRLSetRevoked) {
+ args->was_revoked = true;
+ *chain_ok = PR_FALSE;
+ return SECSuccess;
+ }
+ args->was_revoked = false;
+
+ *chain_ok = PR_TRUE;
+ if (!args->next_callback || !args->next_callback->isChainValid)
+ return SECSuccess;
+
+ return (*args->next_callback->isChainValid)(
+ args->next_callback->isChainValidArg, current_chain, chain_ok);
+}
+
// Forward declarations.
SECStatus RetryPKIXVerifyCertWithWorkarounds(
CERTCertificate* cert_handle, int num_policy_oids,
@@ -825,6 +869,22 @@ int CertVerifyProcNSS::VerifyInternalImpl(
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
}
+ // Setup a callback to call into CheckChainRevocationWithCRLSet with the
+ // current CRLSet. If the CRLSet revokes a given chain, |was_revoked|
+ // will be set to true.
+ // The same callback and args are used for every invocation of
+ // PKIXVerifyCert, as CheckChainRevocationWithCRLSet handles resetting
+ // |was_revoked| as necessary.
+ CheckChainRevocationArgs check_chain_revocation_args;
+ check_chain_revocation_args.crl_set = crl_set;
+ check_chain_revocation_args.next_callback = chain_verify_callback;
+
+ CERTChainVerifyCallback crlset_callback;
+ memset(&crlset_callback, 0, sizeof(crlset_callback));
+ crlset_callback.isChainValid = &CheckChainRevocationWithCRLSet;
+ crlset_callback.isChainValidArg =
+ static_cast<void*>(&check_chain_revocation_args);
+
// Make sure that the cert is valid now.
SECCertTimeValidity validity = CERT_CheckCertValidTimes(
cert_handle, PR_Now(), PR_TRUE);
@@ -862,15 +922,9 @@ int CertVerifyProcNSS::VerifyInternalImpl(
CertificateListToCERTCertList(additional_trust_anchors));
}
- SECStatus status = PKIXVerifyCert(cert_handle,
- check_revocation,
- false,
- cert_io_enabled,
- NULL,
- 0,
- trust_anchors.get(),
- chain_verify_callback,
- cvout);
+ SECStatus status =
+ PKIXVerifyCert(cert_handle, check_revocation, false, cert_io_enabled,
+ NULL, 0, trust_anchors.get(), &crlset_callback, cvout);
if (status == SECSuccess &&
(flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) &&
@@ -880,15 +934,8 @@ int CertVerifyProcNSS::VerifyInternalImpl(
// NSS tests for that feature.
scoped_cvout.Clear();
verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
- status = PKIXVerifyCert(cert_handle,
- true,
- true,
- cert_io_enabled,
- NULL,
- 0,
- trust_anchors.get(),
- chain_verify_callback,
- cvout);
+ status = PKIXVerifyCert(cert_handle, true, true, cert_io_enabled, NULL, 0,
+ trust_anchors.get(), &crlset_callback, cvout);
}
if (status == SECSuccess) {
@@ -910,13 +957,25 @@ int CertVerifyProcNSS::VerifyInternalImpl(
CRLSetResult crl_set_result = kCRLSetUnknown;
if (crl_set) {
- crl_set_result = CheckRevocationWithCRLSet(
- cvout[cvout_cert_list_index].value.pointer.chain,
- cvout[cvout_trust_anchor_index].value.pointer.cert,
- crl_set);
- if (crl_set_result == kCRLSetRevoked) {
+ if (status == SECSuccess) {
+ // Reverify the returned chain; NSS should have already called
+ // CheckChainRevocationWithCRLSet prior to returning, but given the
+ // edge cases (self-signed certs that are trusted; cached chains;
+ // unreadable code), this is more about defense in depth than
+ // functional necessity.
+ crl_set_result = CheckRevocationWithCRLSet(
+ cvout[cvout_cert_list_index].value.pointer.chain,
+ cvout[cvout_trust_anchor_index].value.pointer.cert, crl_set);
+ if (crl_set_result == kCRLSetRevoked) {
+ PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
+ status = SECFailure;
+ }
+ } else if (PORT_GetError() == SEC_ERROR_APPLICATION_CALLBACK_ERROR &&
+ check_chain_revocation_args.was_revoked) {
+ // If a CRLSet was supplied, and the error was an application callback
+ // error, then it was directed through the CRLSet code and that
+ // particular chain was revoked.
PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
- status = SECFailure;
}
}
@@ -949,14 +1008,8 @@ int CertVerifyProcNSS::VerifyInternalImpl(
if (check_revocation)
verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
- if (VerifyEV(cert_handle,
- flags,
- crl_set,
- check_revocation,
- metadata,
- ev_policy_oid,
- trust_anchors.get(),
- chain_verify_callback)) {
+ if (VerifyEV(cert_handle, flags, crl_set, check_revocation, metadata,
+ ev_policy_oid, trust_anchors.get(), &crlset_callback)) {
verify_result->cert_status |= CERT_STATUS_IS_EV;
}
}
« 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