Refactor more TLS handshake tests in QUIC.
QuicCryptoServerStreamTest now only tests QUIC Crypto. The TLS tests from
that file have been moved to a new TlsServerHandshakerTest file. The
remaining tests from TlsHandshakerTest have also been moved to
TlsServerHandshakerTest (client tests were moved to TlsClientHandshakerTest
in cl/306682737) and removes TlsHandshakerTest.
gfe-relnote: n/a - test-only refactor.
PiperOrigin-RevId: 307452036
Change-Id: I3f7cb8d88fcc1da9789a65305a9d4079154dde93
diff --git a/quic/core/quic_crypto_client_stream.h b/quic/core/quic_crypto_client_stream.h
index a66dcba..5ec1b01 100644
--- a/quic/core/quic_crypto_client_stream.h
+++ b/quic/core/quic_crypto_client_stream.h
@@ -21,6 +21,10 @@
namespace quic {
+namespace test {
+class QuicCryptoClientStreamPeer;
+} // namespace test
+
class QUIC_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
public:
explicit QuicCryptoClientStreamBase(QuicSession* session);
@@ -221,6 +225,7 @@
}
private:
+ friend class test::QuicCryptoClientStreamPeer;
std::unique_ptr<HandshakerInterface> handshaker_;
};
diff --git a/quic/core/quic_crypto_server_stream_test.cc b/quic/core/quic_crypto_server_stream_test.cc
index a3f0d11..debfc3b 100644
--- a/quic/core/quic_crypto_server_stream_test.cc
+++ b/quic/core/quic_crypto_server_stream_test.cc
@@ -50,6 +50,8 @@
const char kServerHostname[] = "test.example.com";
const uint16_t kServerPort = 443;
+// This test tests the server-side of the QUIC crypto handshake. It does not
+// test the TLS handshake - that is in tls_server_handshaker_test.cc.
class QuicCryptoServerStreamTest : public QuicTest {
public:
QuicCryptoServerStreamTest()
@@ -152,28 +154,6 @@
server_connection_, server_stream(), 0);
}
- void UseTlsHandshake() {
- client_options_.only_tls_versions = true;
- supported_versions_.clear();
- for (ParsedQuicVersion version : AllSupportedVersions()) {
- if (version.handshake_protocol != PROTOCOL_TLS1_3) {
- continue;
- }
- supported_versions_.push_back(version);
- }
- }
-
- void UseQuicCryptoHandshake() {
- client_options_.only_quic_crypto_versions = true;
- supported_versions_.clear();
- for (ParsedQuicVersion version : AllSupportedVersions()) {
- if (version.handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
- continue;
- }
- supported_versions_.push_back(version);
- }
- }
-
protected:
// Every connection gets its own MockQuicConnectionHelper and
// MockAlarmFactory, tracked separately from the server and client state so
@@ -197,7 +177,8 @@
crypto_test_utils::FakeClientOptions client_options_;
// Which QUIC versions the client and server support.
- ParsedQuicVersionVector supported_versions_ = AllSupportedVersions();
+ ParsedQuicVersionVector supported_versions_ =
+ AllSupportedVersionsWithQuicCrypto();
};
TEST_F(QuicCryptoServerStreamTest, NotInitiallyConected) {
@@ -211,24 +192,13 @@
// test should send:
// * One to get a source-address token and certificates.
// * One to complete the handshake.
- UseQuicCryptoHandshake();
Initialize();
EXPECT_EQ(2, CompleteCryptoHandshake());
EXPECT_TRUE(server_stream()->encryption_established());
EXPECT_TRUE(server_stream()->one_rtt_keys_available());
}
-TEST_F(QuicCryptoServerStreamTest, ConnectedAfterTlsHandshake) {
- UseTlsHandshake();
- Initialize();
- CompleteCryptoHandshake();
- EXPECT_EQ(PROTOCOL_TLS1_3, server_stream()->handshake_protocol());
- EXPECT_TRUE(server_stream()->encryption_established());
- EXPECT_TRUE(server_stream()->one_rtt_keys_available());
-}
-
TEST_F(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
- UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -250,7 +220,6 @@
}
TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
- UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -282,7 +251,6 @@
}
TEST_F(QuicCryptoServerStreamTest, FailByPolicy) {
- UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -295,7 +263,6 @@
}
TEST_F(QuicCryptoServerStreamTest, MessageAfterHandshake) {
- UseQuicCryptoHandshake();
Initialize();
CompleteCryptoHandshake();
EXPECT_CALL(
@@ -307,7 +274,6 @@
}
TEST_F(QuicCryptoServerStreamTest, BadMessageType) {
- UseQuicCryptoHandshake();
Initialize();
message_.set_tag(kSHLO);
@@ -326,7 +292,6 @@
}
TEST_F(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
- UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -359,7 +324,6 @@
};
TEST_F(QuicCryptoServerStreamTestWithFailingProofSource, Test) {
- UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -393,7 +357,6 @@
// connection in close succession could cause a crash, especially when the use
// of Mentat signing meant that it took a while for each CHLO to be processed.
TEST_F(QuicCryptoServerStreamTestWithFakeProofSource, MultipleChlo) {
- UseQuicCryptoHandshake();
Initialize();
GetFakeProofSource()->Activate();
EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
diff --git a/quic/core/tls_client_handshaker_test.cc b/quic/core/tls_client_handshaker_test.cc
index 0283169..bb859c1 100644
--- a/quic/core/tls_client_handshaker_test.cc
+++ b/quic/core/tls_client_handshaker_test.cc
@@ -256,7 +256,7 @@
EXPECT_FALSE(stream()->IsResumption());
}
-TEST_P(TlsClientHandshakerTest, ConnecitonClosedOnTlsError) {
+TEST_P(TlsClientHandshakerTest, ConnectionClosedOnTlsError) {
// Have client send ClientHello.
stream()->CryptoConnect();
EXPECT_CALL(*connection_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
diff --git a/quic/core/tls_handshaker_test.cc b/quic/core/tls_handshaker_test.cc
index de3a8a4..6103743 100644
--- a/quic/core/tls_handshaker_test.cc
+++ b/quic/core/tls_handshaker_test.cc
@@ -434,138 +434,6 @@
ExpectHandshakeSuccessful();
}
-TEST_P(TlsHandshakerTest, HandshakeWithAsyncProofSource) {
- EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
- EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
- // Enable FakeProofSource to capture call to ComputeTlsSignature and run it
- // asynchronously.
- FakeProofSource* proof_source = server_stream_->GetFakeProofSource();
- proof_source->Activate();
-
- // Start handshake.
- client_stream_->CryptoConnect();
- ExchangeHandshakeMessages(client_stream_, server_stream_);
-
- ASSERT_EQ(proof_source->NumPendingCallbacks(), 1);
- proof_source->InvokePendingCallback(0);
-
- ExchangeHandshakeMessages(client_stream_, server_stream_);
-
- ExpectHandshakeSuccessful();
-}
-
-TEST_P(TlsHandshakerTest, CancelPendingProofSource) {
- EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
- EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
- // Enable FakeProofSource to capture call to ComputeTlsSignature and run it
- // asynchronously.
- FakeProofSource* proof_source = server_stream_->GetFakeProofSource();
- proof_source->Activate();
-
- // Start handshake.
- client_stream_->CryptoConnect();
- ExchangeHandshakeMessages(client_stream_, server_stream_);
-
- ASSERT_EQ(proof_source->NumPendingCallbacks(), 1);
- server_stream_ = nullptr;
-
- proof_source->InvokePendingCallback(0);
-}
-
-TEST_P(TlsHandshakerTest, ServerExtractSNI) {
- EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
- EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
- EXPECT_CALL(client_stream_->proof_handler(), OnProofVerifyDetailsAvailable);
- client_stream_->CryptoConnect();
- ExchangeHandshakeMessages(client_stream_, server_stream_);
- ExpectHandshakeSuccessful();
-
- EXPECT_EQ(server_stream_->crypto_negotiated_params().sni, "test.example.com");
-}
-
-TEST_P(TlsHandshakerTest, ServerConnectionClosedOnTlsError) {
- EXPECT_CALL(*server_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
-
- // Send a zero-length ClientHello from client to server.
- char bogus_handshake_message[] = {
- // Handshake struct (RFC 8446 appendix B.3)
- 1, // HandshakeType client_hello
- 0, 0, 0, // uint24 length
- };
- client_stream_->WriteCryptoData(
- ENCRYPTION_INITIAL,
- quiche::QuicheStringPiece(bogus_handshake_message,
- QUICHE_ARRAYSIZE(bogus_handshake_message)));
- client_stream_->SendCryptoMessagesToPeer(server_stream_);
-
- EXPECT_FALSE(server_stream_->one_rtt_keys_available());
-}
-
-TEST_P(TlsHandshakerTest, ClientNotSendingALPN) {
- client_stream_->client_handshaker()->AllowEmptyAlpnForTests();
- EXPECT_CALL(client_session_, GetAlpnsToOffer())
- .WillOnce(Return(std::vector<std::string>()));
- EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED,
- "Server did not select ALPN", _));
- EXPECT_CALL(*server_conn_,
- CloseConnection(QUIC_HANDSHAKE_FAILED,
- "Server did not receive a known ALPN", _));
- client_stream_->CryptoConnect();
- ExchangeHandshakeMessages(client_stream_, server_stream_);
-
- EXPECT_FALSE(client_stream_->one_rtt_keys_available());
- EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
- client_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->one_rtt_keys_available());
- EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
- server_stream_->encryption_established());
-}
-
-TEST_P(TlsHandshakerTest, ClientSendingBadALPN) {
- const std::string kTestBadClientAlpn = "bad-client-alpn";
- EXPECT_CALL(client_session_, GetAlpnsToOffer())
- .WillOnce(Return(std::vector<std::string>({kTestBadClientAlpn})));
- EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED,
- "Server did not select ALPN", _));
- EXPECT_CALL(*server_conn_,
- CloseConnection(QUIC_HANDSHAKE_FAILED,
- "Server did not receive a known ALPN", _));
- client_stream_->CryptoConnect();
- ExchangeHandshakeMessages(client_stream_, server_stream_);
-
- EXPECT_FALSE(client_stream_->one_rtt_keys_available());
- EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
- client_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->one_rtt_keys_available());
- EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
- server_stream_->encryption_established());
-}
-
-TEST_P(TlsHandshakerTest, CustomALPNNegotiation) {
- EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
- EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
-
- const std::string kTestAlpn = "A Custom ALPN Value";
- const std::vector<std::string> kTestAlpns(
- {"foo", "bar", kTestAlpn, "something else"});
- EXPECT_CALL(client_session_, GetAlpnsToOffer())
- .WillRepeatedly(Return(kTestAlpns));
- EXPECT_CALL(server_session_, SelectAlpn(_))
- .WillOnce([kTestAlpn, kTestAlpns](
- const std::vector<quiche::QuicheStringPiece>& alpns) {
- EXPECT_THAT(alpns, ElementsAreArray(kTestAlpns));
- return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
- });
- EXPECT_CALL(client_session_,
- OnAlpnSelected(quiche::QuicheStringPiece(kTestAlpn)));
- EXPECT_CALL(server_session_,
- OnAlpnSelected(quiche::QuicheStringPiece(kTestAlpn)));
- client_stream_->CryptoConnect();
- ExchangeHandshakeMessages(client_stream_, server_stream_);
-
- ExpectHandshakeSuccessful();
-}
-
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/tls_server_handshaker_test.cc b/quic/core/tls_server_handshaker_test.cc
new file mode 100644
index 0000000..7a30a13
--- /dev/null
+++ b/quic/core/tls_server_handshaker_test.cc
@@ -0,0 +1,352 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
+#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quic {
+class QuicConnection;
+class QuicStream;
+} // namespace quic
+
+using testing::_;
+using testing::NiceMock;
+using testing::Return;
+
+namespace quic {
+namespace test {
+
+namespace {
+
+const char kServerHostname[] = "test.example.com";
+const uint16_t kServerPort = 443;
+
+class TlsServerHandshakerTest : public QuicTest {
+ public:
+ TlsServerHandshakerTest()
+ : proof_source_(new FakeProofSource()),
+ server_crypto_config_(QuicCryptoServerConfig::TESTING,
+ QuicRandom::GetInstance(),
+ std::unique_ptr<ProofSource>(proof_source_),
+ KeyExchangeSource::Default()),
+ server_compressed_certs_cache_(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
+ server_id_(kServerHostname, kServerPort, false),
+ client_crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {
+ InitializeServer();
+ InitializeFakeClient();
+ }
+
+ ~TlsServerHandshakerTest() override {
+ // Ensure that anything that might reference |helpers_| is destroyed before
+ // |helpers_| is destroyed.
+ server_session_.reset();
+ client_session_.reset();
+ helpers_.clear();
+ alarm_factories_.clear();
+ }
+
+ // Initializes the crypto server stream state for testing. May be
+ // called multiple times.
+ void InitializeServer() {
+ TestQuicSpdyServerSession* server_session = nullptr;
+ helpers_.push_back(std::make_unique<NiceMock<MockQuicConnectionHelper>>());
+ alarm_factories_.push_back(std::make_unique<MockAlarmFactory>());
+ CreateServerSessionForTest(
+ server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
+ helpers_.back().get(), alarm_factories_.back().get(),
+ &server_crypto_config_, &server_compressed_certs_cache_,
+ &server_connection_, &server_session);
+ CHECK(server_session);
+ server_session_.reset(server_session);
+ EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
+ .Times(testing::AnyNumber());
+ EXPECT_CALL(*server_session_, SelectAlpn(_))
+ .WillRepeatedly(
+ [this](const std::vector<quiche::QuicheStringPiece>& alpns) {
+ return std::find(
+ alpns.cbegin(), alpns.cend(),
+ AlpnForVersion(server_session_->connection()->version()));
+ });
+ crypto_test_utils::SetupCryptoServerConfigForTest(
+ server_connection_->clock(), server_connection_->random_generator(),
+ &server_crypto_config_);
+ }
+
+ QuicCryptoServerStreamBase* server_stream() {
+ return server_session_->GetMutableCryptoStream();
+ }
+
+ QuicCryptoClientStream* client_stream() {
+ return client_session_->GetMutableCryptoStream();
+ }
+
+ // Initializes a fake client, and all its associated state, for
+ // testing. May be called multiple times.
+ void InitializeFakeClient() {
+ TestQuicSpdyClientSession* client_session = nullptr;
+ helpers_.push_back(std::make_unique<NiceMock<MockQuicConnectionHelper>>());
+ alarm_factories_.push_back(std::make_unique<MockAlarmFactory>());
+ CreateClientSessionForTest(
+ server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
+ helpers_.back().get(), alarm_factories_.back().get(),
+ &client_crypto_config_, &client_connection_, &client_session);
+ const std::string default_alpn =
+ AlpnForVersion(client_connection_->version());
+ ON_CALL(*client_session, GetAlpnsToOffer())
+ .WillByDefault(Return(std::vector<std::string>({default_alpn})));
+ CHECK(client_session);
+ client_session_.reset(client_session);
+ }
+
+ void CompleteCryptoHandshake() {
+ while (!client_stream()->one_rtt_keys_available() ||
+ !server_stream()->one_rtt_keys_available()) {
+ auto previous_moved_messages_counts = moved_messages_counts_;
+ AdvanceHandshakeWithFakeClient();
+ // Check that the handshake has made forward progress
+ ASSERT_NE(previous_moved_messages_counts, moved_messages_counts_);
+ }
+ }
+
+ // Performs a single round of handshake message-exchange between the
+ // client and server.
+ void AdvanceHandshakeWithFakeClient() {
+ CHECK(server_connection_);
+ CHECK(client_session_ != nullptr);
+
+ EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
+ EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
+ .Times(testing::AnyNumber());
+ EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
+ EXPECT_CALL(*server_connection_, OnCanWrite()).Times(testing::AnyNumber());
+ // Call CryptoConnect if we haven't moved any client messages yet.
+ if (moved_messages_counts_.first == 0) {
+ client_stream()->CryptoConnect();
+ }
+ moved_messages_counts_ = crypto_test_utils::AdvanceHandshake(
+ client_connection_, client_stream(), moved_messages_counts_.first,
+ server_connection_, server_stream(), moved_messages_counts_.second);
+ }
+
+ void ExpectHandshakeSuccessful() {
+ EXPECT_TRUE(client_stream()->one_rtt_keys_available());
+ EXPECT_TRUE(client_stream()->encryption_established());
+ EXPECT_TRUE(server_stream()->one_rtt_keys_available());
+ EXPECT_TRUE(server_stream()->encryption_established());
+ EXPECT_EQ(HANDSHAKE_COMPLETE, client_stream()->GetHandshakeState());
+ EXPECT_EQ(HANDSHAKE_CONFIRMED, server_stream()->GetHandshakeState());
+
+ const auto& client_crypto_params =
+ client_stream()->crypto_negotiated_params();
+ const auto& server_crypto_params =
+ server_stream()->crypto_negotiated_params();
+ // The TLS params should be filled in on the client.
+ EXPECT_NE(0, client_crypto_params.cipher_suite);
+ EXPECT_NE(0, client_crypto_params.key_exchange_group);
+ EXPECT_NE(0, client_crypto_params.peer_signature_algorithm);
+
+ // The cipher suite and key exchange group should match on the client and
+ // server.
+ EXPECT_EQ(client_crypto_params.cipher_suite,
+ server_crypto_params.cipher_suite);
+ EXPECT_EQ(client_crypto_params.key_exchange_group,
+ server_crypto_params.key_exchange_group);
+ // We don't support client certs on the server (yet), so the server
+ // shouldn't have a peer signature algorithm to report.
+ EXPECT_EQ(0, server_crypto_params.peer_signature_algorithm);
+ }
+
+ protected:
+ // Every connection gets its own MockQuicConnectionHelper and
+ // MockAlarmFactory, tracked separately from the server and client state so
+ // their lifetimes persist through the whole test.
+ std::vector<std::unique_ptr<MockQuicConnectionHelper>> helpers_;
+ std::vector<std::unique_ptr<MockAlarmFactory>> alarm_factories_;
+
+ // Server state.
+ PacketSavingConnection* server_connection_;
+ std::unique_ptr<TestQuicSpdyServerSession> server_session_;
+ FakeProofSource* proof_source_; // owned by server_crypto_config_
+ QuicCryptoServerConfig server_crypto_config_;
+ QuicCompressedCertsCache server_compressed_certs_cache_;
+ QuicServerId server_id_;
+
+ // Client state.
+ PacketSavingConnection* client_connection_;
+ QuicCryptoClientConfig client_crypto_config_;
+ std::unique_ptr<TestQuicSpdyClientSession> client_session_;
+
+ crypto_test_utils::FakeClientOptions client_options_;
+ // How many handshake messages have been moved from client to server and
+ // server to client.
+ std::pair<size_t, size_t> moved_messages_counts_ = {0, 0};
+
+ // Which QUIC versions the client and server support.
+ ParsedQuicVersionVector supported_versions_ = AllSupportedVersionsWithTls();
+};
+
+TEST_F(TlsServerHandshakerTest, NotInitiallyConected) {
+ EXPECT_FALSE(server_stream()->encryption_established());
+ EXPECT_FALSE(server_stream()->one_rtt_keys_available());
+}
+
+TEST_F(TlsServerHandshakerTest, ConnectedAfterTlsHandshake) {
+ CompleteCryptoHandshake();
+ EXPECT_EQ(PROTOCOL_TLS1_3, server_stream()->handshake_protocol());
+ ExpectHandshakeSuccessful();
+}
+
+TEST_F(TlsServerHandshakerTest, HandshakeWithAsyncProofSource) {
+ EXPECT_CALL(*client_connection_, CloseConnection(_, _, _)).Times(0);
+ EXPECT_CALL(*server_connection_, CloseConnection(_, _, _)).Times(0);
+ // Enable FakeProofSource to capture call to ComputeTlsSignature and run it
+ // asynchronously.
+ proof_source_->Activate();
+
+ // Start handshake.
+ AdvanceHandshakeWithFakeClient();
+
+ ASSERT_EQ(proof_source_->NumPendingCallbacks(), 1);
+ proof_source_->InvokePendingCallback(0);
+
+ CompleteCryptoHandshake();
+
+ ExpectHandshakeSuccessful();
+}
+
+TEST_F(TlsServerHandshakerTest, CancelPendingProofSource) {
+ EXPECT_CALL(*client_connection_, CloseConnection(_, _, _)).Times(0);
+ EXPECT_CALL(*server_connection_, CloseConnection(_, _, _)).Times(0);
+ // Enable FakeProofSource to capture call to ComputeTlsSignature and run it
+ // asynchronously.
+ proof_source_->Activate();
+
+ // Start handshake.
+ AdvanceHandshakeWithFakeClient();
+
+ ASSERT_EQ(proof_source_->NumPendingCallbacks(), 1);
+ server_session_ = nullptr;
+
+ proof_source_->InvokePendingCallback(0);
+}
+
+TEST_F(TlsServerHandshakerTest, ExtractSNI) {
+ CompleteCryptoHandshake();
+ ExpectHandshakeSuccessful();
+
+ EXPECT_EQ(server_stream()->crypto_negotiated_params().sni,
+ "test.example.com");
+}
+
+TEST_F(TlsServerHandshakerTest, ConnectionClosedOnTlsError) {
+ EXPECT_CALL(*server_connection_,
+ CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
+
+ // Send a zero-length ClientHello from client to server.
+ char bogus_handshake_message[] = {
+ // Handshake struct (RFC 8446 appendix B.3)
+ 1, // HandshakeType client_hello
+ 0, 0, 0, // uint24 length
+ };
+ server_stream()->crypto_message_parser()->ProcessInput(
+ quiche::QuicheStringPiece(bogus_handshake_message,
+ QUICHE_ARRAYSIZE(bogus_handshake_message)),
+ ENCRYPTION_INITIAL);
+
+ EXPECT_FALSE(server_stream()->one_rtt_keys_available());
+}
+
+TEST_F(TlsServerHandshakerTest, ClientNotSendingALPN) {
+ static_cast<TlsClientHandshaker*>(
+ QuicCryptoClientStreamPeer::GetHandshaker(client_stream()))
+ ->AllowEmptyAlpnForTests();
+ EXPECT_CALL(*client_session_, GetAlpnsToOffer())
+ .WillOnce(Return(std::vector<std::string>()));
+ EXPECT_CALL(
+ *client_connection_,
+ CloseConnection(QUIC_HANDSHAKE_FAILED, "Server did not select ALPN", _));
+ EXPECT_CALL(*server_connection_,
+ CloseConnection(QUIC_HANDSHAKE_FAILED,
+ "Server did not receive a known ALPN", _));
+
+ // Process two flights of handshake messages.
+ AdvanceHandshakeWithFakeClient();
+ AdvanceHandshakeWithFakeClient();
+
+ EXPECT_FALSE(client_stream()->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ client_stream()->encryption_established());
+ EXPECT_FALSE(server_stream()->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ server_stream()->encryption_established());
+}
+
+TEST_F(TlsServerHandshakerTest, ClientSendingBadALPN) {
+ const std::string kTestBadClientAlpn = "bad-client-alpn";
+ EXPECT_CALL(*client_session_, GetAlpnsToOffer())
+ .WillOnce(Return(std::vector<std::string>({kTestBadClientAlpn})));
+ EXPECT_CALL(
+ *client_connection_,
+ CloseConnection(QUIC_HANDSHAKE_FAILED, "Server did not select ALPN", _));
+ EXPECT_CALL(*server_connection_,
+ CloseConnection(QUIC_HANDSHAKE_FAILED,
+ "Server did not receive a known ALPN", _));
+
+ // Process two flights of handshake messages.
+ AdvanceHandshakeWithFakeClient();
+ AdvanceHandshakeWithFakeClient();
+
+ EXPECT_FALSE(client_stream()->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ client_stream()->encryption_established());
+ EXPECT_FALSE(server_stream()->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ server_stream()->encryption_established());
+}
+
+TEST_F(TlsServerHandshakerTest, CustomALPNNegotiation) {
+ EXPECT_CALL(*client_connection_, CloseConnection(_, _, _)).Times(0);
+ EXPECT_CALL(*server_connection_, CloseConnection(_, _, _)).Times(0);
+
+ const std::string kTestAlpn = "A Custom ALPN Value";
+ const std::vector<std::string> kTestAlpns(
+ {"foo", "bar", kTestAlpn, "something else"});
+ EXPECT_CALL(*client_session_, GetAlpnsToOffer())
+ .WillRepeatedly(Return(kTestAlpns));
+ EXPECT_CALL(*server_session_, SelectAlpn(_))
+ .WillOnce([kTestAlpn, kTestAlpns](
+ const std::vector<quiche::QuicheStringPiece>& alpns) {
+ EXPECT_THAT(alpns, testing::ElementsAreArray(kTestAlpns));
+ return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
+ });
+ EXPECT_CALL(*client_session_,
+ OnAlpnSelected(quiche::QuicheStringPiece(kTestAlpn)));
+ EXPECT_CALL(*server_session_,
+ OnAlpnSelected(quiche::QuicheStringPiece(kTestAlpn)));
+
+ CompleteCryptoHandshake();
+ ExpectHandshakeSuccessful();
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
diff --git a/quic/test_tools/crypto_test_utils.cc b/quic/test_tools/crypto_test_utils.cc
index 1e3f14d..21561d9 100644
--- a/quic/test_tools/crypto_test_utils.cc
+++ b/quic/test_tools/crypto_test_utils.cc
@@ -756,6 +756,8 @@
// packets should ever be encrypted with the NullEncrypter, instead
// they're encrypted with an obfuscation cipher based on QUIC version and
// connection ID.
+ QUIC_LOG(INFO) << "Attempting to decrypt with NullDecrypter: "
+ "expect a decryption failure on the next log line.";
ASSERT_FALSE(null_encryption_framer.ProcessPacket(
*source_conn->encrypted_packets_[index]))
<< "No TLS packets should be encrypted with the NullEncrypter";
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc
index b534635..47fd05f 100644
--- a/quic/test_tools/quic_test_utils.cc
+++ b/quic/test_tools/quic_test_utils.cc
@@ -1091,6 +1091,12 @@
MockSessionNotifier::MockSessionNotifier() {}
MockSessionNotifier::~MockSessionNotifier() {}
+// static
+QuicCryptoClientStream::HandshakerInterface*
+QuicCryptoClientStreamPeer::GetHandshaker(QuicCryptoClientStream* stream) {
+ return stream->handshaker_.get();
+}
+
void CreateClientSessionForTest(
QuicServerId server_id,
QuicTime::Delta connection_start_time,
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index fafe8d0..b8e0eae 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -858,6 +858,7 @@
MOCK_CONST_METHOD1(SelectAlpn,
std::vector<quiche::QuicheStringPiece>::const_iterator(
const std::vector<quiche::QuicheStringPiece>&));
+ MOCK_METHOD(void, OnAlpnSelected, (quiche::QuicheStringPiece));
std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override;
@@ -924,6 +925,7 @@
MOCK_METHOD0(ShouldCreateOutgoingBidirectionalStream, bool());
MOCK_METHOD0(ShouldCreateOutgoingUnidirectionalStream, bool());
MOCK_CONST_METHOD0(GetAlpnsToOffer, std::vector<std::string>());
+ MOCK_METHOD(void, OnAlpnSelected, (quiche::QuicheStringPiece));
QuicCryptoClientStream* GetMutableCryptoStream() override;
const QuicCryptoClientStream* GetCryptoStream() const override;
@@ -1190,6 +1192,14 @@
MOCK_CONST_METHOD0(HasUnackedStreamData, bool());
};
+class QuicCryptoClientStreamPeer {
+ public:
+ QuicCryptoClientStreamPeer() = delete;
+
+ static QuicCryptoClientStream::HandshakerInterface* GetHandshaker(
+ QuicCryptoClientStream* stream);
+};
+
// Creates a client session for testing.
//
// server_id: The server id associated with this stream.