Commit c584fb92 authored by rtenneti's avatar rtenneti Committed by Commit bot

Persist the server config that is received via kSCUP.

R=rjshade@chromium.org, rch@chromium.org, asvitkine@chromium.org, rvargas@chromium.org

Review URL: https://codereview.chromium.org/427313002

Cr-Commit-Position: refs/heads/master@{#295582}
parent f4cc5195
......@@ -213,7 +213,9 @@ int DiskCacheBasedQuicServerInfo::DoReadComplete(int rv) {
}
int DiskCacheBasedQuicServerInfo::DoWriteComplete(int rv) {
state_ = SET_DONE;
// Keep the entry open for future writes.
new_data_.clear();
state_ = NONE;
return OK;
}
......@@ -221,7 +223,8 @@ int DiskCacheBasedQuicServerInfo::DoCreateOrOpenComplete(int rv) {
if (rv != OK) {
state_ = SET_DONE;
} else {
entry_ = data_shim_->entry;
if (!entry_)
entry_ = data_shim_->entry;
state_ = WRITE;
}
return OK;
......@@ -264,8 +267,10 @@ int DiskCacheBasedQuicServerInfo::DoWrite() {
}
int DiskCacheBasedQuicServerInfo::DoCreateOrOpen() {
DCHECK(entry_ == NULL);
state_ = CREATE_OR_OPEN_COMPLETE;
if (entry_)
return OK;
if (found_entry_) {
return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_);
}
......
......@@ -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(
......
......@@ -106,6 +106,8 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
STATE_GET_CHANNEL_ID,
STATE_GET_CHANNEL_ID_COMPLETE,
STATE_RECV_SHLO,
STATE_INITIALIZE_SCUP,
STATE_VERIFY_PROOF_DONE,
};
// Handles new server config and optional source-address token provided by the
......@@ -117,6 +119,21 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
// |in| may be NULL if the call did not result from a received message.
void DoHandshakeLoop(const CryptoHandshakeMessage* in);
// Start the proof verification if |server_id_| is https and |cached| has
// signature.
void DoInitializeServerConfigUpdate(
QuicCryptoClientConfig::CachedState* cached);
// Starts the proof verification. Returns the QuicAsyncStatus returned by the
// ProofVerifier's VerifyProof.
QuicAsyncStatus DoVerifyProof(QuicCryptoClientConfig::CachedState* cached);
// If proof is valid then it sets the proof as valid (which persists the
// server config) and returns QUIC_NO_ERROR. If not, it closes the connection
// and returns QUIC_PROOF_INVALID.
QuicErrorCode DoVerifyProofComplete(
QuicCryptoClientConfig::CachedState* cached);
// Called to set the proof of |cached| valid. Also invokes the session's
// OnProofValid() method.
void SetCachedProofValid(QuicCryptoClientConfig::CachedState* cached);
......
......@@ -17167,6 +17167,15 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</summary>
</histogram>
<histogram name="Net.QuicVerifyProofFailed.HandshakeConfirmed"
enum="BooleanHandshakeConfirmed">
<owner>rtenneti@chromium.org</owner>
<summary>
Logged whenever proof verification fails and if the failure occurred before
or after the crypto handshake is confirmed.
</summary>
</histogram>
<histogram name="Net.RenegotiationExtensionSupported">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
......@@ -38783,6 +38792,11 @@ Therefore, the affected-histogram name has to have at least one dot in it.
<int value="1" label="Had blank text"/>
</enum>
<enum name="BooleanHandshakeConfirmed" type="int">
<int value="0" label="Handshake not confirmed"/>
<int value="1" label="Handshake confirmed"/>
</enum>
<enum name="BooleanHasCrc" type="int">
<int value="0" label="No CRC"/>
<int value="1" label="Has CRC"/>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment