Commit e45fe4fc authored by Nick Harper's avatar Nick Harper Committed by Commit Bot

Start refactor of QuicCryptoStream

QuicCryptoClientStream and QuicCryptoServerStream are refactored to delegate
their implementations to a CryptoClientStreamDelegate or
CryptoServerStreamDelegate, and the existing implementations are moved to new
subclasses of the new delegates.

The major work left to do in this refactor is for QuicCryptoStream to no longer
implement CryptoFramerVisitorInterface and to remove the OnHandshakeMessage
method from CryptoClientStreamDelegate and CryptoServerStreamDelegate
interfaces.

Merge internal change: 161549072

Change-Id: I3919d067028cdacd939c64be4362d4645d7e7e65
Reviewed-on: https://chromium-review.googlesource.com/565978
Commit-Queue: Nick Harper <nharper@chromium.org>
Reviewed-by: default avatarRyan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#486185}
parent a6e2065d
...@@ -17,13 +17,6 @@ void QuicChromiumClientSessionPeer::SetMaxOpenStreams( ...@@ -17,13 +17,6 @@ void QuicChromiumClientSessionPeer::SetMaxOpenStreams(
session->config()->SetMaxStreamsPerConnection(max_streams, default_streams); session->config()->SetMaxStreamsPerConnection(max_streams, default_streams);
} }
// static
void QuicChromiumClientSessionPeer::SetChannelIDSent(
QuicChromiumClientSession* session,
bool channel_id_sent) {
session->crypto_stream_->channel_id_sent_ = channel_id_sent;
}
// static // static
void QuicChromiumClientSessionPeer::SetHostname( void QuicChromiumClientSessionPeer::SetHostname(
QuicChromiumClientSession* session, QuicChromiumClientSession* session,
......
...@@ -24,9 +24,6 @@ class QuicChromiumClientSessionPeer { ...@@ -24,9 +24,6 @@ class QuicChromiumClientSessionPeer {
size_t max_streams, size_t max_streams,
size_t default_streams); size_t default_streams);
static void SetChannelIDSent(QuicChromiumClientSession* session,
bool channel_id_sent);
static void SetHostname(QuicChromiumClientSession* session, static void SetHostname(QuicChromiumClientSession* session,
const std::string& hostname); const std::string& hostname);
......
...@@ -58,6 +58,26 @@ const char kServerHostname[] = "test.example.com"; ...@@ -58,6 +58,26 @@ const char kServerHostname[] = "test.example.com";
const uint16_t kServerPort = 443; const uint16_t kServerPort = 443;
const size_t kMaxReadersPerQuicSession = 5; const size_t kMaxReadersPerQuicSession = 5;
// A subclass of QuicChromiumClientSession with GetSSLInfo overriden to allow
// forcing the value of SSLInfo::channel_id_sent to true.
class TestingQuicChromiumClientSession : public QuicChromiumClientSession {
public:
using QuicChromiumClientSession::QuicChromiumClientSession;
bool GetSSLInfo(SSLInfo* ssl_info) const override {
bool ret = QuicChromiumClientSession::GetSSLInfo(ssl_info);
if (ret)
ssl_info->channel_id_sent =
ssl_info->channel_id_sent || force_channel_id_sent_;
return ret;
}
void OverrideChannelIDSent() { force_channel_id_sent_ = true; }
private:
bool force_channel_id_sent_ = false;
};
class QuicChromiumClientSessionTest class QuicChromiumClientSessionTest
: public ::testing::TestWithParam<QuicVersion> { : public ::testing::TestWithParam<QuicVersion> {
protected: protected:
...@@ -97,7 +117,7 @@ class QuicChromiumClientSessionTest ...@@ -97,7 +117,7 @@ class QuicChromiumClientSessionTest
0, QuicSocketAddress(QuicSocketAddressImpl(kIpEndPoint)), &helper_, 0, QuicSocketAddress(QuicSocketAddressImpl(kIpEndPoint)), &helper_,
&alarm_factory_, writer, true, Perspective::IS_CLIENT, &alarm_factory_, writer, true, Perspective::IS_CLIENT,
SupportedVersions(GetParam())); SupportedVersions(GetParam()));
session_.reset(new QuicChromiumClientSession( session_.reset(new TestingQuicChromiumClientSession(
connection, std::move(socket), connection, std::move(socket),
/*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_, /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
&transport_security_state_, &transport_security_state_,
...@@ -159,7 +179,7 @@ class QuicChromiumClientSessionTest ...@@ -159,7 +179,7 @@ class QuicChromiumClientSessionTest
MockCryptoClientStreamFactory crypto_client_stream_factory_; MockCryptoClientStreamFactory crypto_client_stream_factory_;
QuicClientPushPromiseIndex push_promise_index_; QuicClientPushPromiseIndex push_promise_index_;
QuicServerId server_id_; QuicServerId server_id_;
std::unique_ptr<QuicChromiumClientSession> session_; std::unique_ptr<TestingQuicChromiumClientSession> session_;
TestServerPushDelegate test_push_delegate_; TestServerPushDelegate test_push_delegate_;
QuicConnectionVisitorInterface* visitor_; QuicConnectionVisitorInterface* visitor_;
TestCompletionCallback callback_; TestCompletionCallback callback_;
...@@ -976,7 +996,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithTlsChannelId) { ...@@ -976,7 +996,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithTlsChannelId) {
CompleteCryptoHandshake(); CompleteCryptoHandshake();
session_->OnProofVerifyDetailsAvailable(details); session_->OnProofVerifyDetailsAvailable(details);
QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org"); QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org");
QuicChromiumClientSessionPeer::SetChannelIDSent(session_.get(), true); session_->OverrideChannelIDSent();
EXPECT_TRUE(session_->CanPool("www.example.org", PRIVACY_MODE_DISABLED)); EXPECT_TRUE(session_->CanPool("www.example.org", PRIVACY_MODE_DISABLED));
EXPECT_TRUE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED)); EXPECT_TRUE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
...@@ -1012,7 +1032,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionNotPooledWithDifferentPin) { ...@@ -1012,7 +1032,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionNotPooledWithDifferentPin) {
CompleteCryptoHandshake(); CompleteCryptoHandshake();
session_->OnProofVerifyDetailsAvailable(details); session_->OnProofVerifyDetailsAvailable(details);
QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org"); QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org");
QuicChromiumClientSessionPeer::SetChannelIDSent(session_.get(), true); session_->OverrideChannelIDSent();
EXPECT_FALSE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED)); EXPECT_FALSE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
} }
...@@ -1044,7 +1064,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) { ...@@ -1044,7 +1064,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) {
CompleteCryptoHandshake(); CompleteCryptoHandshake();
session_->OnProofVerifyDetailsAvailable(details); session_->OnProofVerifyDetailsAvailable(details);
QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org"); QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org");
QuicChromiumClientSessionPeer::SetChannelIDSent(session_.get(), true); session_->OverrideChannelIDSent();
EXPECT_TRUE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED)); EXPECT_TRUE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
} }
......
...@@ -27,59 +27,59 @@ const int QuicCryptoClientStream::kMaxClientHellos; ...@@ -27,59 +27,59 @@ const int QuicCryptoClientStream::kMaxClientHellos;
QuicCryptoClientStreamBase::QuicCryptoClientStreamBase(QuicSession* session) QuicCryptoClientStreamBase::QuicCryptoClientStreamBase(QuicSession* session)
: QuicCryptoStream(session) {} : QuicCryptoStream(session) {}
QuicCryptoClientStream::ChannelIDSourceCallbackImpl:: QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::
ChannelIDSourceCallbackImpl(QuicCryptoClientStream* stream) ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent)
: stream_(stream) {} : parent_(parent) {}
QuicCryptoClientStream::ChannelIDSourceCallbackImpl:: QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::
~ChannelIDSourceCallbackImpl() {} ~ChannelIDSourceCallbackImpl() {}
void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Run( void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Run(
std::unique_ptr<ChannelIDKey>* channel_id_key) { std::unique_ptr<ChannelIDKey>* channel_id_key) {
if (stream_ == nullptr) { if (parent_ == nullptr) {
return; return;
} }
stream_->channel_id_key_ = std::move(*channel_id_key); parent_->channel_id_key_ = std::move(*channel_id_key);
stream_->channel_id_source_callback_run_ = true; parent_->channel_id_source_callback_run_ = true;
stream_->channel_id_source_callback_ = nullptr; parent_->channel_id_source_callback_ = nullptr;
stream_->DoHandshakeLoop(nullptr); parent_->DoHandshakeLoop(nullptr);
// The ChannelIDSource owns this object and will delete it when this method // The ChannelIDSource owns this object and will delete it when this method
// returns. // returns.
} }
void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Cancel() { void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Cancel() {
stream_ = nullptr; parent_ = nullptr;
} }
QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl( QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::
QuicCryptoClientStream* stream) ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent)
: stream_(stream) {} : parent_(parent) {}
QuicCryptoClientStream::ProofVerifierCallbackImpl:: QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::
~ProofVerifierCallbackImpl() {} ~ProofVerifierCallbackImpl() {}
void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run( void QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::Run(
bool ok, bool ok,
const string& error_details, const string& error_details,
std::unique_ptr<ProofVerifyDetails>* details) { std::unique_ptr<ProofVerifyDetails>* details) {
if (stream_ == nullptr) { if (parent_ == nullptr) {
return; return;
} }
stream_->verify_ok_ = ok; parent_->verify_ok_ = ok;
stream_->verify_error_details_ = error_details; parent_->verify_error_details_ = error_details;
stream_->verify_details_ = std::move(*details); parent_->verify_details_ = std::move(*details);
stream_->proof_verify_callback_ = nullptr; parent_->proof_verify_callback_ = nullptr;
stream_->DoHandshakeLoop(nullptr); parent_->DoHandshakeLoop(nullptr);
// The ProofVerifier owns this object and will delete it when this method // The ProofVerifier owns this object and will delete it when this method
// returns. // returns.
} }
void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { void QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::Cancel() {
stream_ = nullptr; parent_ = nullptr;
} }
QuicCryptoClientStream::QuicCryptoClientStream( QuicCryptoClientStream::QuicCryptoClientStream(
...@@ -88,7 +88,66 @@ QuicCryptoClientStream::QuicCryptoClientStream( ...@@ -88,7 +88,66 @@ QuicCryptoClientStream::QuicCryptoClientStream(
ProofVerifyContext* verify_context, ProofVerifyContext* verify_context,
QuicCryptoClientConfig* crypto_config, QuicCryptoClientConfig* crypto_config,
ProofHandler* proof_handler) ProofHandler* proof_handler)
: QuicCryptoClientStreamBase(session), : QuicCryptoClientStreamBase(session) {
DCHECK_EQ(Perspective::IS_CLIENT, session->connection()->perspective());
handshaker_.reset(new QuicCryptoClientHandshaker(
server_id, this, session, verify_context, crypto_config, proof_handler));
}
QuicCryptoClientStream::~QuicCryptoClientStream() {}
bool QuicCryptoClientStream::CryptoConnect() {
return handshaker_->CryptoConnect();
}
int QuicCryptoClientStream::num_sent_client_hellos() const {
return handshaker_->num_sent_client_hellos();
}
int QuicCryptoClientStream::num_scup_messages_received() const {
return handshaker_->num_scup_messages_received();
}
bool QuicCryptoClientStream::encryption_established() const {
return handshaker_->encryption_established();
}
bool QuicCryptoClientStream::handshake_confirmed() const {
return handshaker_->handshake_confirmed();
}
const QuicCryptoNegotiatedParameters&
QuicCryptoClientStream::crypto_negotiated_params() const {
return handshaker_->crypto_negotiated_params();
}
void QuicCryptoClientStream::OnHandshakeMessage(
const CryptoHandshakeMessage& message) {
QuicCryptoClientStreamBase::OnHandshakeMessage(message);
handshaker_->OnHandshakeMessage(message);
}
bool QuicCryptoClientStream::WasChannelIDSent() const {
return handshaker_->WasChannelIDSent();
}
bool QuicCryptoClientStream::WasChannelIDSourceCallbackRun() const {
return handshaker_->WasChannelIDSourceCallbackRun();
}
string QuicCryptoClientStream::chlo_hash() const {
return handshaker_->chlo_hash();
}
QuicCryptoClientHandshaker::QuicCryptoClientHandshaker(
const QuicServerId& server_id,
QuicCryptoClientStream* stream,
QuicSession* session,
ProofVerifyContext* verify_context,
QuicCryptoClientConfig* crypto_config,
QuicCryptoClientStream::ProofHandler* proof_handler)
: stream_(stream),
session_(session),
next_state_(STATE_IDLE), next_state_(STATE_IDLE),
num_client_hellos_(0), num_client_hellos_(0),
crypto_config_(crypto_config), crypto_config_(crypto_config),
...@@ -105,11 +164,9 @@ QuicCryptoClientStream::QuicCryptoClientStream( ...@@ -105,11 +164,9 @@ QuicCryptoClientStream::QuicCryptoClientStream(
num_scup_messages_received_(0), num_scup_messages_received_(0),
encryption_established_(false), encryption_established_(false),
handshake_confirmed_(false), handshake_confirmed_(false),
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) { crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
DCHECK_EQ(Perspective::IS_CLIENT, session->connection()->perspective());
}
QuicCryptoClientStream::~QuicCryptoClientStream() { QuicCryptoClientHandshaker::~QuicCryptoClientHandshaker() {
if (channel_id_source_callback_) { if (channel_id_source_callback_) {
channel_id_source_callback_->Cancel(); channel_id_source_callback_->Cancel();
} }
...@@ -118,14 +175,13 @@ QuicCryptoClientStream::~QuicCryptoClientStream() { ...@@ -118,14 +175,13 @@ QuicCryptoClientStream::~QuicCryptoClientStream() {
} }
} }
void QuicCryptoClientStream::OnHandshakeMessage( void QuicCryptoClientHandshaker::OnHandshakeMessage(
const CryptoHandshakeMessage& message) { const CryptoHandshakeMessage& message) {
QuicCryptoClientStreamBase::OnHandshakeMessage(message);
if (message.tag() == kSCUP) { if (message.tag() == kSCUP) {
if (!handshake_confirmed()) { if (!handshake_confirmed()) {
CloseConnectionWithDetails(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE, stream_->CloseConnectionWithDetails(
"Early SCUP disallowed"); QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE,
"Early SCUP disallowed");
return; return;
} }
...@@ -138,51 +194,55 @@ void QuicCryptoClientStream::OnHandshakeMessage( ...@@ -138,51 +194,55 @@ void QuicCryptoClientStream::OnHandshakeMessage(
// Do not process handshake messages after the handshake is confirmed. // Do not process handshake messages after the handshake is confirmed.
if (handshake_confirmed()) { if (handshake_confirmed()) {
CloseConnectionWithDetails(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, stream_->CloseConnectionWithDetails(
"Unexpected handshake message"); QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
"Unexpected handshake message");
return; return;
} }
DoHandshakeLoop(&message); DoHandshakeLoop(&message);
} }
bool QuicCryptoClientStream::CryptoConnect() { bool QuicCryptoClientHandshaker::CryptoConnect() {
next_state_ = STATE_INITIALIZE; next_state_ = STATE_INITIALIZE;
DoHandshakeLoop(nullptr); DoHandshakeLoop(nullptr);
return session()->connection()->connected(); return session()->connection()->connected();
} }
int QuicCryptoClientStream::num_sent_client_hellos() const { int QuicCryptoClientHandshaker::num_sent_client_hellos() const {
return num_client_hellos_; return num_client_hellos_;
} }
int QuicCryptoClientStream::num_scup_messages_received() const { int QuicCryptoClientHandshaker::num_scup_messages_received() const {
return num_scup_messages_received_; return num_scup_messages_received_;
} }
// Used in Chromium, but not in the server. bool QuicCryptoClientHandshaker::WasChannelIDSent() const {
bool QuicCryptoClientStream::WasChannelIDSent() const {
return channel_id_sent_; return channel_id_sent_;
} }
bool QuicCryptoClientStream::WasChannelIDSourceCallbackRun() const { bool QuicCryptoClientHandshaker::WasChannelIDSourceCallbackRun() const {
return channel_id_source_callback_run_; return channel_id_source_callback_run_;
} }
bool QuicCryptoClientStream::encryption_established() const { string QuicCryptoClientHandshaker::chlo_hash() const {
return chlo_hash_;
}
bool QuicCryptoClientHandshaker::encryption_established() const {
return encryption_established_; return encryption_established_;
} }
bool QuicCryptoClientStream::handshake_confirmed() const { bool QuicCryptoClientHandshaker::handshake_confirmed() const {
return handshake_confirmed_; return handshake_confirmed_;
} }
const QuicCryptoNegotiatedParameters& const QuicCryptoNegotiatedParameters&
QuicCryptoClientStream::crypto_negotiated_params() const { QuicCryptoClientHandshaker::crypto_negotiated_params() const {
return *crypto_negotiated_params_; return *crypto_negotiated_params_;
} }
void QuicCryptoClientStream::HandleServerConfigUpdateMessage( void QuicCryptoClientHandshaker::HandleServerConfigUpdateMessage(
const CryptoHandshakeMessage& server_config_update) { const CryptoHandshakeMessage& server_config_update) {
DCHECK(server_config_update.tag() == kSCUP); DCHECK(server_config_update.tag() == kSCUP);
string error_details; string error_details;
...@@ -194,7 +254,7 @@ void QuicCryptoClientStream::HandleServerConfigUpdateMessage( ...@@ -194,7 +254,7 @@ void QuicCryptoClientStream::HandleServerConfigUpdateMessage(
crypto_negotiated_params_, &error_details); crypto_negotiated_params_, &error_details);
if (error != QUIC_NO_ERROR) { if (error != QUIC_NO_ERROR) {
CloseConnectionWithDetails( stream_->CloseConnectionWithDetails(
error, "Server config update invalid: " + error_details); error, "Server config update invalid: " + error_details);
return; return;
} }
...@@ -207,7 +267,8 @@ void QuicCryptoClientStream::HandleServerConfigUpdateMessage( ...@@ -207,7 +267,8 @@ void QuicCryptoClientStream::HandleServerConfigUpdateMessage(
DoHandshakeLoop(nullptr); DoHandshakeLoop(nullptr);
} }
void QuicCryptoClientStream::DoHandshakeLoop(const CryptoHandshakeMessage* in) { void QuicCryptoClientHandshaker::DoHandshakeLoop(
const CryptoHandshakeMessage* in) {
QuicCryptoClientConfig::CachedState* cached = QuicCryptoClientConfig::CachedState* cached =
crypto_config_->LookupOrCreate(server_id_); crypto_config_->LookupOrCreate(server_id_);
...@@ -244,8 +305,8 @@ void QuicCryptoClientStream::DoHandshakeLoop(const CryptoHandshakeMessage* in) { ...@@ -244,8 +305,8 @@ void QuicCryptoClientStream::DoHandshakeLoop(const CryptoHandshakeMessage* in) {
break; break;
case STATE_IDLE: case STATE_IDLE:
// This means that the peer sent us a message that we weren't expecting. // This means that the peer sent us a message that we weren't expecting.
CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
"Handshake in idle state"); "Handshake in idle state");
return; return;
case STATE_INITIALIZE_SCUP: case STATE_INITIALIZE_SCUP:
DoInitializeServerConfigUpdate(cached); DoInitializeServerConfigUpdate(cached);
...@@ -257,7 +318,7 @@ void QuicCryptoClientStream::DoHandshakeLoop(const CryptoHandshakeMessage* in) { ...@@ -257,7 +318,7 @@ void QuicCryptoClientStream::DoHandshakeLoop(const CryptoHandshakeMessage* in) {
} while (rv != QUIC_PENDING && next_state_ != STATE_NONE); } while (rv != QUIC_PENDING && next_state_ != STATE_NONE);
} }
void QuicCryptoClientStream::DoInitialize( void QuicCryptoClientHandshaker::DoInitialize(
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
if (!cached->IsEmpty() && !cached->signature().empty()) { if (!cached->IsEmpty() && !cached->signature().empty()) {
// Note that we verify the proof even if the cached proof is valid. // Note that we verify the proof even if the cached proof is valid.
...@@ -275,7 +336,7 @@ void QuicCryptoClientStream::DoInitialize( ...@@ -275,7 +336,7 @@ void QuicCryptoClientStream::DoInitialize(
} }
} }
void QuicCryptoClientStream::DoSendCHLO( void QuicCryptoClientHandshaker::DoSendCHLO(
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
if (stateless_reject_received_) { if (stateless_reject_received_) {
// If we've gotten to this point, we've sent at least one hello // If we've gotten to this point, we've sent at least one hello
...@@ -294,10 +355,11 @@ void QuicCryptoClientStream::DoSendCHLO( ...@@ -294,10 +355,11 @@ void QuicCryptoClientStream::DoSendCHLO(
// Send the client hello in plaintext. // Send the client hello in plaintext.
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
encryption_established_ = false; encryption_established_ = false;
if (num_client_hellos_ > kMaxClientHellos) { if (num_client_hellos_ > QuicCryptoClientStream::kMaxClientHellos) {
CloseConnectionWithDetails( stream_->CloseConnectionWithDetails(
QUIC_CRYPTO_TOO_MANY_REJECTS, QUIC_CRYPTO_TOO_MANY_REJECTS,
QuicStrCat("More than ", kMaxClientHellos, " rejects")); QuicStrCat("More than ", QuicCryptoClientStream::kMaxClientHellos,
" rejects"));
return; return;
} }
num_client_hellos_++; num_client_hellos_++;
...@@ -325,13 +387,14 @@ void QuicCryptoClientStream::DoSendCHLO( ...@@ -325,13 +387,14 @@ void QuicCryptoClientStream::DoSendCHLO(
if (max_packet_size <= kFramingOverhead) { if (max_packet_size <= kFramingOverhead) {
QUIC_DLOG(DFATAL) << "max_packet_length (" << max_packet_size QUIC_DLOG(DFATAL) << "max_packet_length (" << max_packet_size
<< ") has no room for framing overhead."; << ") has no room for framing overhead.";
CloseConnectionWithDetails(QUIC_INTERNAL_ERROR, stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
"max_packet_size too smalll"); "max_packet_size too smalll");
return; return;
} }
if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) { if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
QUIC_DLOG(DFATAL) << "Client hello won't fit in a single packet."; QUIC_DLOG(DFATAL) << "Client hello won't fit in a single packet.";
CloseConnectionWithDetails(QUIC_INTERNAL_ERROR, "CHLO too large"); stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
"CHLO too large");
return; return;
} }
// TODO(rch): Remove this when we remove: // TODO(rch): Remove this when we remove:
...@@ -340,7 +403,7 @@ void QuicCryptoClientStream::DoSendCHLO( ...@@ -340,7 +403,7 @@ void QuicCryptoClientStream::DoSendCHLO(
static_cast<size_t>(max_packet_size - kFramingOverhead)); static_cast<size_t>(max_packet_size - kFramingOverhead));
next_state_ = STATE_RECV_REJ; next_state_ = STATE_RECV_REJ;
CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT); CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT);
SendHandshakeMessage(out); stream_->SendHandshakeMessage(out);
return; return;
} }
...@@ -364,7 +427,7 @@ void QuicCryptoClientStream::DoSendCHLO( ...@@ -364,7 +427,7 @@ void QuicCryptoClientStream::DoSendCHLO(
// Flush the cached config so that, if it's bad, the server has a // Flush the cached config so that, if it's bad, the server has a
// chance to send us another in the future. // chance to send us another in the future.
cached->InvalidateServerConfig(); cached->InvalidateServerConfig();
CloseConnectionWithDetails(error, error_details); stream_->CloseConnectionWithDetails(error, error_details);
return; return;
} }
CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT); CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT);
...@@ -374,7 +437,7 @@ void QuicCryptoClientStream::DoSendCHLO( ...@@ -374,7 +437,7 @@ void QuicCryptoClientStream::DoSendCHLO(
*cached->proof_verify_details()); *cached->proof_verify_details());
} }
next_state_ = STATE_RECV_SHLO; next_state_ = STATE_RECV_SHLO;
SendHandshakeMessage(out); stream_->SendHandshakeMessage(out);
// Be prepared to decrypt with the new server write key. // Be prepared to decrypt with the new server write key.
session()->connection()->SetAlternativeDecrypter( session()->connection()->SetAlternativeDecrypter(
ENCRYPTION_INITIAL, ENCRYPTION_INITIAL,
...@@ -393,7 +456,7 @@ void QuicCryptoClientStream::DoSendCHLO( ...@@ -393,7 +456,7 @@ void QuicCryptoClientStream::DoSendCHLO(
session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_REESTABLISHED); session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_REESTABLISHED);
} }
void QuicCryptoClientStream::DoReceiveREJ( void QuicCryptoClientHandshaker::DoReceiveREJ(
const CryptoHandshakeMessage* in, const CryptoHandshakeMessage* in,
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
// We sent a dummy CHLO because we didn't have enough information to // We sent a dummy CHLO because we didn't have enough information to
...@@ -402,8 +465,8 @@ void QuicCryptoClientStream::DoReceiveREJ( ...@@ -402,8 +465,8 @@ void QuicCryptoClientStream::DoReceiveREJ(
// that we need. // that we need.
if ((in->tag() != kREJ) && (in->tag() != kSREJ)) { if ((in->tag() != kREJ) && (in->tag() != kSREJ)) {
next_state_ = STATE_NONE; next_state_ = STATE_NONE;
CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
"Expected REJ"); "Expected REJ");
return; return;
} }
...@@ -421,7 +484,7 @@ void QuicCryptoClientStream::DoReceiveREJ( ...@@ -421,7 +484,7 @@ void QuicCryptoClientStream::DoReceiveREJ(
packed_error |= 1 << (reason - 1); packed_error |= 1 << (reason - 1);
} }
DVLOG(1) << "Reasons for rejection: " << packed_error; DVLOG(1) << "Reasons for rejection: " << packed_error;
if (num_client_hellos_ == kMaxClientHellos) { if (num_client_hellos_ == QuicCryptoClientStream::kMaxClientHellos) {
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.TooMany", UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.TooMany",
packed_error); packed_error);
} }
...@@ -442,7 +505,7 @@ void QuicCryptoClientStream::DoReceiveREJ( ...@@ -442,7 +505,7 @@ void QuicCryptoClientStream::DoReceiveREJ(
if (error != QUIC_NO_ERROR) { if (error != QUIC_NO_ERROR) {
next_state_ = STATE_NONE; next_state_ = STATE_NONE;
CloseConnectionWithDetails(error, error_details); stream_->CloseConnectionWithDetails(error, error_details);
return; return;
} }
if (!cached->proof_valid()) { if (!cached->proof_valid()) {
...@@ -459,7 +522,7 @@ void QuicCryptoClientStream::DoReceiveREJ( ...@@ -459,7 +522,7 @@ void QuicCryptoClientStream::DoReceiveREJ(
next_state_ = STATE_GET_CHANNEL_ID; next_state_ = STATE_GET_CHANNEL_ID;
} }
QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof( QuicAsyncStatus QuicCryptoClientHandshaker::DoVerifyProof(
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
ProofVerifier* verifier = crypto_config_->proof_verifier(); ProofVerifier* verifier = crypto_config_->proof_verifier();
DCHECK(verifier); DCHECK(verifier);
...@@ -492,7 +555,7 @@ QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof( ...@@ -492,7 +555,7 @@ QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
return status; return status;
} }
void QuicCryptoClientStream::DoVerifyProofComplete( void QuicCryptoClientHandshaker::DoVerifyProofComplete(
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
if (!proof_verify_start_time_.is_null()) { if (!proof_verify_start_time_.is_null()) {
UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime.CachedServerConfig", UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime.CachedServerConfig",
...@@ -510,8 +573,8 @@ void QuicCryptoClientStream::DoVerifyProofComplete( ...@@ -510,8 +573,8 @@ void QuicCryptoClientStream::DoVerifyProofComplete(
next_state_ = STATE_NONE; next_state_ = STATE_NONE;
UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed", UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
handshake_confirmed()); handshake_confirmed());
CloseConnectionWithDetails(QUIC_PROOF_INVALID, stream_->CloseConnectionWithDetails(
"Proof invalid: " + verify_error_details_); QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
return; return;
} }
...@@ -531,7 +594,7 @@ void QuicCryptoClientStream::DoVerifyProofComplete( ...@@ -531,7 +594,7 @@ void QuicCryptoClientStream::DoVerifyProofComplete(
} }
} }
QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID( QuicAsyncStatus QuicCryptoClientHandshaker::DoGetChannelID(
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
next_state_ = STATE_GET_CHANNEL_ID_COMPLETE; next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
channel_id_key_.reset(); channel_id_key_.reset();
...@@ -553,8 +616,8 @@ QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID( ...@@ -553,8 +616,8 @@ QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID(
case QUIC_FAILURE: case QUIC_FAILURE:
next_state_ = STATE_NONE; next_state_ = STATE_NONE;
delete channel_id_source_callback; delete channel_id_source_callback;
CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE, stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
"Channel ID lookup failed"); "Channel ID lookup failed");
break; break;
case QUIC_SUCCESS: case QUIC_SUCCESS:
delete channel_id_source_callback; delete channel_id_source_callback;
...@@ -563,17 +626,17 @@ QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID( ...@@ -563,17 +626,17 @@ QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID(
return status; return status;
} }
void QuicCryptoClientStream::DoGetChannelIDComplete() { void QuicCryptoClientHandshaker::DoGetChannelIDComplete() {
if (!channel_id_key_.get()) { if (!channel_id_key_.get()) {
next_state_ = STATE_NONE; next_state_ = STATE_NONE;
CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE, stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
"Channel ID lookup failed"); "Channel ID lookup failed");
return; return;
} }
next_state_ = STATE_SEND_CHLO; next_state_ = STATE_SEND_CHLO;
} }
void QuicCryptoClientStream::DoReceiveSHLO( void QuicCryptoClientHandshaker::DoReceiveSHLO(
const CryptoHandshakeMessage* in, const CryptoHandshakeMessage* in,
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
next_state_ = STATE_NONE; next_state_ = STATE_NONE;
...@@ -587,8 +650,8 @@ void QuicCryptoClientStream::DoReceiveSHLO( ...@@ -587,8 +650,8 @@ void QuicCryptoClientStream::DoReceiveSHLO(
// if we received a message encrypted with the INITIAL key. // if we received a message encrypted with the INITIAL key.
if (session()->connection()->alternative_decrypter() == nullptr) { if (session()->connection()->alternative_decrypter() == nullptr) {
// The rejection was sent encrypted! // The rejection was sent encrypted!
CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, stream_->CloseConnectionWithDetails(
"encrypted REJ message"); QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, "encrypted REJ message");
return; return;
} }
next_state_ = STATE_RECV_REJ; next_state_ = STATE_RECV_REJ;
...@@ -596,8 +659,8 @@ void QuicCryptoClientStream::DoReceiveSHLO( ...@@ -596,8 +659,8 @@ void QuicCryptoClientStream::DoReceiveSHLO(
} }
if (in->tag() != kSHLO) { if (in->tag() != kSHLO) {
CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
"Expected SHLO or REJ"); "Expected SHLO or REJ");
return; return;
} }
...@@ -606,8 +669,8 @@ void QuicCryptoClientStream::DoReceiveSHLO( ...@@ -606,8 +669,8 @@ void QuicCryptoClientStream::DoReceiveSHLO(
// if we received a message encrypted with the INITIAL key. // if we received a message encrypted with the INITIAL key.
if (session()->connection()->alternative_decrypter() != nullptr) { if (session()->connection()->alternative_decrypter() != nullptr) {
// The server hello was sent without encryption. // The server hello was sent without encryption.
CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, stream_->CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
"unencrypted SHLO message"); "unencrypted SHLO message");
return; return;
} }
...@@ -619,12 +682,14 @@ void QuicCryptoClientStream::DoReceiveSHLO( ...@@ -619,12 +682,14 @@ void QuicCryptoClientStream::DoReceiveSHLO(
crypto_negotiated_params_, &error_details); crypto_negotiated_params_, &error_details);
if (error != QUIC_NO_ERROR) { if (error != QUIC_NO_ERROR) {
CloseConnectionWithDetails(error, "Server hello invalid: " + error_details); stream_->CloseConnectionWithDetails(
error, "Server hello invalid: " + error_details);
return; return;
} }
error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details); error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
if (error != QUIC_NO_ERROR) { if (error != QUIC_NO_ERROR) {
CloseConnectionWithDetails(error, "Server hello invalid: " + error_details); stream_->CloseConnectionWithDetails(
error, "Server hello invalid: " + error_details);
return; return;
} }
session()->OnConfigNegotiated(); session()->OnConfigNegotiated();
...@@ -646,7 +711,7 @@ void QuicCryptoClientStream::DoReceiveSHLO( ...@@ -646,7 +711,7 @@ void QuicCryptoClientStream::DoReceiveSHLO(
session()->connection()->OnHandshakeComplete(); session()->connection()->OnHandshakeComplete();
} }
void QuicCryptoClientStream::DoInitializeServerConfigUpdate( void QuicCryptoClientHandshaker::DoInitializeServerConfigUpdate(
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
bool update_ignored = false; bool update_ignored = false;
if (!cached->IsEmpty() && !cached->signature().empty()) { if (!cached->IsEmpty() && !cached->signature().empty()) {
...@@ -661,13 +726,13 @@ void QuicCryptoClientStream::DoInitializeServerConfigUpdate( ...@@ -661,13 +726,13 @@ void QuicCryptoClientStream::DoInitializeServerConfigUpdate(
update_ignored); update_ignored);
} }
void QuicCryptoClientStream::SetCachedProofValid( void QuicCryptoClientHandshaker::SetCachedProofValid(
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
cached->SetProofValid(); cached->SetProofValid();
proof_handler_->OnProofValid(*cached); proof_handler_->OnProofValid(*cached);
} }
bool QuicCryptoClientStream::RequiresChannelID( bool QuicCryptoClientHandshaker::RequiresChannelID(
QuicCryptoClientConfig::CachedState* cached) { QuicCryptoClientConfig::CachedState* cached) {
if (server_id_.privacy_mode() == PRIVACY_MODE_ENABLED || if (server_id_.privacy_mode() == PRIVACY_MODE_ENABLED ||
!crypto_config_->channel_id_source()) { !crypto_config_->channel_id_source()) {
......
...@@ -56,6 +56,58 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -56,6 +56,58 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// token. // token.
static const int kMaxClientHellos = 3; static const int kMaxClientHellos = 3;
// QuicCryptoClientStream creates a HandshakerDelegate at construction time
// based on the QuicVersion of the connection. Different HandshakerDelegates
// provide implementations of different crypto handshake protocols. Currently
// QUIC crypto is the only protocol implemented; a future HandshakerDelegate
// will use TLS as the handshake protocol. QuicCryptoClientStream delegates
// all of its public methods to its HandshakerDelegate.
//
// This setup of the crypto stream delegating its implementation to the
// handshaker results in the handshaker reading and writing bytes on the
// crypto stream, instead of the handshaker passing the stream bytes to send.
class QUIC_EXPORT_PRIVATE HandshakerDelegate {
public:
virtual ~HandshakerDelegate() {}
// Performs a crypto handshake with the server. Returns true if the
// connection is still connected.
virtual bool CryptoConnect() = 0;
// num_sent_client_hellos returns the number of client hello messages that
// have been sent. If the handshake has completed then this is one greater
// than the number of round-trips needed for the handshake.
virtual int num_sent_client_hellos() const = 0;
// The number of server config update messages received by the
// client. Does not count update messages that were received prior
// to handshake confirmation.
virtual int num_scup_messages_received() const = 0;
// TODO(nharper): Move this to QuicCryptoClientHandshaker.
virtual void OnHandshakeMessage(const CryptoHandshakeMessage& message) = 0;
// Returns true if a channel ID was sent on this connection.
virtual bool WasChannelIDSent() const = 0;
// Returns true if our ChannelIDSourceCallback was run, which implies the
// ChannelIDSource operated asynchronously. Intended for testing.
virtual bool WasChannelIDSourceCallbackRun() const = 0;
virtual std::string chlo_hash() const = 0;
// Returns true once any encrypter (initial/0RTT or final/1RTT) has been set
// for the connection.
virtual bool encryption_established() const = 0;
// Returns true once the crypto handshake has completed.
virtual bool handshake_confirmed() const = 0;
// Returns the parameters negotiated in the crypto handshake.
virtual const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const = 0;
};
// ProofHandler is an interface that handles callbacks from the crypto // ProofHandler is an interface that handles callbacks from the crypto
// stream when the client has proof verification details of the server. // stream when the client has proof verification details of the server.
class QUIC_EXPORT_PRIVATE ProofHandler { class QUIC_EXPORT_PRIVATE ProofHandler {
...@@ -89,6 +141,12 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -89,6 +141,12 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
int num_scup_messages_received() const override; int num_scup_messages_received() const override;
// From QuicCryptoStream
bool encryption_established() const override;
bool handshake_confirmed() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
// CryptoFramerVisitorInterface implementation // CryptoFramerVisitorInterface implementation
void OnHandshakeMessage(const CryptoHandshakeMessage& message) override; void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
...@@ -99,8 +157,37 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -99,8 +157,37 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// ChannelIDSource operated asynchronously. Intended for testing. // ChannelIDSource operated asynchronously. Intended for testing.
bool WasChannelIDSourceCallbackRun() const; bool WasChannelIDSourceCallbackRun() const;
std::string chlo_hash() const { return chlo_hash_; } std::string chlo_hash() const;
private:
std::unique_ptr<HandshakerDelegate> handshaker_;
DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientStream);
};
// An implementation of QuicCryptoClientStream::HandshakerDelegate which uses
// QUIC crypto as the crypto handshake protocol.
class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
: public QuicCryptoClientStream::HandshakerDelegate {
public:
QuicCryptoClientHandshaker(
const QuicServerId& server_id,
QuicCryptoClientStream* stream,
QuicSession* session,
ProofVerifyContext* verify_context,
QuicCryptoClientConfig* crypto_config,
QuicCryptoClientStream::ProofHandler* proof_handler);
~QuicCryptoClientHandshaker() override;
// From QuicCryptoClientStream::HandshakerDelegate
bool CryptoConnect() override;
int num_sent_client_hellos() const override;
int num_scup_messages_received() const override;
void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
bool WasChannelIDSent() const override;
bool WasChannelIDSourceCallbackRun() const override;
std::string chlo_hash() const override;
bool encryption_established() const override; bool encryption_established() const override;
bool handshake_confirmed() const override; bool handshake_confirmed() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params() const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
...@@ -112,7 +199,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -112,7 +199,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// channel ID lookup when lookup is performed asynchronously. // channel ID lookup when lookup is performed asynchronously.
class ChannelIDSourceCallbackImpl : public ChannelIDSourceCallback { class ChannelIDSourceCallbackImpl : public ChannelIDSourceCallback {
public: public:
explicit ChannelIDSourceCallbackImpl(QuicCryptoClientStream* stream); explicit ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent);
~ChannelIDSourceCallbackImpl() override; ~ChannelIDSourceCallbackImpl() override;
// ChannelIDSourceCallback interface. // ChannelIDSourceCallback interface.
...@@ -123,7 +210,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -123,7 +210,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
void Cancel(); void Cancel();
private: private:
QuicCryptoClientStream* stream_; QuicCryptoClientHandshaker* parent_;
}; };
// ProofVerifierCallbackImpl is passed as the callback method to VerifyProof. // ProofVerifierCallbackImpl is passed as the callback method to VerifyProof.
...@@ -131,7 +218,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -131,7 +218,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// when verification is performed asynchronously. // when verification is performed asynchronously.
class ProofVerifierCallbackImpl : public ProofVerifierCallback { class ProofVerifierCallbackImpl : public ProofVerifierCallback {
public: public:
explicit ProofVerifierCallbackImpl(QuicCryptoClientStream* stream); explicit ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent);
~ProofVerifierCallbackImpl() override; ~ProofVerifierCallbackImpl() override;
// ProofVerifierCallback interface. // ProofVerifierCallback interface.
...@@ -144,7 +231,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -144,7 +231,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
void Cancel(); void Cancel();
private: private:
QuicCryptoClientStream* stream_; QuicCryptoClientHandshaker* parent_;
}; };
friend class test::QuicChromiumClientSessionPeer; friend class test::QuicChromiumClientSessionPeer;
...@@ -216,6 +303,13 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -216,6 +303,13 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// and the client config settings also allow sending a ChannelID. // and the client config settings also allow sending a ChannelID.
bool RequiresChannelID(QuicCryptoClientConfig::CachedState* cached); bool RequiresChannelID(QuicCryptoClientConfig::CachedState* cached);
// Returns the QuicSession that this stream belongs to.
QuicSession* session() const { return session_; }
QuicCryptoClientStream* stream_;
QuicSession* session_;
State next_state_; State next_state_;
// num_client_hellos_ contains the number of client hello messages that this // num_client_hellos_ contains the number of client hello messages that this
// connection has sent. // connection has sent.
...@@ -257,7 +351,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -257,7 +351,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
ProofVerifierCallbackImpl* proof_verify_callback_; ProofVerifierCallbackImpl* proof_verify_callback_;
// proof_handler_ contains the callback object used by a quic client // proof_handler_ contains the callback object used by a quic client
// for proof verification. It is not owned by this class. // for proof verification. It is not owned by this class.
ProofHandler* proof_handler_; QuicCryptoClientStream::ProofHandler* proof_handler_;
// These members are used to store the result of an asynchronous proof // These members are used to store the result of an asynchronous proof
// verification. These members must not be used after // verification. These members must not be used after
...@@ -281,7 +375,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream ...@@ -281,7 +375,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
crypto_negotiated_params_; crypto_negotiated_params_;
DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientStream); DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientHandshaker);
}; };
} // namespace net } // namespace net
......
...@@ -314,6 +314,14 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) { ...@@ -314,6 +314,14 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
/*offset=*/0, data->AsStringPiece())); /*offset=*/0, data->AsStringPiece()));
} }
TEST_F(QuicCryptoClientStreamTest, NoChannelID) {
crypto_config_.SetChannelIDSource(nullptr);
CompleteCryptoHandshake();
EXPECT_FALSE(stream()->WasChannelIDSent());
EXPECT_FALSE(stream()->WasChannelIDSourceCallbackRun());
}
TEST_F(QuicCryptoClientStreamTest, TokenBindingNegotiation) { TEST_F(QuicCryptoClientStreamTest, TokenBindingNegotiation) {
server_options_.token_binding_params = QuicTagVector{kTB10, kP256}; server_options_.token_binding_params = QuicTagVector{kTB10, kP256};
crypto_config_.tb_key_params = QuicTagVector{kTB10}; crypto_config_.tb_key_params = QuicTagVector{kTB10};
......
...@@ -24,14 +24,14 @@ using std::string; ...@@ -24,14 +24,14 @@ using std::string;
namespace net { namespace net {
class QuicCryptoServerStream::ProcessClientHelloCallback class QuicCryptoServerHandshaker::ProcessClientHelloCallback
: public ProcessClientHelloResultCallback { : public ProcessClientHelloResultCallback {
public: public:
ProcessClientHelloCallback( ProcessClientHelloCallback(
QuicCryptoServerStream* stream, QuicCryptoServerHandshaker* parent,
const QuicReferenceCountedPointer< const QuicReferenceCountedPointer<
ValidateClientHelloResultCallback::Result>& result) ValidateClientHelloResultCallback::Result>& result)
: stream_(stream), result_(result) {} : parent_(parent), result_(result) {}
void Run(QuicErrorCode error, void Run(QuicErrorCode error,
const string& error_details, const string& error_details,
...@@ -39,19 +39,19 @@ class QuicCryptoServerStream::ProcessClientHelloCallback ...@@ -39,19 +39,19 @@ class QuicCryptoServerStream::ProcessClientHelloCallback
std::unique_ptr<DiversificationNonce> diversification_nonce, std::unique_ptr<DiversificationNonce> diversification_nonce,
std::unique_ptr<net::ProofSource::Details> proof_source_details) std::unique_ptr<net::ProofSource::Details> proof_source_details)
override { override {
if (stream_ == nullptr) { if (parent_ == nullptr) {
return; return;
} }
stream_->FinishProcessingHandshakeMessageAfterProcessClientHello( parent_->FinishProcessingHandshakeMessageAfterProcessClientHello(
*result_, error, error_details, std::move(message), *result_, error, error_details, std::move(message),
std::move(diversification_nonce), std::move(proof_source_details)); std::move(diversification_nonce), std::move(proof_source_details));
} }
void Cancel() { stream_ = nullptr; } void Cancel() { parent_ = nullptr; }
private: private:
QuicCryptoServerStream* stream_; QuicCryptoServerHandshaker* parent_;
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
result_; result_;
}; };
...@@ -83,7 +83,106 @@ QuicCryptoServerStream::QuicCryptoServerStream( ...@@ -83,7 +83,106 @@ QuicCryptoServerStream::QuicCryptoServerStream(
bool use_stateless_rejects_if_peer_supported, bool use_stateless_rejects_if_peer_supported,
QuicSession* session, QuicSession* session,
Helper* helper) Helper* helper)
: QuicCryptoServerStreamBase(session), : QuicCryptoServerStreamBase(session) {
DCHECK_EQ(Perspective::IS_SERVER, session->connection()->perspective());
handshaker_.reset(new QuicCryptoServerHandshaker(
crypto_config, this, compressed_certs_cache,
use_stateless_rejects_if_peer_supported, session, helper));
}
QuicCryptoServerStream::~QuicCryptoServerStream() {}
void QuicCryptoServerStream::CancelOutstandingCallbacks() {
handshaker()->CancelOutstandingCallbacks();
}
void QuicCryptoServerStream::OnHandshakeMessage(
const CryptoHandshakeMessage& message) {
QuicCryptoServerStreamBase::OnHandshakeMessage(message);
handshaker()->OnHandshakeMessage(message);
}
bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
string* output) const {
return handshaker()->GetBase64SHA256ClientChannelID(output);
}
void QuicCryptoServerStream::SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) {
handshaker()->SendServerConfigUpdate(cached_network_params);
}
uint8_t QuicCryptoServerStream::NumHandshakeMessages() const {
return handshaker()->NumHandshakeMessages();
}
uint8_t QuicCryptoServerStream::NumHandshakeMessagesWithServerNonces() const {
return handshaker()->NumHandshakeMessagesWithServerNonces();
}
int QuicCryptoServerStream::NumServerConfigUpdateMessagesSent() const {
return handshaker()->NumServerConfigUpdateMessagesSent();
}
const CachedNetworkParameters*
QuicCryptoServerStream::PreviousCachedNetworkParams() const {
return handshaker()->PreviousCachedNetworkParams();
}
bool QuicCryptoServerStream::UseStatelessRejectsIfPeerSupported() const {
return handshaker()->UseStatelessRejectsIfPeerSupported();
}
bool QuicCryptoServerStream::PeerSupportsStatelessRejects() const {
return handshaker()->PeerSupportsStatelessRejects();
}
bool QuicCryptoServerStream::ZeroRttAttempted() const {
return handshaker()->ZeroRttAttempted();
}
void QuicCryptoServerStream::SetPeerSupportsStatelessRejects(
bool peer_supports_stateless_rejects) {
handshaker()->SetPeerSupportsStatelessRejects(
peer_supports_stateless_rejects);
}
void QuicCryptoServerStream::SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) {
handshaker()->SetPreviousCachedNetworkParams(cached_network_params);
}
bool QuicCryptoServerStream::ShouldSendExpectCTHeader() const {
return handshaker()->ShouldSendExpectCTHeader();
}
bool QuicCryptoServerStream::encryption_established() const {
return handshaker()->encryption_established();
}
bool QuicCryptoServerStream::handshake_confirmed() const {
return handshaker()->handshake_confirmed();
}
const QuicCryptoNegotiatedParameters&
QuicCryptoServerStream::crypto_negotiated_params() const {
return handshaker()->crypto_negotiated_params();
}
QuicCryptoServerStream::HandshakerDelegate* QuicCryptoServerStream::handshaker()
const {
return handshaker_.get();
}
QuicCryptoServerHandshaker::QuicCryptoServerHandshaker(
const QuicCryptoServerConfig* crypto_config,
QuicCryptoServerStream* stream,
QuicCompressedCertsCache* compressed_certs_cache,
bool use_stateless_rejects_if_peer_supported,
QuicSession* session,
QuicCryptoServerStream::Helper* helper)
: stream_(stream),
session_(session),
crypto_config_(crypto_config), crypto_config_(crypto_config),
compressed_certs_cache_(compressed_certs_cache), compressed_certs_cache_(compressed_certs_cache),
signed_config_(new QuicSignedServerConfig), signed_config_(new QuicSignedServerConfig),
...@@ -101,15 +200,13 @@ QuicCryptoServerStream::QuicCryptoServerStream( ...@@ -101,15 +200,13 @@ QuicCryptoServerStream::QuicCryptoServerStream(
process_client_hello_cb_(nullptr), process_client_hello_cb_(nullptr),
encryption_established_(false), encryption_established_(false),
handshake_confirmed_(false), handshake_confirmed_(false),
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) { crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
DCHECK_EQ(Perspective::IS_SERVER, session->connection()->perspective());
}
QuicCryptoServerStream::~QuicCryptoServerStream() { QuicCryptoServerHandshaker::~QuicCryptoServerHandshaker() {
CancelOutstandingCallbacks(); CancelOutstandingCallbacks();
} }
void QuicCryptoServerStream::CancelOutstandingCallbacks() { void QuicCryptoServerHandshaker::CancelOutstandingCallbacks() {
// Detach from the validation callback. Calling this multiple times is safe. // Detach from the validation callback. Calling this multiple times is safe.
if (validate_client_hello_cb_ != nullptr) { if (validate_client_hello_cb_ != nullptr) {
validate_client_hello_cb_->Cancel(); validate_client_hello_cb_->Cancel();
...@@ -125,22 +222,22 @@ void QuicCryptoServerStream::CancelOutstandingCallbacks() { ...@@ -125,22 +222,22 @@ void QuicCryptoServerStream::CancelOutstandingCallbacks() {
} }
} }
void QuicCryptoServerStream::OnHandshakeMessage( void QuicCryptoServerHandshaker::OnHandshakeMessage(
const CryptoHandshakeMessage& message) { const CryptoHandshakeMessage& message) {
QuicCryptoServerStreamBase::OnHandshakeMessage(message);
++num_handshake_messages_; ++num_handshake_messages_;
chlo_packet_size_ = session()->connection()->GetCurrentPacket().length(); chlo_packet_size_ = session()->connection()->GetCurrentPacket().length();
// Do not process handshake messages after the handshake is confirmed. // Do not process handshake messages after the handshake is confirmed.
if (handshake_confirmed_) { if (handshake_confirmed_) {
CloseConnectionWithDetails(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, stream_->CloseConnectionWithDetails(
"Unexpected handshake message from client"); QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
"Unexpected handshake message from client");
return; return;
} }
if (message.tag() != kCHLO) { if (message.tag() != kCHLO) {
CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
"Handshake packet not CHLO"); "Handshake packet not CHLO");
return; return;
} }
...@@ -149,7 +246,7 @@ void QuicCryptoServerStream::OnHandshakeMessage( ...@@ -149,7 +246,7 @@ void QuicCryptoServerStream::OnHandshakeMessage(
// Already processing some other handshake message. The protocol // Already processing some other handshake message. The protocol
// does not allow for clients to send multiple handshake messages // does not allow for clients to send multiple handshake messages
// before the server has a chance to respond. // before the server has a chance to respond.
CloseConnectionWithDetails( stream_->CloseConnectionWithDetails(
QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO, QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO,
"Unexpected handshake message while processing CHLO"); "Unexpected handshake message while processing CHLO");
return; return;
...@@ -168,7 +265,7 @@ void QuicCryptoServerStream::OnHandshakeMessage( ...@@ -168,7 +265,7 @@ void QuicCryptoServerStream::OnHandshakeMessage(
session()->connection()->clock(), signed_config_, std::move(cb)); session()->connection()->clock(), signed_config_, std::move(cb));
} }
void QuicCryptoServerStream::FinishProcessingHandshakeMessage( void QuicCryptoServerHandshaker::FinishProcessingHandshakeMessage(
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
result, result,
std::unique_ptr<ProofSource::Details> details) { std::unique_ptr<ProofSource::Details> details) {
...@@ -180,7 +277,8 @@ void QuicCryptoServerStream::FinishProcessingHandshakeMessage( ...@@ -180,7 +277,8 @@ void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
validate_client_hello_cb_ = nullptr; validate_client_hello_cb_ = nullptr;
if (use_stateless_rejects_if_peer_supported_) { if (use_stateless_rejects_if_peer_supported_) {
peer_supports_stateless_rejects_ = DoesPeerSupportStatelessRejects(message); peer_supports_stateless_rejects_ =
QuicCryptoServerStreamBase::DoesPeerSupportStatelessRejects(message);
} }
std::unique_ptr<ProcessClientHelloCallback> cb( std::unique_ptr<ProcessClientHelloCallback> cb(
...@@ -189,7 +287,7 @@ void QuicCryptoServerStream::FinishProcessingHandshakeMessage( ...@@ -189,7 +287,7 @@ void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
ProcessClientHello(result, std::move(details), std::move(cb)); ProcessClientHello(result, std::move(details), std::move(cb));
} }
void QuicCryptoServerStream:: void QuicCryptoServerHandshaker::
FinishProcessingHandshakeMessageAfterProcessClientHello( FinishProcessingHandshakeMessageAfterProcessClientHello(
const ValidateClientHelloResultCallback::Result& result, const ValidateClientHelloResultCallback::Result& result,
QuicErrorCode error, QuicErrorCode error,
...@@ -204,7 +302,7 @@ void QuicCryptoServerStream:: ...@@ -204,7 +302,7 @@ void QuicCryptoServerStream::
const CryptoHandshakeMessage& message = result.client_hello; const CryptoHandshakeMessage& message = result.client_hello;
if (error != QUIC_NO_ERROR) { if (error != QUIC_NO_ERROR) {
CloseConnectionWithDetails(error, error_details); stream_->CloseConnectionWithDetails(error, error_details);
return; return;
} }
...@@ -217,7 +315,7 @@ void QuicCryptoServerStream:: ...@@ -217,7 +315,7 @@ void QuicCryptoServerStream::
// retransmitted. // retransmitted.
session()->connection()->EnableSavingCryptoPackets(); session()->connection()->EnableSavingCryptoPackets();
} }
SendHandshakeMessage(*reply); stream_->SendHandshakeMessage(*reply);
if (reply->tag() == kSREJ) { if (reply->tag() == kSREJ) {
DCHECK(use_stateless_rejects_if_peer_supported_); DCHECK(use_stateless_rejects_if_peer_supported_);
...@@ -242,7 +340,7 @@ void QuicCryptoServerStream:: ...@@ -242,7 +340,7 @@ void QuicCryptoServerStream::
const QuicErrorCode process_error = const QuicErrorCode process_error =
config->ProcessPeerHello(message, CLIENT, &process_error_details); config->ProcessPeerHello(message, CLIENT, &process_error_details);
if (process_error != QUIC_NO_ERROR) { if (process_error != QUIC_NO_ERROR) {
CloseConnectionWithDetails(process_error, process_error_details); stream_->CloseConnectionWithDetails(process_error, process_error_details);
return; return;
} }
...@@ -266,7 +364,7 @@ void QuicCryptoServerStream:: ...@@ -266,7 +364,7 @@ void QuicCryptoServerStream::
crypto_negotiated_params_->initial_crypters.decrypter.release()); crypto_negotiated_params_->initial_crypters.decrypter.release());
session()->connection()->SetDiversificationNonce(*diversification_nonce); session()->connection()->SetDiversificationNonce(*diversification_nonce);
SendHandshakeMessage(*reply); stream_->SendHandshakeMessage(*reply);
session()->connection()->SetEncrypter( session()->connection()->SetEncrypter(
ENCRYPTION_FORWARD_SECURE, ENCRYPTION_FORWARD_SECURE,
...@@ -283,7 +381,7 @@ void QuicCryptoServerStream:: ...@@ -283,7 +381,7 @@ void QuicCryptoServerStream::
session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
} }
void QuicCryptoServerStream::SendServerConfigUpdate( void QuicCryptoServerHandshaker::SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) { const CachedNetworkParameters* cached_network_params) {
if (!handshake_confirmed_) { if (!handshake_confirmed_) {
return; return;
...@@ -311,16 +409,16 @@ void QuicCryptoServerStream::SendServerConfigUpdate( ...@@ -311,16 +409,16 @@ void QuicCryptoServerStream::SendServerConfigUpdate(
std::move(cb)); std::move(cb));
} }
QuicCryptoServerStream::SendServerConfigUpdateCallback:: QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::
SendServerConfigUpdateCallback(QuicCryptoServerStream* parent) SendServerConfigUpdateCallback(QuicCryptoServerHandshaker* parent)
: parent_(parent) {} : parent_(parent) {}
void QuicCryptoServerStream::SendServerConfigUpdateCallback::Cancel() { void QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::Cancel() {
parent_ = nullptr; parent_ = nullptr;
} }
// From BuildServerConfigUpdateMessageResultCallback // From BuildServerConfigUpdateMessageResultCallback
void QuicCryptoServerStream::SendServerConfigUpdateCallback::Run( void QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::Run(
bool ok, bool ok,
const CryptoHandshakeMessage& message) { const CryptoHandshakeMessage& message) {
if (parent_ == nullptr) { if (parent_ == nullptr) {
...@@ -329,7 +427,7 @@ void QuicCryptoServerStream::SendServerConfigUpdateCallback::Run( ...@@ -329,7 +427,7 @@ void QuicCryptoServerStream::SendServerConfigUpdateCallback::Run(
parent_->FinishSendServerConfigUpdate(ok, message); parent_->FinishSendServerConfigUpdate(ok, message);
} }
void QuicCryptoServerStream::FinishSendServerConfigUpdate( void QuicCryptoServerHandshaker::FinishSendServerConfigUpdate(
bool ok, bool ok,
const CryptoHandshakeMessage& message) { const CryptoHandshakeMessage& message) {
// Clear the callback that got us here. // Clear the callback that got us here.
...@@ -344,53 +442,58 @@ void QuicCryptoServerStream::FinishSendServerConfigUpdate( ...@@ -344,53 +442,58 @@ void QuicCryptoServerStream::FinishSendServerConfigUpdate(
QUIC_DVLOG(1) << "Server: Sending server config update: " QUIC_DVLOG(1) << "Server: Sending server config update: "
<< message.DebugString(Perspective::IS_SERVER); << message.DebugString(Perspective::IS_SERVER);
const QuicData& data = message.GetSerialized(Perspective::IS_SERVER); const QuicData& data = message.GetSerialized(Perspective::IS_SERVER);
WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false, stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false,
nullptr); nullptr);
++num_server_config_update_messages_sent_; ++num_server_config_update_messages_sent_;
} }
uint8_t QuicCryptoServerStream::NumHandshakeMessages() const { uint8_t QuicCryptoServerHandshaker::NumHandshakeMessages() const {
return num_handshake_messages_; return num_handshake_messages_;
} }
uint8_t QuicCryptoServerStream::NumHandshakeMessagesWithServerNonces() const { uint8_t QuicCryptoServerHandshaker::NumHandshakeMessagesWithServerNonces()
const {
return num_handshake_messages_with_server_nonces_; return num_handshake_messages_with_server_nonces_;
} }
int QuicCryptoServerStream::NumServerConfigUpdateMessagesSent() const { int QuicCryptoServerHandshaker::NumServerConfigUpdateMessagesSent() const {
return num_server_config_update_messages_sent_; return num_server_config_update_messages_sent_;
} }
const CachedNetworkParameters* const CachedNetworkParameters*
QuicCryptoServerStream::PreviousCachedNetworkParams() const { QuicCryptoServerHandshaker::PreviousCachedNetworkParams() const {
return previous_cached_network_params_.get(); return previous_cached_network_params_.get();
} }
bool QuicCryptoServerStream::UseStatelessRejectsIfPeerSupported() const { bool QuicCryptoServerHandshaker::UseStatelessRejectsIfPeerSupported() const {
return use_stateless_rejects_if_peer_supported_; return use_stateless_rejects_if_peer_supported_;
} }
bool QuicCryptoServerStream::PeerSupportsStatelessRejects() const { bool QuicCryptoServerHandshaker::PeerSupportsStatelessRejects() const {
return peer_supports_stateless_rejects_; return peer_supports_stateless_rejects_;
} }
bool QuicCryptoServerStream::ZeroRttAttempted() const { bool QuicCryptoServerHandshaker::ZeroRttAttempted() const {
return zero_rtt_attempted_; return zero_rtt_attempted_;
} }
void QuicCryptoServerStream::SetPeerSupportsStatelessRejects( void QuicCryptoServerHandshaker::SetPeerSupportsStatelessRejects(
bool peer_supports_stateless_rejects) { bool peer_supports_stateless_rejects) {
peer_supports_stateless_rejects_ = peer_supports_stateless_rejects; peer_supports_stateless_rejects_ = peer_supports_stateless_rejects;
} }
void QuicCryptoServerStream::SetPreviousCachedNetworkParams( void QuicCryptoServerHandshaker::SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) { CachedNetworkParameters cached_network_params) {
previous_cached_network_params_.reset( previous_cached_network_params_.reset(
new CachedNetworkParameters(cached_network_params)); new CachedNetworkParameters(cached_network_params));
} }
bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID( bool QuicCryptoServerHandshaker::ShouldSendExpectCTHeader() const {
return signed_config_->proof.send_expect_ct_header;
}
bool QuicCryptoServerHandshaker::GetBase64SHA256ClientChannelID(
string* output) const { string* output) const {
if (!encryption_established() || if (!encryption_established() ||
crypto_negotiated_params_->channel_id.empty()) { crypto_negotiated_params_->channel_id.empty()) {
...@@ -406,20 +509,20 @@ bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID( ...@@ -406,20 +509,20 @@ bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
return true; return true;
} }
bool QuicCryptoServerStream::encryption_established() const { bool QuicCryptoServerHandshaker::encryption_established() const {
return encryption_established_; return encryption_established_;
} }
bool QuicCryptoServerStream::handshake_confirmed() const { bool QuicCryptoServerHandshaker::handshake_confirmed() const {
return handshake_confirmed_; return handshake_confirmed_;
} }
const QuicCryptoNegotiatedParameters& const QuicCryptoNegotiatedParameters&
QuicCryptoServerStream::crypto_negotiated_params() const { QuicCryptoServerHandshaker::crypto_negotiated_params() const {
return *crypto_negotiated_params_; return *crypto_negotiated_params_;
} }
void QuicCryptoServerStream::ProcessClientHello( void QuicCryptoServerHandshaker::ProcessClientHello(
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
result, result,
std::unique_ptr<ProofSource::Details> proof_source_details, std::unique_ptr<ProofSource::Details> proof_source_details,
...@@ -466,17 +569,18 @@ void QuicCryptoServerStream::ProcessClientHello( ...@@ -466,17 +569,18 @@ void QuicCryptoServerStream::ProcessClientHello(
chlo_packet_size_, std::move(done_cb)); chlo_packet_size_, std::move(done_cb));
} }
void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) {} void QuicCryptoServerHandshaker::OverrideQuicConfigDefaults(
QuicConfig* config) {}
QuicCryptoServerStream::ValidateCallback::ValidateCallback( QuicCryptoServerHandshaker::ValidateCallback::ValidateCallback(
QuicCryptoServerStream* parent) QuicCryptoServerHandshaker* parent)
: parent_(parent) {} : parent_(parent) {}
void QuicCryptoServerStream::ValidateCallback::Cancel() { void QuicCryptoServerHandshaker::ValidateCallback::Cancel() {
parent_ = nullptr; parent_ = nullptr;
} }
void QuicCryptoServerStream::ValidateCallback::Run( void QuicCryptoServerHandshaker::ValidateCallback::Run(
QuicReferenceCountedPointer<Result> result, QuicReferenceCountedPointer<Result> result,
std::unique_ptr<ProofSource::Details> details) { std::unique_ptr<ProofSource::Details> details) {
if (parent_ != nullptr) { if (parent_ != nullptr) {
...@@ -485,7 +589,7 @@ void QuicCryptoServerStream::ValidateCallback::Run( ...@@ -485,7 +589,7 @@ void QuicCryptoServerStream::ValidateCallback::Run(
} }
} }
QuicConnectionId QuicCryptoServerStream::GenerateConnectionIdForReject( QuicConnectionId QuicCryptoServerHandshaker::GenerateConnectionIdForReject(
bool use_stateless_rejects) { bool use_stateless_rejects) {
if (!use_stateless_rejects) { if (!use_stateless_rejects) {
return 0; return 0;
...@@ -494,7 +598,7 @@ QuicConnectionId QuicCryptoServerStream::GenerateConnectionIdForReject( ...@@ -494,7 +598,7 @@ QuicConnectionId QuicCryptoServerStream::GenerateConnectionIdForReject(
session()->connection()->connection_id()); session()->connection()->connection_id());
} }
const QuicSocketAddress QuicCryptoServerStream::GetClientAddress() { const QuicSocketAddress QuicCryptoServerHandshaker::GetClientAddress() {
return session()->connection()->peer_address(); return session()->connection()->peer_address();
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "net/quic/core/proto/source_address_token.pb.h" #include "net/quic/core/proto/source_address_token.pb.h"
#include "net/quic/core/quic_config.h" #include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_crypto_stream.h" #include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/platform/api/quic_export.h" #include "net/quic/platform/api/quic_export.h"
namespace net { namespace net {
...@@ -73,6 +74,69 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream { ...@@ -73,6 +74,69 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
class QUIC_EXPORT_PRIVATE QuicCryptoServerStream class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
: public QuicCryptoServerStreamBase { : public QuicCryptoServerStreamBase {
public: public:
// QuicCryptoServerStream creates a HandshakerDelegate at construction time
// based on the QuicVersion of the connection. Different HandshakerDelegates
// provide implementations of different crypto handshake protocols. Currently
// QUIC crypto is the only protocol implemented; a future HandshakerDelegate
// will use TLS as the handshake protocol. QuicCryptoServerStream delegates
// all of its public methods to its HandshakerDelegate.
//
// This setup of the crypto stream delegating its implementation to the
// handshaker results in the handshaker reading and writing bytes on the
// crypto stream, instead of the handshake rpassing the stream bytes to send.
class QUIC_EXPORT_PRIVATE HandshakerDelegate {
public:
virtual ~HandshakerDelegate() {}
// Cancel any outstanding callbacks, such as asynchronous validation of
// client hello.
virtual void CancelOutstandingCallbacks() = 0;
// TODO(nharper): Move this to QuicCryptoServerHandshaker.
virtual void OnHandshakeMessage(const CryptoHandshakeMessage& message) = 0;
// GetBase64SHA256ClientChannelID sets |*output| to the base64 encoded,
// SHA-256 hash of the client's ChannelID key and returns true, if the
// client presented a ChannelID. Otherwise it returns false.
virtual bool GetBase64SHA256ClientChannelID(std::string* output) const = 0;
// Sends the latest server config and source-address token to the client.
virtual void SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) = 0;
// These are all accessors and setters to their respective counters.
virtual uint8_t NumHandshakeMessages() const = 0;
virtual uint8_t NumHandshakeMessagesWithServerNonces() const = 0;
virtual int NumServerConfigUpdateMessagesSent() const = 0;
virtual const CachedNetworkParameters* PreviousCachedNetworkParams()
const = 0;
virtual bool UseStatelessRejectsIfPeerSupported() const = 0;
virtual bool PeerSupportsStatelessRejects() const = 0;
virtual bool ZeroRttAttempted() const = 0;
virtual void SetPeerSupportsStatelessRejects(
bool peer_supports_stateless_rejects) = 0;
virtual void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) = 0;
// NOTE: Indicating that the Expect-CT header should be sent here presents a
// layering violation to some extent. The Expect-CT header only applies to
// HTTP connections, while this class can be used for non-HTTP applications.
// However, it is exposed here because that is the only place where the
// configuration for the certificate used in the connection is accessible.
virtual bool ShouldSendExpectCTHeader() const = 0;
// Returns true once any encrypter (initial/0RTT or final/1RTT) has been set
// for the connection.
virtual bool encryption_established() const = 0;
// Returns true once the crypto handshake has completed.
virtual bool handshake_confirmed() const = 0;
// Returns the parameters negotiated in the crypto handshake.
virtual const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const = 0;
};
class Helper { class Helper {
public: public:
virtual ~Helper() {} virtual ~Helper() {}
...@@ -124,9 +188,56 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream ...@@ -124,9 +188,56 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
// HTTP connections, while this class can be used for non-HTTP applications. // HTTP connections, while this class can be used for non-HTTP applications.
// However, it is exposed here because that is the only place where the // However, it is exposed here because that is the only place where the
// configuration for the certificate used in the connection is accessible. // configuration for the certificate used in the connection is accessible.
bool ShouldSendExpectCTHeader() const { bool ShouldSendExpectCTHeader() const;
return signed_config_->proof.send_expect_ct_header;
} bool encryption_established() const override;
bool handshake_confirmed() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
protected:
// Provided so that subclasses can provide their own handshaker.
virtual HandshakerDelegate* handshaker() const;
private:
std::unique_ptr<HandshakerDelegate> handshaker_;
DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerStream);
};
class QUIC_EXPORT_PRIVATE QuicCryptoServerHandshaker
: public QuicCryptoServerStream::HandshakerDelegate {
public:
// |crypto_config| must outlive the stream.
// |session| must outlive the stream.
// |helper| must outlive the stream.
QuicCryptoServerHandshaker(const QuicCryptoServerConfig* crypto_config,
QuicCryptoServerStream* stream,
QuicCompressedCertsCache* compressed_certs_cache,
bool use_stateless_rejects_if_peer_supported,
QuicSession* session,
QuicCryptoServerStream::Helper* helper);
~QuicCryptoServerHandshaker() override;
// From HandshakerDelegate
void CancelOutstandingCallbacks() override;
void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
bool GetBase64SHA256ClientChannelID(std::string* output) const override;
void SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) override;
uint8_t NumHandshakeMessages() const override;
uint8_t NumHandshakeMessagesWithServerNonces() const override;
int NumServerConfigUpdateMessagesSent() const override;
const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
bool UseStatelessRejectsIfPeerSupported() const override;
bool PeerSupportsStatelessRejects() const override;
bool ZeroRttAttempted() const override;
void SetPeerSupportsStatelessRejects(
bool peer_supports_stateless_rejects) override;
void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) override;
bool ShouldSendExpectCTHeader() const override;
bool encryption_established() const override; bool encryption_established() const override;
bool handshake_confirmed() const override; bool handshake_confirmed() const override;
...@@ -152,7 +263,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream ...@@ -152,7 +263,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
class ValidateCallback : public ValidateClientHelloResultCallback { class ValidateCallback : public ValidateClientHelloResultCallback {
public: public:
explicit ValidateCallback(QuicCryptoServerStream* parent); explicit ValidateCallback(QuicCryptoServerHandshaker* parent);
// To allow the parent to detach itself from the callback before deletion. // To allow the parent to detach itself from the callback before deletion.
void Cancel(); void Cancel();
...@@ -161,7 +272,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream ...@@ -161,7 +272,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
std::unique_ptr<ProofSource::Details> details) override; std::unique_ptr<ProofSource::Details> details) override;
private: private:
QuicCryptoServerStream* parent_; QuicCryptoServerHandshaker* parent_;
DISALLOW_COPY_AND_ASSIGN(ValidateCallback); DISALLOW_COPY_AND_ASSIGN(ValidateCallback);
}; };
...@@ -169,7 +280,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream ...@@ -169,7 +280,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
class SendServerConfigUpdateCallback class SendServerConfigUpdateCallback
: public BuildServerConfigUpdateMessageResultCallback { : public BuildServerConfigUpdateMessageResultCallback {
public: public:
explicit SendServerConfigUpdateCallback(QuicCryptoServerStream* parent); explicit SendServerConfigUpdateCallback(QuicCryptoServerHandshaker* parent);
SendServerConfigUpdateCallback(const SendServerConfigUpdateCallback&) = SendServerConfigUpdateCallback(const SendServerConfigUpdateCallback&) =
delete; delete;
void operator=(const SendServerConfigUpdateCallback&) = delete; void operator=(const SendServerConfigUpdateCallback&) = delete;
...@@ -181,7 +292,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream ...@@ -181,7 +292,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
void Run(bool ok, const CryptoHandshakeMessage& message) override; void Run(bool ok, const CryptoHandshakeMessage& message) override;
private: private:
QuicCryptoServerStream* parent_; QuicCryptoServerHandshaker* parent_;
}; };
// Invoked by ValidateCallback::RunImpl once initial validation of // Invoked by ValidateCallback::RunImpl once initial validation of
...@@ -216,6 +327,16 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream ...@@ -216,6 +327,16 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
// if |use_stateless_rejects| is true. Returns 0 otherwise. // if |use_stateless_rejects| is true. Returns 0 otherwise.
QuicConnectionId GenerateConnectionIdForReject(bool use_stateless_rejects); QuicConnectionId GenerateConnectionIdForReject(bool use_stateless_rejects);
// Returns the QuicSession that this stream belongs to.
QuicSession* session() const { return session_; }
// Returns the QuicVersion of the connection.
QuicVersion version() const { return session_->connection()->version(); }
QuicCryptoServerStream* stream_;
QuicSession* session_;
// crypto_config_ contains crypto parameters for the handshake. // crypto_config_ contains crypto parameters for the handshake.
const QuicCryptoServerConfig* crypto_config_; const QuicCryptoServerConfig* crypto_config_;
...@@ -232,7 +353,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream ...@@ -232,7 +353,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
std::string chlo_hash_; std::string chlo_hash_;
// Pointer to the helper for this crypto stream. Must outlive this stream. // Pointer to the helper for this crypto stream. Must outlive this stream.
Helper* helper_; QuicCryptoServerStream::Helper* helper_;
// Number of handshake messages received by this stream. // Number of handshake messages received by this stream.
uint8_t num_handshake_messages_; uint8_t num_handshake_messages_;
...@@ -295,7 +416,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream ...@@ -295,7 +416,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
crypto_negotiated_params_; crypto_negotiated_params_;
DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerStream); DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerHandshaker);
}; };
} // namespace net } // namespace net
......
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