| Index: net/quic/quic_crypto_client_stream.cc
|
| diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
|
| index 40e4d45901c531d6fd711e3d1067a3b4cda7d953..4d9d032a9041b0c9827818d6d4f6564fe45448cc 100644
|
| --- a/net/quic/quic_crypto_client_stream.cc
|
| +++ b/net/quic/quic_crypto_client_stream.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "net/quic/quic_crypto_client_stream.h"
|
|
|
| +#include "base/metrics/histogram.h"
|
| #include "net/quic/crypto/crypto_protocol.h"
|
| #include "net/quic/crypto/crypto_utils.h"
|
| #include "net/quic/crypto/null_encrypter.h"
|
| @@ -156,6 +157,13 @@ void QuicCryptoClientStream::HandleServerConfigUpdateMessage(
|
| error, "Server config update invalid: " + error_details);
|
| return;
|
| }
|
| +
|
| + DCHECK(handshake_confirmed());
|
| + if (proof_verify_callback_) {
|
| + proof_verify_callback_->Cancel();
|
| + }
|
| + next_state_ = STATE_INITIALIZE_SCUP;
|
| + DoHandshakeLoop(NULL);
|
| }
|
|
|
| // kMaxClientHellos is the maximum number of times that we'll send a client
|
| @@ -308,57 +316,15 @@ void QuicCryptoClientStream::DoHandshakeLoop(
|
| next_state_ = STATE_GET_CHANNEL_ID;
|
| break;
|
| case STATE_VERIFY_PROOF: {
|
| - ProofVerifier* verifier = crypto_config_->proof_verifier();
|
| - DCHECK(verifier);
|
| - next_state_ = STATE_VERIFY_PROOF_COMPLETE;
|
| - generation_counter_ = cached->generation_counter();
|
| -
|
| - ProofVerifierCallbackImpl* proof_verify_callback =
|
| - new ProofVerifierCallbackImpl(this);
|
| -
|
| - verify_ok_ = false;
|
| -
|
| - QuicAsyncStatus status = verifier->VerifyProof(
|
| - server_id_.host(),
|
| - cached->server_config(),
|
| - cached->certs(),
|
| - cached->signature(),
|
| - verify_context_.get(),
|
| - &verify_error_details_,
|
| - &verify_details_,
|
| - proof_verify_callback);
|
| -
|
| - switch (status) {
|
| - case QUIC_PENDING:
|
| - proof_verify_callback_ = proof_verify_callback;
|
| - DVLOG(1) << "Doing VerifyProof";
|
| - return;
|
| - case QUIC_FAILURE:
|
| - delete proof_verify_callback;
|
| - break;
|
| - case QUIC_SUCCESS:
|
| - delete proof_verify_callback;
|
| - verify_ok_ = true;
|
| - break;
|
| + if (QUIC_PENDING == DoVerifyProof(cached)) {
|
| + return;
|
| }
|
| break;
|
| }
|
| case STATE_VERIFY_PROOF_COMPLETE:
|
| - if (!verify_ok_) {
|
| - client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
|
| - CloseConnectionWithDetails(
|
| - QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
|
| + if (QUIC_PROOF_INVALID == DoVerifyProofComplete(cached)) {
|
| return;
|
| }
|
| - // Check if generation_counter has changed between STATE_VERIFY_PROOF
|
| - // and STATE_VERIFY_PROOF_COMPLETE state changes.
|
| - if (generation_counter_ != cached->generation_counter()) {
|
| - next_state_ = STATE_VERIFY_PROOF;
|
| - } else {
|
| - SetCachedProofValid(cached);
|
| - cached->SetProofVerifyDetails(verify_details_.release());
|
| - next_state_ = STATE_GET_CHANNEL_ID;
|
| - }
|
| break;
|
| case STATE_GET_CHANNEL_ID: {
|
| next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
|
| @@ -471,8 +437,93 @@ void QuicCryptoClientStream::DoHandshakeLoop(
|
| // This means that the peer sent us a message that we weren't expecting.
|
| CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
|
| return;
|
| + case STATE_INITIALIZE_SCUP:
|
| + DoInitializeServerConfigUpdate(cached);
|
| + break;
|
| + case STATE_VERIFY_PROOF_DONE:
|
| + return; // We are done.
|
| + }
|
| + }
|
| +}
|
| +
|
| +void QuicCryptoClientStream::DoInitializeServerConfigUpdate(
|
| + QuicCryptoClientConfig::CachedState* cached) {
|
| + if (!server_id_.is_https()) {
|
| + // We don't check the certificates for insecure QUIC connections.
|
| + SetCachedProofValid(cached);
|
| + next_state_ = STATE_VERIFY_PROOF_DONE;
|
| + return;
|
| + }
|
| + if (!cached->IsEmpty() && !cached->signature().empty()) {
|
| + // Note that we verify the proof even if the cached proof is valid.
|
| + DCHECK(crypto_config_->proof_verifier());
|
| + next_state_ = STATE_VERIFY_PROOF;
|
| + }
|
| +}
|
| +
|
| +QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
|
| + QuicCryptoClientConfig::CachedState* cached) {
|
| + ProofVerifier* verifier = crypto_config_->proof_verifier();
|
| + DCHECK(verifier);
|
| + next_state_ = STATE_VERIFY_PROOF_COMPLETE;
|
| + generation_counter_ = cached->generation_counter();
|
| +
|
| + ProofVerifierCallbackImpl* proof_verify_callback =
|
| + new ProofVerifierCallbackImpl(this);
|
| +
|
| + verify_ok_ = false;
|
| +
|
| + QuicAsyncStatus status = verifier->VerifyProof(
|
| + server_id_.host(),
|
| + cached->server_config(),
|
| + cached->certs(),
|
| + cached->signature(),
|
| + verify_context_.get(),
|
| + &verify_error_details_,
|
| + &verify_details_,
|
| + proof_verify_callback);
|
| +
|
| + switch (status) {
|
| + case QUIC_PENDING:
|
| + proof_verify_callback_ = proof_verify_callback;
|
| + DVLOG(1) << "Doing VerifyProof";
|
| + break;
|
| + case QUIC_FAILURE:
|
| + delete proof_verify_callback;
|
| + break;
|
| + case QUIC_SUCCESS:
|
| + delete proof_verify_callback;
|
| + verify_ok_ = true;
|
| + break;
|
| + }
|
| + return status;
|
| +}
|
| +
|
| +QuicErrorCode QuicCryptoClientStream::DoVerifyProofComplete(
|
| + QuicCryptoClientConfig::CachedState* cached) {
|
| + if (!verify_ok_) {
|
| + client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
|
| + UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
|
| + handshake_confirmed());
|
| + CloseConnectionWithDetails(
|
| + QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
|
| + return QUIC_PROOF_INVALID;
|
| + }
|
| +
|
| + // Check if generation_counter has changed between STATE_VERIFY_PROOF and
|
| + // STATE_VERIFY_PROOF_COMPLETE state changes.
|
| + if (generation_counter_ != cached->generation_counter()) {
|
| + next_state_ = STATE_VERIFY_PROOF;
|
| + } else {
|
| + SetCachedProofValid(cached);
|
| + cached->SetProofVerifyDetails(verify_details_.release());
|
| + if (!handshake_confirmed()) {
|
| + next_state_ = STATE_GET_CHANNEL_ID;
|
| + } else {
|
| + next_state_ = STATE_VERIFY_PROOF_DONE;
|
| }
|
| }
|
| + return QUIC_NO_ERROR;
|
| }
|
|
|
| void QuicCryptoClientStream::SetCachedProofValid(
|
|
|