Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_crypto_server_stream_test.cc
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 "net/quic/quic_crypto_server_stream.h"
6
7 #include <map>
8 #include <vector>
9
10 #include "base/memory/scoped_ptr.h"
11 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
12 #include "net/quic/crypto/crypto_framer.h"
13 #include "net/quic/crypto/crypto_handshake.h"
14 #include "net/quic/crypto/crypto_protocol.h"
15 #include "net/quic/crypto/crypto_utils.h"
16 #include "net/quic/crypto/quic_crypto_server_config.h"
17 #include "net/quic/crypto/quic_decrypter.h"
18 #include "net/quic/crypto/quic_encrypter.h"
19 #include "net/quic/crypto/quic_random.h"
20 #include "net/quic/quic_crypto_client_stream.h"
21 #include "net/quic/quic_protocol.h"
22 #include "net/quic/quic_session.h"
23 #include "net/quic/test_tools/crypto_test_utils.h"
24 #include "net/quic/test_tools/delayed_verify_strike_register_client.h"
25 #include "net/quic/test_tools/quic_test_utils.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 namespace net {
30 class QuicConnection;
31 class ReliableQuicStream;
32 }  // namespace net
33
34 using std::pair;
35 using testing::_;
36
37 namespace net {
38 namespace test {
39
40 class QuicCryptoServerConfigPeer {
41  public:
42   static string GetPrimaryOrbit(const QuicCryptoServerConfig& config) {
43     base::AutoLock lock(config.configs_lock_);
44     CHECK(config.primary_config_.get() != NULL);
45     return string(reinterpret_cast<const char*>(config.primary_config_->orbit),
46                   kOrbitSize);
47   }
48 };
49
50 namespace {
51
52 const char kServerHostname[] = "test.example.com";
53 const uint16 kServerPort = 80;
54
55 class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
56  public:
57   QuicCryptoServerStreamTest()
58       : connection_(new PacketSavingConnection(true)),
59         session_(connection_, DefaultQuicConfig()),
60         crypto_config_(QuicCryptoServerConfig::TESTING,
61                        QuicRandom::GetInstance()),
62         stream_(crypto_config_, &session_),
63         strike_register_client_(NULL) {
64     config_.SetDefaults();
65     session_.config()->SetDefaults();
66     session_.SetCryptoStream(&stream_);
67     // We advance the clock initially because the default time is zero and the
68     // strike register worries that we've just overflowed a uint32 time.
69     connection_->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
70     // TODO(wtc): replace this with ProofSourceForTesting() when Chromium has
71     // a working ProofSourceForTesting().
72     crypto_config_.SetProofSource(CryptoTestUtils::FakeProofSourceForTesting());
73     crypto_config_.set_strike_register_no_startup_period();
74
75     CryptoTestUtils::SetupCryptoServerConfigForTest(
76         connection_->clock(), connection_->random_generator(),
77         session_.config(), &crypto_config_);
78
79     if (AsyncStrikeRegisterVerification()) {
80       string orbit =
81           QuicCryptoServerConfigPeer::GetPrimaryOrbit(crypto_config_);
82       strike_register_client_ = new DelayedVerifyStrikeRegisterClient(
83           10000,  // strike_register_max_entries
84           static_cast<uint32>(connection_->clock()->WallNow().ToUNIXSeconds()),
85           60,  // strike_register_window_secs
86           reinterpret_cast<const uint8 *>(orbit.data()),
87           StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
88       strike_register_client_->StartDelayingVerification();
89       crypto_config_.SetStrikeRegisterClient(strike_register_client_);
90     }
91   }
92
93   bool AsyncStrikeRegisterVerification() {
94     return GetParam();
95   }
96
97   void ConstructHandshakeMessage() {
98     CryptoFramer framer;
99     message_data_.reset(framer.ConstructHandshakeMessage(message_));
100   }
101
102   int CompleteCryptoHandshake() {
103     return CryptoTestUtils::HandshakeWithFakeClient(connection_, &stream_,
104                                                     client_options_);
105   }
106
107  protected:
108   PacketSavingConnection* connection_;
109   TestClientSession session_;
110   QuicConfig config_;
111   QuicCryptoServerConfig crypto_config_;
112   QuicCryptoServerStream stream_;
113   CryptoHandshakeMessage message_;
114   scoped_ptr<QuicData> message_data_;
115   CryptoTestUtils::FakeClientOptions client_options_;
116   DelayedVerifyStrikeRegisterClient* strike_register_client_;
117 };
118
119 INSTANTIATE_TEST_CASE_P(Tests, QuicCryptoServerStreamTest, testing::Bool());
120
121 TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
122   EXPECT_FALSE(stream_.encryption_established());
123   EXPECT_FALSE(stream_.handshake_confirmed());
124 }
125
126 TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
127   // CompleteCryptoHandshake returns the number of client hellos sent. This
128   // test should send:
129   //   * One to get a source-address token and certificates.
130   //   * One to complete the handshake.
131   EXPECT_EQ(2, CompleteCryptoHandshake());
132   EXPECT_TRUE(stream_.encryption_established());
133   EXPECT_TRUE(stream_.handshake_confirmed());
134   EXPECT_EQ(1, stream_.num_server_config_update_messages_sent());
135 }
136
137 TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
138   PacketSavingConnection* client_conn = new PacketSavingConnection(false);
139   PacketSavingConnection* server_conn = new PacketSavingConnection(false);
140   client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
141   server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
142
143   QuicConfig client_config;
144   client_config.SetDefaults();
145   scoped_ptr<TestClientSession> client_session(
146       new TestClientSession(client_conn, client_config));
147   QuicCryptoClientConfig client_crypto_config;
148   client_crypto_config.SetDefaults();
149
150   QuicServerId server_id(kServerHostname, kServerPort, false,
151                          PRIVACY_MODE_DISABLED);
152   scoped_ptr<QuicCryptoClientStream> client(new QuicCryptoClientStream(
153       server_id, client_session.get(), NULL, &client_crypto_config));
154   client_session->SetCryptoStream(client.get());
155
156   // Do a first handshake in order to prime the client config with the server's
157   // information.
158   CHECK(client->CryptoConnect());
159   CHECK_EQ(1u, client_conn->packets_.size());
160
161   scoped_ptr<TestSession> server_session(new TestSession(server_conn, config_));
162   scoped_ptr<QuicCryptoServerStream> server(
163       new QuicCryptoServerStream(crypto_config_, server_session.get()));
164   server_session->SetCryptoStream(server.get());
165
166   CryptoTestUtils::CommunicateHandshakeMessages(
167       client_conn, client.get(), server_conn, server.get());
168   EXPECT_EQ(2, client->num_sent_client_hellos());
169
170   // Now do another handshake, hopefully in 0-RTT.
171   LOG(INFO) << "Resetting for 0-RTT handshake attempt";
172
173   client_conn = new PacketSavingConnection(false);
174   server_conn = new PacketSavingConnection(false);
175   // We need to advance time past the strike-server window so that it's
176   // authoritative in this time span.
177   client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000));
178   server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000));
179
180   // This causes the client's nonce to be different and thus stops the
181   // strike-register from rejecting the repeated nonce.
182   reinterpret_cast<MockRandom*>(client_conn->random_generator())->ChangeValue();
183   client_session.reset(new TestClientSession(client_conn, client_config));
184   server_session.reset(new TestSession(server_conn, config_));
185   client.reset(new QuicCryptoClientStream(
186       server_id, client_session.get(), NULL, &client_crypto_config));
187   client_session->SetCryptoStream(client.get());
188
189   server.reset(new QuicCryptoServerStream(crypto_config_,
190                                           server_session.get()));
191   server_session->SetCryptoStream(server.get());
192
193   CHECK(client->CryptoConnect());
194
195   if (AsyncStrikeRegisterVerification()) {
196     EXPECT_FALSE(client->handshake_confirmed());
197     EXPECT_FALSE(server->handshake_confirmed());
198
199     // Advance the handshake.  Expect that the server will be stuck
200     // waiting for client nonce verification to complete.
201     pair<size_t, size_t> messages_moved = CryptoTestUtils::AdvanceHandshake(
202         client_conn, client.get(), 0, server_conn, server.get(), 0);
203     EXPECT_EQ(1u, messages_moved.first);
204     EXPECT_EQ(0u, messages_moved.second);
205     EXPECT_EQ(1, strike_register_client_->PendingVerifications());
206     EXPECT_FALSE(client->handshake_confirmed());
207     EXPECT_FALSE(server->handshake_confirmed());
208
209     // The server handshake completes once the nonce verification completes.
210     strike_register_client_->RunPendingVerifications();
211     EXPECT_FALSE(client->handshake_confirmed());
212     EXPECT_TRUE(server->handshake_confirmed());
213
214     messages_moved = CryptoTestUtils::AdvanceHandshake(
215         client_conn, client.get(), messages_moved.first,
216         server_conn, server.get(), messages_moved.second);
217     EXPECT_EQ(1u, messages_moved.first);
218     EXPECT_EQ(1u, messages_moved.second);
219     EXPECT_TRUE(client->handshake_confirmed());
220     EXPECT_TRUE(server->handshake_confirmed());
221   } else {
222     CryptoTestUtils::CommunicateHandshakeMessages(
223         client_conn, client.get(), server_conn, server.get());
224   }
225
226   EXPECT_EQ(1, client->num_sent_client_hellos());
227   EXPECT_EQ(1, server->num_server_config_update_messages_sent());
228 }
229
230 TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
231   CompleteCryptoHandshake();
232   EXPECT_CALL(*connection_, SendConnectionClose(
233       QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
234   message_.set_tag(kCHLO);
235   ConstructHandshakeMessage();
236   stream_.ProcessRawData(message_data_->data(), message_data_->length());
237 }
238
239 TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
240   message_.set_tag(kSHLO);
241   ConstructHandshakeMessage();
242   EXPECT_CALL(*connection_, SendConnectionClose(
243       QUIC_INVALID_CRYPTO_MESSAGE_TYPE));
244   stream_.ProcessRawData(message_data_->data(), message_data_->length());
245 }
246
247 TEST_P(QuicCryptoServerStreamTest, WithoutCertificates) {
248   crypto_config_.SetProofSource(NULL);
249   client_options_.dont_verify_certs = true;
250
251   // Only 2 client hellos need to be sent in the no-certs case: one to get the
252   // source-address token and the second to finish.
253   EXPECT_EQ(2, CompleteCryptoHandshake());
254   EXPECT_TRUE(stream_.encryption_established());
255   EXPECT_TRUE(stream_.handshake_confirmed());
256 }
257
258 TEST_P(QuicCryptoServerStreamTest, ChannelID) {
259   client_options_.channel_id_enabled = true;
260   client_options_.channel_id_source_async = false;
261   // CompleteCryptoHandshake verifies
262   // stream_.crypto_negotiated_params().channel_id is correct.
263   EXPECT_EQ(2, CompleteCryptoHandshake());
264   EXPECT_TRUE(stream_.encryption_established());
265   EXPECT_TRUE(stream_.handshake_confirmed());
266 }
267
268 TEST_P(QuicCryptoServerStreamTest, ChannelIDAsync) {
269   client_options_.channel_id_enabled = true;
270   client_options_.channel_id_source_async = true;
271   // CompleteCryptoHandshake verifies
272   // stream_.crypto_negotiated_params().channel_id is correct.
273   EXPECT_EQ(2, CompleteCryptoHandshake());
274   EXPECT_TRUE(stream_.encryption_established());
275   EXPECT_TRUE(stream_.handshake_confirmed());
276 }
277
278 TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) {
279   // An attempt to send a SCUP before completing handshake should fail.
280   stream_.SendServerConfigUpdate(NULL);
281   EXPECT_EQ(0, stream_.num_server_config_update_messages_sent());
282 }
283
284 }  // namespace
285 }  // namespace test
286 }  // namespace net