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

Side by Side 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 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/crypto/proof_verifier_chromium.h" 5 #include "net/quic/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 ProofVerifierCallback* callback); 79 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 uint16_t port,
87 const std::vector<std::string>& certs,
88 std::string* error_details,
89 std::unique_ptr<ProofVerifyDetails>* verify_details,
90 ProofVerifierCallback* callback);
91
81 private: 92 private:
82 enum State { 93 enum State {
83 STATE_NONE, 94 STATE_NONE,
84 STATE_VERIFY_CERT, 95 STATE_VERIFY_CERT,
85 STATE_VERIFY_CERT_COMPLETE, 96 STATE_VERIFY_CERT_COMPLETE,
86 }; 97 };
87 98
99 // Convert |certs| to |cert_|(X509Certificate). Returns true if successful.
100 bool GetX509Certificate(const vector<string>& certs,
101 std::string* error_details,
102 std::unique_ptr<ProofVerifyDetails>* verify_details);
103
104 // Start the cert verification.
105 QuicAsyncStatus VerifyCert(
106 const string& hostname,
107 const uint16_t port,
108 std::string* error_details,
109 std::unique_ptr<ProofVerifyDetails>* verify_details,
110 ProofVerifierCallback* callback);
111
88 int DoLoop(int last_io_result); 112 int DoLoop(int last_io_result);
89 void OnIOComplete(int result); 113 void OnIOComplete(int result);
90 int DoVerifyCert(int result); 114 int DoVerifyCert(int result);
91 int DoVerifyCertComplete(int result); 115 int DoVerifyCertComplete(int result);
92 116
93 bool VerifySignature(const std::string& signed_data, 117 bool VerifySignature(const std::string& signed_data,
94 QuicVersion quic_version, 118 QuicVersion quic_version,
95 StringPiece chlo_hash, 119 StringPiece chlo_hash,
96 const std::string& signature, 120 const std::string& signature,
97 const std::string& cert); 121 const std::string& cert);
(...skipping 20 matching lines...) Expand all
118 std::unique_ptr<ProofVerifyDetailsChromium> verify_details_; 142 std::unique_ptr<ProofVerifyDetailsChromium> verify_details_;
119 std::string error_details_; 143 std::string error_details_;
120 144
121 // X509Certificate from a chain of DER encoded certificates. 145 // X509Certificate from a chain of DER encoded certificates.
122 scoped_refptr<X509Certificate> cert_; 146 scoped_refptr<X509Certificate> cert_;
123 147
124 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is 148 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is
125 // passed to CertVerifier::Verify. 149 // passed to CertVerifier::Verify.
126 int cert_verify_flags_; 150 int cert_verify_flags_;
127 151
152 // If set to true, enforces policy checking in DoVerifyCertComplete().
153 bool enforce_policy_checking_;
ramant (doing other things) 2016/07/07 19:31:49 Hi Ryan, As we had discussed offline, added this
154
128 State next_state_; 155 State next_state_;
129 156
130 base::TimeTicks start_time_; 157 base::TimeTicks start_time_;
131 158
132 BoundNetLog net_log_; 159 BoundNetLog net_log_;
133 160
134 DISALLOW_COPY_AND_ASSIGN(Job); 161 DISALLOW_COPY_AND_ASSIGN(Job);
135 }; 162 };
136 163
137 ProofVerifierChromium::Job::Job( 164 ProofVerifierChromium::Job::Job(
138 ProofVerifierChromium* proof_verifier, 165 ProofVerifierChromium* proof_verifier,
139 CertVerifier* cert_verifier, 166 CertVerifier* cert_verifier,
140 CTPolicyEnforcer* ct_policy_enforcer, 167 CTPolicyEnforcer* ct_policy_enforcer,
141 TransportSecurityState* transport_security_state, 168 TransportSecurityState* transport_security_state,
142 CTVerifier* cert_transparency_verifier, 169 CTVerifier* cert_transparency_verifier,
143 int cert_verify_flags, 170 int cert_verify_flags,
144 const BoundNetLog& net_log) 171 const BoundNetLog& net_log)
145 : proof_verifier_(proof_verifier), 172 : proof_verifier_(proof_verifier),
146 verifier_(cert_verifier), 173 verifier_(cert_verifier),
147 policy_enforcer_(ct_policy_enforcer), 174 policy_enforcer_(ct_policy_enforcer),
148 transport_security_state_(transport_security_state), 175 transport_security_state_(transport_security_state),
149 cert_transparency_verifier_(cert_transparency_verifier), 176 cert_transparency_verifier_(cert_transparency_verifier),
150 cert_verify_flags_(cert_verify_flags), 177 cert_verify_flags_(cert_verify_flags),
178 enforce_policy_checking_(true),
151 next_state_(STATE_NONE), 179 next_state_(STATE_NONE),
152 start_time_(base::TimeTicks::Now()), 180 start_time_(base::TimeTicks::Now()),
153 net_log_(net_log) { 181 net_log_(net_log) {
154 CHECK(proof_verifier_); 182 CHECK(proof_verifier_);
155 CHECK(verifier_); 183 CHECK(verifier_);
156 CHECK(policy_enforcer_); 184 CHECK(policy_enforcer_);
157 CHECK(transport_security_state_); 185 CHECK(transport_security_state_);
158 CHECK(cert_transparency_verifier_); 186 CHECK(cert_transparency_verifier_);
159 } 187 }
160 188
(...skipping 27 matching lines...) Expand all
188 error_details->clear(); 216 error_details->clear();
189 217
190 if (STATE_NONE != next_state_) { 218 if (STATE_NONE != next_state_) {
191 *error_details = "Certificate is already set and VerifyProof has begun"; 219 *error_details = "Certificate is already set and VerifyProof has begun";
192 DLOG(DFATAL) << *error_details; 220 DLOG(DFATAL) << *error_details;
193 return QUIC_FAILURE; 221 return QUIC_FAILURE;
194 } 222 }
195 223
196 verify_details_.reset(new ProofVerifyDetailsChromium); 224 verify_details_.reset(new ProofVerifyDetailsChromium);
197 225
198 if (certs.empty()) { 226 // Converts |certs| to |cert_|.
199 *error_details = "Failed to create certificate chain. Certs are empty."; 227 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; 228 return QUIC_FAILURE;
204 } 229 }
205 230
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
220 if (!cert_sct.empty()) { 231 if (!cert_sct.empty()) {
221 // Note that this is a completely synchronous operation: The CT Log Verifier 232 // 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 233 // gets all the data it needs for SCT verification and does not do any
223 // external communication. 234 // external communication.
224 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, 235 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct,
225 &verify_details_->ct_verify_result, 236 &verify_details_->ct_verify_result,
226 net_log_); 237 net_log_);
227 } 238 }
228 239
229 // We call VerifySignature first to avoid copying of server_config and 240 // We call VerifySignature first to avoid copying of server_config and
230 // signature. 241 // signature.
231 if (!VerifySignature(server_config, quic_version, chlo_hash, signature, 242 if (!VerifySignature(server_config, quic_version, chlo_hash, signature,
232 certs[0])) { 243 certs[0])) {
233 *error_details = "Failed to verify signature of server config"; 244 *error_details = "Failed to verify signature of server config";
234 DLOG(WARNING) << *error_details; 245 DLOG(WARNING) << *error_details;
235 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; 246 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
236 *verify_details = std::move(verify_details_); 247 *verify_details = std::move(verify_details_);
237 return QUIC_FAILURE; 248 return QUIC_FAILURE;
238 } 249 }
239 250
251 DCHECK(enforce_policy_checking_);
252 return VerifyCert(hostname, port, error_details, verify_details, callback);
253 }
254
255 QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain(
256 const string& hostname,
257 const uint16_t port,
258 const vector<string>& certs,
259 std::string* error_details,
260 std::unique_ptr<ProofVerifyDetails>* verify_details,
261 ProofVerifierCallback* callback) {
262 DCHECK(error_details);
263 DCHECK(verify_details);
264 DCHECK(callback);
265
266 error_details->clear();
267
268 if (STATE_NONE != next_state_) {
269 *error_details = "Certificate is already set and VerifyCertChain has begun";
270 DLOG(DFATAL) << *error_details;
271 return QUIC_FAILURE;
272 }
273
274 verify_details_.reset(new ProofVerifyDetailsChromium);
275
276 // Converts |certs| to |cert_|.
277 if (!GetX509Certificate(certs, error_details, verify_details)) {
278 return QUIC_FAILURE;
279 }
280
281 enforce_policy_checking_ = false;
282 return VerifyCert(hostname, port, error_details, verify_details, 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 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_.reset(callback); 328 callback_.reset(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 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
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, callback); 587 signature, error_details, verify_details, callback);
508 if (status == QUIC_PENDING) { 588 if (status == QUIC_PENDING) {
509 active_jobs_.insert(job.release()); 589 active_jobs_.insert(job.release());
510 } 590 }
511 return status; 591 return status;
512 } 592 }
513 593
594 QuicAsyncStatus ProofVerifierChromium::VerifyCertChain(
595 const std::string& hostname,
596 const uint16_t port,
597 const std::vector<std::string>& certs,
598 const ProofVerifyContext* verify_context,
599 std::string* error_details,
600 std::unique_ptr<ProofVerifyDetails>* verify_details,
601 ProofVerifierCallback* callback) {
602 if (!verify_context) {
603 *error_details = "Missing context";
604 return QUIC_FAILURE;
605 }
606 const ProofVerifyContextChromium* chromium_context =
607 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
608 std::unique_ptr<Job> job(
609 new Job(this, cert_verifier_, ct_policy_enforcer_,
610 transport_security_state_, cert_transparency_verifier_,
611 chromium_context->cert_verify_flags, chromium_context->net_log));
612 QuicAsyncStatus status = job->VerifyCertChain(
613 hostname, port, certs, error_details, verify_details, callback);
614 if (status == QUIC_PENDING) {
615 active_jobs_.insert(job.release());
616 }
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
617 return status;
618 }
619
514 void ProofVerifierChromium::OnJobComplete(Job* job) { 620 void ProofVerifierChromium::OnJobComplete(Job* job) {
515 active_jobs_.erase(job); 621 active_jobs_.erase(job);
516 delete job; 622 delete job;
517 } 623 }
518 624
519 } // namespace net 625 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698