blob: 4c59d1f5bd7fe6250be65d70666ebf277c979d67 [file] [log] [blame]
[email protected]ed3fc15d2013-03-08 18:37:441// 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/test_tools/crypto_test_utils.h"
[email protected]72818ea2013-03-13 03:23:576
[email protected]d069c11a2013-04-13 00:01:557#include "base/strings/string_piece.h"
[email protected]ef95114d2013-04-17 17:57:018#include "net/quic/crypto/crypto_handshake.h"
[email protected]fe053f92013-04-23 20:18:559#include "net/quic/crypto/crypto_server_config.h"
[email protected]14e8106c2013-03-14 16:25:3310#include "net/quic/crypto/quic_decrypter.h"
11#include "net/quic/crypto/quic_encrypter.h"
[email protected]ef95114d2013-04-17 17:57:0112#include "net/quic/crypto/quic_random.h"
13#include "net/quic/quic_clock.h"
[email protected]ed3fc15d2013-03-08 18:37:4414#include "net/quic/quic_crypto_client_stream.h"
15#include "net/quic/quic_crypto_server_stream.h"
16#include "net/quic/quic_crypto_stream.h"
17#include "net/quic/test_tools/quic_test_utils.h"
18#include "net/quic/test_tools/simple_quic_framer.h"
[email protected]ed3fc15d2013-03-08 18:37:4419
[email protected]14e8106c2013-03-14 16:25:3320using base::StringPiece;
[email protected]ccc66e8a2013-03-26 08:26:1421using std::string;
[email protected]fe053f92013-04-23 20:18:5522using std::vector;
[email protected]14e8106c2013-03-14 16:25:3323
[email protected]ed3fc15d2013-03-08 18:37:4424namespace net {
25namespace test {
26
27namespace {
28
29class TestSession : public QuicSession {
30 public:
31 TestSession(QuicConnection* connection, bool is_server)
32 : QuicSession(connection, is_server) {
33 }
34
35 MOCK_METHOD1(CreateIncomingReliableStream,
36 ReliableQuicStream*(QuicStreamId id));
37 MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*());
38 MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
39};
40
[email protected]fe053f92013-04-23 20:18:5541// CryptoFramerVisitor is a framer visitor that records handshake messages.
42class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
43 public:
44 CryptoFramerVisitor()
45 : error_(false) {
46 }
[email protected]ed3fc15d2013-03-08 18:37:4447
[email protected]fe053f92013-04-23 20:18:5548 void OnError(CryptoFramer* framer) {
49 error_ = true;
50 }
[email protected]ed3fc15d2013-03-08 18:37:4451
[email protected]fe053f92013-04-23 20:18:5552 void OnHandshakeMessage(const CryptoHandshakeMessage& message) {
53 messages_.push_back(message);
54 }
[email protected]ed3fc15d2013-03-08 18:37:4455
[email protected]fe053f92013-04-23 20:18:5556 bool error() const {
57 return error_;
58 }
[email protected]ed3fc15d2013-03-08 18:37:4459
[email protected]fe053f92013-04-23 20:18:5560 const vector<CryptoHandshakeMessage>& messages() const {
61 return messages_;
62 }
[email protected]ed3fc15d2013-03-08 18:37:4463
[email protected]fe053f92013-04-23 20:18:5564 private:
65 bool error_;
66 vector<CryptoHandshakeMessage> messages_;
67};
68
69// MovePackets parses crypto handshake messages from packet number
70// |*inout_packet_index| through to the last packet and has |dest_stream|
71// process them. |*inout_packet_index| is updated with an index one greater
72// than the last packet processed.
73void MovePackets(PacketSavingConnection* source_conn,
74 size_t *inout_packet_index,
75 QuicCryptoStream* dest_stream) {
76 SimpleQuicFramer framer;
77 CryptoFramer crypto_framer;
78 CryptoFramerVisitor crypto_visitor;
79
80 crypto_framer.set_visitor(&crypto_visitor);
81
82 size_t index = *inout_packet_index;
83 for (; index < source_conn->packets_.size(); index++) {
84 ASSERT_TRUE(framer.ProcessPacket(*source_conn->packets_[index]));
85 for (vector<QuicStreamFrame>::const_iterator
86 i = framer.stream_frames().begin();
87 i != framer.stream_frames().end(); ++i) {
88 ASSERT_TRUE(crypto_framer.ProcessInput(i->data));
89 ASSERT_FALSE(crypto_visitor.error());
90 }
91 }
92 *inout_packet_index = index;
93
94 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
95
96 for (vector<CryptoHandshakeMessage>::const_iterator
97 i = crypto_visitor.messages().begin();
98 i != crypto_visitor.messages().end(); ++i) {
99 dest_stream->OnHandshakeMessage(*i);
[email protected]ed3fc15d2013-03-08 18:37:44100 }
101}
102
103} // anonymous namespace
104
105// static
[email protected]fe053f92013-04-23 20:18:55106void CryptoTestUtils::CommunicateHandshakeMessages(
107 PacketSavingConnection* a_conn,
108 QuicCryptoStream* a,
109 PacketSavingConnection* b_conn,
110 QuicCryptoStream* b) {
111 size_t a_i = 0, b_i = 0;
112 while (!a->handshake_complete()) {
113 ASSERT_GT(a_conn->packets_.size(), a_i);
114 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
115 << " packets a->b";
116 MovePackets(a_conn, &a_i, b);
117
118 ASSERT_GT(b_conn->packets_.size(), b_i);
119 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
120 << " packets b->a";
121 if (b_conn->packets_.size() - b_i == 2) {
122 LOG(INFO) << "here";
123 }
124 MovePackets(b_conn, &b_i, a);
125 }
126}
127
128// static
129int CryptoTestUtils::HandshakeWithFakeServer(
[email protected]ed3fc15d2013-03-08 18:37:44130 PacketSavingConnection* client_conn,
[email protected]14e8106c2013-03-14 16:25:33131 QuicCryptoClientStream* client) {
[email protected]ed3fc15d2013-03-08 18:37:44132 QuicGuid guid(1);
[email protected]72818ea2013-03-13 03:23:57133 IPAddressNumber ip;
134 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
135 IPEndPoint addr = IPEndPoint(ip, 1);
[email protected]ed3fc15d2013-03-08 18:37:44136 PacketSavingConnection* server_conn =
[email protected]14e8106c2013-03-14 16:25:33137 new PacketSavingConnection(guid, addr, true);
[email protected]ed3fc15d2013-03-08 18:37:44138 TestSession server_session(server_conn, true);
[email protected]ef95114d2013-04-17 17:57:01139
140 QuicConfig config;
141 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING);
142 SetupCryptoServerConfigForTest(
143 server_session.connection()->clock(),
144 server_session.connection()->random_generator(),
145 &config, &crypto_config);
146
147 QuicCryptoServerStream server(config, crypto_config, &server_session);
[email protected]ed3fc15d2013-03-08 18:37:44148
149 // The client's handshake must have been started already.
150 CHECK_NE(0u, client_conn->packets_.size());
151
152 CommunicateHandshakeMessages(client_conn, client, server_conn, &server);
[email protected]14e8106c2013-03-14 16:25:33153
154 CompareClientAndServerKeys(client, &server);
[email protected]fe053f92013-04-23 20:18:55155
156 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44157}
158
159// static
[email protected]fe053f92013-04-23 20:18:55160int CryptoTestUtils::HandshakeWithFakeClient(
[email protected]ed3fc15d2013-03-08 18:37:44161 PacketSavingConnection* server_conn,
[email protected]14e8106c2013-03-14 16:25:33162 QuicCryptoServerStream* server) {
[email protected]ed3fc15d2013-03-08 18:37:44163 QuicGuid guid(1);
[email protected]72818ea2013-03-13 03:23:57164 IPAddressNumber ip;
165 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
166 IPEndPoint addr = IPEndPoint(ip, 1);
[email protected]ed3fc15d2013-03-08 18:37:44167 PacketSavingConnection* client_conn =
[email protected]14e8106c2013-03-14 16:25:33168 new PacketSavingConnection(guid, addr, false);
[email protected]ed3fc15d2013-03-08 18:37:44169 TestSession client_session(client_conn, true);
[email protected]ef95114d2013-04-17 17:57:01170 QuicConfig config;
171 QuicCryptoClientConfig crypto_config;
172
173 config.SetDefaults();
174 crypto_config.SetDefaults();
175 QuicCryptoClientStream client("test.example.com", config, &client_session,
176 &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44177
178 CHECK(client.CryptoConnect());
179 CHECK_EQ(1u, client_conn->packets_.size());
180
181 CommunicateHandshakeMessages(client_conn, &client, server_conn, server);
[email protected]14e8106c2013-03-14 16:25:33182
183 CompareClientAndServerKeys(&client, server);
[email protected]fe053f92013-04-23 20:18:55184
185 return client.num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33186}
187
188// static
[email protected]ef95114d2013-04-17 17:57:01189void CryptoTestUtils::SetupCryptoServerConfigForTest(
190 const QuicClock* clock,
191 QuicRandom* rand,
192 QuicConfig* config,
193 QuicCryptoServerConfig* crypto_config) {
194 config->SetDefaults();
195 CryptoHandshakeMessage extra_tags;
196 config->ToHandshakeMessage(&extra_tags);
197
198 scoped_ptr<CryptoHandshakeMessage> scfg(
199 crypto_config->AddDefaultConfig(rand, clock, extra_tags));
200 if (!config->SetFromHandshakeMessage(*scfg)) {
201 CHECK(false) << "Crypto config could not be parsed by QuicConfig.";
202 }
203}
204
205// static
[email protected]ccc66e8a2013-03-26 08:26:14206string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
207 CryptoTag tag) {
208 CryptoTagValueMap::const_iterator it = message.tag_value_map().find(tag);
209 if (it == message.tag_value_map().end()) {
210 return string();
211 }
212 return it->second;
213}
214
[email protected]14e8106c2013-03-14 16:25:33215void CryptoTestUtils::CompareClientAndServerKeys(
216 QuicCryptoClientStream* client,
217 QuicCryptoServerStream* server) {
218 StringPiece client_encrypter_key =
[email protected]74bda142013-03-31 02:49:11219 client->session()->connection()->encrypter()->GetKey();
[email protected]14e8106c2013-03-14 16:25:33220 StringPiece client_encrypter_iv =
[email protected]74bda142013-03-31 02:49:11221 client->session()->connection()->encrypter()->GetNoncePrefix();
[email protected]14e8106c2013-03-14 16:25:33222 StringPiece client_decrypter_key =
[email protected]74bda142013-03-31 02:49:11223 client->session()->connection()->decrypter()->GetKey();
[email protected]14e8106c2013-03-14 16:25:33224 StringPiece client_decrypter_iv =
[email protected]74bda142013-03-31 02:49:11225 client->session()->connection()->decrypter()->GetNoncePrefix();
[email protected]14e8106c2013-03-14 16:25:33226 StringPiece server_encrypter_key =
[email protected]74bda142013-03-31 02:49:11227 server->session()->connection()->encrypter()->GetKey();
[email protected]14e8106c2013-03-14 16:25:33228 StringPiece server_encrypter_iv =
[email protected]74bda142013-03-31 02:49:11229 server->session()->connection()->encrypter()->GetNoncePrefix();
[email protected]14e8106c2013-03-14 16:25:33230 StringPiece server_decrypter_key =
[email protected]74bda142013-03-31 02:49:11231 server->session()->connection()->decrypter()->GetKey();
[email protected]14e8106c2013-03-14 16:25:33232 StringPiece server_decrypter_iv =
[email protected]74bda142013-03-31 02:49:11233 server->session()->connection()->decrypter()->GetNoncePrefix();
[email protected]14e8106c2013-03-14 16:25:33234 CompareCharArraysWithHexError("client write key",
235 client_encrypter_key.data(),
236 client_encrypter_key.length(),
237 server_decrypter_key.data(),
238 server_decrypter_key.length());
239 CompareCharArraysWithHexError("client write IV",
240 client_encrypter_iv.data(),
241 client_encrypter_iv.length(),
242 server_decrypter_iv.data(),
243 server_decrypter_iv.length());
244 CompareCharArraysWithHexError("server write key",
245 server_encrypter_key.data(),
246 server_encrypter_key.length(),
247 client_decrypter_key.data(),
248 client_decrypter_key.length());
249 CompareCharArraysWithHexError("server write IV",
250 server_encrypter_iv.data(),
251 server_encrypter_iv.length(),
252 client_decrypter_iv.data(),
253 client_decrypter_iv.length());
[email protected]ed3fc15d2013-03-08 18:37:44254}
255} // namespace test
256} // namespace net