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.
5 #include "net/quic/quic_crypto_client_stream.h"
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"
22 const char kServerHostname
[] = "example.com";
24 class TestQuicVisitor
: public NoOpFramerVisitor
{
27 : frame_valid_(false) {
31 virtual bool OnStreamFrame(const QuicStreamFrame
& frame
) OVERRIDE
{
37 bool frame_valid() const {
40 QuicStreamFrame
* frame() { return &frame_
; }
43 QuicStreamFrame frame_
;
46 DISALLOW_COPY_AND_ASSIGN(TestQuicVisitor
);
49 class QuicCryptoClientStreamTest
: public ::testing::Test
{
51 QuicCryptoClientStreamTest()
53 connection_(new PacketSavingConnection(1, addr_
, true)),
54 session_(new TestSession(connection_
, DefaultQuicConfig(), true)),
55 stream_(new QuicCryptoClientStream(kServerHostname
, session_
.get(),
57 session_
->SetCryptoStream(stream_
.get());
58 crypto_config_
.SetDefaults();
61 void CompleteCryptoHandshake() {
62 EXPECT_TRUE(stream_
->CryptoConnect());
63 CryptoTestUtils::HandshakeWithFakeServer(connection_
, stream_
.get());
66 void ConstructHandshakeMessage() {
68 message_data_
.reset(framer
.ConstructHandshakeMessage(message_
));
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_
;
80 TEST_F(QuicCryptoClientStreamTest
, NotInitiallyConected
) {
81 if (!Aes128Gcm12Encrypter::IsSupported()) {
82 LOG(INFO
) << "AES GCM not supported. Test skipped.";
86 EXPECT_FALSE(stream_
->encryption_established());
87 EXPECT_FALSE(stream_
->handshake_confirmed());
90 TEST_F(QuicCryptoClientStreamTest
, ConnectedAfterSHLO
) {
91 if (!Aes128Gcm12Encrypter::IsSupported()) {
92 LOG(INFO
) << "AES GCM not supported. Test skipped.";
96 CompleteCryptoHandshake();
97 EXPECT_TRUE(stream_
->encryption_established());
98 EXPECT_TRUE(stream_
->handshake_confirmed());
101 TEST_F(QuicCryptoClientStreamTest
, MessageAfterHandshake
) {
102 if (!Aes128Gcm12Encrypter::IsSupported()) {
103 LOG(INFO
) << "AES GCM not supported. Test skipped.";
107 CompleteCryptoHandshake();
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());
116 TEST_F(QuicCryptoClientStreamTest
, BadMessageType
) {
117 if (!Aes128Gcm12Encrypter::IsSupported()) {
118 LOG(INFO
) << "AES GCM not supported. Test skipped.";
122 EXPECT_TRUE(stream_
->CryptoConnect());
124 message_
.set_tag(kCHLO
);
125 ConstructHandshakeMessage();
127 EXPECT_CALL(*connection_
, SendConnectionCloseWithDetails(
128 QUIC_INVALID_CRYPTO_MESSAGE_TYPE
, "Expected REJ"));
129 stream_
->ProcessData(message_data_
->data(), message_data_
->length());
132 TEST_F(QuicCryptoClientStreamTest
, NegotiatedParameters
) {
133 if (!Aes128Gcm12Encrypter::IsSupported()) {
134 LOG(INFO
) << "AES GCM not supported. Test skipped.";
138 CompleteCryptoHandshake();
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());
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
);
154 TEST_F(QuicCryptoClientStreamTest
, InvalidHostname
) {
155 if (!Aes128Gcm12Encrypter::IsSupported()) {
156 LOG(INFO
) << "AES GCM not supported. Test skipped.";
160 stream_
.reset(new QuicCryptoClientStream("invalid", session_
.get(),
162 session_
->SetCryptoStream(stream_
.get());
164 CompleteCryptoHandshake();
165 EXPECT_TRUE(stream_
->encryption_established());
166 EXPECT_TRUE(stream_
->handshake_confirmed());
169 TEST_F(QuicCryptoClientStreamTest
, ExpiredServerConfig
) {
170 // Seed the config with a cached server config.
171 CompleteCryptoHandshake();
173 connection_
= new PacketSavingConnection(1, addr_
, true);
174 session_
.reset(new TestSession(connection_
, QuicConfig(), true));
175 stream_
.reset(new QuicCryptoClientStream(kServerHostname
, session_
.get(),
178 session_
->SetCryptoStream(stream_
.get());
179 session_
->config()->SetDefaults();
181 // Advance time 5 years to ensure that we pass the expiry time of the cached
183 reinterpret_cast<MockClock
*>(const_cast<QuicClock
*>(connection_
->clock()))
184 ->AdvanceTime(QuicTime::Delta::FromSeconds(60 * 60 * 24 * 365 * 5));
186 // Check that a client hello was sent and that CryptoConnect doesn't fail
188 EXPECT_TRUE(stream_
->CryptoConnect());
189 ASSERT_EQ(1u, connection_
->packets_
.size());