Add some instrumentation to investigate a possible use after free.
[chromium-blink-merge.git] / net / quic / quic_crypto_client_stream_test.cc
blob170a921818538637cc7bd8b9bc020bf92b3adcb9
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.
5 #include "net/quic/quic_crypto_client_stream.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
9 #include "net/quic/crypto/quic_decrypter.h"
10 #include "net/quic/crypto/quic_encrypter.h"
11 #include "net/quic/quic_flags.h"
12 #include "net/quic/quic_protocol.h"
13 #include "net/quic/quic_server_id.h"
14 #include "net/quic/quic_utils.h"
15 #include "net/quic/test_tools/crypto_test_utils.h"
16 #include "net/quic/test_tools/quic_test_utils.h"
17 #include "net/quic/test_tools/simple_quic_framer.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using std::string;
23 namespace net {
24 namespace test {
25 namespace {
27 const char kServerHostname[] = "example.com";
28 const uint16 kServerPort = 80;
30 class QuicCryptoClientStreamTest : public ::testing::Test {
31 public:
32 QuicCryptoClientStreamTest()
33 : server_id_(kServerHostname, kServerPort, false, PRIVACY_MODE_DISABLED) {
34 CreateConnection();
37 void CreateConnection() {
38 connection_ = new PacketSavingConnection(Perspective::IS_CLIENT);
39 // Advance the time, because timers do not like uninitialized times.
40 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
42 session_.reset(new TestQuicSpdyClientSession(
43 connection_, DefaultQuicConfig(), server_id_, &crypto_config_));
46 void CompleteCryptoHandshake() {
47 stream()->CryptoConnect();
48 CryptoTestUtils::HandshakeWithFakeServer(connection_, stream());
51 void ConstructHandshakeMessage() {
52 CryptoFramer framer;
53 message_data_.reset(framer.ConstructHandshakeMessage(message_));
56 QuicCryptoClientStream* stream() { return session_->GetCryptoStream(); }
58 PacketSavingConnection* connection_;
59 scoped_ptr<TestQuicSpdyClientSession> session_;
60 QuicServerId server_id_;
61 CryptoHandshakeMessage message_;
62 scoped_ptr<QuicData> message_data_;
63 QuicCryptoClientConfig crypto_config_;
66 TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
67 EXPECT_FALSE(stream()->encryption_established());
68 EXPECT_FALSE(stream()->handshake_confirmed());
71 TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
72 CompleteCryptoHandshake();
73 EXPECT_TRUE(stream()->encryption_established());
74 EXPECT_TRUE(stream()->handshake_confirmed());
77 TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
78 CompleteCryptoHandshake();
80 EXPECT_CALL(*connection_, SendConnectionClose(
81 QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
82 message_.set_tag(kCHLO);
83 ConstructHandshakeMessage();
84 stream()->OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
85 /*offset=*/0,
86 message_data_->AsStringPiece()));
89 TEST_F(QuicCryptoClientStreamTest, BadMessageType) {
90 stream()->CryptoConnect();
92 message_.set_tag(kCHLO);
93 ConstructHandshakeMessage();
95 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
96 QUIC_INVALID_CRYPTO_MESSAGE_TYPE, "Expected REJ"));
97 stream()->OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
98 /*offset=*/0,
99 message_data_->AsStringPiece()));
102 TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
103 CompleteCryptoHandshake();
105 const QuicConfig* config = session_->config();
106 EXPECT_EQ(kMaximumIdleTimeoutSecs,
107 config->IdleConnectionStateLifetime().ToSeconds());
108 EXPECT_EQ(kDefaultMaxStreamsPerConnection,
109 config->MaxStreamsPerConnection());
111 const QuicCryptoNegotiatedParameters& crypto_params(
112 stream()->crypto_negotiated_params());
113 EXPECT_EQ(crypto_config_.aead[0], crypto_params.aead);
114 EXPECT_EQ(crypto_config_.kexs[0], crypto_params.key_exchange);
117 TEST_F(QuicCryptoClientStreamTest, InvalidHostname) {
118 server_id_ =
119 QuicServerId("invalid", kServerPort, false, PRIVACY_MODE_DISABLED);
121 CreateConnection();
123 CompleteCryptoHandshake();
124 EXPECT_TRUE(stream()->encryption_established());
125 EXPECT_TRUE(stream()->handshake_confirmed());
128 TEST_F(QuicCryptoClientStreamTest, ExpiredServerConfig) {
129 // Seed the config with a cached server config.
130 CompleteCryptoHandshake();
132 // Recreate connection with the new config.
133 CreateConnection();
135 // Advance time 5 years to ensure that we pass the expiry time of the cached
136 // server config.
137 connection_->AdvanceTime(
138 QuicTime::Delta::FromSeconds(60 * 60 * 24 * 365 * 5));
140 stream()->CryptoConnect();
141 // Check that a client hello was sent.
142 ASSERT_EQ(1u, connection_->encrypted_packets_.size());
145 TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdate) {
146 // Test that the crypto client stream can receive server config updates after
147 // the connection has been established.
148 CompleteCryptoHandshake();
150 QuicCryptoClientConfig::CachedState* state =
151 crypto_config_.LookupOrCreate(server_id_);
153 // Ensure cached STK is different to what we send in the handshake.
154 EXPECT_NE("xstk", state->source_address_token());
156 // Initialize using {...} syntax to avoid trailing \0 if converting from
157 // string.
158 unsigned char stk[] = { 'x', 's', 't', 'k' };
160 // Minimum SCFG that passes config validation checks.
161 unsigned char scfg[] = {
162 // SCFG
163 0x53, 0x43, 0x46, 0x47,
164 // num entries
165 0x01, 0x00,
166 // padding
167 0x00, 0x00,
168 // EXPY
169 0x45, 0x58, 0x50, 0x59,
170 // EXPY end offset
171 0x08, 0x00, 0x00, 0x00,
172 // Value
173 '1', '2', '3', '4',
174 '5', '6', '7', '8'
177 CryptoHandshakeMessage server_config_update;
178 server_config_update.set_tag(kSCUP);
179 server_config_update.SetValue(kSourceAddressTokenTag, stk);
180 server_config_update.SetValue(kSCFG, scfg);
182 scoped_ptr<QuicData> data(
183 CryptoFramer::ConstructHandshakeMessage(server_config_update));
184 stream()->OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
185 /*offset=*/0, data->AsStringPiece()));
187 // Make sure that the STK and SCFG are cached correctly.
188 EXPECT_EQ("xstk", state->source_address_token());
190 string cached_scfg = state->server_config();
191 test::CompareCharArraysWithHexError(
192 "scfg", cached_scfg.data(), cached_scfg.length(),
193 QuicUtils::AsChars(scfg), arraysize(scfg));
196 TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
197 EXPECT_CALL(*connection_, SendConnectionClose(
198 QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE));
199 CryptoHandshakeMessage server_config_update;
200 server_config_update.set_tag(kSCUP);
201 scoped_ptr<QuicData> data(
202 CryptoFramer::ConstructHandshakeMessage(server_config_update));
203 stream()->OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
204 /*offset=*/0, data->AsStringPiece()));
207 class QuicCryptoClientStreamStatelessTest : public ::testing::Test {
208 public:
209 QuicCryptoClientStreamStatelessTest()
210 : server_crypto_config_(QuicCryptoServerConfig::TESTING,
211 QuicRandom::GetInstance()),
212 server_id_(kServerHostname, kServerPort, false, PRIVACY_MODE_DISABLED) {
213 TestQuicSpdyClientSession* client_session = nullptr;
214 CreateClientSessionForTest(server_id_,
215 /* supports_stateless_rejects= */ true,
216 QuicTime::Delta::FromSeconds(100000),
217 &client_crypto_config_, &client_connection_,
218 &client_session);
219 CHECK(client_session);
220 client_session_.reset(client_session);
223 QuicCryptoServerStream* server_stream() {
224 return server_session_->GetCryptoStream();
227 void AdvanceHandshakeWithFakeServer() {
228 client_session_->GetCryptoStream()->CryptoConnect();
229 CryptoTestUtils::AdvanceHandshake(client_connection_,
230 client_session_->GetCryptoStream(), 0,
231 server_connection_, server_stream(), 0);
234 // Initializes the server_stream_ for stateless rejects.
235 void InitializeFakeStatelessRejectServer() {
236 TestQuicSpdyServerSession* server_session = nullptr;
237 CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000),
238 &server_crypto_config_, &server_connection_,
239 &server_session);
240 CHECK(server_session);
241 server_session_.reset(server_session);
242 CryptoTestUtils::SetupCryptoServerConfigForTest(
243 server_connection_->clock(), server_connection_->random_generator(),
244 server_session_->config(), &server_crypto_config_);
245 server_stream()->set_use_stateless_rejects_if_peer_supported(true);
248 // Client crypto stream state
249 PacketSavingConnection* client_connection_;
250 scoped_ptr<TestQuicSpdyClientSession> client_session_;
251 QuicCryptoClientConfig client_crypto_config_;
253 // Server crypto stream state
254 PacketSavingConnection* server_connection_;
255 scoped_ptr<TestQuicSpdyServerSession> server_session_;
256 QuicCryptoServerConfig server_crypto_config_;
257 QuicServerId server_id_;
260 TEST_F(QuicCryptoClientStreamStatelessTest, StatelessReject) {
261 ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support,
262 true);
264 QuicCryptoClientConfig::CachedState* client_state =
265 client_crypto_config_.LookupOrCreate(server_id_);
267 EXPECT_FALSE(client_state->has_server_designated_connection_id());
268 EXPECT_CALL(*client_session_, OnProofValid(testing::_));
270 InitializeFakeStatelessRejectServer();
271 AdvanceHandshakeWithFakeServer();
273 EXPECT_EQ(1, server_stream()->num_handshake_messages());
274 EXPECT_EQ(0, server_stream()->num_handshake_messages_with_server_nonces());
276 EXPECT_FALSE(client_session_->GetCryptoStream()->encryption_established());
277 EXPECT_FALSE(client_session_->GetCryptoStream()->handshake_confirmed());
278 // Even though the handshake was not complete, the cached client_state is
279 // complete, and can be used for a subsequent successful handshake.
280 EXPECT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
282 ASSERT_TRUE(client_state->has_server_nonce());
283 ASSERT_FALSE(client_state->GetNextServerNonce().empty());
284 ASSERT_TRUE(client_state->has_server_designated_connection_id());
285 QuicConnectionId server_designated_id =
286 client_state->GetNextServerDesignatedConnectionId();
287 QuicConnectionId expected_id =
288 server_session_->connection()->random_generator()->RandUint64();
289 EXPECT_EQ(expected_id, server_designated_id);
290 EXPECT_FALSE(client_state->has_server_designated_connection_id());
293 } // namespace
294 } // namespace test
295 } // namespace net