quic_crypto_server_stream_test.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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
29namespace net {
30class QuicConnection;
31class ReliableQuicStream;
32}  // namespace net
33
34using std::pair;
35using testing::_;
36
37namespace net {
38namespace test {
39
40class QuicCryptoServerConfigPeer {
41 public:
42  static string GetPrimaryOrbit(const QuicCryptoServerConfig& config) {
43    base::AutoLock lock(config.configs_lock_);
44    CHECK(config.primary_config_ != NULL);
45    return string(reinterpret_cast<const char*>(config.primary_config_->orbit),
46                  kOrbitSize);
47  }
48};
49
50namespace {
51
52const char kServerHostname[] = "test.example.com";
53const uint16 kServerPort = 80;
54
55class 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(rtenneti): Enable testing of ProofSource.
71    // crypto_config_.SetProofSource(CryptoTestUtils::ProofSourceForTesting());
72    crypto_config_.set_strike_register_no_startup_period();
73
74    CryptoTestUtils::SetupCryptoServerConfigForTest(
75        connection_->clock(), connection_->random_generator(),
76        session_.config(), &crypto_config_);
77
78    if (AsyncStrikeRegisterVerification()) {
79      string orbit =
80          QuicCryptoServerConfigPeer::GetPrimaryOrbit(crypto_config_);
81      strike_register_client_ = new DelayedVerifyStrikeRegisterClient(
82          10000,  // strike_register_max_entries
83          static_cast<uint32>(connection_->clock()->WallNow().ToUNIXSeconds()),
84          60,  // strike_register_window_secs
85          reinterpret_cast<const uint8 *>(orbit.data()),
86          StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
87      strike_register_client_->StartDelayingVerification();
88      crypto_config_.SetStrikeRegisterClient(strike_register_client_);
89    }
90  }
91
92  bool AsyncStrikeRegisterVerification() {
93    return GetParam();
94  }
95
96  void ConstructHandshakeMessage() {
97    CryptoFramer framer;
98    message_data_.reset(framer.ConstructHandshakeMessage(message_));
99  }
100
101  int CompleteCryptoHandshake() {
102    return CryptoTestUtils::HandshakeWithFakeClient(connection_, &stream_,
103                                                    client_options_);
104  }
105
106 protected:
107  PacketSavingConnection* connection_;
108  TestClientSession session_;
109  QuicConfig config_;
110  QuicCryptoServerConfig crypto_config_;
111  QuicCryptoServerStream stream_;
112  CryptoHandshakeMessage message_;
113  scoped_ptr<QuicData> message_data_;
114  CryptoTestUtils::FakeClientOptions client_options_;
115  DelayedVerifyStrikeRegisterClient* strike_register_client_;
116};
117
118INSTANTIATE_TEST_CASE_P(Tests, QuicCryptoServerStreamTest, testing::Bool());
119
120TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
121  EXPECT_FALSE(stream_.encryption_established());
122  EXPECT_FALSE(stream_.handshake_confirmed());
123}
124
125TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
126  // CompleteCryptoHandshake returns the number of client hellos sent. This
127  // test should send:
128  //   * One to get a source-address token and certificates.
129  //   * One to complete the handshake.
130  EXPECT_EQ(2, CompleteCryptoHandshake());
131  EXPECT_TRUE(stream_.encryption_established());
132  EXPECT_TRUE(stream_.handshake_confirmed());
133}
134
135TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
136  PacketSavingConnection* client_conn = new PacketSavingConnection(false);
137  PacketSavingConnection* server_conn = new PacketSavingConnection(false);
138  client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
139  server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
140
141  QuicConfig client_config;
142  client_config.SetDefaults();
143  scoped_ptr<TestClientSession> client_session(
144      new TestClientSession(client_conn, client_config));
145  QuicCryptoClientConfig client_crypto_config;
146  client_crypto_config.SetDefaults();
147
148  QuicServerId server_id(kServerHostname, kServerPort, false,
149                         PRIVACY_MODE_DISABLED);
150  scoped_ptr<QuicCryptoClientStream> client(new QuicCryptoClientStream(
151      server_id, client_session.get(), NULL, &client_crypto_config));
152  client_session->SetCryptoStream(client.get());
153
154  // Do a first handshake in order to prime the client config with the server's
155  // information.
156  CHECK(client->CryptoConnect());
157  CHECK_EQ(1u, client_conn->packets_.size());
158
159  scoped_ptr<TestSession> server_session(new TestSession(server_conn, config_));
160  scoped_ptr<QuicCryptoServerStream> server(
161      new QuicCryptoServerStream(crypto_config_, server_session.get()));
162  server_session->SetCryptoStream(server.get());
163
164  CryptoTestUtils::CommunicateHandshakeMessages(
165      client_conn, client.get(), server_conn, server.get());
166  EXPECT_EQ(2, client->num_sent_client_hellos());
167
168  // Now do another handshake, hopefully in 0-RTT.
169  LOG(INFO) << "Resetting for 0-RTT handshake attempt";
170
171  client_conn = new PacketSavingConnection(false);
172  server_conn = new PacketSavingConnection(false);
173  // We need to advance time past the strike-server window so that it's
174  // authoritative in this time span.
175  client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000));
176  server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000));
177
178  // This causes the client's nonce to be different and thus stops the
179  // strike-register from rejecting the repeated nonce.
180  reinterpret_cast<MockRandom*>(client_conn->random_generator())->ChangeValue();
181  client_session.reset(new TestClientSession(client_conn, client_config));
182  server_session.reset(new TestSession(server_conn, config_));
183  client.reset(new QuicCryptoClientStream(
184      server_id, client_session.get(), NULL, &client_crypto_config));
185  client_session->SetCryptoStream(client.get());
186
187  server.reset(new QuicCryptoServerStream(crypto_config_,
188                                          server_session.get()));
189  server_session->SetCryptoStream(server.get());
190
191  CHECK(client->CryptoConnect());
192
193  if (AsyncStrikeRegisterVerification()) {
194    EXPECT_FALSE(client->handshake_confirmed());
195    EXPECT_FALSE(server->handshake_confirmed());
196
197    // Advance the handshake.  Expect that the server will be stuck
198    // waiting for client nonce verification to complete.
199    pair<size_t, size_t> messages_moved = CryptoTestUtils::AdvanceHandshake(
200        client_conn, client.get(), 0, server_conn, server.get(), 0);
201    EXPECT_EQ(1u, messages_moved.first);
202    EXPECT_EQ(0u, messages_moved.second);
203    EXPECT_EQ(1, strike_register_client_->PendingVerifications());
204    EXPECT_FALSE(client->handshake_confirmed());
205    EXPECT_FALSE(server->handshake_confirmed());
206
207    // The server handshake completes once the nonce verification completes.
208    strike_register_client_->RunPendingVerifications();
209    EXPECT_FALSE(client->handshake_confirmed());
210    EXPECT_TRUE(server->handshake_confirmed());
211
212    messages_moved = CryptoTestUtils::AdvanceHandshake(
213        client_conn, client.get(), messages_moved.first,
214        server_conn, server.get(), messages_moved.second);
215    EXPECT_EQ(1u, messages_moved.first);
216    EXPECT_EQ(1u, messages_moved.second);
217    EXPECT_TRUE(client->handshake_confirmed());
218    EXPECT_TRUE(server->handshake_confirmed());
219  } else {
220    CryptoTestUtils::CommunicateHandshakeMessages(
221        client_conn, client.get(), server_conn, server.get());
222  }
223
224  EXPECT_EQ(1, client->num_sent_client_hellos());
225}
226
227TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
228  CompleteCryptoHandshake();
229  EXPECT_CALL(*connection_, SendConnectionClose(
230      QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
231  message_.set_tag(kCHLO);
232  ConstructHandshakeMessage();
233  stream_.ProcessRawData(message_data_->data(), message_data_->length());
234}
235
236TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
237  message_.set_tag(kSHLO);
238  ConstructHandshakeMessage();
239  EXPECT_CALL(*connection_, SendConnectionClose(
240      QUIC_INVALID_CRYPTO_MESSAGE_TYPE));
241  stream_.ProcessRawData(message_data_->data(), message_data_->length());
242}
243
244TEST_P(QuicCryptoServerStreamTest, WithoutCertificates) {
245  crypto_config_.SetProofSource(NULL);
246  client_options_.dont_verify_certs = true;
247
248  // Only 2 client hellos need to be sent in the no-certs case: one to get the
249  // source-address token and the second to finish.
250  EXPECT_EQ(2, CompleteCryptoHandshake());
251  EXPECT_TRUE(stream_.encryption_established());
252  EXPECT_TRUE(stream_.handshake_confirmed());
253}
254
255TEST_P(QuicCryptoServerStreamTest, ChannelID) {
256  client_options_.channel_id_enabled = true;
257  // CompleteCryptoHandshake verifies
258  // stream_.crypto_negotiated_params().channel_id is correct.
259  EXPECT_EQ(2, CompleteCryptoHandshake());
260  EXPECT_TRUE(stream_.encryption_established());
261  EXPECT_TRUE(stream_.handshake_confirmed());
262}
263
264}  // namespace
265}  // namespace test
266}  // namespace net
267