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