Home | History | Annotate | Download | only in quic
      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
    287