blob: 238162c96efeb064be2d9a82a31cf25254d1c6c6 [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>
9#include <vector>
10
11#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter.h"
12#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
13#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
14#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
15#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
16#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
17#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
18#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
19#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
20#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
21#include "net/third_party/quiche/src/quic/core/quic_packets.h"
22#include "net/third_party/quiche/src/quic/core/quic_session.h"
23#include "net/third_party/quiche/src/quic/core/quic_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050024#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
25#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
26#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
27#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
28#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
29#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
30#include "net/third_party/quiche/src/quic/test_tools/failing_proof_source.h"
31#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
32#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
34
35namespace quic {
36class QuicConnection;
37class QuicStream;
38} // namespace quic
39
40using testing::_;
41using testing::NiceMock;
42
43namespace quic {
44namespace test {
45
QUICHE teama6ef0a62019-03-07 20:34:33 -050046namespace {
47
48const char kServerHostname[] = "test.example.com";
49const uint16_t kServerPort = 443;
50
51class QuicCryptoServerStreamTest : public QuicTestWithParam<bool> {
52 public:
53 QuicCryptoServerStreamTest()
54 : QuicCryptoServerStreamTest(crypto_test_utils::ProofSourceForTesting()) {
55 }
56
57 explicit QuicCryptoServerStreamTest(std::unique_ptr<ProofSource> proof_source)
58 : server_crypto_config_(QuicCryptoServerConfig::TESTING,
59 QuicRandom::GetInstance(),
60 std::move(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -070061 KeyExchangeSource::Default()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050062 server_compressed_certs_cache_(
63 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
64 server_id_(kServerHostname, kServerPort, false),
nharper6ebe83b2019-06-13 17:43:52 -070065 client_crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050066
67 void Initialize() { InitializeServer(); }
68
69 ~QuicCryptoServerStreamTest() override {
70 // Ensure that anything that might reference |helpers_| is destroyed before
71 // |helpers_| is destroyed.
72 server_session_.reset();
73 client_session_.reset();
74 helpers_.clear();
75 alarm_factories_.clear();
76 }
77
78 // Initializes the crypto server stream state for testing. May be
79 // called multiple times.
80 void InitializeServer() {
81 TestQuicSpdyServerSession* server_session = nullptr;
82 helpers_.push_back(QuicMakeUnique<NiceMock<MockQuicConnectionHelper>>());
83 alarm_factories_.push_back(QuicMakeUnique<MockAlarmFactory>());
84 CreateServerSessionForTest(
85 server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
86 helpers_.back().get(), alarm_factories_.back().get(),
87 &server_crypto_config_, &server_compressed_certs_cache_,
88 &server_connection_, &server_session);
89 CHECK(server_session);
90 server_session_.reset(server_session);
91 EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
92 .Times(testing::AnyNumber());
93 EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_, _))
94 .Times(testing::AnyNumber());
QUICHE teama6ef0a62019-03-07 20:34:33 -050095 crypto_test_utils::SetupCryptoServerConfigForTest(
96 server_connection_->clock(), server_connection_->random_generator(),
nharperba5f32c2019-05-13 12:21:31 -070097 &server_crypto_config_);
QUICHE teama6ef0a62019-03-07 20:34:33 -050098 server_session_->GetMutableCryptoStream()->OnSuccessfulVersionNegotiation(
99 supported_versions_.front());
100 }
101
102 QuicCryptoServerStream* server_stream() {
103 return server_session_->GetMutableCryptoStream();
104 }
105
106 QuicCryptoClientStream* client_stream() {
107 return client_session_->GetMutableCryptoStream();
108 }
109
110 // Initializes a fake client, and all its associated state, for
111 // testing. May be called multiple times.
wube9dc7da2019-05-22 06:08:54 -0700112 void InitializeFakeClient() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500113 TestQuicSpdyClientSession* client_session = nullptr;
114 helpers_.push_back(QuicMakeUnique<NiceMock<MockQuicConnectionHelper>>());
115 alarm_factories_.push_back(QuicMakeUnique<MockAlarmFactory>());
116 CreateClientSessionForTest(
wube9dc7da2019-05-22 06:08:54 -0700117 server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500118 helpers_.back().get(), alarm_factories_.back().get(),
119 &client_crypto_config_, &client_connection_, &client_session);
120 CHECK(client_session);
121 client_session_.reset(client_session);
122 }
123
124 int CompleteCryptoHandshake() {
125 CHECK(server_connection_);
126 CHECK(server_session_ != nullptr);
127
128 return crypto_test_utils::HandshakeWithFakeClient(
129 helpers_.back().get(), alarm_factories_.back().get(),
130 server_connection_, server_stream(), server_id_, client_options_);
131 }
132
133 // Performs a single round of handshake message-exchange between the
134 // client and server.
135 void AdvanceHandshakeWithFakeClient() {
136 CHECK(server_connection_);
137 CHECK(client_session_ != nullptr);
138
139 EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
140 EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
141 .Times(testing::AnyNumber());
142 EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
143 EXPECT_CALL(*server_connection_, OnCanWrite()).Times(testing::AnyNumber());
144 client_stream()->CryptoConnect();
145 crypto_test_utils::AdvanceHandshake(client_connection_, client_stream(), 0,
146 server_connection_, server_stream(), 0);
147 }
148
149 protected:
150 // Every connection gets its own MockQuicConnectionHelper and
151 // MockAlarmFactory, tracked separately from the server and client state so
152 // their lifetimes persist through the whole test.
153 std::vector<std::unique_ptr<MockQuicConnectionHelper>> helpers_;
154 std::vector<std::unique_ptr<MockAlarmFactory>> alarm_factories_;
155
156 // Server state.
157 PacketSavingConnection* server_connection_;
158 std::unique_ptr<TestQuicSpdyServerSession> server_session_;
159 QuicCryptoServerConfig server_crypto_config_;
160 QuicCompressedCertsCache server_compressed_certs_cache_;
161 QuicServerId server_id_;
162
163 // Client state.
164 PacketSavingConnection* client_connection_;
165 QuicCryptoClientConfig client_crypto_config_;
166 std::unique_ptr<TestQuicSpdyClientSession> client_session_;
167
168 CryptoHandshakeMessage message_;
169 crypto_test_utils::FakeClientOptions client_options_;
170
171 // Which QUIC versions the client and server support.
172 ParsedQuicVersionVector supported_versions_ = AllSupportedVersions();
173};
174
175INSTANTIATE_TEST_SUITE_P(Tests, QuicCryptoServerStreamTest, testing::Bool());
176
177TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
178 Initialize();
179 EXPECT_FALSE(server_stream()->encryption_established());
180 EXPECT_FALSE(server_stream()->handshake_confirmed());
181}
182
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
184 // CompleteCryptoHandshake returns the number of client hellos sent. This
185 // test should send:
186 // * One to get a source-address token and certificates.
187 // * One to complete the handshake.
188 Initialize();
189 EXPECT_EQ(2, CompleteCryptoHandshake());
190 EXPECT_TRUE(server_stream()->encryption_established());
191 EXPECT_TRUE(server_stream()->handshake_confirmed());
192}
193
194TEST_P(QuicCryptoServerStreamTest, ConnectedAfterTlsHandshake) {
wub49855982019-05-01 14:16:26 -0700195 SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500196 client_options_.only_tls_versions = true;
197 supported_versions_.clear();
198 for (QuicTransportVersion transport_version :
199 AllSupportedTransportVersions()) {
200 supported_versions_.push_back(
201 ParsedQuicVersion(PROTOCOL_TLS1_3, transport_version));
202 }
203 Initialize();
204 CompleteCryptoHandshake();
205 EXPECT_EQ(PROTOCOL_TLS1_3, server_stream()->handshake_protocol());
206 EXPECT_TRUE(server_stream()->encryption_established());
207 EXPECT_TRUE(server_stream()->handshake_confirmed());
208}
209
210TEST_P(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
211 Initialize();
wube9dc7da2019-05-22 06:08:54 -0700212 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213
214 // Do a first handshake in order to prime the client config with the server's
215 // information.
216 AdvanceHandshakeWithFakeClient();
217 EXPECT_FALSE(server_stream()->encryption_established());
218 EXPECT_FALSE(server_stream()->handshake_confirmed());
219
220 // Now do another handshake, with the blocking SHLO connection option.
221 InitializeServer();
wube9dc7da2019-05-22 06:08:54 -0700222 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500223
224 AdvanceHandshakeWithFakeClient();
225 EXPECT_TRUE(server_stream()->encryption_established());
226 EXPECT_TRUE(server_stream()->handshake_confirmed());
227 EXPECT_EQ(ENCRYPTION_FORWARD_SECURE,
228 server_session_->connection()->encryption_level());
229}
230
QUICHE teama6ef0a62019-03-07 20:34:33 -0500231TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
232 Initialize();
wube9dc7da2019-05-22 06:08:54 -0700233 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500234
235 // Do a first handshake in order to prime the client config with the server's
236 // information.
237 AdvanceHandshakeWithFakeClient();
238 EXPECT_FALSE(server_stream()->ZeroRttAttempted());
239
240 // Now do another handshake, hopefully in 0-RTT.
241 QUIC_LOG(INFO) << "Resetting for 0-RTT handshake attempt";
wube9dc7da2019-05-22 06:08:54 -0700242 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500243 InitializeServer();
244
245 EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
246 EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
247 .Times(testing::AnyNumber());
248 EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
249 client_stream()->CryptoConnect();
250
251 EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
252 EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
253 .Times(testing::AnyNumber());
254 EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
255 crypto_test_utils::CommunicateHandshakeMessages(
256 client_connection_, client_stream(), server_connection_, server_stream());
257
258 EXPECT_EQ(1, client_stream()->num_sent_client_hellos());
259 EXPECT_TRUE(server_stream()->ZeroRttAttempted());
260}
261
262TEST_P(QuicCryptoServerStreamTest, FailByPolicy) {
263 Initialize();
wube9dc7da2019-05-22 06:08:54 -0700264 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500265
266 EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
267 .WillOnce(testing::Return(false));
268 EXPECT_CALL(*server_connection_,
269 CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
270
271 AdvanceHandshakeWithFakeClient();
272}
273
274TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
275 Initialize();
276 CompleteCryptoHandshake();
277 EXPECT_CALL(
278 *server_connection_,
279 CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, _, _));
280 message_.set_tag(kCHLO);
281 crypto_test_utils::SendHandshakeMessageToStream(server_stream(), message_,
282 Perspective::IS_CLIENT);
283}
284
285TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
286 Initialize();
287
288 message_.set_tag(kSHLO);
289 EXPECT_CALL(*server_connection_,
290 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, _, _));
291 crypto_test_utils::SendHandshakeMessageToStream(server_stream(), message_,
292 Perspective::IS_SERVER);
293}
294
QUICHE teama6ef0a62019-03-07 20:34:33 -0500295TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) {
296 // An attempt to send a SCUP before completing handshake should fail.
297 Initialize();
298
299 server_stream()->SendServerConfigUpdate(nullptr);
300 EXPECT_EQ(0, server_stream()->NumServerConfigUpdateMessagesSent());
301}
302
303TEST_P(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
304 Initialize();
305
wube9dc7da2019-05-22 06:08:54 -0700306 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500307
308 // Do a first handshake in order to prime the client config with the server's
309 // information.
310 AdvanceHandshakeWithFakeClient();
311
312 // Now do another handshake, with the blocking SHLO connection option.
313 InitializeServer();
wube9dc7da2019-05-22 06:08:54 -0700314 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500315 AdvanceHandshakeWithFakeClient();
316
317 // Send a SCUP message and ensure that the client was able to verify it.
318 EXPECT_CALL(*client_connection_, CloseConnection(_, _, _)).Times(0);
319 server_stream()->SendServerConfigUpdate(nullptr);
320 crypto_test_utils::AdvanceHandshake(client_connection_, client_stream(), 1,
321 server_connection_, server_stream(), 1);
322
323 EXPECT_EQ(1, server_stream()->NumServerConfigUpdateMessagesSent());
324 EXPECT_EQ(1, client_stream()->num_scup_messages_received());
325}
326
QUICHE teama6ef0a62019-03-07 20:34:33 -0500327class QuicCryptoServerStreamTestWithFailingProofSource
328 : public QuicCryptoServerStreamTest {
329 public:
330 QuicCryptoServerStreamTestWithFailingProofSource()
331 : QuicCryptoServerStreamTest(
332 std::unique_ptr<FailingProofSource>(new FailingProofSource)) {}
333};
334
335INSTANTIATE_TEST_SUITE_P(MoreTests,
336 QuicCryptoServerStreamTestWithFailingProofSource,
337 testing::Bool());
338
339TEST_P(QuicCryptoServerStreamTestWithFailingProofSource, Test) {
340 Initialize();
wube9dc7da2019-05-22 06:08:54 -0700341 InitializeFakeClient();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500342
343 EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
344 .WillOnce(testing::Return(true));
345 EXPECT_CALL(*server_connection_,
346 CloseConnection(QUIC_HANDSHAKE_FAILED, "Failed to get proof", _));
347 // Regression test for b/31521252, in which a crash would happen here.
348 AdvanceHandshakeWithFakeClient();
349 EXPECT_FALSE(server_stream()->encryption_established());
350 EXPECT_FALSE(server_stream()->handshake_confirmed());
351}
352
353class QuicCryptoServerStreamTestWithFakeProofSource
354 : public QuicCryptoServerStreamTest {
355 public:
356 QuicCryptoServerStreamTestWithFakeProofSource()
357 : QuicCryptoServerStreamTest(
358 std::unique_ptr<FakeProofSource>(new FakeProofSource)),
359 crypto_config_peer_(&server_crypto_config_) {}
360
361 FakeProofSource* GetFakeProofSource() const {
362 return static_cast<FakeProofSource*>(crypto_config_peer_.GetProofSource());
363 }
364
365 protected:
366 QuicCryptoServerConfigPeer crypto_config_peer_;
367};
368
369INSTANTIATE_TEST_SUITE_P(YetMoreTests,
370 QuicCryptoServerStreamTestWithFakeProofSource,
371 testing::Bool());
372
373// Regression test for b/35422225, in which multiple CHLOs arriving on the same
374// connection in close succession could cause a crash, especially when the use
375// of Mentat signing meant that it took a while for each CHLO to be processed.
376TEST_P(QuicCryptoServerStreamTestWithFakeProofSource, MultipleChlo) {
377 Initialize();
378 GetFakeProofSource()->Activate();
379 EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
380 .WillOnce(testing::Return(true));
381
382 // Create a minimal CHLO
383 MockClock clock;
384 QuicTransportVersion version = AllSupportedTransportVersions().front();
385 CryptoHandshakeMessage chlo = crypto_test_utils::GenerateDefaultInchoateCHLO(
386 &clock, version, &server_crypto_config_);
387
388 // Send in the CHLO, and check that a callback is now pending in the
389 // ProofSource.
390 crypto_test_utils::SendHandshakeMessageToStream(server_stream(), chlo,
391 Perspective::IS_CLIENT);
392 EXPECT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
393
394 // Send in a second CHLO while processing of the first is still pending.
395 // Verify that the server closes the connection rather than crashing. Note
396 // that the crash is a use-after-free, so it may only show up consistently in
397 // ASAN tests.
398 EXPECT_CALL(
399 *server_connection_,
400 CloseConnection(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO,
401 "Unexpected handshake message while processing CHLO", _));
402 crypto_test_utils::SendHandshakeMessageToStream(server_stream(), chlo,
403 Perspective::IS_CLIENT);
404}
405
406} // namespace
407} // namespace test
408} // namespace quic