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_client_stream.h"
      6 
      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"
     20 
     21 namespace net {
     22 namespace test {
     23 namespace {
     24 
     25 const char kServerHostname[] = "example.com";
     26 const uint16 kServerPort = 80;
     27 
     28 class QuicCryptoClientStreamTest : public ::testing::Test {
     29  public:
     30   QuicCryptoClientStreamTest()
     31       : connection_(new PacketSavingConnection(false)),
     32         session_(new TestClientSession(connection_, DefaultQuicConfig())),
     33         server_id_(kServerHostname, kServerPort, false, PRIVACY_MODE_DISABLED),
     34         stream_(new QuicCryptoClientStream(
     35             server_id_, session_.get(), NULL, &crypto_config_)) {
     36     session_->SetCryptoStream(stream_.get());
     37     session_->config()->SetDefaults();
     38     crypto_config_.SetDefaults();
     39   }
     40 
     41   void CompleteCryptoHandshake() {
     42     EXPECT_TRUE(stream_->CryptoConnect());
     43     CryptoTestUtils::HandshakeWithFakeServer(connection_, stream_.get());
     44   }
     45 
     46   void ConstructHandshakeMessage() {
     47     CryptoFramer framer;
     48     message_data_.reset(framer.ConstructHandshakeMessage(message_));
     49   }
     50 
     51   PacketSavingConnection* connection_;
     52   scoped_ptr<TestClientSession> session_;
     53   QuicServerId server_id_;
     54   scoped_ptr<QuicCryptoClientStream> stream_;
     55   CryptoHandshakeMessage message_;
     56   scoped_ptr<QuicData> message_data_;
     57   QuicCryptoClientConfig crypto_config_;
     58 };
     59 
     60 TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
     61   EXPECT_FALSE(stream_->encryption_established());
     62   EXPECT_FALSE(stream_->handshake_confirmed());
     63 }
     64 
     65 TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
     66   CompleteCryptoHandshake();
     67   EXPECT_TRUE(stream_->encryption_established());
     68   EXPECT_TRUE(stream_->handshake_confirmed());
     69 }
     70 
     71 TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
     72   CompleteCryptoHandshake();
     73 
     74   EXPECT_CALL(*connection_, SendConnectionClose(
     75       QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
     76   message_.set_tag(kCHLO);
     77   ConstructHandshakeMessage();
     78   stream_->ProcessRawData(message_data_->data(), message_data_->length());
     79 }
     80 
     81 TEST_F(QuicCryptoClientStreamTest, BadMessageType) {
     82   EXPECT_TRUE(stream_->CryptoConnect());
     83 
     84   message_.set_tag(kCHLO);
     85   ConstructHandshakeMessage();
     86 
     87   EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
     88         QUIC_INVALID_CRYPTO_MESSAGE_TYPE, "Expected REJ"));
     89   stream_->ProcessRawData(message_data_->data(), message_data_->length());
     90 }
     91 
     92 TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
     93   CompleteCryptoHandshake();
     94 
     95   const QuicConfig* config = session_->config();
     96   EXPECT_EQ(kQBIC, config->congestion_feedback());
     97   EXPECT_EQ(kMaximumIdleTimeoutSecs,
     98             config->idle_connection_state_lifetime().ToSeconds());
     99   EXPECT_EQ(kDefaultMaxStreamsPerConnection,
    100             config->max_streams_per_connection());
    101   EXPECT_EQ(0, config->keepalive_timeout().ToSeconds());
    102 
    103   const QuicCryptoNegotiatedParameters& crypto_params(
    104       stream_->crypto_negotiated_params());
    105   EXPECT_EQ(crypto_config_.aead[0], crypto_params.aead);
    106   EXPECT_EQ(crypto_config_.kexs[0], crypto_params.key_exchange);
    107 }
    108 
    109 TEST_F(QuicCryptoClientStreamTest, InvalidHostname) {
    110   QuicServerId server_id("invalid", 80, false, PRIVACY_MODE_DISABLED);
    111   stream_.reset(new QuicCryptoClientStream(server_id, session_.get(), NULL,
    112                                            &crypto_config_));
    113   session_->SetCryptoStream(stream_.get());
    114 
    115   CompleteCryptoHandshake();
    116   EXPECT_TRUE(stream_->encryption_established());
    117   EXPECT_TRUE(stream_->handshake_confirmed());
    118 }
    119 
    120 TEST_F(QuicCryptoClientStreamTest, ExpiredServerConfig) {
    121   // Seed the config with a cached server config.
    122   CompleteCryptoHandshake();
    123 
    124   connection_ = new PacketSavingConnection(true);
    125   session_.reset(new TestClientSession(connection_, DefaultQuicConfig()));
    126   stream_.reset(new QuicCryptoClientStream(server_id_, session_.get(), NULL,
    127                                            &crypto_config_));
    128 
    129   session_->SetCryptoStream(stream_.get());
    130   session_->config()->SetDefaults();
    131 
    132   // Advance time 5 years to ensure that we pass the expiry time of the cached
    133   // server config.
    134   reinterpret_cast<MockClock*>(const_cast<QuicClock*>(connection_->clock()))
    135       ->AdvanceTime(QuicTime::Delta::FromSeconds(60 * 60 * 24 * 365 * 5));
    136 
    137   // Check that a client hello was sent and that CryptoConnect doesn't fail
    138   // with an error.
    139   EXPECT_TRUE(stream_->CryptoConnect());
    140   ASSERT_EQ(1u, connection_->packets_.size());
    141 }
    142 
    143 TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdate) {
    144   // Test that the crypto client stream can receive server config updates after
    145   // the connection has been established.
    146   CompleteCryptoHandshake();
    147 
    148   QuicCryptoClientConfig::CachedState* state =
    149       crypto_config_.LookupOrCreate(server_id_);
    150 
    151   // Ensure cached STK is different to what we send in the handshake.
    152   EXPECT_NE("xstk", state->source_address_token());
    153 
    154   // Initialize using {...} syntax to avoid trailing \0 if converting from
    155   // string.
    156   unsigned char stk[] = { 'x', 's', 't', 'k' };
    157 
    158   // Minimum SCFG that passes config validation checks.
    159   unsigned char scfg[] = {
    160     // SCFG
    161     0x53, 0x43, 0x46, 0x47,
    162     // num entries
    163     0x01, 0x00,
    164     // padding
    165     0x00, 0x00,
    166     // EXPY
    167     0x45, 0x58, 0x50, 0x59,
    168     // EXPY end offset
    169     0x08, 0x00, 0x00, 0x00,
    170     // Value
    171     '1',  '2',  '3',  '4',
    172     '5',  '6',  '7',  '8'
    173   };
    174 
    175   CryptoHandshakeMessage server_config_update;
    176   server_config_update.set_tag(kSCUP);
    177   server_config_update.SetValue(kSourceAddressTokenTag, stk);
    178   server_config_update.SetValue(kSCFG, scfg);
    179 
    180   scoped_ptr<QuicData> data(
    181       CryptoFramer::ConstructHandshakeMessage(server_config_update));
    182   stream_->ProcessRawData(data->data(), data->length());
    183 
    184   // Make sure that the STK and SCFG are cached correctly.
    185   EXPECT_EQ("xstk", state->source_address_token());
    186 
    187   string cached_scfg = state->server_config();
    188   test::CompareCharArraysWithHexError(
    189       "scfg", cached_scfg.data(), cached_scfg.length(),
    190       QuicUtils::AsChars(scfg), arraysize(scfg));
    191 }
    192 
    193 TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
    194   EXPECT_CALL(*connection_, SendConnectionClose(
    195       QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE));
    196   CryptoHandshakeMessage server_config_update;
    197   server_config_update.set_tag(kSCUP);
    198   scoped_ptr<QuicData> data(
    199       CryptoFramer::ConstructHandshakeMessage(server_config_update));
    200   stream_->ProcessRawData(data->data(), data->length());
    201 }
    202 
    203 }  // namespace
    204 }  // namespace test
    205 }  // namespace net
    206