Commit 8651d314 authored by Renjie Tang's avatar Renjie Tang Committed by Commit Bot

In QUIC with TLS, when 0-RTT keys are available and the session doesn't...

In QUIC with TLS, when 0-RTT keys are available and the session doesn't require confirmation, run crypto callback to notify QuicStreamFactory that the session can be activated.

Bug: 1117331
Change-Id: I9863bf2cc03250393f67af2420313dfbf585ffad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2363629Reviewed-by: default avatarDavid Schinazi <dschinazi@chromium.org>
Commit-Queue: David Schinazi <dschinazi@chromium.org>
Auto-Submit: Renjie Tang <renjietang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#799347}
parent 5647dd6d
......@@ -154,6 +154,17 @@ bool MockCryptoClientStream::CryptoConnect() {
break;
}
case ASYNC_ZERO_RTT: {
DCHECK(session()->version().UsesTls());
handshake_confirmed_ = false;
FillCryptoParams();
if (proof_verify_details_) {
reinterpret_cast<QuicSpdyClientSessionBase*>(session())
->OnProofVerifyDetailsAvailable(*proof_verify_details_);
}
break;
}
case CONFIRM_HANDSHAKE: {
encryption_established_ = true;
handshake_confirmed_ = true;
......@@ -245,6 +256,23 @@ CryptoMessageParser* MockCryptoClientStream::crypto_message_parser() {
// DCHECKs within the handshaker from failing.
void MockCryptoClientStream::OnOneRttPacketAcknowledged() {}
void MockCryptoClientStream::NotifySessionZeroRttComplete() {
DCHECK(session()->version().UsesTls());
encryption_established_ = true;
handshake_confirmed_ = false;
session()->connection()->InstallDecrypter(
ENCRYPTION_ZERO_RTT,
std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
if (session()->version().UsesHttp3()) {
SetConfigNegotiated();
}
session()->OnNewEncryptionKeyAvailable(
ENCRYPTION_ZERO_RTT,
std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
}
void MockCryptoClientStream::NotifySessionOneRttKeyAvailable() {
encryption_established_ = true;
handshake_confirmed_ = true;
......
......@@ -33,6 +33,11 @@ class MockCryptoClientStream : public quic::QuicCryptoClientStream,
// not confirm the handshake.
ZERO_RTT,
// ASYNC_ZERO_RTT indicates that 0-RTT setup will be completed
// asynchronously. This is possible in TLS. Tests need to call
// NotifySessionZeroRttComplete() to setup 0-RTT encryption.
ASYNC_ZERO_RTT,
// COLD_START indicates that CryptoConnect will neither establish encryption
// nor confirm the handshake.
COLD_START,
......@@ -71,6 +76,9 @@ class MockCryptoClientStream : public quic::QuicCryptoClientStream,
// Notify session that 1-RTT key is available.
void NotifySessionOneRttKeyAvailable();
// Notify session that 0-RTT setup is complete.
void NotifySessionZeroRttComplete();
static quic::CryptoHandshakeMessage GetDummyCHLOMessage();
protected:
......
......@@ -1584,7 +1584,7 @@ void QuicChromiumClientSession::SetDefaultEncryptionLevel(
if (!callback_.is_null() &&
(!require_confirmation_ || level == quic::ENCRYPTION_FORWARD_SECURE ||
level == quic::ENCRYPTION_ZERO_RTT)) {
// TODO(rtenneti): Currently for all CryptoHandshakeEvent events, callback_
// Currently for all CryptoHandshakeEvent events, callback_
// could be called because there are no error events in CryptoHandshakeEvent
// enum. If error events are added to CryptoHandshakeEvent, then the
// following code needs to changed.
......@@ -1601,7 +1601,7 @@ void QuicChromiumClientSession::SetDefaultEncryptionLevel(
void QuicChromiumClientSession::OnOneRttKeysAvailable() {
if (!callback_.is_null()) {
// TODO(rtenneti): Currently for all CryptoHandshakeEvent events, callback_
// Currently for all CryptoHandshakeEvent events, callback_
// could be called because there are no error events in CryptoHandshakeEvent
// enum. If error events are added to CryptoHandshakeEvent, then the
// following code needs to changed.
......@@ -1626,6 +1626,15 @@ void QuicChromiumClientSession::OnNewEncryptionKeyAvailable(
if (level == quic::ENCRYPTION_ZERO_RTT)
attempted_zero_rtt_ = true;
QuicSpdySession::OnNewEncryptionKeyAvailable(level, std::move(encrypter));
if (!callback_.is_null() &&
(!require_confirmation_ && level == quic::ENCRYPTION_ZERO_RTT)) {
// Currently for all CryptoHandshakeEvent events, callback_
// could be called because there are no error events in CryptoHandshakeEvent
// enum. If error events are added to CryptoHandshakeEvent, then the
// following code needs to changed.
std::move(callback_).Run(OK);
}
}
void QuicChromiumClientSession::LogZeroRttStats() {
......
......@@ -1036,6 +1036,52 @@ TEST_P(QuicStreamFactoryTest, CreateZeroRtt) {
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
// Regression test for crbug.com/1117331.
TEST_P(QuicStreamFactoryTest, AsyncZeroRtt) {
Initialize();
if (!version_.UsesTls())
return;
factory_->set_is_quic_known_to_work_on_current_network(true);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
MockQuicData socket_data(version_);
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
socket_data.AddSocketDataToFactory(socket_factory_.get());
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ASYNC_ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
"192.168.0.1", "");
QuicStreamRequest request(factory_.get());
EXPECT_EQ(
ERR_IO_PENDING,
request.Request(
host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), false /* disable_secure_dns */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
EXPECT_FALSE(HasActiveSession(host_port_pair_));
EXPECT_EQ(nullptr, CreateStream(&request));
crypto_client_stream_factory_.last_stream()->NotifySessionZeroRttComplete();
EXPECT_TRUE(HasActiveSession(host_port_pair_));
EXPECT_THAT(callback_.WaitForResult(), IsOk());
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
TEST_P(QuicStreamFactoryTest, DefaultInitialRtt) {
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
......
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