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_ != 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(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 
    118 INSTANTIATE_TEST_CASE_P(Tests, QuicCryptoServerStreamTest, testing::Bool());
    119 
    120 TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
    121   EXPECT_FALSE(stream_.encryption_established());
    122   EXPECT_FALSE(stream_.handshake_confirmed());
    123 }
    124 
    125 TEST_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 
    135 TEST_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 
    227 TEST_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 
    236 TEST_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 
    244 TEST_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 
    255 TEST_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