blob: 40a61a421426e706fea136a53530343d9a206392 [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]c244c5a12013-05-07 20:55:047#include "net/quic/crypto/common_cert_set.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"
[email protected]2532de12013-05-09 12:29:3317#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]ed3fc15d2013-03-08 18:37:4418#include "net/quic/test_tools/quic_test_utils.h"
19#include "net/quic/test_tools/simple_quic_framer.h"
[email protected]ed3fc15d2013-03-08 18:37:4420
[email protected]14e8106c2013-03-14 16:25:3321using base::StringPiece;
[email protected]ccc66e8a2013-03-26 08:26:1422using std::string;
[email protected]fe053f92013-04-23 20:18:5523using std::vector;
[email protected]14e8106c2013-03-14 16:25:3324
[email protected]ed3fc15d2013-03-08 18:37:4425namespace net {
26namespace test {
27
28namespace {
29
[email protected]fe053f92013-04-23 20:18:5530// CryptoFramerVisitor is a framer visitor that records handshake messages.
31class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
32 public:
33 CryptoFramerVisitor()
34 : error_(false) {
35 }
[email protected]ed3fc15d2013-03-08 18:37:4436
[email protected]42091902013-05-02 02:24:1237 virtual void OnError(CryptoFramer* framer) OVERRIDE {
[email protected]fe053f92013-04-23 20:18:5538 error_ = true;
39 }
[email protected]ed3fc15d2013-03-08 18:37:4440
[email protected]42091902013-05-02 02:24:1241 virtual void OnHandshakeMessage(
42 const CryptoHandshakeMessage& message) OVERRIDE {
[email protected]fe053f92013-04-23 20:18:5543 messages_.push_back(message);
44 }
[email protected]ed3fc15d2013-03-08 18:37:4445
[email protected]fe053f92013-04-23 20:18:5546 bool error() const {
47 return error_;
48 }
[email protected]ed3fc15d2013-03-08 18:37:4449
[email protected]fe053f92013-04-23 20:18:5550 const vector<CryptoHandshakeMessage>& messages() const {
51 return messages_;
52 }
[email protected]ed3fc15d2013-03-08 18:37:4453
[email protected]fe053f92013-04-23 20:18:5554 private:
55 bool error_;
56 vector<CryptoHandshakeMessage> messages_;
57};
58
59// MovePackets parses crypto handshake messages from packet number
60// |*inout_packet_index| through to the last packet and has |dest_stream|
61// process them. |*inout_packet_index| is updated with an index one greater
62// than the last packet processed.
63void MovePackets(PacketSavingConnection* source_conn,
64 size_t *inout_packet_index,
[email protected]2532de12013-05-09 12:29:3365 QuicCryptoStream* dest_stream,
66 PacketSavingConnection* dest_conn) {
[email protected]fe053f92013-04-23 20:18:5567 SimpleQuicFramer framer;
68 CryptoFramer crypto_framer;
69 CryptoFramerVisitor crypto_visitor;
70
[email protected]2532de12013-05-09 12:29:3371 // In order to properly test the code we need to perform encryption and
72 // decryption so that the crypters latch when expected. The crypters are in
73 // |dest_conn|, but we don't want to try and use them there. Instead we swap
74 // them into |framer|, perform the decryption with them, and then swap them
75 // back.
76 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
77
[email protected]fe053f92013-04-23 20:18:5578 crypto_framer.set_visitor(&crypto_visitor);
79
80 size_t index = *inout_packet_index;
[email protected]2532de12013-05-09 12:29:3381 for (; index < source_conn->encrypted_packets_.size(); index++) {
82 ASSERT_TRUE(framer.ProcessPacket(*source_conn->encrypted_packets_[index]));
[email protected]fe053f92013-04-23 20:18:5583 for (vector<QuicStreamFrame>::const_iterator
84 i = framer.stream_frames().begin();
85 i != framer.stream_frames().end(); ++i) {
86 ASSERT_TRUE(crypto_framer.ProcessInput(i->data));
87 ASSERT_FALSE(crypto_visitor.error());
88 }
89 }
90 *inout_packet_index = index;
91
[email protected]2532de12013-05-09 12:29:3392 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
93
[email protected]fe053f92013-04-23 20:18:5594 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
[email protected]0bbeb6972013-05-23 04:10:21103// HexChar parses |c| as a hex character. If valid, it sets |*value| to the
104// value of the hex character and returns true. Otherwise it returns false.
105bool HexChar(char c, uint8* value) {
106 if (c >= '0' && c <= '9') {
107 *value = c - '0';
108 return true;
109 }
110 if (c >= 'a' && c <= 'f') {
111 *value = c - 'a';
112 return true;
113 }
114 if (c >= 'A' && c <= 'F') {
115 *value = c - 'A';
116 return true;
117 }
118 return false;
119}
120
[email protected]ed3fc15d2013-03-08 18:37:44121} // anonymous namespace
122
[email protected]899951652013-05-16 12:52:39123CryptoTestUtils::FakeClientOptions::FakeClientOptions()
124 : dont_verify_certs(false) {
125}
126
[email protected]ed3fc15d2013-03-08 18:37:44127// static
[email protected]fe053f92013-04-23 20:18:55128int CryptoTestUtils::HandshakeWithFakeServer(
[email protected]ed3fc15d2013-03-08 18:37:44129 PacketSavingConnection* client_conn,
[email protected]14e8106c2013-03-14 16:25:33130 QuicCryptoClientStream* client) {
[email protected]ed3fc15d2013-03-08 18:37:44131 QuicGuid guid(1);
[email protected]72818ea2013-03-13 03:23:57132 IPAddressNumber ip;
133 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
134 IPEndPoint addr = IPEndPoint(ip, 1);
[email protected]ed3fc15d2013-03-08 18:37:44135 PacketSavingConnection* server_conn =
[email protected]14e8106c2013-03-14 16:25:33136 new PacketSavingConnection(guid, addr, true);
[email protected]899951652013-05-16 12:52:39137 TestSession server_session(server_conn, QuicConfig(), true);
[email protected]ef95114d2013-04-17 17:57:01138
[email protected]ef95114d2013-04-17 17:57:01139 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING);
140 SetupCryptoServerConfigForTest(
141 server_session.connection()->clock(),
142 server_session.connection()->random_generator(),
[email protected]899951652013-05-16 12:52:39143 server_session.config(), &crypto_config);
[email protected]ef95114d2013-04-17 17:57:01144
[email protected]899951652013-05-16 12:52:39145 QuicCryptoServerStream server(crypto_config, &server_session);
[email protected]2532de12013-05-09 12:29:33146 server_session.SetCryptoStream(&server);
[email protected]ed3fc15d2013-03-08 18:37:44147
148 // The client's handshake must have been started already.
149 CHECK_NE(0u, client_conn->packets_.size());
150
151 CommunicateHandshakeMessages(client_conn, client, server_conn, &server);
[email protected]14e8106c2013-03-14 16:25:33152
153 CompareClientAndServerKeys(client, &server);
[email protected]fe053f92013-04-23 20:18:55154
155 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44156}
157
158// static
[email protected]fe053f92013-04-23 20:18:55159int CryptoTestUtils::HandshakeWithFakeClient(
[email protected]ed3fc15d2013-03-08 18:37:44160 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39161 QuicCryptoServerStream* server,
162 const FakeClientOptions& options) {
[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]899951652013-05-16 12:52:39169 TestSession client_session(client_conn, QuicConfig(), false);
[email protected]ef95114d2013-04-17 17:57:01170 QuicCryptoClientConfig crypto_config;
171
[email protected]899951652013-05-16 12:52:39172 client_session.config()->SetDefaults();
[email protected]ef95114d2013-04-17 17:57:01173 crypto_config.SetDefaults();
[email protected]a57e0272013-04-26 07:31:47174 // TODO(rtenneti): Enable testing of ProofVerifier.
[email protected]899951652013-05-16 12:52:39175 // if (!options.dont_verify_certs) {
176 // crypto_config.SetProofVerifier(ProofVerifierForTesting());
177 // }
178 QuicCryptoClientStream client("test.example.com", &client_session,
[email protected]ef95114d2013-04-17 17:57:01179 &crypto_config);
[email protected]2532de12013-05-09 12:29:33180 client_session.SetCryptoStream(&client);
[email protected]ed3fc15d2013-03-08 18:37:44181
182 CHECK(client.CryptoConnect());
183 CHECK_EQ(1u, client_conn->packets_.size());
184
185 CommunicateHandshakeMessages(client_conn, &client, server_conn, server);
[email protected]14e8106c2013-03-14 16:25:33186
187 CompareClientAndServerKeys(&client, server);
[email protected]fe053f92013-04-23 20:18:55188
189 return client.num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33190}
191
192// static
[email protected]ef95114d2013-04-17 17:57:01193void CryptoTestUtils::SetupCryptoServerConfigForTest(
194 const QuicClock* clock,
195 QuicRandom* rand,
196 QuicConfig* config,
197 QuicCryptoServerConfig* crypto_config) {
198 config->SetDefaults();
[email protected]ef95114d2013-04-17 17:57:01199 scoped_ptr<CryptoHandshakeMessage> scfg(
[email protected]2532de12013-05-09 12:29:33200 crypto_config->AddDefaultConfig(
[email protected]899951652013-05-16 12:52:39201 rand, clock, QuicCryptoServerConfig::kDefaultExpiry));
[email protected]ef95114d2013-04-17 17:57:01202}
203
204// static
[email protected]0bbeb6972013-05-23 04:10:21205void CryptoTestUtils::CommunicateHandshakeMessages(
206 PacketSavingConnection* a_conn,
207 QuicCryptoStream* a,
208 PacketSavingConnection* b_conn,
209 QuicCryptoStream* b) {
210 size_t a_i = 0, b_i = 0;
211 while (!a->handshake_confirmed()) {
212 ASSERT_GT(a_conn->packets_.size(), a_i);
213 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
214 << " packets a->b";
215 MovePackets(a_conn, &a_i, b, b_conn);
216
217 ASSERT_GT(b_conn->packets_.size(), b_i);
218 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
219 << " packets b->a";
220 if (b_conn->packets_.size() - b_i == 2) {
221 LOG(INFO) << "here";
222 }
223 MovePackets(b_conn, &b_i, a, a_conn);
224 }
225}
226
227// static
[email protected]ccc66e8a2013-03-26 08:26:14228string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33229 QuicTag tag) {
230 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14231 if (it == message.tag_value_map().end()) {
232 return string();
233 }
234 return it->second;
235}
236
[email protected]2532de12013-05-09 12:29:33237class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04238 public:
[email protected]2532de12013-05-09 12:29:33239 MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
[email protected]c244c5a12013-05-07 20:55:04240 : cert_(cert.as_string()),
241 hash_(hash),
242 index_(index) {
243 }
244
[email protected]2532de12013-05-09 12:29:33245 virtual StringPiece GetCommonHashes() const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04246 CHECK(false) << "not implemented";
247 return StringPiece();
248 }
249
[email protected]2532de12013-05-09 12:29:33250 virtual StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04251 if (hash == hash_ && index == index_) {
252 return cert_;
253 }
254 return StringPiece();
255 }
256
257 virtual bool MatchCert(StringPiece cert,
258 StringPiece common_set_hashes,
259 uint64* out_hash,
[email protected]2532de12013-05-09 12:29:33260 uint32* out_index) const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04261 if (cert != cert_) {
262 return false;
263 }
264
265 if (common_set_hashes.size() % sizeof(uint64) != 0) {
266 return false;
267 }
268 bool client_has_set = false;
269 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) {
270 uint64 hash;
271 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
272 if (hash == hash_) {
273 client_has_set = true;
274 break;
275 }
276 }
277
278 if (!client_has_set) {
279 return false;
280 }
281
282 *out_hash = hash_;
283 *out_index = index_;
284 return true;
285 }
286
287 private:
288 const string cert_;
289 const uint64 hash_;
290 const uint32 index_;
291};
292
[email protected]2532de12013-05-09 12:29:33293CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
[email protected]899951652013-05-16 12:52:39294 uint64 hash,
295 uint32 index) {
[email protected]2532de12013-05-09 12:29:33296 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04297}
298
[email protected]14e8106c2013-03-14 16:25:33299void CryptoTestUtils::CompareClientAndServerKeys(
300 QuicCryptoClientStream* client,
301 QuicCryptoServerStream* server) {
[email protected]8ba81212013-05-03 13:11:48302 const QuicEncrypter* client_encrypter(
303 client->session()->connection()->encrypter(ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48304 const QuicDecrypter* client_decrypter(
[email protected]2532de12013-05-09 12:29:33305 client->session()->connection()->decrypter());
306 const QuicEncrypter* client_forward_secure_encrypter(
307 client->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
308 const QuicDecrypter* client_forward_secure_decrypter(
[email protected]8ba81212013-05-03 13:11:48309 client->session()->connection()->alternative_decrypter());
310 const QuicEncrypter* server_encrypter(
311 server->session()->connection()->encrypter(ENCRYPTION_INITIAL));
312 const QuicDecrypter* server_decrypter(
313 server->session()->connection()->decrypter());
[email protected]2532de12013-05-09 12:29:33314 const QuicEncrypter* server_forward_secure_encrypter(
315 server->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
316 const QuicDecrypter* server_forward_secure_decrypter(
317 server->session()->connection()->alternative_decrypter());
[email protected]8ba81212013-05-03 13:11:48318
319 StringPiece client_encrypter_key = client_encrypter->GetKey();
320 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
321 StringPiece client_decrypter_key = client_decrypter->GetKey();
322 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33323 StringPiece client_forward_secure_encrypter_key =
324 client_forward_secure_encrypter->GetKey();
325 StringPiece client_forward_secure_encrypter_iv =
326 client_forward_secure_encrypter->GetNoncePrefix();
327 StringPiece client_forward_secure_decrypter_key =
328 client_forward_secure_decrypter->GetKey();
329 StringPiece client_forward_secure_decrypter_iv =
330 client_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48331 StringPiece server_encrypter_key = server_encrypter->GetKey();
332 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
333 StringPiece server_decrypter_key = server_decrypter->GetKey();
334 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33335 StringPiece server_forward_secure_encrypter_key =
336 server_forward_secure_encrypter->GetKey();
337 StringPiece server_forward_secure_encrypter_iv =
338 server_forward_secure_encrypter->GetNoncePrefix();
339 StringPiece server_forward_secure_decrypter_key =
340 server_forward_secure_decrypter->GetKey();
341 StringPiece server_forward_secure_decrypter_iv =
342 server_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48343
[email protected]14e8106c2013-03-14 16:25:33344 CompareCharArraysWithHexError("client write key",
345 client_encrypter_key.data(),
346 client_encrypter_key.length(),
347 server_decrypter_key.data(),
348 server_decrypter_key.length());
349 CompareCharArraysWithHexError("client write IV",
350 client_encrypter_iv.data(),
351 client_encrypter_iv.length(),
352 server_decrypter_iv.data(),
353 server_decrypter_iv.length());
354 CompareCharArraysWithHexError("server write key",
355 server_encrypter_key.data(),
356 server_encrypter_key.length(),
357 client_decrypter_key.data(),
358 client_decrypter_key.length());
359 CompareCharArraysWithHexError("server write IV",
360 server_encrypter_iv.data(),
361 server_encrypter_iv.length(),
362 client_decrypter_iv.data(),
363 client_decrypter_iv.length());
[email protected]2532de12013-05-09 12:29:33364 CompareCharArraysWithHexError("client forward secure write key",
365 client_forward_secure_encrypter_key.data(),
366 client_forward_secure_encrypter_key.length(),
367 server_forward_secure_decrypter_key.data(),
368 server_forward_secure_decrypter_key.length());
369 CompareCharArraysWithHexError("client forward secure write IV",
370 client_forward_secure_encrypter_iv.data(),
371 client_forward_secure_encrypter_iv.length(),
372 server_forward_secure_decrypter_iv.data(),
373 server_forward_secure_decrypter_iv.length());
374 CompareCharArraysWithHexError("server forward secure write key",
375 server_forward_secure_encrypter_key.data(),
376 server_forward_secure_encrypter_key.length(),
377 client_forward_secure_decrypter_key.data(),
378 client_forward_secure_decrypter_key.length());
379 CompareCharArraysWithHexError("server forward secure write IV",
380 server_forward_secure_encrypter_iv.data(),
381 server_forward_secure_encrypter_iv.length(),
382 client_forward_secure_decrypter_iv.data(),
383 client_forward_secure_decrypter_iv.length());
[email protected]ed3fc15d2013-03-08 18:37:44384}
[email protected]0bbeb6972013-05-23 04:10:21385
386// static
387QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
388 const size_t len = strlen(tagstr);
389 CHECK_NE(0u, len);
390
391 QuicTag tag = 0;
392
393 if (tagstr[0] == '#') {
394 CHECK_EQ(static_cast<size_t>(1 + 2*4), len);
395 tagstr++;
396
397 for (size_t i = 0; i < 8; i++) {
398 tag <<= 4;
399
400 uint8 v = 0;
401 CHECK(HexChar(tagstr[i], &v));
402 tag |= v;
403 }
404
405 return tag;
406 }
407
408 CHECK_LE(len, 4u);
409 for (size_t i = 0; i < 4; i++) {
410 tag >>= 8;
411 if (i < len) {
412 tag |= static_cast<uint32>(tagstr[i]) << 24;
413 }
414 }
415
416 return tag;
417}
418
419// static
420CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
421 va_list ap;
422 va_start(ap, message_tag);
423
424 CryptoHandshakeMessage message = BuildMessage(message_tag, ap);
425 va_end(ap);
426 return message;
427}
428
429// static
430CryptoHandshakeMessage CryptoTestUtils::BuildMessage(const char* message_tag,
431 va_list ap) {
432 CryptoHandshakeMessage msg;
433 msg.set_tag(ParseTag(message_tag));
434
435 for (;;) {
436 const char* tagstr = va_arg(ap, const char*);
437 if (tagstr == NULL) {
438 break;
439 }
440
441 const QuicTag tag = ParseTag(tagstr);
442 const char* valuestr = va_arg(ap, const char*);
443
444 size_t len = strlen(valuestr);
445 if (len > 0 && valuestr[0] == '#') {
446 valuestr++;
447 len--;
448
449 CHECK(len % 2 == 0);
450 scoped_ptr<uint8[]> buf(new uint8[len/2]);
451
452 for (size_t i = 0; i < len/2; i++) {
453 uint8 v = 0;
454 CHECK(HexChar(valuestr[i*2], &v));
455 buf[i] = v << 4;
456 CHECK(HexChar(valuestr[i*2 + 1], &v));
457 buf[i] |= v;
458 }
459
460 msg.SetStringPiece(
461 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len/2));
462 continue;
463 }
464
465 msg.SetStringPiece(tag, valuestr);
466 }
467
468 return msg;
469}
470
[email protected]ed3fc15d2013-03-08 18:37:44471} // namespace test
472} // namespace net