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_protocol.h" 12 #include "net/quic/test_tools/crypto_test_utils.h" 13 #include "net/quic/test_tools/quic_test_utils.h" 14 #include "net/quic/test_tools/simple_quic_framer.h" 15 #include "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 namespace net { 19 namespace test { 20 namespace { 21 22 const char kServerHostname[] = "example.com"; 23 24 class TestQuicVisitor : public NoOpFramerVisitor { 25 public: 26 TestQuicVisitor() 27 : frame_valid_(false) { 28 } 29 30 // NoOpFramerVisitor 31 virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE { 32 frame_ = frame; 33 frame_valid_ = true; 34 return true; 35 } 36 37 bool frame_valid() const { 38 return frame_valid_; 39 } 40 QuicStreamFrame* frame() { return &frame_; } 41 42 private: 43 QuicStreamFrame frame_; 44 bool frame_valid_; 45 46 DISALLOW_COPY_AND_ASSIGN(TestQuicVisitor); 47 }; 48 49 class QuicCryptoClientStreamTest : public ::testing::Test { 50 public: 51 QuicCryptoClientStreamTest() 52 : addr_(), 53 connection_(new PacketSavingConnection(1, addr_, true)), 54 session_(new TestSession(connection_, DefaultQuicConfig(), true)), 55 stream_(new QuicCryptoClientStream(kServerHostname, session_.get(), 56 &crypto_config_)) { 57 session_->SetCryptoStream(stream_.get()); 58 crypto_config_.SetDefaults(); 59 } 60 61 void CompleteCryptoHandshake() { 62 EXPECT_TRUE(stream_->CryptoConnect()); 63 CryptoTestUtils::HandshakeWithFakeServer(connection_, stream_.get()); 64 } 65 66 void ConstructHandshakeMessage() { 67 CryptoFramer framer; 68 message_data_.reset(framer.ConstructHandshakeMessage(message_)); 69 } 70 71 IPEndPoint addr_; 72 PacketSavingConnection* connection_; 73 scoped_ptr<TestSession> session_; 74 scoped_ptr<QuicCryptoClientStream> stream_; 75 CryptoHandshakeMessage message_; 76 scoped_ptr<QuicData> message_data_; 77 QuicCryptoClientConfig crypto_config_; 78 }; 79 80 TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) { 81 if (!Aes128Gcm12Encrypter::IsSupported()) { 82 LOG(INFO) << "AES GCM not supported. Test skipped."; 83 return; 84 } 85 86 EXPECT_FALSE(stream_->encryption_established()); 87 EXPECT_FALSE(stream_->handshake_confirmed()); 88 } 89 90 TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) { 91 if (!Aes128Gcm12Encrypter::IsSupported()) { 92 LOG(INFO) << "AES GCM not supported. Test skipped."; 93 return; 94 } 95 96 CompleteCryptoHandshake(); 97 EXPECT_TRUE(stream_->encryption_established()); 98 EXPECT_TRUE(stream_->handshake_confirmed()); 99 } 100 101 TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) { 102 if (!Aes128Gcm12Encrypter::IsSupported()) { 103 LOG(INFO) << "AES GCM not supported. Test skipped."; 104 return; 105 } 106 107 CompleteCryptoHandshake(); 108 109 EXPECT_CALL(*connection_, SendConnectionClose( 110 QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE)); 111 message_.set_tag(kCHLO); 112 ConstructHandshakeMessage(); 113 stream_->ProcessData(message_data_->data(), message_data_->length()); 114 } 115 116 TEST_F(QuicCryptoClientStreamTest, BadMessageType) { 117 if (!Aes128Gcm12Encrypter::IsSupported()) { 118 LOG(INFO) << "AES GCM not supported. Test skipped."; 119 return; 120 } 121 122 EXPECT_TRUE(stream_->CryptoConnect()); 123 124 message_.set_tag(kCHLO); 125 ConstructHandshakeMessage(); 126 127 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( 128 QUIC_INVALID_CRYPTO_MESSAGE_TYPE, "Expected REJ")); 129 stream_->ProcessData(message_data_->data(), message_data_->length()); 130 } 131 132 TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) { 133 if (!Aes128Gcm12Encrypter::IsSupported()) { 134 LOG(INFO) << "AES GCM not supported. Test skipped."; 135 return; 136 } 137 138 CompleteCryptoHandshake(); 139 140 const QuicConfig* config = session_->config(); 141 EXPECT_EQ(kQBIC, config->congestion_control()); 142 EXPECT_EQ(kDefaultTimeoutSecs, 143 config->idle_connection_state_lifetime().ToSeconds()); 144 EXPECT_EQ(kDefaultMaxStreamsPerConnection, 145 config->max_streams_per_connection()); 146 EXPECT_EQ(0, config->keepalive_timeout().ToSeconds()); 147 148 const QuicCryptoNegotiatedParameters& crypto_params( 149 stream_->crypto_negotiated_params()); 150 EXPECT_EQ(kAESG, crypto_params.aead); 151 EXPECT_EQ(kC255, crypto_params.key_exchange); 152 } 153 154 TEST_F(QuicCryptoClientStreamTest, InvalidHostname) { 155 if (!Aes128Gcm12Encrypter::IsSupported()) { 156 LOG(INFO) << "AES GCM not supported. Test skipped."; 157 return; 158 } 159 160 stream_.reset(new QuicCryptoClientStream("invalid", session_.get(), 161 &crypto_config_)); 162 session_->SetCryptoStream(stream_.get()); 163 164 CompleteCryptoHandshake(); 165 EXPECT_TRUE(stream_->encryption_established()); 166 EXPECT_TRUE(stream_->handshake_confirmed()); 167 } 168 169 TEST_F(QuicCryptoClientStreamTest, ExpiredServerConfig) { 170 // Seed the config with a cached server config. 171 CompleteCryptoHandshake(); 172 173 connection_ = new PacketSavingConnection(1, addr_, true); 174 session_.reset(new TestSession(connection_, QuicConfig(), true)); 175 stream_.reset(new QuicCryptoClientStream(kServerHostname, session_.get(), 176 &crypto_config_)); 177 178 session_->SetCryptoStream(stream_.get()); 179 session_->config()->SetDefaults(); 180 181 // Advance time 5 years to ensure that we pass the expiry time of the cached 182 // server config. 183 reinterpret_cast<MockClock*>(const_cast<QuicClock*>(connection_->clock())) 184 ->AdvanceTime(QuicTime::Delta::FromSeconds(60 * 60 * 24 * 365 * 5)); 185 186 // Check that a client hello was sent and that CryptoConnect doesn't fail 187 // with an error. 188 EXPECT_TRUE(stream_->CryptoConnect()); 189 ASSERT_EQ(1u, connection_->packets_.size()); 190 } 191 192 } // namespace 193 } // namespace test 194 } // namespace net 195