blob: 9b131733d8d0b631d258ea6128d06226a7f889c2 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
6
7#include <map>
8#include <memory>
bnc463f2352019-10-10 04:49:34 -07009#include <utility>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include <vector>
11
12#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter.h"
13#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
14#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
15#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
16#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
17#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
18#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
19#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
20#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
21#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
22#include "net/third_party/quiche/src/quic/core/quic_packets.h"
23#include "net/third_party/quiche/src/quic/core/quic_session.h"
24#include "net/third_party/quiche/src/quic/core/quic_utils.h"
vasilvve6472f62019-10-02 06:50:56 -070025#include "net/third_party/quiche/src/quic/core/quic_versions.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050026#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
27#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050028#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
29#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
30#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
31#include "net/third_party/quiche/src/quic/test_tools/failing_proof_source.h"
32#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
34#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080035#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050036
37namespace quic {
38class QuicConnection;
39class QuicStream;
40} // namespace quic
41
42using testing::_;
43using testing::NiceMock;
44
45namespace quic {
46namespace test {
47
QUICHE teama6ef0a62019-03-07 20:34:33 -050048namespace {
49
50const char kServerHostname[] = "test.example.com";
51const uint16_t kServerPort = 443;
52
53class QuicCryptoServerStreamTest : public QuicTestWithParam<bool> {
54 public:
55 QuicCryptoServerStreamTest()
56 : QuicCryptoServerStreamTest(crypto_test_utils::ProofSourceForTesting()) {
57 }
58
59 explicit QuicCryptoServerStreamTest(std::unique_ptr<ProofSource> proof_source)
60 : server_crypto_config_(QuicCryptoServerConfig::TESTING,
61 QuicRandom::GetInstance(),
62 std::move(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -070063 KeyExchangeSource::Default()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050064 server_compressed_certs_cache_(
65 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
66 server_id_(kServerHostname, kServerPort, false),
nharper6ebe83b2019-06-13 17:43:52 -070067 client_crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050068
69 void Initialize() { InitializeServer(); }
70
71 ~QuicCryptoServerStreamTest() override {
72 // Ensure that anything that might reference |helpers_| is destroyed before
73 // |helpers_| is destroyed.
74 server_session_.reset();
75 client_session_.reset();
76 helpers_.clear();
77 alarm_factories_.clear();
78 }
79
80 // Initializes the crypto server stream state for testing. May be
81 // called multiple times.
82 void InitializeServer() {
83 TestQuicSpdyServerSession* server_session = nullptr;
vasilvv0fc587f2019-09-06 13:33:08 -070084 helpers_.push_back(std::make_unique<NiceMock<MockQuicConnectionHelper>>());
85 alarm_factories_.push_back(std::make_unique<MockAlarmFactory>());
QUICHE teama6ef0a62019-03-07 20:34:33 -050086 CreateServerSessionForTest(
87 server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
88 helpers_.back().get(), alarm_factories_.back().get(),
89 &server_crypto_config_, &server_compressed_certs_cache_,
90 &server_connection_, &server_session);
91 CHECK(server_session);
92 server_session_.reset(server_session);
93 EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
94 .Times(testing::AnyNumber());
vasilvve6472f62019-10-02 06:50:56 -070095 EXPECT_CALL(*server_session_, SelectAlpn(_))
dmcardlecf0bfcf2019-12-13 08:08:21 -080096 .WillRepeatedly(
97 [this](const std::vector<quiche::QuicheStringPiece>& alpns) {
98 return std::find(
99 alpns.cbegin(), alpns.cend(),
100 AlpnForVersion(server_session_->connection()->version()));
101 });
QUICHE teama6ef0a62019-03-07 20:34:33 -0500102 crypto_test_utils::SetupCryptoServerConfigForTest(
103 server_connection_->clock(), server_connection_->random_generator(),
nharperba5f32c2019-05-13 12:21:31 -0700104 &server_crypto_config_);
wub256b2d62019-11-25 08:46:55 -0800105 if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
106 server_session_->GetMutableCryptoStream()->OnSuccessfulVersionNegotiation(
107 supported_versions_.front());
108 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500109 }
110
111 QuicCryptoServerStream* server_stream() {
112 return server_session_->GetMutableCryptoStream();
113 }
114
115 QuicCryptoClientStream* client_stream() {
116 return client_session_->GetMutableCryptoStream();
117 }
118
119 // Initializes a fake client, and all its associated state, for
120 // testing. May be called multiple times.
wube9dc7da2019-05-22 06:08:54 -0700121 void InitializeFakeClient() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500122 TestQuicSpdyClientSession* client_session = nullptr;
vasilvv0fc587f2019-09-06 13:33:08 -0700123 helpers_.push_back(std::make_unique<NiceMock<MockQuicConnectionHelper>>());
124 alarm_factories_.push_back(std::make_unique<MockAlarmFactory>());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500125 CreateClientSessionForTest(
wube9dc7da2019-05-22 06:08:54 -0700126 server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500127 helpers_.back().get(), alarm_factories_.back().get(),
128 &client_crypto_config_, &client_connection_, &client_session);
129 CHECK(client_session);
130 client_session_.reset(client_session);
131 }
132
133 int CompleteCryptoHandshake() {
134 CHECK(server_connection_);
135 CHECK(server_session_ != nullptr);
136
137 return crypto_test_utils::HandshakeWithFakeClient(
138 helpers_.back().get(), alarm_factories_.back().get(),
vasilvvefc6af82019-10-11 12:46:56 -0700139 server_connection_, server_stream(), server_id_, client_options_,
140 /*alpn=*/"");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500141 }
142
143 // Performs a single round of handshake message-exchange between the
144 // client and server.
145 void AdvanceHandshakeWithFakeClient() {
146 CHECK(server_connection_);
147 CHECK(client_session_ != nullptr);
148
149 EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
150 EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
151 .Times(testing::AnyNumber());
152 EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
153 EXPECT_CALL(*server_connection_, OnCanWrite()).Times(testing::AnyNumber());
154 client_stream()->CryptoConnect();
155 crypto_test_utils::AdvanceHandshake(client_connection_, client_stream(), 0,
156 server_connection_, server_stream(), 0);
157 }
158
159 protected:
160 // Every connection gets its own MockQuicConnectionHelper and
161 // MockAlarmFactory, tracked separately from the server and client state so
162 // their lifetimes persist through the whole test.
163 std::vector<std::unique_ptr<MockQuicConnectionHelper>> helpers_;
164 std::vector<std::unique_ptr<MockAlarmFactory>> alarm_factories_;
165
166 // Server state.
167 PacketSavingConnection* server_connection_;
168 std::unique_ptr<TestQuicSpdyServerSession> server_session_;
169 QuicCryptoServerConfig server_crypto_config_;
170 QuicCompressedCertsCache server_compressed_certs_cache_;
171 QuicServerId server_id_;
172
173 // Client state.
174 PacketSavingConnection* client_connection_;
175 QuicCryptoClientConfig client_crypto_config_;
176 std::unique_ptr<TestQuicSpdyClientSession> client_session_;
177
178 CryptoHandshakeMessage message_;
179 crypto_test_utils::FakeClientOptions client_options_;
180
181 // Which QUIC versions the client and server support.
182 ParsedQuicVersionVector supported_versions_ = AllSupportedVersions();
183};
184
dschinazi142051a2019-09-18 18:17:29 -0700185INSTANTIATE_TEST_SUITE_P(Tests,
186 QuicCryptoServerStreamTest,
187 ::testing::Bool(),
188 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500189
190TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
191 Initialize();
192 EXPECT_FALSE(server_stream()->encryption_established());
fayang685367a2020-01-14 10:40:15 -0800193 EXPECT_FALSE(server_stream()->one_rtt_keys_available());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500194}
195
QUICHE teama6ef0a62019-03-07 20:34:33 -0500196TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
197 // CompleteCryptoHandshake returns the number of client hellos sent. This
198 // test should send:
199 // * One to get a source-address token and certificates.
200 // * One to complete the handshake.
201 Initialize();
202 EXPECT_EQ(2, CompleteCryptoHandshake());
203 EXPECT_TRUE(server_stream()->encryption_established());
fayang685367a2020-01-14 10:40:15 -0800204 EXPECT_TRUE(server_stream()->one_rtt_keys_available());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500205}
206
207TEST_P(QuicCryptoServerStreamTest, ConnectedAfterTlsHandshake) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500208 client_options_.only_tls_versions = true;
209 supported_versions_.clear();
dschinazidc770fc2020-01-13 15:42:41 -0800210 for (ParsedQuicVersion version : AllSupportedVersions()) {
211 if (version.handshake_protocol != PROTOCOL_TLS1_3) {
212 continue;
213 }
214 supported_versions_.push_back(version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500215 }
216 Initialize();
217 CompleteCryptoHandshake();
218 EXPECT_EQ(PROTOCOL_TLS1_3, server_stream()->handshake_protocol());
219 EXPECT_TRUE(server_stream()->encryption_established());
fayang685367a2020-01-14 10:40:15 -0800220 EXPECT_TRUE(server_stream()->one_rtt_keys_available());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500221}
222
223TEST_P(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
224 Initialize();
wube9dc7da2019-05-22 06:08:54 -0700225 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500226
227 // Do a first handshake in order to prime the client config with the server's
228 // information.
229 AdvanceHandshakeWithFakeClient();
230 EXPECT_FALSE(server_stream()->encryption_established());
fayang685367a2020-01-14 10:40:15 -0800231 EXPECT_FALSE(server_stream()->one_rtt_keys_available());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500232
233 // Now do another handshake, with the blocking SHLO connection option.
234 InitializeServer();
wube9dc7da2019-05-22 06:08:54 -0700235 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500236
237 AdvanceHandshakeWithFakeClient();
238 EXPECT_TRUE(server_stream()->encryption_established());
fayang685367a2020-01-14 10:40:15 -0800239 EXPECT_TRUE(server_stream()->one_rtt_keys_available());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240 EXPECT_EQ(ENCRYPTION_FORWARD_SECURE,
241 server_session_->connection()->encryption_level());
242}
243
QUICHE teama6ef0a62019-03-07 20:34:33 -0500244TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
245 Initialize();
wube9dc7da2019-05-22 06:08:54 -0700246 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500247
248 // Do a first handshake in order to prime the client config with the server's
249 // information.
250 AdvanceHandshakeWithFakeClient();
251 EXPECT_FALSE(server_stream()->ZeroRttAttempted());
252
253 // Now do another handshake, hopefully in 0-RTT.
254 QUIC_LOG(INFO) << "Resetting for 0-RTT handshake attempt";
wube9dc7da2019-05-22 06:08:54 -0700255 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500256 InitializeServer();
257
258 EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
259 EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
260 .Times(testing::AnyNumber());
261 EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
262 client_stream()->CryptoConnect();
263
264 EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
265 EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
266 .Times(testing::AnyNumber());
267 EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
268 crypto_test_utils::CommunicateHandshakeMessages(
269 client_connection_, client_stream(), server_connection_, server_stream());
270
271 EXPECT_EQ(1, client_stream()->num_sent_client_hellos());
272 EXPECT_TRUE(server_stream()->ZeroRttAttempted());
273}
274
275TEST_P(QuicCryptoServerStreamTest, FailByPolicy) {
276 Initialize();
wube9dc7da2019-05-22 06:08:54 -0700277 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500278
279 EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
280 .WillOnce(testing::Return(false));
281 EXPECT_CALL(*server_connection_,
282 CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
283
284 AdvanceHandshakeWithFakeClient();
285}
286
287TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
288 Initialize();
289 CompleteCryptoHandshake();
290 EXPECT_CALL(
291 *server_connection_,
292 CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, _, _));
293 message_.set_tag(kCHLO);
294 crypto_test_utils::SendHandshakeMessageToStream(server_stream(), message_,
295 Perspective::IS_CLIENT);
296}
297
298TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
299 Initialize();
300
301 message_.set_tag(kSHLO);
302 EXPECT_CALL(*server_connection_,
303 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, _, _));
304 crypto_test_utils::SendHandshakeMessageToStream(server_stream(), message_,
305 Perspective::IS_SERVER);
306}
307
QUICHE teama6ef0a62019-03-07 20:34:33 -0500308TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) {
309 // An attempt to send a SCUP before completing handshake should fail.
310 Initialize();
311
312 server_stream()->SendServerConfigUpdate(nullptr);
313 EXPECT_EQ(0, server_stream()->NumServerConfigUpdateMessagesSent());
314}
315
316TEST_P(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
317 Initialize();
318
wube9dc7da2019-05-22 06:08:54 -0700319 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500320
321 // Do a first handshake in order to prime the client config with the server's
322 // information.
323 AdvanceHandshakeWithFakeClient();
324
325 // Now do another handshake, with the blocking SHLO connection option.
326 InitializeServer();
wube9dc7da2019-05-22 06:08:54 -0700327 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500328 AdvanceHandshakeWithFakeClient();
329
330 // Send a SCUP message and ensure that the client was able to verify it.
331 EXPECT_CALL(*client_connection_, CloseConnection(_, _, _)).Times(0);
332 server_stream()->SendServerConfigUpdate(nullptr);
333 crypto_test_utils::AdvanceHandshake(client_connection_, client_stream(), 1,
334 server_connection_, server_stream(), 1);
335
336 EXPECT_EQ(1, server_stream()->NumServerConfigUpdateMessagesSent());
337 EXPECT_EQ(1, client_stream()->num_scup_messages_received());
338}
339
QUICHE teama6ef0a62019-03-07 20:34:33 -0500340class QuicCryptoServerStreamTestWithFailingProofSource
341 : public QuicCryptoServerStreamTest {
342 public:
343 QuicCryptoServerStreamTestWithFailingProofSource()
344 : QuicCryptoServerStreamTest(
345 std::unique_ptr<FailingProofSource>(new FailingProofSource)) {}
346};
347
348INSTANTIATE_TEST_SUITE_P(MoreTests,
349 QuicCryptoServerStreamTestWithFailingProofSource,
dschinazi142051a2019-09-18 18:17:29 -0700350 ::testing::Bool(),
351 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500352
353TEST_P(QuicCryptoServerStreamTestWithFailingProofSource, Test) {
354 Initialize();
wube9dc7da2019-05-22 06:08:54 -0700355 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500356
357 EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
358 .WillOnce(testing::Return(true));
359 EXPECT_CALL(*server_connection_,
360 CloseConnection(QUIC_HANDSHAKE_FAILED, "Failed to get proof", _));
361 // Regression test for b/31521252, in which a crash would happen here.
362 AdvanceHandshakeWithFakeClient();
363 EXPECT_FALSE(server_stream()->encryption_established());
fayang685367a2020-01-14 10:40:15 -0800364 EXPECT_FALSE(server_stream()->one_rtt_keys_available());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500365}
366
367class QuicCryptoServerStreamTestWithFakeProofSource
368 : public QuicCryptoServerStreamTest {
369 public:
370 QuicCryptoServerStreamTestWithFakeProofSource()
371 : QuicCryptoServerStreamTest(
372 std::unique_ptr<FakeProofSource>(new FakeProofSource)),
373 crypto_config_peer_(&server_crypto_config_) {}
374
375 FakeProofSource* GetFakeProofSource() const {
376 return static_cast<FakeProofSource*>(crypto_config_peer_.GetProofSource());
377 }
378
379 protected:
380 QuicCryptoServerConfigPeer crypto_config_peer_;
381};
382
383INSTANTIATE_TEST_SUITE_P(YetMoreTests,
384 QuicCryptoServerStreamTestWithFakeProofSource,
dschinazi142051a2019-09-18 18:17:29 -0700385 ::testing::Bool(),
386 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500387
388// Regression test for b/35422225, in which multiple CHLOs arriving on the same
389// connection in close succession could cause a crash, especially when the use
390// of Mentat signing meant that it took a while for each CHLO to be processed.
391TEST_P(QuicCryptoServerStreamTestWithFakeProofSource, MultipleChlo) {
392 Initialize();
393 GetFakeProofSource()->Activate();
394 EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
395 .WillOnce(testing::Return(true));
396
397 // Create a minimal CHLO
398 MockClock clock;
399 QuicTransportVersion version = AllSupportedTransportVersions().front();
400 CryptoHandshakeMessage chlo = crypto_test_utils::GenerateDefaultInchoateCHLO(
401 &clock, version, &server_crypto_config_);
402
403 // Send in the CHLO, and check that a callback is now pending in the
404 // ProofSource.
405 crypto_test_utils::SendHandshakeMessageToStream(server_stream(), chlo,
406 Perspective::IS_CLIENT);
407 EXPECT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
408
409 // Send in a second CHLO while processing of the first is still pending.
410 // Verify that the server closes the connection rather than crashing. Note
411 // that the crash is a use-after-free, so it may only show up consistently in
412 // ASAN tests.
413 EXPECT_CALL(
414 *server_connection_,
415 CloseConnection(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO,
416 "Unexpected handshake message while processing CHLO", _));
417 crypto_test_utils::SendHandshakeMessageToStream(server_stream(), chlo,
418 Perspective::IS_CLIENT);
419}
420
421} // namespace
422} // namespace test
423} // namespace quic