OLD | NEW |
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 <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
10 #include "base/metrics/sparse_histogram.h" | 10 #include "base/metrics/sparse_histogram.h" |
11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
12 #include "net/quic/crypto/crypto_protocol.h" | 12 #include "net/quic/crypto/crypto_protocol.h" |
13 #include "net/quic/crypto/crypto_utils.h" | 13 #include "net/quic/crypto/crypto_utils.h" |
14 #include "net/quic/crypto/null_encrypter.h" | 14 #include "net/quic/crypto/null_encrypter.h" |
15 #include "net/quic/quic_flags.h" | 15 #include "net/quic/quic_flags.h" |
16 #include "net/quic/quic_protocol.h" | 16 #include "net/quic/quic_protocol.h" |
17 #include "net/quic/quic_session.h" | 17 #include "net/quic/quic_session.h" |
| 18 #include "net/quic/quic_utils.h" |
18 | 19 |
19 using std::string; | 20 using std::string; |
20 using std::vector; | 21 using std::vector; |
21 | 22 |
22 namespace net { | 23 namespace net { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 void AppendFixed(CryptoHandshakeMessage* message) { | 27 void AppendFixed(CryptoHandshakeMessage* message) { |
27 vector<QuicTag> tags; | 28 vector<QuicTag> tags; |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 } | 177 } |
177 | 178 |
178 void QuicCryptoClientStream::HandleServerConfigUpdateMessage( | 179 void QuicCryptoClientStream::HandleServerConfigUpdateMessage( |
179 const CryptoHandshakeMessage& server_config_update) { | 180 const CryptoHandshakeMessage& server_config_update) { |
180 DCHECK(server_config_update.tag() == kSCUP); | 181 DCHECK(server_config_update.tag() == kSCUP); |
181 string error_details; | 182 string error_details; |
182 QuicCryptoClientConfig::CachedState* cached = | 183 QuicCryptoClientConfig::CachedState* cached = |
183 crypto_config_->LookupOrCreate(server_id_); | 184 crypto_config_->LookupOrCreate(server_id_); |
184 QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate( | 185 QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate( |
185 server_config_update, session()->connection()->clock()->WallNow(), | 186 server_config_update, session()->connection()->clock()->WallNow(), |
186 session()->connection()->version(), cached, &crypto_negotiated_params_, | 187 session()->connection()->version(), cached->chlo_hash(), cached, |
187 &error_details); | 188 &crypto_negotiated_params_, &error_details); |
188 | 189 |
189 if (error != QUIC_NO_ERROR) { | 190 if (error != QUIC_NO_ERROR) { |
190 CloseConnectionWithDetails( | 191 CloseConnectionWithDetails( |
191 error, "Server config update invalid: " + error_details); | 192 error, "Server config update invalid: " + error_details); |
192 return; | 193 return; |
193 } | 194 } |
194 | 195 |
195 DCHECK(handshake_confirmed()); | 196 DCHECK(handshake_confirmed()); |
196 if (proof_verify_callback_) { | 197 if (proof_verify_callback_) { |
197 proof_verify_callback_->Cancel(); | 198 proof_verify_callback_->Cancel(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 void QuicCryptoClientStream::DoInitialize( | 254 void QuicCryptoClientStream::DoInitialize( |
254 QuicCryptoClientConfig::CachedState* cached) { | 255 QuicCryptoClientConfig::CachedState* cached) { |
255 if (!cached->IsEmpty() && !cached->signature().empty()) { | 256 if (!cached->IsEmpty() && !cached->signature().empty()) { |
256 // Note that we verify the proof even if the cached proof is valid. | 257 // Note that we verify the proof even if the cached proof is valid. |
257 // This allows us to respond to CA trust changes or certificate | 258 // This allows us to respond to CA trust changes or certificate |
258 // expiration because it may have been a while since we last verified | 259 // expiration because it may have been a while since we last verified |
259 // the proof. | 260 // the proof. |
260 DCHECK(crypto_config_->proof_verifier()); | 261 DCHECK(crypto_config_->proof_verifier()); |
261 // Track proof verification time when cached server config is used. | 262 // Track proof verification time when cached server config is used. |
262 proof_verify_start_time_ = base::TimeTicks::Now(); | 263 proof_verify_start_time_ = base::TimeTicks::Now(); |
| 264 chlo_hash_ = cached->chlo_hash(); |
263 // If the cached state needs to be verified, do it now. | 265 // If the cached state needs to be verified, do it now. |
264 next_state_ = STATE_VERIFY_PROOF; | 266 next_state_ = STATE_VERIFY_PROOF; |
265 } else { | 267 } else { |
266 next_state_ = STATE_GET_CHANNEL_ID; | 268 next_state_ = STATE_GET_CHANNEL_ID; |
267 } | 269 } |
268 } | 270 } |
269 | 271 |
270 void QuicCryptoClientStream::DoSendCHLO( | 272 void QuicCryptoClientStream::DoSendCHLO( |
271 QuicCryptoClientConfig::CachedState* cached) { | 273 QuicCryptoClientConfig::CachedState* cached) { |
272 if (stateless_reject_received_) { | 274 if (stateless_reject_received_) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 return; | 323 return; |
322 } | 324 } |
323 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) { | 325 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) { |
324 DLOG(DFATAL) << "Client hello won't fit in a single packet."; | 326 DLOG(DFATAL) << "Client hello won't fit in a single packet."; |
325 CloseConnectionWithDetails(QUIC_INTERNAL_ERROR, "CHLO too large"); | 327 CloseConnectionWithDetails(QUIC_INTERNAL_ERROR, "CHLO too large"); |
326 return; | 328 return; |
327 } | 329 } |
328 out.set_minimum_size( | 330 out.set_minimum_size( |
329 static_cast<size_t>(max_packet_size - kFramingOverhead)); | 331 static_cast<size_t>(max_packet_size - kFramingOverhead)); |
330 next_state_ = STATE_RECV_REJ; | 332 next_state_ = STATE_RECV_REJ; |
| 333 CryptoUtils::HashHandshakeMessage(out, &chlo_hash_); |
331 SendHandshakeMessage(out); | 334 SendHandshakeMessage(out); |
332 return; | 335 return; |
333 } | 336 } |
334 | 337 |
335 // If the server nonce is empty, copy over the server nonce from a previous | 338 // If the server nonce is empty, copy over the server nonce from a previous |
336 // SREJ, if there is one. | 339 // SREJ, if there is one. |
337 if (FLAGS_enable_quic_stateless_reject_support && | 340 if (FLAGS_enable_quic_stateless_reject_support && |
338 crypto_negotiated_params_.server_nonce.empty() && | 341 crypto_negotiated_params_.server_nonce.empty() && |
339 cached->has_server_nonce()) { | 342 cached->has_server_nonce()) { |
340 crypto_negotiated_params_.server_nonce = cached->GetNextServerNonce(); | 343 crypto_negotiated_params_.server_nonce = cached->GetNextServerNonce(); |
341 DCHECK(!crypto_negotiated_params_.server_nonce.empty()); | 344 DCHECK(!crypto_negotiated_params_.server_nonce.empty()); |
342 } | 345 } |
343 | 346 |
344 string error_details; | 347 string error_details; |
345 QuicErrorCode error = crypto_config_->FillClientHello( | 348 QuicErrorCode error = crypto_config_->FillClientHello( |
346 server_id_, session()->connection()->connection_id(), | 349 server_id_, session()->connection()->connection_id(), |
347 session()->connection()->supported_versions().front(), cached, | 350 session()->connection()->supported_versions().front(), cached, |
348 session()->connection()->clock()->WallNow(), | 351 session()->connection()->clock()->WallNow(), |
349 session()->connection()->random_generator(), channel_id_key_.get(), | 352 session()->connection()->random_generator(), channel_id_key_.get(), |
350 &crypto_negotiated_params_, &out, &error_details); | 353 &crypto_negotiated_params_, &out, &error_details); |
351 if (error != QUIC_NO_ERROR) { | 354 if (error != QUIC_NO_ERROR) { |
352 // Flush the cached config so that, if it's bad, the server has a | 355 // Flush the cached config so that, if it's bad, the server has a |
353 // chance to send us another in the future. | 356 // chance to send us another in the future. |
354 cached->InvalidateServerConfig(); | 357 cached->InvalidateServerConfig(); |
355 CloseConnectionWithDetails(error, error_details); | 358 CloseConnectionWithDetails(error, error_details); |
356 return; | 359 return; |
357 } | 360 } |
| 361 CryptoUtils::HashHandshakeMessage(out, &chlo_hash_); |
358 channel_id_sent_ = (channel_id_key_.get() != nullptr); | 362 channel_id_sent_ = (channel_id_key_.get() != nullptr); |
359 if (cached->proof_verify_details()) { | 363 if (cached->proof_verify_details()) { |
360 proof_handler_->OnProofVerifyDetailsAvailable( | 364 proof_handler_->OnProofVerifyDetailsAvailable( |
361 *cached->proof_verify_details()); | 365 *cached->proof_verify_details()); |
362 } | 366 } |
363 next_state_ = STATE_RECV_SHLO; | 367 next_state_ = STATE_RECV_SHLO; |
364 SendHandshakeMessage(out); | 368 SendHandshakeMessage(out); |
365 // Be prepared to decrypt with the new server write key. | 369 // Be prepared to decrypt with the new server write key. |
366 session()->connection()->SetAlternativeDecrypter( | 370 session()->connection()->SetAlternativeDecrypter( |
367 ENCRYPTION_INITIAL, | 371 ENCRYPTION_INITIAL, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 packed_error); | 421 packed_error); |
418 } | 422 } |
419 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.Secure", | 423 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.Secure", |
420 packed_error); | 424 packed_error); |
421 } | 425 } |
422 | 426 |
423 stateless_reject_received_ = in->tag() == kSREJ; | 427 stateless_reject_received_ = in->tag() == kSREJ; |
424 string error_details; | 428 string error_details; |
425 QuicErrorCode error = crypto_config_->ProcessRejection( | 429 QuicErrorCode error = crypto_config_->ProcessRejection( |
426 *in, session()->connection()->clock()->WallNow(), | 430 *in, session()->connection()->clock()->WallNow(), |
427 session()->connection()->version(), cached, &crypto_negotiated_params_, | 431 session()->connection()->version(), chlo_hash_, cached, |
428 &error_details); | 432 &crypto_negotiated_params_, &error_details); |
429 | 433 |
430 if (error != QUIC_NO_ERROR) { | 434 if (error != QUIC_NO_ERROR) { |
431 next_state_ = STATE_NONE; | 435 next_state_ = STATE_NONE; |
432 CloseConnectionWithDetails(error, error_details); | 436 CloseConnectionWithDetails(error, error_details); |
433 return; | 437 return; |
434 } | 438 } |
435 if (!cached->proof_valid()) { | 439 if (!cached->proof_valid()) { |
436 if (!cached->signature().empty()) { | 440 if (!cached->signature().empty()) { |
437 // Note that we only verify the proof if the cached proof is not | 441 // Note that we only verify the proof if the cached proof is not |
438 // valid. If the cached proof is valid here, someone else must have | 442 // valid. If the cached proof is valid here, someone else must have |
(...skipping 13 matching lines...) Expand all Loading... |
452 DCHECK(verifier); | 456 DCHECK(verifier); |
453 next_state_ = STATE_VERIFY_PROOF_COMPLETE; | 457 next_state_ = STATE_VERIFY_PROOF_COMPLETE; |
454 generation_counter_ = cached->generation_counter(); | 458 generation_counter_ = cached->generation_counter(); |
455 | 459 |
456 ProofVerifierCallbackImpl* proof_verify_callback = | 460 ProofVerifierCallbackImpl* proof_verify_callback = |
457 new ProofVerifierCallbackImpl(this); | 461 new ProofVerifierCallbackImpl(this); |
458 | 462 |
459 verify_ok_ = false; | 463 verify_ok_ = false; |
460 | 464 |
461 QuicAsyncStatus status = verifier->VerifyProof( | 465 QuicAsyncStatus status = verifier->VerifyProof( |
462 server_id_.host(), cached->server_config(), cached->certs(), | 466 server_id_.host(), cached->server_config(), |
| 467 session()->connection()->version(), chlo_hash_, cached->certs(), |
463 cached->cert_sct(), cached->signature(), verify_context_.get(), | 468 cached->cert_sct(), cached->signature(), verify_context_.get(), |
464 &verify_error_details_, &verify_details_, proof_verify_callback); | 469 &verify_error_details_, &verify_details_, proof_verify_callback); |
465 | 470 |
466 switch (status) { | 471 switch (status) { |
467 case QUIC_PENDING: | 472 case QUIC_PENDING: |
468 proof_verify_callback_ = proof_verify_callback; | 473 proof_verify_callback_ = proof_verify_callback; |
469 DVLOG(1) << "Doing VerifyProof"; | 474 DVLOG(1) << "Doing VerifyProof"; |
470 break; | 475 break; |
471 case QUIC_FAILURE: | 476 case QUIC_FAILURE: |
472 delete proof_verify_callback; | 477 delete proof_verify_callback; |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 } | 676 } |
672 for (size_t i = 0; i < num_their_proof_demands; i++) { | 677 for (size_t i = 0; i < num_their_proof_demands; i++) { |
673 if (their_proof_demands[i] == kCHID) { | 678 if (their_proof_demands[i] == kCHID) { |
674 return true; | 679 return true; |
675 } | 680 } |
676 } | 681 } |
677 return false; | 682 return false; |
678 } | 683 } |
679 | 684 |
680 } // namespace net | 685 } // namespace net |
OLD | NEW |