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

Side by Side Diff: net/quic/chromium/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: Fix for buildbot failure. Created 4 years, 4 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/quic/chromium/crypto/proof_verifier_chromium.h" 5 #include "net/quic/chromium/crypto/proof_verifier_chromium.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 const std::string& server_config, 71 const std::string& server_config,
72 QuicVersion quic_version, 72 QuicVersion quic_version,
73 base::StringPiece chlo_hash, 73 base::StringPiece chlo_hash,
74 const std::vector<std::string>& certs, 74 const std::vector<std::string>& certs,
75 const std::string& cert_sct, 75 const std::string& cert_sct,
76 const std::string& signature, 76 const std::string& signature,
77 std::string* error_details, 77 std::string* error_details,
78 std::unique_ptr<ProofVerifyDetails>* verify_details, 78 std::unique_ptr<ProofVerifyDetails>* verify_details,
79 std::unique_ptr<ProofVerifierCallback> callback); 79 std::unique_ptr<ProofVerifierCallback> callback);
80 80
81 // Starts the certificate chain verification of |certs|. If |QUIC_PENDING| is
82 // returned, then |callback| will be invoked asynchronously when the
83 // verification completes.
84 QuicAsyncStatus VerifyCertChain(
85 const std::string& hostname,
86 const std::vector<std::string>& certs,
87 std::string* error_details,
88 std::unique_ptr<ProofVerifyDetails>* verify_details,
89 std::unique_ptr<ProofVerifierCallback> callback);
90
81 private: 91 private:
82 enum State { 92 enum State {
83 STATE_NONE, 93 STATE_NONE,
84 STATE_VERIFY_CERT, 94 STATE_VERIFY_CERT,
85 STATE_VERIFY_CERT_COMPLETE, 95 STATE_VERIFY_CERT_COMPLETE,
86 }; 96 };
87 97
98 // Convert |certs| to |cert_|(X509Certificate). Returns true if successful.
99 bool GetX509Certificate(const vector<string>& certs,
100 std::string* error_details,
101 std::unique_ptr<ProofVerifyDetails>* verify_details);
102
103 // Start the cert verification.
104 QuicAsyncStatus VerifyCert(
105 const string& hostname,
106 const uint16_t port,
107 std::string* error_details,
108 std::unique_ptr<ProofVerifyDetails>* verify_details,
109 std::unique_ptr<ProofVerifierCallback> callback);
110
88 int DoLoop(int last_io_result); 111 int DoLoop(int last_io_result);
89 void OnIOComplete(int result); 112 void OnIOComplete(int result);
90 int DoVerifyCert(int result); 113 int DoVerifyCert(int result);
91 int DoVerifyCertComplete(int result); 114 int DoVerifyCertComplete(int result);
92 115
93 bool VerifySignature(const std::string& signed_data, 116 bool VerifySignature(const std::string& signed_data,
94 QuicVersion quic_version, 117 QuicVersion quic_version,
95 StringPiece chlo_hash, 118 StringPiece chlo_hash,
96 const std::string& signature, 119 const std::string& signature,
97 const std::string& cert); 120 const std::string& cert);
(...skipping 20 matching lines...) Expand all
118 std::unique_ptr<ProofVerifyDetailsChromium> verify_details_; 141 std::unique_ptr<ProofVerifyDetailsChromium> verify_details_;
119 std::string error_details_; 142 std::string error_details_;
120 143
121 // X509Certificate from a chain of DER encoded certificates. 144 // X509Certificate from a chain of DER encoded certificates.
122 scoped_refptr<X509Certificate> cert_; 145 scoped_refptr<X509Certificate> cert_;
123 146
124 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is 147 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is
125 // passed to CertVerifier::Verify. 148 // passed to CertVerifier::Verify.
126 int cert_verify_flags_; 149 int cert_verify_flags_;
127 150
151 // If set to true, enforces policy checking in DoVerifyCertComplete().
152 bool enforce_policy_checking_;
153
128 State next_state_; 154 State next_state_;
129 155
130 base::TimeTicks start_time_; 156 base::TimeTicks start_time_;
131 157
132 BoundNetLog net_log_; 158 BoundNetLog net_log_;
133 159
134 DISALLOW_COPY_AND_ASSIGN(Job); 160 DISALLOW_COPY_AND_ASSIGN(Job);
135 }; 161 };
136 162
137 ProofVerifierChromium::Job::Job( 163 ProofVerifierChromium::Job::Job(
138 ProofVerifierChromium* proof_verifier, 164 ProofVerifierChromium* proof_verifier,
139 CertVerifier* cert_verifier, 165 CertVerifier* cert_verifier,
140 CTPolicyEnforcer* ct_policy_enforcer, 166 CTPolicyEnforcer* ct_policy_enforcer,
141 TransportSecurityState* transport_security_state, 167 TransportSecurityState* transport_security_state,
142 CTVerifier* cert_transparency_verifier, 168 CTVerifier* cert_transparency_verifier,
143 int cert_verify_flags, 169 int cert_verify_flags,
144 const BoundNetLog& net_log) 170 const BoundNetLog& net_log)
145 : proof_verifier_(proof_verifier), 171 : proof_verifier_(proof_verifier),
146 verifier_(cert_verifier), 172 verifier_(cert_verifier),
147 policy_enforcer_(ct_policy_enforcer), 173 policy_enforcer_(ct_policy_enforcer),
148 transport_security_state_(transport_security_state), 174 transport_security_state_(transport_security_state),
149 cert_transparency_verifier_(cert_transparency_verifier), 175 cert_transparency_verifier_(cert_transparency_verifier),
150 cert_verify_flags_(cert_verify_flags), 176 cert_verify_flags_(cert_verify_flags),
177 enforce_policy_checking_(true),
151 next_state_(STATE_NONE), 178 next_state_(STATE_NONE),
152 start_time_(base::TimeTicks::Now()), 179 start_time_(base::TimeTicks::Now()),
153 net_log_(net_log) { 180 net_log_(net_log) {
154 CHECK(proof_verifier_); 181 CHECK(proof_verifier_);
155 CHECK(verifier_); 182 CHECK(verifier_);
156 CHECK(policy_enforcer_); 183 CHECK(policy_enforcer_);
157 CHECK(transport_security_state_); 184 CHECK(transport_security_state_);
158 CHECK(cert_transparency_verifier_); 185 CHECK(cert_transparency_verifier_);
159 } 186 }
160 187
(...skipping 27 matching lines...) Expand all
188 error_details->clear(); 215 error_details->clear();
189 216
190 if (STATE_NONE != next_state_) { 217 if (STATE_NONE != next_state_) {
191 *error_details = "Certificate is already set and VerifyProof has begun"; 218 *error_details = "Certificate is already set and VerifyProof has begun";
192 DLOG(DFATAL) << *error_details; 219 DLOG(DFATAL) << *error_details;
193 return QUIC_FAILURE; 220 return QUIC_FAILURE;
194 } 221 }
195 222
196 verify_details_.reset(new ProofVerifyDetailsChromium); 223 verify_details_.reset(new ProofVerifyDetailsChromium);
197 224
198 if (certs.empty()) { 225 // Converts |certs| to |cert_|.
199 *error_details = "Failed to create certificate chain. Certs are empty."; 226 if (!GetX509Certificate(certs, error_details, verify_details))
200 DLOG(WARNING) << *error_details;
201 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
202 *verify_details = std::move(verify_details_);
203 return QUIC_FAILURE; 227 return QUIC_FAILURE;
204 }
205
206 // Convert certs to X509Certificate.
207 vector<StringPiece> cert_pieces(certs.size());
208 for (unsigned i = 0; i < certs.size(); i++) {
209 cert_pieces[i] = base::StringPiece(certs[i]);
210 }
211 cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces);
212 if (!cert_.get()) {
213 *error_details = "Failed to create certificate chain";
214 DLOG(WARNING) << *error_details;
215 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
216 *verify_details = std::move(verify_details_);
217 return QUIC_FAILURE;
218 }
219 228
220 if (!cert_sct.empty()) { 229 if (!cert_sct.empty()) {
221 // Note that this is a completely synchronous operation: The CT Log Verifier 230 // Note that this is a completely synchronous operation: The CT Log Verifier
222 // gets all the data it needs for SCT verification and does not do any 231 // gets all the data it needs for SCT verification and does not do any
223 // external communication. 232 // external communication.
224 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, 233 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct,
225 &verify_details_->ct_verify_result, 234 &verify_details_->ct_verify_result,
226 net_log_); 235 net_log_);
227 } 236 }
228 237
229 // We call VerifySignature first to avoid copying of server_config and 238 // We call VerifySignature first to avoid copying of server_config and
230 // signature. 239 // signature.
231 if (!VerifySignature(server_config, quic_version, chlo_hash, signature, 240 if (!signature.empty() &&
241 !VerifySignature(server_config, quic_version, chlo_hash, signature,
232 certs[0])) { 242 certs[0])) {
233 *error_details = "Failed to verify signature of server config"; 243 *error_details = "Failed to verify signature of server config";
234 DLOG(WARNING) << *error_details; 244 DLOG(WARNING) << *error_details;
235 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; 245 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
236 *verify_details = std::move(verify_details_); 246 *verify_details = std::move(verify_details_);
237 return QUIC_FAILURE; 247 return QUIC_FAILURE;
238 } 248 }
239 249
250 DCHECK(enforce_policy_checking_);
251 return VerifyCert(hostname, port, error_details, verify_details,
252 std::move(callback));
253 }
254
255 QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain(
256 const string& hostname,
257 const vector<string>& certs,
258 std::string* error_details,
259 std::unique_ptr<ProofVerifyDetails>* verify_details,
260 std::unique_ptr<ProofVerifierCallback> callback) {
261 DCHECK(error_details);
262 DCHECK(verify_details);
263 DCHECK(callback);
264
265 error_details->clear();
266
267 if (STATE_NONE != next_state_) {
268 *error_details = "Certificate is already set and VerifyCertChain has begun";
269 DLOG(DFATAL) << *error_details;
270 return QUIC_FAILURE;
271 }
272
273 verify_details_.reset(new ProofVerifyDetailsChromium);
274
275 // Converts |certs| to |cert_|.
276 if (!GetX509Certificate(certs, error_details, verify_details))
277 return QUIC_FAILURE;
278
279 enforce_policy_checking_ = false;
280 // |port| is not needed because |enforce_policy_checking_| is false.
281 return VerifyCert(hostname, /*port=*/0, error_details, verify_details,
282 std::move(callback));
283 }
284
285 bool ProofVerifierChromium::Job::GetX509Certificate(
286 const vector<string>& certs,
287 std::string* error_details,
288 std::unique_ptr<ProofVerifyDetails>* verify_details) {
289 if (certs.empty()) {
290 *error_details = "Failed to create certificate chain. Certs are empty.";
291 DLOG(WARNING) << *error_details;
292 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
293 *verify_details = std::move(verify_details_);
294 return false;
295 }
296
297 // Convert certs to X509Certificate.
298 vector<StringPiece> cert_pieces(certs.size());
299 for (unsigned i = 0; i < certs.size(); i++) {
300 cert_pieces[i] = base::StringPiece(certs[i]);
301 }
302 cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces);
303 if (!cert_.get()) {
304 *error_details = "Failed to create certificate chain";
305 DLOG(WARNING) << *error_details;
306 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
307 *verify_details = std::move(verify_details_);
308 return false;
309 }
310 return true;
311 }
312
313 QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert(
314 const string& hostname,
315 const uint16_t port,
316 std::string* error_details,
317 std::unique_ptr<ProofVerifyDetails>* verify_details,
318 std::unique_ptr<ProofVerifierCallback> callback) {
240 hostname_ = hostname; 319 hostname_ = hostname;
241 port_ = port; 320 port_ = port;
242 321
243 next_state_ = STATE_VERIFY_CERT; 322 next_state_ = STATE_VERIFY_CERT;
244 switch (DoLoop(OK)) { 323 switch (DoLoop(OK)) {
245 case OK: 324 case OK:
246 *verify_details = std::move(verify_details_); 325 *verify_details = std::move(verify_details_);
247 return QUIC_SUCCESS; 326 return QUIC_SUCCESS;
248 case ERR_IO_PENDING: 327 case ERR_IO_PENDING:
249 callback_ = std::move(callback); 328 callback_ = std::move(callback);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 387
309 const CertVerifyResult& cert_verify_result = 388 const CertVerifyResult& cert_verify_result =
310 verify_details_->cert_verify_result; 389 verify_details_->cert_verify_result;
311 const CertStatus cert_status = cert_verify_result.cert_status; 390 const CertStatus cert_status = cert_verify_result.cert_status;
312 verify_details_->ct_verify_result.ct_policies_applied = result == OK; 391 verify_details_->ct_verify_result.ct_policies_applied = result == OK;
313 verify_details_->ct_verify_result.ev_policy_compliance = 392 verify_details_->ct_verify_result.ev_policy_compliance =
314 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; 393 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
315 394
316 // If the connection was good, check HPKP and CT status simultaneously, 395 // If the connection was good, check HPKP and CT status simultaneously,
317 // but prefer to treat the HPKP error as more serious, if there was one. 396 // but prefer to treat the HPKP error as more serious, if there was one.
318 if ((result == OK || 397 if (enforce_policy_checking_ &&
398 (result == OK ||
319 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { 399 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) {
320 if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { 400 if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) {
321 ct::EVPolicyCompliance ev_policy_compliance = 401 ct::EVPolicyCompliance ev_policy_compliance =
322 policy_enforcer_->DoesConformToCTEVPolicy( 402 policy_enforcer_->DoesConformToCTEVPolicy(
323 cert_verify_result.verified_cert.get(), 403 cert_verify_result.verified_cert.get(),
324 SSLConfigService::GetEVCertsWhitelist().get(), 404 SSLConfigService::GetEVCertsWhitelist().get(),
325 verify_details_->ct_verify_result.verified_scts, net_log_); 405 verify_details_->ct_verify_result.verified_scts, net_log_);
326 verify_details_->ct_verify_result.ev_policy_compliance = 406 verify_details_->ct_verify_result.ev_policy_compliance =
327 ev_policy_compliance; 407 ev_policy_compliance;
328 if (ev_policy_compliance != 408 if (ev_policy_compliance !=
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 } 578 }
499 const ProofVerifyContextChromium* chromium_context = 579 const ProofVerifyContextChromium* chromium_context =
500 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); 580 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
501 std::unique_ptr<Job> job( 581 std::unique_ptr<Job> job(
502 new Job(this, cert_verifier_, ct_policy_enforcer_, 582 new Job(this, cert_verifier_, ct_policy_enforcer_,
503 transport_security_state_, cert_transparency_verifier_, 583 transport_security_state_, cert_transparency_verifier_,
504 chromium_context->cert_verify_flags, chromium_context->net_log)); 584 chromium_context->cert_verify_flags, chromium_context->net_log));
505 QuicAsyncStatus status = job->VerifyProof( 585 QuicAsyncStatus status = job->VerifyProof(
506 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, 586 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct,
507 signature, error_details, verify_details, std::move(callback)); 587 signature, error_details, verify_details, std::move(callback));
508 if (status == QUIC_PENDING) { 588 if (status == QUIC_PENDING)
509 active_jobs_.insert(job.release()); 589 active_jobs_.insert(job.release());
510 }
511 return status; 590 return status;
512 } 591 }
513 592
593 QuicAsyncStatus ProofVerifierChromium::VerifyCertChain(
594 const std::string& hostname,
595 const std::vector<std::string>& certs,
596 const ProofVerifyContext* verify_context,
597 std::string* error_details,
598 std::unique_ptr<ProofVerifyDetails>* verify_details,
599 std::unique_ptr<ProofVerifierCallback> callback) {
600 if (!verify_context) {
601 *error_details = "Missing context";
602 return QUIC_FAILURE;
603 }
604 const ProofVerifyContextChromium* chromium_context =
605 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
606 std::unique_ptr<Job> job(
607 new Job(this, cert_verifier_, ct_policy_enforcer_,
608 transport_security_state_, cert_transparency_verifier_,
609 chromium_context->cert_verify_flags, chromium_context->net_log));
610 QuicAsyncStatus status = job->VerifyCertChain(
611 hostname, certs, error_details, verify_details, std::move(callback));
612 if (status == QUIC_PENDING)
613 active_jobs_.insert(job.release());
614 return status;
615 }
616
514 void ProofVerifierChromium::OnJobComplete(Job* job) { 617 void ProofVerifierChromium::OnJobComplete(Job* job) {
515 active_jobs_.erase(job); 618 active_jobs_.erase(job);
516 delete job; 619 delete job;
517 } 620 }
518 621
519 } // namespace net 622 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/chromium/crypto/proof_verifier_chromium.h ('k') | net/quic/chromium/crypto/proof_verifier_chromium_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698