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

Unified Diff: net/quic/crypto/proof_verifier_chromium.cc

Issue 2120703003: QUIC - Race Cert Verification with host resolution if certs are (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Minor optimization, when verifying certs only skip policy checks. Created 4 years, 5 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/quic/crypto/proof_verifier_chromium.cc
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index 096374a747255b451000cf3afccf034083a13368..fdcd2161ab302b19b3e0e802453175c57ca150da 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -78,6 +78,17 @@ class ProofVerifierChromium::Job {
std::unique_ptr<ProofVerifyDetails>* verify_details,
ProofVerifierCallback* callback);
+ // Starts the certificate chain verification of |certs|. If |QUIC_PENDING| is
+ // returned, then |callback| will be invoked asynchronously when the
+ // verification completes.
+ QuicAsyncStatus VerifyCertChain(
+ const std::string& hostname,
+ const uint16_t port,
+ const std::vector<std::string>& certs,
+ std::string* error_details,
+ std::unique_ptr<ProofVerifyDetails>* verify_details,
+ ProofVerifierCallback* callback);
+
private:
enum State {
STATE_NONE,
@@ -85,6 +96,19 @@ class ProofVerifierChromium::Job {
STATE_VERIFY_CERT_COMPLETE,
};
+ // Convert |certs| to |cert_|(X509Certificate). Returns true if successful.
+ bool GetX509Certificate(const vector<string>& certs,
+ std::string* error_details,
+ std::unique_ptr<ProofVerifyDetails>* verify_details);
+
+ // Start the cert verification.
+ QuicAsyncStatus VerifyCert(
+ const string& hostname,
+ const uint16_t port,
+ std::string* error_details,
+ std::unique_ptr<ProofVerifyDetails>* verify_details,
+ ProofVerifierCallback* callback);
+
int DoLoop(int last_io_result);
void OnIOComplete(int result);
int DoVerifyCert(int result);
@@ -125,6 +149,9 @@ class ProofVerifierChromium::Job {
// passed to CertVerifier::Verify.
int cert_verify_flags_;
+ // If set to true, enforces policy checking in DoVerifyCertComplete().
+ bool enforce_policy_checking_;
ramant (doing other things) 2016/07/07 19:31:49 Hi Ryan, As we had discussed offline, added this
+
State next_state_;
base::TimeTicks start_time_;
@@ -148,6 +175,7 @@ ProofVerifierChromium::Job::Job(
transport_security_state_(transport_security_state),
cert_transparency_verifier_(cert_transparency_verifier),
cert_verify_flags_(cert_verify_flags),
+ enforce_policy_checking_(true),
next_state_(STATE_NONE),
start_time_(base::TimeTicks::Now()),
net_log_(net_log) {
@@ -195,25 +223,8 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
verify_details_.reset(new ProofVerifyDetailsChromium);
- if (certs.empty()) {
- *error_details = "Failed to create certificate chain. Certs are empty.";
- DLOG(WARNING) << *error_details;
- verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
- *verify_details = std::move(verify_details_);
- return QUIC_FAILURE;
- }
-
- // Convert certs to X509Certificate.
- vector<StringPiece> cert_pieces(certs.size());
- for (unsigned i = 0; i < certs.size(); i++) {
- cert_pieces[i] = base::StringPiece(certs[i]);
- }
- cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces);
- if (!cert_.get()) {
- *error_details = "Failed to create certificate chain";
- DLOG(WARNING) << *error_details;
- verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
- *verify_details = std::move(verify_details_);
+ // Converts |certs| to |cert_|.
+ if (!GetX509Certificate(certs, error_details, verify_details)) {
return QUIC_FAILURE;
}
@@ -237,6 +248,74 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
return QUIC_FAILURE;
}
+ DCHECK(enforce_policy_checking_);
+ return VerifyCert(hostname, port, error_details, verify_details, callback);
+}
+
+QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain(
+ const string& hostname,
+ const uint16_t port,
+ const vector<string>& certs,
+ std::string* error_details,
+ std::unique_ptr<ProofVerifyDetails>* verify_details,
+ ProofVerifierCallback* callback) {
+ DCHECK(error_details);
+ DCHECK(verify_details);
+ DCHECK(callback);
+
+ error_details->clear();
+
+ if (STATE_NONE != next_state_) {
+ *error_details = "Certificate is already set and VerifyCertChain has begun";
+ DLOG(DFATAL) << *error_details;
+ return QUIC_FAILURE;
+ }
+
+ verify_details_.reset(new ProofVerifyDetailsChromium);
+
+ // Converts |certs| to |cert_|.
+ if (!GetX509Certificate(certs, error_details, verify_details)) {
+ return QUIC_FAILURE;
+ }
+
+ enforce_policy_checking_ = false;
+ return VerifyCert(hostname, port, error_details, verify_details, callback);
+}
+
+bool ProofVerifierChromium::Job::GetX509Certificate(
+ const vector<string>& certs,
+ std::string* error_details,
+ std::unique_ptr<ProofVerifyDetails>* verify_details) {
+ if (certs.empty()) {
+ *error_details = "Failed to create certificate chain. Certs are empty.";
+ DLOG(WARNING) << *error_details;
+ verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
+ *verify_details = std::move(verify_details_);
+ return false;
+ }
+
+ // Convert certs to X509Certificate.
+ vector<StringPiece> cert_pieces(certs.size());
+ for (unsigned i = 0; i < certs.size(); i++) {
+ cert_pieces[i] = base::StringPiece(certs[i]);
+ }
+ cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces);
+ if (!cert_.get()) {
+ *error_details = "Failed to create certificate chain";
+ DLOG(WARNING) << *error_details;
+ verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
+ *verify_details = std::move(verify_details_);
+ return false;
+ }
+ return true;
+}
+
+QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert(
+ const string& hostname,
+ const uint16_t port,
+ std::string* error_details,
+ std::unique_ptr<ProofVerifyDetails>* verify_details,
+ ProofVerifierCallback* callback) {
hostname_ = hostname;
port_ = port;
@@ -315,7 +394,8 @@ int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
// If the connection was good, check HPKP and CT status simultaneously,
// but prefer to treat the HPKP error as more serious, if there was one.
- if ((result == OK ||
+ if (enforce_policy_checking_ &&
+ (result == OK ||
(IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) {
if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) {
ct::EVPolicyCompliance ev_policy_compliance =
@@ -511,6 +591,32 @@ QuicAsyncStatus ProofVerifierChromium::VerifyProof(
return status;
}
+QuicAsyncStatus ProofVerifierChromium::VerifyCertChain(
+ const std::string& hostname,
+ const uint16_t port,
+ const std::vector<std::string>& certs,
+ const ProofVerifyContext* verify_context,
+ std::string* error_details,
+ std::unique_ptr<ProofVerifyDetails>* verify_details,
+ ProofVerifierCallback* callback) {
+ if (!verify_context) {
+ *error_details = "Missing context";
+ return QUIC_FAILURE;
+ }
+ const ProofVerifyContextChromium* chromium_context =
+ reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
+ std::unique_ptr<Job> job(
+ new Job(this, cert_verifier_, ct_policy_enforcer_,
+ transport_security_state_, cert_transparency_verifier_,
+ chromium_context->cert_verify_flags, chromium_context->net_log));
+ QuicAsyncStatus status = job->VerifyCertChain(
+ hostname, port, certs, error_details, verify_details, callback);
+ if (status == QUIC_PENDING) {
+ active_jobs_.insert(job.release());
+ }
Ryan Hamilton 2016/07/07 21:36:12 nit: no {}s
ramant (doing other things) 2016/07/07 22:18:27 Done. Used no {}s in chromium specific files. They
+ return status;
+}
+
void ProofVerifierChromium::OnJobComplete(Job* job) {
active_jobs_.erase(job);
delete job;

Powered by Google App Engine
This is Rietveld 408576698