Chromium Code Reviews| 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 "base/metrics/histogram.h" | |
| 7 #include "net/quic/crypto/crypto_protocol.h" | 8 #include "net/quic/crypto/crypto_protocol.h" |
| 8 #include "net/quic/crypto/crypto_utils.h" | 9 #include "net/quic/crypto/crypto_utils.h" |
| 9 #include "net/quic/crypto/null_encrypter.h" | 10 #include "net/quic/crypto/null_encrypter.h" |
| 10 #include "net/quic/quic_client_session_base.h" | 11 #include "net/quic/quic_client_session_base.h" |
| 11 #include "net/quic/quic_protocol.h" | 12 #include "net/quic/quic_protocol.h" |
| 12 #include "net/quic/quic_session.h" | 13 #include "net/quic/quic_session.h" |
| 13 | 14 |
| 14 namespace net { | 15 namespace net { |
| 15 | 16 |
| 16 QuicCryptoClientStream::ChannelIDSourceCallbackImpl:: | 17 QuicCryptoClientStream::ChannelIDSourceCallbackImpl:: |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 149 session()->connection()->clock()->WallNow(), | 150 session()->connection()->clock()->WallNow(), |
| 150 cached, | 151 cached, |
| 151 &crypto_negotiated_params_, | 152 &crypto_negotiated_params_, |
| 152 &error_details); | 153 &error_details); |
| 153 | 154 |
| 154 if (error != QUIC_NO_ERROR) { | 155 if (error != QUIC_NO_ERROR) { |
| 155 CloseConnectionWithDetails( | 156 CloseConnectionWithDetails( |
| 156 error, "Server config update invalid: " + error_details); | 157 error, "Server config update invalid: " + error_details); |
| 157 return; | 158 return; |
| 158 } | 159 } |
| 160 | |
| 161 DCHECK(handshake_confirmed()); | |
| 162 if (proof_verify_callback_) { | |
| 163 proof_verify_callback_->Cancel(); | |
| 164 } | |
| 165 next_state_ = STATE_INITIALIZE_SCUP; | |
| 166 DoHandshakeLoop(NULL); | |
| 159 } | 167 } |
| 160 | 168 |
| 161 // kMaxClientHellos is the maximum number of times that we'll send a client | 169 // kMaxClientHellos is the maximum number of times that we'll send a client |
| 162 // hello. The value 3 accounts for: | 170 // hello. The value 3 accounts for: |
| 163 // * One failure due to an incorrect or missing source-address token. | 171 // * One failure due to an incorrect or missing source-address token. |
| 164 // * One failure due the server's certificate chain being unavailible and the | 172 // * One failure due the server's certificate chain being unavailible and the |
| 165 // server being unwilling to send it without a valid source-address token. | 173 // server being unwilling to send it without a valid source-address token. |
| 166 static const int kMaxClientHellos = 3; | 174 static const int kMaxClientHellos = 3; |
| 167 | 175 |
| 168 void QuicCryptoClientStream::DoHandshakeLoop( | 176 void QuicCryptoClientStream::DoHandshakeLoop( |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 // just added the server config to the cache and verified the proof, | 309 // just added the server config to the cache and verified the proof, |
| 302 // so we can assume no CA trust changes or certificate expiration | 310 // so we can assume no CA trust changes or certificate expiration |
| 303 // has happened since then. | 311 // has happened since then. |
| 304 next_state_ = STATE_VERIFY_PROOF; | 312 next_state_ = STATE_VERIFY_PROOF; |
| 305 break; | 313 break; |
| 306 } | 314 } |
| 307 } | 315 } |
| 308 next_state_ = STATE_GET_CHANNEL_ID; | 316 next_state_ = STATE_GET_CHANNEL_ID; |
| 309 break; | 317 break; |
| 310 case STATE_VERIFY_PROOF: { | 318 case STATE_VERIFY_PROOF: { |
| 311 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 319 DCHECK(!handshake_confirmed()); |
| 312 DCHECK(verifier); | 320 if (QUIC_PENDING == DoVerifyProof(cached)) { |
| 313 next_state_ = STATE_VERIFY_PROOF_COMPLETE; | 321 return; |
| 314 generation_counter_ = cached->generation_counter(); | |
| 315 | |
| 316 ProofVerifierCallbackImpl* proof_verify_callback = | |
| 317 new ProofVerifierCallbackImpl(this); | |
| 318 | |
| 319 verify_ok_ = false; | |
| 320 | |
| 321 QuicAsyncStatus status = verifier->VerifyProof( | |
| 322 server_id_.host(), | |
| 323 cached->server_config(), | |
| 324 cached->certs(), | |
| 325 cached->signature(), | |
| 326 verify_context_.get(), | |
| 327 &verify_error_details_, | |
| 328 &verify_details_, | |
| 329 proof_verify_callback); | |
| 330 | |
| 331 switch (status) { | |
| 332 case QUIC_PENDING: | |
| 333 proof_verify_callback_ = proof_verify_callback; | |
| 334 DVLOG(1) << "Doing VerifyProof"; | |
| 335 return; | |
| 336 case QUIC_FAILURE: | |
| 337 delete proof_verify_callback; | |
| 338 break; | |
| 339 case QUIC_SUCCESS: | |
| 340 delete proof_verify_callback; | |
| 341 verify_ok_ = true; | |
| 342 break; | |
| 343 } | 322 } |
| 344 break; | 323 break; |
| 345 } | 324 } |
| 346 case STATE_VERIFY_PROOF_COMPLETE: | 325 case STATE_VERIFY_PROOF_COMPLETE: |
| 347 if (!verify_ok_) { | 326 DCHECK(!handshake_confirmed()); |
| 348 client_session()->OnProofVerifyDetailsAvailable(*verify_details_); | 327 if (QUIC_PROOF_INVALID == DoVerifyProofComplete(cached)) { |
| 349 CloseConnectionWithDetails( | |
| 350 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); | |
| 351 return; | 328 return; |
| 352 } | 329 } |
| 353 // Check if generation_counter has changed between STATE_VERIFY_PROOF | |
| 354 // and STATE_VERIFY_PROOF_COMPLETE state changes. | |
| 355 if (generation_counter_ != cached->generation_counter()) { | |
| 356 next_state_ = STATE_VERIFY_PROOF; | |
| 357 } else { | |
| 358 SetCachedProofValid(cached); | |
| 359 cached->SetProofVerifyDetails(verify_details_.release()); | |
| 360 next_state_ = STATE_GET_CHANNEL_ID; | |
| 361 } | |
| 362 break; | 330 break; |
| 363 case STATE_GET_CHANNEL_ID: { | 331 case STATE_GET_CHANNEL_ID: { |
| 364 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE; | 332 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE; |
| 365 channel_id_key_.reset(); | 333 channel_id_key_.reset(); |
| 366 if (!RequiresChannelID(cached)) { | 334 if (!RequiresChannelID(cached)) { |
| 367 next_state_ = STATE_SEND_CHLO; | 335 next_state_ = STATE_SEND_CHLO; |
| 368 break; | 336 break; |
| 369 } | 337 } |
| 370 | 338 |
| 371 ChannelIDSourceCallbackImpl* channel_id_source_callback = | 339 ChannelIDSourceCallbackImpl* channel_id_source_callback = |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 | 432 |
| 465 handshake_confirmed_ = true; | 433 handshake_confirmed_ = true; |
| 466 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); | 434 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); |
| 467 session()->connection()->OnHandshakeComplete(); | 435 session()->connection()->OnHandshakeComplete(); |
| 468 return; | 436 return; |
| 469 } | 437 } |
| 470 case STATE_IDLE: | 438 case STATE_IDLE: |
| 471 // This means that the peer sent us a message that we weren't expecting. | 439 // This means that the peer sent us a message that we weren't expecting. |
| 472 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | 440 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); |
| 473 return; | 441 return; |
| 442 case STATE_INITIALIZE_SCUP: { | |
| 443 if (!server_id_.is_https()) { | |
| 444 // We don't check the certificates for insecure QUIC connections. | |
| 445 SetCachedProofValid(cached); | |
| 446 } else { | |
| 447 if (!cached->IsEmpty() && !cached->signature().empty()) { | |
| 448 // Note that we verify the proof even if the cached proof is valid. | |
| 449 DCHECK(crypto_config_->proof_verifier()); | |
| 450 next_state_ = STATE_VERIFY_PROOF_SCUP; | |
| 451 } | |
| 452 } | |
| 453 break; | |
| 454 } | |
| 455 case STATE_VERIFY_PROOF_SCUP: { | |
| 456 DCHECK(handshake_confirmed()); | |
| 457 if (QUIC_PENDING == DoVerifyProof(cached)) { | |
| 458 return; | |
| 459 } | |
| 460 break; | |
| 461 } | |
| 462 case STATE_VERIFY_PROOF_COMPLETE_SCUP: { | |
| 463 DCHECK(handshake_confirmed()); | |
| 464 if (QUIC_PROOF_INVALID == DoVerifyProofComplete(cached)) { | |
| 465 return; | |
| 466 } | |
| 467 break; | |
|
Ryan Hamilton
2014/09/17 15:52:41
Since the implementation of these two states are b
ramant (doing other things)
2014/09/17 22:13:04
Done.
| |
| 468 } | |
| 469 case STATE_VERIFY_PROOF_DONE: { | |
| 470 return; // We are done. | |
| 471 } | |
| 474 } | 472 } |
| 475 } | 473 } |
| 476 } | 474 } |
| 477 | 475 |
| 476 QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof( | |
| 477 QuicCryptoClientConfig::CachedState* cached) { | |
| 478 ProofVerifier* verifier = crypto_config_->proof_verifier(); | |
| 479 DCHECK(verifier); | |
| 480 if (handshake_confirmed()) { | |
| 481 next_state_ = STATE_VERIFY_PROOF_COMPLETE_SCUP; | |
| 482 } else { | |
| 483 next_state_ = STATE_VERIFY_PROOF_COMPLETE; | |
| 484 } | |
| 485 generation_counter_ = cached->generation_counter(); | |
| 486 | |
| 487 ProofVerifierCallbackImpl* proof_verify_callback = | |
| 488 new ProofVerifierCallbackImpl(this); | |
| 489 | |
| 490 verify_ok_ = false; | |
| 491 | |
| 492 QuicAsyncStatus status = verifier->VerifyProof( | |
| 493 server_id_.host(), | |
| 494 cached->server_config(), | |
| 495 cached->certs(), | |
| 496 cached->signature(), | |
| 497 verify_context_.get(), | |
| 498 &verify_error_details_, | |
| 499 &verify_details_, | |
| 500 proof_verify_callback); | |
| 501 | |
| 502 switch (status) { | |
| 503 case QUIC_PENDING: | |
| 504 proof_verify_callback_ = proof_verify_callback; | |
| 505 DVLOG(1) << "Doing VerifyProof"; | |
| 506 break; | |
| 507 case QUIC_FAILURE: | |
| 508 delete proof_verify_callback; | |
| 509 break; | |
| 510 case QUIC_SUCCESS: | |
| 511 delete proof_verify_callback; | |
| 512 verify_ok_ = true; | |
| 513 break; | |
| 514 } | |
| 515 return status; | |
| 516 } | |
| 517 | |
| 518 QuicErrorCode QuicCryptoClientStream::DoVerifyProofComplete( | |
| 519 QuicCryptoClientConfig::CachedState* cached) { | |
| 520 if (!verify_ok_) { | |
| 521 client_session()->OnProofVerifyDetailsAvailable(*verify_details_); | |
| 522 UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed", | |
| 523 handshake_confirmed()); | |
| 524 CloseConnectionWithDetails( | |
| 525 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); | |
| 526 return QUIC_PROOF_INVALID; | |
| 527 } | |
| 528 | |
| 529 // Check if generation_counter has changed between STATE_VERIFY_PROOF (or | |
| 530 // STATE_VERIFY_PROOF_SCUP) and STATE_VERIFY_PROOF_COMPLETE (or | |
| 531 // STATE_VERIFY_PROOF_COMPLETE_SCUP) state changes. | |
| 532 if (generation_counter_ != cached->generation_counter()) { | |
| 533 if (handshake_confirmed()) { | |
| 534 next_state_ = STATE_VERIFY_PROOF_SCUP; | |
| 535 } else { | |
| 536 next_state_ = STATE_VERIFY_PROOF; | |
| 537 } | |
| 538 } else { | |
| 539 SetCachedProofValid(cached); | |
| 540 cached->SetProofVerifyDetails(verify_details_.release()); | |
| 541 if (!handshake_confirmed()) { | |
| 542 next_state_ = STATE_GET_CHANNEL_ID; | |
| 543 } else { | |
| 544 next_state_ = STATE_VERIFY_PROOF_DONE; | |
| 545 } | |
| 546 } | |
| 547 return QUIC_NO_ERROR; | |
| 548 } | |
| 549 | |
| 478 void QuicCryptoClientStream::SetCachedProofValid( | 550 void QuicCryptoClientStream::SetCachedProofValid( |
| 479 QuicCryptoClientConfig::CachedState* cached) { | 551 QuicCryptoClientConfig::CachedState* cached) { |
| 480 cached->SetProofValid(); | 552 cached->SetProofValid(); |
| 481 client_session()->OnProofValid(*cached); | 553 client_session()->OnProofValid(*cached); |
| 482 } | 554 } |
| 483 | 555 |
| 484 bool QuicCryptoClientStream::RequiresChannelID( | 556 bool QuicCryptoClientStream::RequiresChannelID( |
| 485 QuicCryptoClientConfig::CachedState* cached) { | 557 QuicCryptoClientConfig::CachedState* cached) { |
| 486 if (!server_id_.is_https() || | 558 if (!server_id_.is_https() || |
| 487 server_id_.privacy_mode() == PRIVACY_MODE_ENABLED || | 559 server_id_.privacy_mode() == PRIVACY_MODE_ENABLED || |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 504 } | 576 } |
| 505 } | 577 } |
| 506 return false; | 578 return false; |
| 507 } | 579 } |
| 508 | 580 |
| 509 QuicClientSessionBase* QuicCryptoClientStream::client_session() { | 581 QuicClientSessionBase* QuicCryptoClientStream::client_session() { |
| 510 return reinterpret_cast<QuicClientSessionBase*>(session()); | 582 return reinterpret_cast<QuicClientSessionBase*>(session()); |
| 511 } | 583 } |
| 512 | 584 |
| 513 } // namespace net | 585 } // namespace net |
| OLD | NEW |