| 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 |