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

Side by Side Diff: net/quic/quic_crypto_client_stream.cc

Issue 1139183002: Flag-protected. Add stateless reject support to crypto streams. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@QuicCryptoClientConfig_ProcessRejection_92637704
Patch Set: Created 5 years, 7 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 | « net/quic/quic_crypto_client_stream.h ('k') | net/quic/quic_crypto_client_stream_test.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/quic/quic_crypto_client_stream.h" 5 #include "net/quic/quic_crypto_client_stream.h"
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "base/profiler/scoped_tracker.h" 8 #include "base/profiler/scoped_tracker.h"
9 #include "net/quic/crypto/crypto_protocol.h" 9 #include "net/quic/crypto/crypto_protocol.h"
10 #include "net/quic/crypto/crypto_utils.h" 10 #include "net/quic/crypto/crypto_utils.h"
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 : QuicCryptoStream(session), 80 : QuicCryptoStream(session),
81 next_state_(STATE_IDLE), 81 next_state_(STATE_IDLE),
82 num_client_hellos_(0), 82 num_client_hellos_(0),
83 crypto_config_(crypto_config), 83 crypto_config_(crypto_config),
84 server_id_(server_id), 84 server_id_(server_id),
85 generation_counter_(0), 85 generation_counter_(0),
86 channel_id_sent_(false), 86 channel_id_sent_(false),
87 channel_id_source_callback_run_(false), 87 channel_id_source_callback_run_(false),
88 channel_id_source_callback_(nullptr), 88 channel_id_source_callback_(nullptr),
89 verify_context_(verify_context), 89 verify_context_(verify_context),
90 proof_verify_callback_(nullptr) { 90 proof_verify_callback_(nullptr),
91 stateless_reject_received_(false) {
91 DCHECK_EQ(Perspective::IS_CLIENT, session->connection()->perspective()); 92 DCHECK_EQ(Perspective::IS_CLIENT, session->connection()->perspective());
92 } 93 }
93 94
94 QuicCryptoClientStream::~QuicCryptoClientStream() { 95 QuicCryptoClientStream::~QuicCryptoClientStream() {
95 if (channel_id_source_callback_) { 96 if (channel_id_source_callback_) {
96 channel_id_source_callback_->Cancel(); 97 channel_id_source_callback_->Cancel();
97 } 98 }
98 if (proof_verify_callback_) { 99 if (proof_verify_callback_) {
99 proof_verify_callback_->Cancel(); 100 proof_verify_callback_->Cancel();
100 } 101 }
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 // If the cached state needs to be verified, do it now. 240 // If the cached state needs to be verified, do it now.
240 next_state_ = STATE_VERIFY_PROOF; 241 next_state_ = STATE_VERIFY_PROOF;
241 } else { 242 } else {
242 next_state_ = STATE_GET_CHANNEL_ID; 243 next_state_ = STATE_GET_CHANNEL_ID;
243 } 244 }
244 } 245 }
245 246
246 void QuicCryptoClientStream::DoSendCHLO( 247 void QuicCryptoClientStream::DoSendCHLO(
247 const CryptoHandshakeMessage* in, 248 const CryptoHandshakeMessage* in,
248 QuicCryptoClientConfig::CachedState* cached) { 249 QuicCryptoClientConfig::CachedState* cached) {
250 if (stateless_reject_received_) {
251 // If we've gotten to this point, we've sent at least one hello
252 // and received a stateless reject in response. We cannot
253 // continue to send hellos because the server has abandoned state
254 // for this connection. Abandon further handshakes.
255 next_state_ = STATE_NONE;
256 if (session()->connection()->connected()) {
257 session()->connection()->CloseConnection(
258 QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, false);
259 }
260 return;
261 }
262
249 // Send the client hello in plaintext. 263 // Send the client hello in plaintext.
250 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); 264 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
251 if (num_client_hellos_ > kMaxClientHellos) { 265 if (num_client_hellos_ > kMaxClientHellos) {
252 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); 266 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
253 return; 267 return;
254 } 268 }
255 num_client_hellos_++; 269 num_client_hellos_++;
256 270
257 CryptoHandshakeMessage out; 271 CryptoHandshakeMessage out;
272 DCHECK(session() != nullptr);
273 DCHECK(session()->config() != nullptr);
274 // Send all the options, regardless of whether we're sending an
275 // inchoate or subsequent hello.
276 session()->config()->ToHandshakeMessage(&out);
258 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { 277 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
259 crypto_config_->FillInchoateClientHello( 278 crypto_config_->FillInchoateClientHello(
260 server_id_, 279 server_id_,
261 session()->connection()->supported_versions().front(), 280 session()->connection()->supported_versions().front(),
262 cached, &crypto_negotiated_params_, &out); 281 cached, &crypto_negotiated_params_, &out);
263 // Pad the inchoate client hello to fill up a packet. 282 // Pad the inchoate client hello to fill up a packet.
264 const QuicByteCount kFramingOverhead = 50; // A rough estimate. 283 const QuicByteCount kFramingOverhead = 50; // A rough estimate.
265 const QuicByteCount max_packet_size = 284 const QuicByteCount max_packet_size =
266 session()->connection()->max_packet_length(); 285 session()->connection()->max_packet_length();
267 if (max_packet_size <= kFramingOverhead) { 286 if (max_packet_size <= kFramingOverhead) {
268 DLOG(DFATAL) << "max_packet_length (" << max_packet_size 287 DLOG(DFATAL) << "max_packet_length (" << max_packet_size
269 << ") has no room for framing overhead."; 288 << ") has no room for framing overhead.";
270 CloseConnection(QUIC_INTERNAL_ERROR); 289 CloseConnection(QUIC_INTERNAL_ERROR);
271 return; 290 return;
272 } 291 }
273 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) { 292 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
274 DLOG(DFATAL) << "Client hello won't fit in a single packet."; 293 DLOG(DFATAL) << "Client hello won't fit in a single packet.";
275 CloseConnection(QUIC_INTERNAL_ERROR); 294 CloseConnection(QUIC_INTERNAL_ERROR);
276 return; 295 return;
277 } 296 }
278 out.set_minimum_size( 297 out.set_minimum_size(
279 static_cast<size_t>(max_packet_size - kFramingOverhead)); 298 static_cast<size_t>(max_packet_size - kFramingOverhead));
280 next_state_ = STATE_RECV_REJ; 299 next_state_ = STATE_RECV_REJ;
281 SendHandshakeMessage(out); 300 SendHandshakeMessage(out);
282 return; 301 return;
283 } 302 }
284 303
285 session()->config()->ToHandshakeMessage(&out);
286 string error_details; 304 string error_details;
287 QuicErrorCode error = crypto_config_->FillClientHello( 305 QuicErrorCode error = crypto_config_->FillClientHello(
288 server_id_, 306 server_id_,
289 session()->connection()->connection_id(), 307 session()->connection()->connection_id(),
290 session()->connection()->supported_versions().front(), 308 session()->connection()->supported_versions().front(),
291 cached, 309 cached,
292 session()->connection()->clock()->WallNow(), 310 session()->connection()->clock()->WallNow(),
293 session()->connection()->random_generator(), 311 session()->connection()->random_generator(),
294 channel_id_key_.get(), 312 channel_id_key_.get(),
295 &crypto_negotiated_params_, 313 &crypto_negotiated_params_,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 QuicCryptoClientConfig::CachedState* cached) { 355 QuicCryptoClientConfig::CachedState* cached) {
338 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. 356 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
339 tracked_objects::ScopedTracker tracking_profile( 357 tracked_objects::ScopedTracker tracking_profile(
340 FROM_HERE_WITH_EXPLICIT_FUNCTION( 358 FROM_HERE_WITH_EXPLICIT_FUNCTION(
341 "422516 QuicCryptoClientStream::DoReceiveREJ")); 359 "422516 QuicCryptoClientStream::DoReceiveREJ"));
342 360
343 // We sent a dummy CHLO because we didn't have enough information to 361 // We sent a dummy CHLO because we didn't have enough information to
344 // perform a handshake, or we sent a full hello that the server 362 // perform a handshake, or we sent a full hello that the server
345 // rejected. Here we hope to have a REJ that contains the information 363 // rejected. Here we hope to have a REJ that contains the information
346 // that we need. 364 // that we need.
347 if (in->tag() != kREJ) { 365 if ((in->tag() != kREJ) && (in->tag() != kSREJ)) {
348 next_state_ = STATE_NONE; 366 next_state_ = STATE_NONE;
349 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, 367 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
350 "Expected REJ"); 368 "Expected REJ");
351 return; 369 return;
352 } 370 }
371 stateless_reject_received_ = in->tag() == kSREJ;
353 string error_details; 372 string error_details;
354 QuicErrorCode error = crypto_config_->ProcessRejection( 373 QuicErrorCode error = crypto_config_->ProcessRejection(
355 *in, session()->connection()->clock()->WallNow(), cached, 374 *in, session()->connection()->clock()->WallNow(), cached,
356 server_id_.is_https(), &crypto_negotiated_params_, &error_details); 375 server_id_.is_https(), &crypto_negotiated_params_, &error_details);
376
357 if (error != QUIC_NO_ERROR) { 377 if (error != QUIC_NO_ERROR) {
358 next_state_ = STATE_NONE; 378 next_state_ = STATE_NONE;
359 CloseConnectionWithDetails(error, error_details); 379 CloseConnectionWithDetails(error, error_details);
360 return; 380 return;
361 } 381 }
362 if (!cached->proof_valid()) { 382 if (!cached->proof_valid()) {
363 if (!server_id_.is_https()) { 383 if (!server_id_.is_https()) {
364 // We don't check the certificates for insecure QUIC connections. 384 // We don't check the certificates for insecure QUIC connections.
365 SetCachedProofValid(cached); 385 SetCachedProofValid(cached);
366 } else if (!cached->signature().empty()) { 386 } else if (!cached->signature().empty()) {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 "Channel ID lookup failed"); 504 "Channel ID lookup failed");
485 return; 505 return;
486 } 506 }
487 next_state_ = STATE_SEND_CHLO; 507 next_state_ = STATE_SEND_CHLO;
488 } 508 }
489 509
490 void QuicCryptoClientStream::DoReceiveSHLO( 510 void QuicCryptoClientStream::DoReceiveSHLO(
491 const CryptoHandshakeMessage* in, 511 const CryptoHandshakeMessage* in,
492 QuicCryptoClientConfig::CachedState* cached) { 512 QuicCryptoClientConfig::CachedState* cached) {
493 next_state_ = STATE_NONE; 513 next_state_ = STATE_NONE;
494 // We sent a CHLO that we expected to be accepted and now we're hoping 514 // We sent a CHLO that we expected to be accepted and now we're
495 // for a SHLO from the server to confirm that. 515 // hoping for a SHLO from the server to confirm that. First check
496 if (in->tag() == kREJ) { 516 // to see whether the response was a reject, and if so, move on to
517 // the reject-processing state.
518 if ((in->tag() == kREJ) || (in->tag() == kSREJ)) {
497 // alternative_decrypter will be nullptr if the original alternative 519 // alternative_decrypter will be nullptr if the original alternative
498 // decrypter latched and became the primary decrypter. That happens 520 // decrypter latched and became the primary decrypter. That happens
499 // if we received a message encrypted with the INITIAL key. 521 // if we received a message encrypted with the INITIAL key.
500 if (session()->connection()->alternative_decrypter() == nullptr) { 522 if (session()->connection()->alternative_decrypter() == nullptr) {
501 // The rejection was sent encrypted! 523 // The rejection was sent encrypted!
502 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, 524 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
503 "encrypted REJ message"); 525 "encrypted REJ message");
504 return; 526 return;
505 } 527 }
506 next_state_ = STATE_RECV_REJ; 528 next_state_ = STATE_RECV_REJ;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 } 628 }
607 } 629 }
608 return false; 630 return false;
609 } 631 }
610 632
611 QuicClientSessionBase* QuicCryptoClientStream::client_session() { 633 QuicClientSessionBase* QuicCryptoClientStream::client_session() {
612 return reinterpret_cast<QuicClientSessionBase*>(session()); 634 return reinterpret_cast<QuicClientSessionBase*>(session());
613 } 635 }
614 636
615 } // namespace net 637 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_crypto_client_stream.h ('k') | net/quic/quic_crypto_client_stream_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698