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 if (QUIC_PENDING == DoVerifyProof(cached)) { |
312 DCHECK(verifier); | 320 return; |
313 next_state_ = STATE_VERIFY_PROOF_COMPLETE; | |
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 } | 321 } |
344 break; | 322 break; |
345 } | 323 } |
346 case STATE_VERIFY_PROOF_COMPLETE: | 324 case STATE_VERIFY_PROOF_COMPLETE: |
347 if (!verify_ok_) { | 325 if (QUIC_PROOF_INVALID == DoVerifyProofComplete(cached)) { |
348 client_session()->OnProofVerifyDetailsAvailable(*verify_details_); | |
349 CloseConnectionWithDetails( | |
350 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); | |
351 return; | 326 return; |
352 } | 327 } |
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; | 328 break; |
363 case STATE_GET_CHANNEL_ID: { | 329 case STATE_GET_CHANNEL_ID: { |
364 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE; | 330 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE; |
365 channel_id_key_.reset(); | 331 channel_id_key_.reset(); |
366 if (!RequiresChannelID(cached)) { | 332 if (!RequiresChannelID(cached)) { |
367 next_state_ = STATE_SEND_CHLO; | 333 next_state_ = STATE_SEND_CHLO; |
368 break; | 334 break; |
369 } | 335 } |
370 | 336 |
371 ChannelIDSourceCallbackImpl* channel_id_source_callback = | 337 ChannelIDSourceCallbackImpl* channel_id_source_callback = |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 | 430 |
465 handshake_confirmed_ = true; | 431 handshake_confirmed_ = true; |
466 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); | 432 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); |
467 session()->connection()->OnHandshakeComplete(); | 433 session()->connection()->OnHandshakeComplete(); |
468 return; | 434 return; |
469 } | 435 } |
470 case STATE_IDLE: | 436 case STATE_IDLE: |
471 // This means that the peer sent us a message that we weren't expecting. | 437 // This means that the peer sent us a message that we weren't expecting. |
472 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | 438 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); |
473 return; | 439 return; |
| 440 case STATE_INITIALIZE_SCUP: |
| 441 DoInitializeServerConfigUpdate(cached); |
| 442 break; |
| 443 case STATE_VERIFY_PROOF_DONE: |
| 444 return; // We are done. |
474 } | 445 } |
475 } | 446 } |
476 } | 447 } |
477 | 448 |
| 449 void QuicCryptoClientStream::DoInitializeServerConfigUpdate( |
| 450 QuicCryptoClientConfig::CachedState* cached) { |
| 451 if (!server_id_.is_https()) { |
| 452 // We don't check the certificates for insecure QUIC connections. |
| 453 SetCachedProofValid(cached); |
| 454 next_state_ = STATE_VERIFY_PROOF_DONE; |
| 455 return; |
| 456 } |
| 457 if (!cached->IsEmpty() && !cached->signature().empty()) { |
| 458 // Note that we verify the proof even if the cached proof is valid. |
| 459 DCHECK(crypto_config_->proof_verifier()); |
| 460 next_state_ = STATE_VERIFY_PROOF; |
| 461 } |
| 462 } |
| 463 |
| 464 QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof( |
| 465 QuicCryptoClientConfig::CachedState* cached) { |
| 466 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
| 467 DCHECK(verifier); |
| 468 next_state_ = STATE_VERIFY_PROOF_COMPLETE; |
| 469 generation_counter_ = cached->generation_counter(); |
| 470 |
| 471 ProofVerifierCallbackImpl* proof_verify_callback = |
| 472 new ProofVerifierCallbackImpl(this); |
| 473 |
| 474 verify_ok_ = false; |
| 475 |
| 476 QuicAsyncStatus status = verifier->VerifyProof( |
| 477 server_id_.host(), |
| 478 cached->server_config(), |
| 479 cached->certs(), |
| 480 cached->signature(), |
| 481 verify_context_.get(), |
| 482 &verify_error_details_, |
| 483 &verify_details_, |
| 484 proof_verify_callback); |
| 485 |
| 486 switch (status) { |
| 487 case QUIC_PENDING: |
| 488 proof_verify_callback_ = proof_verify_callback; |
| 489 DVLOG(1) << "Doing VerifyProof"; |
| 490 break; |
| 491 case QUIC_FAILURE: |
| 492 delete proof_verify_callback; |
| 493 break; |
| 494 case QUIC_SUCCESS: |
| 495 delete proof_verify_callback; |
| 496 verify_ok_ = true; |
| 497 break; |
| 498 } |
| 499 return status; |
| 500 } |
| 501 |
| 502 QuicErrorCode QuicCryptoClientStream::DoVerifyProofComplete( |
| 503 QuicCryptoClientConfig::CachedState* cached) { |
| 504 if (!verify_ok_) { |
| 505 client_session()->OnProofVerifyDetailsAvailable(*verify_details_); |
| 506 UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed", |
| 507 handshake_confirmed()); |
| 508 CloseConnectionWithDetails( |
| 509 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); |
| 510 return QUIC_PROOF_INVALID; |
| 511 } |
| 512 |
| 513 // Check if generation_counter has changed between STATE_VERIFY_PROOF and |
| 514 // STATE_VERIFY_PROOF_COMPLETE state changes. |
| 515 if (generation_counter_ != cached->generation_counter()) { |
| 516 next_state_ = STATE_VERIFY_PROOF; |
| 517 } else { |
| 518 SetCachedProofValid(cached); |
| 519 cached->SetProofVerifyDetails(verify_details_.release()); |
| 520 if (!handshake_confirmed()) { |
| 521 next_state_ = STATE_GET_CHANNEL_ID; |
| 522 } else { |
| 523 next_state_ = STATE_VERIFY_PROOF_DONE; |
| 524 } |
| 525 } |
| 526 return QUIC_NO_ERROR; |
| 527 } |
| 528 |
478 void QuicCryptoClientStream::SetCachedProofValid( | 529 void QuicCryptoClientStream::SetCachedProofValid( |
479 QuicCryptoClientConfig::CachedState* cached) { | 530 QuicCryptoClientConfig::CachedState* cached) { |
480 cached->SetProofValid(); | 531 cached->SetProofValid(); |
481 client_session()->OnProofValid(*cached); | 532 client_session()->OnProofValid(*cached); |
482 } | 533 } |
483 | 534 |
484 bool QuicCryptoClientStream::RequiresChannelID( | 535 bool QuicCryptoClientStream::RequiresChannelID( |
485 QuicCryptoClientConfig::CachedState* cached) { | 536 QuicCryptoClientConfig::CachedState* cached) { |
486 if (!server_id_.is_https() || | 537 if (!server_id_.is_https() || |
487 server_id_.privacy_mode() == PRIVACY_MODE_ENABLED || | 538 server_id_.privacy_mode() == PRIVACY_MODE_ENABLED || |
(...skipping 16 matching lines...) Expand all Loading... |
504 } | 555 } |
505 } | 556 } |
506 return false; | 557 return false; |
507 } | 558 } |
508 | 559 |
509 QuicClientSessionBase* QuicCryptoClientStream::client_session() { | 560 QuicClientSessionBase* QuicCryptoClientStream::client_session() { |
510 return reinterpret_cast<QuicClientSessionBase*>(session()); | 561 return reinterpret_cast<QuicClientSessionBase*>(session()); |
511 } | 562 } |
512 | 563 |
513 } // namespace net | 564 } // namespace net |
OLD | NEW |