xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // 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 <map>
6 #include <memory>
7 #include <utility>
8 #include <vector>
9 
10 #include "absl/strings/string_view.h"
11 #include "quiche/quic/core/crypto/aes_128_gcm_12_encrypter.h"
12 #include "quiche/quic/core/crypto/crypto_framer.h"
13 #include "quiche/quic/core/crypto/crypto_handshake.h"
14 #include "quiche/quic/core/crypto/crypto_protocol.h"
15 #include "quiche/quic/core/crypto/crypto_utils.h"
16 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
17 #include "quiche/quic/core/crypto/quic_decrypter.h"
18 #include "quiche/quic/core/crypto/quic_encrypter.h"
19 #include "quiche/quic/core/crypto/quic_random.h"
20 #include "quiche/quic/core/quic_crypto_client_stream.h"
21 #include "quiche/quic/core/quic_crypto_server_stream_base.h"
22 #include "quiche/quic/core/quic_packets.h"
23 #include "quiche/quic/core/quic_session.h"
24 #include "quiche/quic/core/quic_utils.h"
25 #include "quiche/quic/core/quic_versions.h"
26 #include "quiche/quic/platform/api/quic_flags.h"
27 #include "quiche/quic/platform/api/quic_logging.h"
28 #include "quiche/quic/platform/api/quic_socket_address.h"
29 #include "quiche/quic/platform/api/quic_test.h"
30 #include "quiche/quic/test_tools/crypto_test_utils.h"
31 #include "quiche/quic/test_tools/failing_proof_source.h"
32 #include "quiche/quic/test_tools/fake_proof_source.h"
33 #include "quiche/quic/test_tools/quic_crypto_server_config_peer.h"
34 #include "quiche/quic/test_tools/quic_test_utils.h"
35 
36 namespace quic {
37 class QuicConnection;
38 class QuicStream;
39 }  // namespace quic
40 
41 using testing::_;
42 using testing::NiceMock;
43 
44 namespace quic {
45 namespace test {
46 
47 namespace {
48 
49 const char kServerHostname[] = "test.example.com";
50 const uint16_t kServerPort = 443;
51 
52 // This test tests the server-side of the QUIC crypto handshake. It does not
53 // test the TLS handshake - that is in tls_server_handshaker_test.cc.
54 class QuicCryptoServerStreamTest : public QuicTest {
55  public:
QuicCryptoServerStreamTest()56   QuicCryptoServerStreamTest()
57       : QuicCryptoServerStreamTest(crypto_test_utils::ProofSourceForTesting()) {
58   }
59 
QuicCryptoServerStreamTest(std::unique_ptr<ProofSource> proof_source)60   explicit QuicCryptoServerStreamTest(std::unique_ptr<ProofSource> proof_source)
61       : server_crypto_config_(
62             QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
63             std::move(proof_source), KeyExchangeSource::Default()),
64         server_compressed_certs_cache_(
65             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
66         server_id_(kServerHostname, kServerPort, false),
67         client_crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {}
68 
Initialize()69   void Initialize() { InitializeServer(); }
70 
~QuicCryptoServerStreamTest()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.
InitializeServer()82   void InitializeServer() {
83     TestQuicSpdyServerSession* server_session = nullptr;
84     helpers_.push_back(std::make_unique<NiceMock<MockQuicConnectionHelper>>());
85     alarm_factories_.push_back(std::make_unique<MockAlarmFactory>());
86     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     QUICHE_CHECK(server_session);
92     server_session_.reset(server_session);
93     EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
94         .Times(testing::AnyNumber());
95     EXPECT_CALL(*server_session_, SelectAlpn(_))
96         .WillRepeatedly([this](const std::vector<absl::string_view>& alpns) {
97           return std::find(
98               alpns.cbegin(), alpns.cend(),
99               AlpnForVersion(server_session_->connection()->version()));
100         });
101     crypto_test_utils::SetupCryptoServerConfigForTest(
102         server_connection_->clock(), server_connection_->random_generator(),
103         &server_crypto_config_);
104   }
105 
server_stream()106   QuicCryptoServerStreamBase* server_stream() {
107     return server_session_->GetMutableCryptoStream();
108   }
109 
client_stream()110   QuicCryptoClientStream* client_stream() {
111     return client_session_->GetMutableCryptoStream();
112   }
113 
114   // Initializes a fake client, and all its associated state, for
115   // testing.  May be called multiple times.
InitializeFakeClient()116   void InitializeFakeClient() {
117     TestQuicSpdyClientSession* client_session = nullptr;
118     helpers_.push_back(std::make_unique<NiceMock<MockQuicConnectionHelper>>());
119     alarm_factories_.push_back(std::make_unique<MockAlarmFactory>());
120     CreateClientSessionForTest(
121         server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
122         helpers_.back().get(), alarm_factories_.back().get(),
123         &client_crypto_config_, &client_connection_, &client_session);
124     QUICHE_CHECK(client_session);
125     client_session_.reset(client_session);
126   }
127 
CompleteCryptoHandshake()128   int CompleteCryptoHandshake() {
129     QUICHE_CHECK(server_connection_);
130     QUICHE_CHECK(server_session_ != nullptr);
131 
132     return crypto_test_utils::HandshakeWithFakeClient(
133         helpers_.back().get(), alarm_factories_.back().get(),
134         server_connection_, server_stream(), server_id_, client_options_,
135         /*alpn=*/"");
136   }
137 
138   // Performs a single round of handshake message-exchange between the
139   // client and server.
AdvanceHandshakeWithFakeClient()140   void AdvanceHandshakeWithFakeClient() {
141     QUICHE_CHECK(server_connection_);
142     QUICHE_CHECK(client_session_ != nullptr);
143 
144     EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
145     EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
146         .Times(testing::AnyNumber());
147     EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
148     EXPECT_CALL(*server_connection_, OnCanWrite()).Times(testing::AnyNumber());
149     client_stream()->CryptoConnect();
150     crypto_test_utils::AdvanceHandshake(client_connection_, client_stream(), 0,
151                                         server_connection_, server_stream(), 0);
152   }
153 
154  protected:
155   // Every connection gets its own MockQuicConnectionHelper and
156   // MockAlarmFactory, tracked separately from the server and client state so
157   // their lifetimes persist through the whole test.
158   std::vector<std::unique_ptr<MockQuicConnectionHelper>> helpers_;
159   std::vector<std::unique_ptr<MockAlarmFactory>> alarm_factories_;
160 
161   // Server state.
162   PacketSavingConnection* server_connection_;
163   std::unique_ptr<TestQuicSpdyServerSession> server_session_;
164   QuicCryptoServerConfig server_crypto_config_;
165   QuicCompressedCertsCache server_compressed_certs_cache_;
166   QuicServerId server_id_;
167 
168   // Client state.
169   PacketSavingConnection* client_connection_;
170   QuicCryptoClientConfig client_crypto_config_;
171   std::unique_ptr<TestQuicSpdyClientSession> client_session_;
172 
173   CryptoHandshakeMessage message_;
174   crypto_test_utils::FakeClientOptions client_options_;
175 
176   // Which QUIC versions the client and server support.
177   ParsedQuicVersionVector supported_versions_ =
178       AllSupportedVersionsWithQuicCrypto();
179 };
180 
TEST_F(QuicCryptoServerStreamTest,NotInitiallyConected)181 TEST_F(QuicCryptoServerStreamTest, NotInitiallyConected) {
182   Initialize();
183   EXPECT_FALSE(server_stream()->encryption_established());
184   EXPECT_FALSE(server_stream()->one_rtt_keys_available());
185 }
186 
TEST_F(QuicCryptoServerStreamTest,ConnectedAfterCHLO)187 TEST_F(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
188   // CompleteCryptoHandshake returns the number of client hellos sent. This
189   // test should send:
190   //   * One to get a source-address token and certificates.
191   //   * One to complete the handshake.
192   Initialize();
193   EXPECT_EQ(2, CompleteCryptoHandshake());
194   EXPECT_TRUE(server_stream()->encryption_established());
195   EXPECT_TRUE(server_stream()->one_rtt_keys_available());
196 }
197 
TEST_F(QuicCryptoServerStreamTest,ForwardSecureAfterCHLO)198 TEST_F(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
199   Initialize();
200   InitializeFakeClient();
201 
202   // Do a first handshake in order to prime the client config with the server's
203   // information.
204   AdvanceHandshakeWithFakeClient();
205   EXPECT_FALSE(server_stream()->encryption_established());
206   EXPECT_FALSE(server_stream()->one_rtt_keys_available());
207 
208   // Now do another handshake, with the blocking SHLO connection option.
209   InitializeServer();
210   InitializeFakeClient();
211 
212   AdvanceHandshakeWithFakeClient();
213   if (GetQuicReloadableFlag(quic_require_handshake_confirmation)) {
214     crypto_test_utils::AdvanceHandshake(client_connection_, client_stream(), 0,
215                                         server_connection_, server_stream(), 0);
216   }
217   EXPECT_TRUE(server_stream()->encryption_established());
218   EXPECT_TRUE(server_stream()->one_rtt_keys_available());
219   EXPECT_EQ(ENCRYPTION_FORWARD_SECURE,
220             server_session_->connection()->encryption_level());
221 }
222 
TEST_F(QuicCryptoServerStreamTest,ZeroRTT)223 TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
224   Initialize();
225   InitializeFakeClient();
226 
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()->ResumptionAttempted());
231 
232   // Now do another handshake, hopefully in 0-RTT.
233   QUIC_LOG(INFO) << "Resetting for 0-RTT handshake attempt";
234   InitializeFakeClient();
235   InitializeServer();
236 
237   EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
238   EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
239       .Times(testing::AnyNumber());
240   EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
241   client_stream()->CryptoConnect();
242 
243   EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
244   EXPECT_CALL(*client_session_, OnProofVerifyDetailsAvailable(_))
245       .Times(testing::AnyNumber());
246   EXPECT_CALL(*client_connection_, OnCanWrite()).Times(testing::AnyNumber());
247   crypto_test_utils::CommunicateHandshakeMessages(
248       client_connection_, client_stream(), server_connection_, server_stream());
249 
250   EXPECT_EQ(
251       (GetQuicReloadableFlag(quic_require_handshake_confirmation) ? 2 : 1),
252       client_stream()->num_sent_client_hellos());
253   EXPECT_TRUE(server_stream()->ResumptionAttempted());
254 }
255 
TEST_F(QuicCryptoServerStreamTest,FailByPolicy)256 TEST_F(QuicCryptoServerStreamTest, FailByPolicy) {
257   Initialize();
258   InitializeFakeClient();
259 
260   EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
261       .WillOnce(testing::Return(false));
262   EXPECT_CALL(*server_connection_,
263               CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
264 
265   AdvanceHandshakeWithFakeClient();
266 }
267 
TEST_F(QuicCryptoServerStreamTest,MessageAfterHandshake)268 TEST_F(QuicCryptoServerStreamTest, MessageAfterHandshake) {
269   Initialize();
270   CompleteCryptoHandshake();
271   EXPECT_CALL(
272       *server_connection_,
273       CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, _, _));
274   message_.set_tag(kCHLO);
275   crypto_test_utils::SendHandshakeMessageToStream(server_stream(), message_,
276                                                   Perspective::IS_CLIENT);
277 }
278 
TEST_F(QuicCryptoServerStreamTest,BadMessageType)279 TEST_F(QuicCryptoServerStreamTest, BadMessageType) {
280   Initialize();
281 
282   message_.set_tag(kSHLO);
283   EXPECT_CALL(*server_connection_,
284               CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, _, _));
285   crypto_test_utils::SendHandshakeMessageToStream(server_stream(), message_,
286                                                   Perspective::IS_SERVER);
287 }
288 
TEST_F(QuicCryptoServerStreamTest,OnlySendSCUPAfterHandshakeComplete)289 TEST_F(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) {
290   // An attempt to send a SCUP before completing handshake should fail.
291   Initialize();
292 
293   server_stream()->SendServerConfigUpdate(nullptr);
294   EXPECT_EQ(0, server_stream()->NumServerConfigUpdateMessagesSent());
295 }
296 
TEST_F(QuicCryptoServerStreamTest,SendSCUPAfterHandshakeComplete)297 TEST_F(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
298   Initialize();
299 
300   InitializeFakeClient();
301 
302   // Do a first handshake in order to prime the client config with the server's
303   // information.
304   AdvanceHandshakeWithFakeClient();
305 
306   // Now do another handshake, with the blocking SHLO connection option.
307   InitializeServer();
308   InitializeFakeClient();
309   AdvanceHandshakeWithFakeClient();
310   if (GetQuicReloadableFlag(quic_require_handshake_confirmation)) {
311     crypto_test_utils::AdvanceHandshake(client_connection_, client_stream(), 0,
312                                         server_connection_, server_stream(), 0);
313   }
314 
315   // Send a SCUP message and ensure that the client was able to verify it.
316   EXPECT_CALL(*client_connection_, CloseConnection(_, _, _)).Times(0);
317   server_stream()->SendServerConfigUpdate(nullptr);
318   crypto_test_utils::AdvanceHandshake(client_connection_, client_stream(), 1,
319                                       server_connection_, server_stream(), 1);
320 
321   EXPECT_EQ(1, server_stream()->NumServerConfigUpdateMessagesSent());
322   EXPECT_EQ(1, client_stream()->num_scup_messages_received());
323 }
324 
325 class QuicCryptoServerStreamTestWithFailingProofSource
326     : public QuicCryptoServerStreamTest {
327  public:
QuicCryptoServerStreamTestWithFailingProofSource()328   QuicCryptoServerStreamTestWithFailingProofSource()
329       : QuicCryptoServerStreamTest(
330             std::unique_ptr<FailingProofSource>(new FailingProofSource)) {}
331 };
332 
TEST_F(QuicCryptoServerStreamTestWithFailingProofSource,Test)333 TEST_F(QuicCryptoServerStreamTestWithFailingProofSource, Test) {
334   Initialize();
335   InitializeFakeClient();
336 
337   EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
338       .WillOnce(testing::Return(true));
339   EXPECT_CALL(*server_connection_,
340               CloseConnection(QUIC_HANDSHAKE_FAILED, "Failed to get proof", _));
341   // Regression test for b/31521252, in which a crash would happen here.
342   AdvanceHandshakeWithFakeClient();
343   EXPECT_FALSE(server_stream()->encryption_established());
344   EXPECT_FALSE(server_stream()->one_rtt_keys_available());
345 }
346 
347 class QuicCryptoServerStreamTestWithFakeProofSource
348     : public QuicCryptoServerStreamTest {
349  public:
QuicCryptoServerStreamTestWithFakeProofSource()350   QuicCryptoServerStreamTestWithFakeProofSource()
351       : QuicCryptoServerStreamTest(
352             std::unique_ptr<FakeProofSource>(new FakeProofSource)),
353         crypto_config_peer_(&server_crypto_config_) {}
354 
GetFakeProofSource() const355   FakeProofSource* GetFakeProofSource() const {
356     return static_cast<FakeProofSource*>(crypto_config_peer_.GetProofSource());
357   }
358 
359  protected:
360   QuicCryptoServerConfigPeer crypto_config_peer_;
361 };
362 
363 // Regression test for b/35422225, in which multiple CHLOs arriving on the same
364 // connection in close succession could cause a crash.
TEST_F(QuicCryptoServerStreamTestWithFakeProofSource,MultipleChlo)365 TEST_F(QuicCryptoServerStreamTestWithFakeProofSource, MultipleChlo) {
366   Initialize();
367   GetFakeProofSource()->Activate();
368   EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
369       .WillOnce(testing::Return(true));
370 
371   // The methods below use a PROTOCOL_QUIC_CRYPTO version so we pick the
372   // first one from the list of supported versions.
373   QuicTransportVersion transport_version = QUIC_VERSION_UNSUPPORTED;
374   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
375     if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
376       transport_version = version.transport_version;
377       break;
378     }
379   }
380   ASSERT_NE(QUIC_VERSION_UNSUPPORTED, transport_version);
381 
382   // Create a minimal CHLO
383   MockClock clock;
384   CryptoHandshakeMessage chlo = crypto_test_utils::GenerateDefaultInchoateCHLO(
385       &clock, transport_version, &server_crypto_config_);
386 
387   // Send in the CHLO, and check that a callback is now pending in the
388   // ProofSource.
389   crypto_test_utils::SendHandshakeMessageToStream(server_stream(), chlo,
390                                                   Perspective::IS_CLIENT);
391   EXPECT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
392 
393   // Send in a second CHLO while processing of the first is still pending.
394   // Verify that the server closes the connection rather than crashing.  Note
395   // that the crash is a use-after-free, so it may only show up consistently in
396   // ASAN tests.
397   EXPECT_CALL(
398       *server_connection_,
399       CloseConnection(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO,
400                       "Unexpected handshake message while processing CHLO", _));
401   crypto_test_utils::SendHandshakeMessageToStream(server_stream(), chlo,
402                                                   Perspective::IS_CLIENT);
403 }
404 
405 }  // namespace
406 }  // namespace test
407 }  // namespace quic
408