blob: 50fc2cae879e0ab594d0d52ce4a9f62b03edd331 [file] [log] [blame]
[email protected]72818ea2013-03-13 03:23:571// 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"
[email protected]74bda142013-03-31 02:49:1111#include "net/quic/crypto/aes_128_gcm_encrypter.h"
[email protected]72818ea2013-03-13 03:23:5712#include "net/quic/crypto/crypto_framer.h"
13#include "net/quic/crypto/crypto_handshake.h"
14#include "net/quic/crypto/crypto_protocol.h"
[email protected]fe053f92013-04-23 20:18:5515#include "net/quic/crypto/crypto_server_config.h"
[email protected]72818ea2013-03-13 03:23:5716#include "net/quic/crypto/crypto_utils.h"
17#include "net/quic/crypto/quic_decrypter.h"
18#include "net/quic/crypto/quic_encrypter.h"
[email protected]fe053f92013-04-23 20:18:5519#include "net/quic/quic_crypto_client_stream.h"
[email protected]72818ea2013-03-13 03:23:5720#include "net/quic/quic_protocol.h"
21#include "net/quic/quic_session.h"
22#include "net/quic/test_tools/crypto_test_utils.h"
23#include "net/quic/test_tools/quic_test_utils.h"
24#include "testing/gmock/include/gmock/gmock.h"
25#include "testing/gtest/include/gtest/gtest.h"
26
27namespace net {
28class QuicConnection;
29class ReliableQuicStream;
30} // namespace net
31
32using testing::_;
33
34namespace net {
35namespace test {
36namespace {
37
38// TODO(agl): Use rch's utility class for parsing a message when committed.
39class TestQuicVisitor : public NoOpFramerVisitor {
40 public:
41 TestQuicVisitor() {}
42
43 // NoOpFramerVisitor
[email protected]a57e0272013-04-26 07:31:4744 virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE {
[email protected]72818ea2013-03-13 03:23:5745 frame_ = frame;
[email protected]a57e0272013-04-26 07:31:4746 return true;
[email protected]72818ea2013-03-13 03:23:5747 }
48
49 QuicStreamFrame* frame() { return &frame_; }
50
51 private:
52 QuicStreamFrame frame_;
53
54 DISALLOW_COPY_AND_ASSIGN(TestQuicVisitor);
55};
56
57class TestSession: public QuicSession {
58 public:
59 TestSession(QuicConnection* connection, bool is_server)
60 : QuicSession(connection, is_server) {
61 }
62
63 MOCK_METHOD1(CreateIncomingReliableStream,
64 ReliableQuicStream*(QuicStreamId id));
65 MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*());
66 MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
67};
68
69class QuicCryptoServerStreamTest : public ::testing::Test {
70 public:
71 QuicCryptoServerStreamTest()
72 : guid_(1),
[email protected]74bda142013-03-31 02:49:1173 addr_(ParseIPLiteralToNumber("192.0.2.33", &ip_) ?
74 ip_ : IPAddressNumber(), 1),
[email protected]14e8106c2013-03-14 16:25:3375 connection_(new PacketSavingConnection(guid_, addr_, true)),
[email protected]72818ea2013-03-13 03:23:5776 session_(connection_, true),
[email protected]ef95114d2013-04-17 17:57:0177 crypto_config_(QuicCryptoServerConfig::TESTING),
78 stream_(config_, crypto_config_, &session_) {
[email protected]fe053f92013-04-23 20:18:5579 // We advance the clock initially because the default time is zero and the
80 // strike register worries that we've just overflowed a uint32 time.
81 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
82 // TODO(rtenneti): Enable testing of ProofSource.
83 // crypto_config_.SetProofSource(CryptoTestUtils::ProofSourceForTesting());
84
[email protected]ef95114d2013-04-17 17:57:0185 CryptoTestUtils::SetupCryptoServerConfigForTest(
86 connection_->clock(), connection_->random_generator(), &config_,
87 &crypto_config_);
[email protected]72818ea2013-03-13 03:23:5788 }
89
90 void ConstructHandshakeMessage() {
91 CryptoFramer framer;
92 message_data_.reset(framer.ConstructHandshakeMessage(message_));
93 }
94
[email protected]fe053f92013-04-23 20:18:5595 int CompleteCryptoHandshake() {
96 return CryptoTestUtils::HandshakeWithFakeClient(connection_, &stream_);
[email protected]72818ea2013-03-13 03:23:5797 }
98
99 protected:
[email protected]74bda142013-03-31 02:49:11100 IPAddressNumber ip_;
[email protected]72818ea2013-03-13 03:23:57101 QuicGuid guid_;
102 IPEndPoint addr_;
103 PacketSavingConnection* connection_;
104 TestSession session_;
[email protected]ef95114d2013-04-17 17:57:01105 QuicConfig config_;
106 QuicCryptoServerConfig crypto_config_;
[email protected]72818ea2013-03-13 03:23:57107 QuicCryptoServerStream stream_;
108 CryptoHandshakeMessage message_;
109 scoped_ptr<QuicData> message_data_;
110};
111
112TEST_F(QuicCryptoServerStreamTest, NotInitiallyConected) {
[email protected]74bda142013-03-31 02:49:11113 if (!Aes128GcmEncrypter::IsSupported()) {
114 LOG(INFO) << "AES GCM not supported. Test skipped.";
115 return;
116 }
117
[email protected]72818ea2013-03-13 03:23:57118 EXPECT_FALSE(stream_.handshake_complete());
119}
120
121TEST_F(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
[email protected]74bda142013-03-31 02:49:11122 if (!Aes128GcmEncrypter::IsSupported()) {
123 LOG(INFO) << "AES GCM not supported. Test skipped.";
124 return;
125 }
126
[email protected]a57e0272013-04-26 07:31:47127 // CompleteCryptoHandshake returns the number of client hellos sent. This
128 // test should send:
129 // * One to get a source-address token.
130 // * One to complete the handshake.
131 // TODO(rtenneti): Until we set the crypto_config.SetProofVerifier to enable
132 // ProofVerifier in CryptoTestUtils::HandshakeWithFakeClient, we would not
133 // have sent the following client hello.
134 // * One to get the server's certificates
[email protected]fe053f92013-04-23 20:18:55135 EXPECT_EQ(2, CompleteCryptoHandshake());
[email protected]72818ea2013-03-13 03:23:57136 EXPECT_TRUE(stream_.handshake_complete());
137}
138
[email protected]fe053f92013-04-23 20:18:55139TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
140 if (!Aes128GcmEncrypter::IsSupported()) {
141 LOG(INFO) << "AES GCM not supported. Test skipped.";
142 return;
143 }
144
145 QuicGuid guid(1);
146 IPAddressNumber ip;
147 ParseIPLiteralToNumber("127.0.0.1", &ip);
148 IPEndPoint addr(ip, 0);
149 PacketSavingConnection* client_conn =
150 new PacketSavingConnection(guid, addr, false);
151 PacketSavingConnection* server_conn =
152 new PacketSavingConnection(guid, addr, false);
153 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
154 server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
155
156 scoped_ptr<TestSession> client_session(new TestSession(client_conn, true));
157 scoped_ptr<TestSession> server_session(new TestSession(server_conn, true));
158
159 QuicConfig client_config;
160 QuicCryptoClientConfig client_crypto_config;
161
162 client_config.SetDefaults();
163 client_crypto_config.SetDefaults();
164
165 scoped_ptr<QuicCryptoClientStream> client(new QuicCryptoClientStream(
166 "test.example.com", client_config, client_session.get(),
167 &client_crypto_config));
168
169 // Do a first handshake in order to prime the client config with the server's
170 // information.
171 CHECK(client->CryptoConnect());
172 CHECK_EQ(1u, client_conn->packets_.size());
173
174 scoped_ptr<QuicCryptoServerStream> server(
175 new QuicCryptoServerStream(config_, crypto_config_,
176 server_session.get()));
177
178 CryptoTestUtils::CommunicateHandshakeMessages(
179 client_conn, client.get(), server_conn, server.get());
180 EXPECT_EQ(2, client->num_sent_client_hellos());
181
182 // Now do another handshake, hopefully in 0-RTT.
183 LOG(INFO) << "Resetting for 0-RTT handshake attempt";
184
185 client_conn = new PacketSavingConnection(guid, addr, false);
186 server_conn = new PacketSavingConnection(guid, addr, false);
187 // We need to advance time past the strike-server window so that it's
188 // authoritative in this time span.
189 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1002000));
190 server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1002000));
191
192 // This causes the client's nonce to be different and thus stops the
193 // strike-register from rejecting the repeated nonce.
194 client_conn->random_generator()->Reseed(NULL, 0);
195 client_session.reset(new TestSession(client_conn, true));
196 server_session.reset(new TestSession(server_conn, true));
197 client.reset(new QuicCryptoClientStream(
198 "test.example.com", client_config, client_session.get(),
199 &client_crypto_config));
200 server.reset(new QuicCryptoServerStream(config_, crypto_config_,
201 server_session.get()));
202
203 CHECK(client->CryptoConnect());
204
205 CryptoTestUtils::CommunicateHandshakeMessages(
206 client_conn, client.get(), server_conn, server.get());
207 EXPECT_EQ(1, client->num_sent_client_hellos());
208}
209
[email protected]72818ea2013-03-13 03:23:57210TEST_F(QuicCryptoServerStreamTest, MessageAfterHandshake) {
[email protected]74bda142013-03-31 02:49:11211 if (!Aes128GcmEncrypter::IsSupported()) {
212 LOG(INFO) << "AES GCM not supported. Test skipped.";
213 return;
214 }
215
[email protected]72818ea2013-03-13 03:23:57216 CompleteCryptoHandshake();
217 EXPECT_CALL(*connection_, SendConnectionClose(
218 QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
[email protected]ccc66e8a2013-03-26 08:26:14219 message_.set_tag(kCHLO);
[email protected]72818ea2013-03-13 03:23:57220 ConstructHandshakeMessage();
221 stream_.ProcessData(message_data_->data(), message_data_->length());
222}
223
224TEST_F(QuicCryptoServerStreamTest, BadMessageType) {
[email protected]74bda142013-03-31 02:49:11225 if (!Aes128GcmEncrypter::IsSupported()) {
226 LOG(INFO) << "AES GCM not supported. Test skipped.";
227 return;
228 }
229
[email protected]ccc66e8a2013-03-26 08:26:14230 message_.set_tag(kSHLO);
[email protected]72818ea2013-03-13 03:23:57231 ConstructHandshakeMessage();
232 EXPECT_CALL(*connection_, SendConnectionClose(
233 QUIC_INVALID_CRYPTO_MESSAGE_TYPE));
234 stream_.ProcessData(message_data_->data(), message_data_->length());
235}
236
237} // namespace
238} // namespace test
239} // namespace net