Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / net / quic / test_tools / crypto_test_utils.cc
blob86ff6422460a70b34c74b413331195290a7a28ae
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/test_tools/crypto_test_utils.h"
7 #include "net/quic/crypto/channel_id.h"
8 #include "net/quic/crypto/common_cert_set.h"
9 #include "net/quic/crypto/crypto_handshake.h"
10 #include "net/quic/crypto/quic_crypto_server_config.h"
11 #include "net/quic/crypto/quic_decrypter.h"
12 #include "net/quic/crypto/quic_encrypter.h"
13 #include "net/quic/crypto/quic_random.h"
14 #include "net/quic/quic_clock.h"
15 #include "net/quic/quic_crypto_client_stream.h"
16 #include "net/quic/quic_crypto_server_stream.h"
17 #include "net/quic/quic_crypto_stream.h"
18 #include "net/quic/quic_server_id.h"
19 #include "net/quic/test_tools/quic_connection_peer.h"
20 #include "net/quic/test_tools/quic_test_utils.h"
21 #include "net/quic/test_tools/simple_quic_framer.h"
23 using base::StringPiece;
24 using std::make_pair;
25 using std::pair;
26 using std::string;
27 using std::vector;
29 namespace net {
30 namespace test {
32 namespace {
34 const char kServerHostname[] = "test.example.com";
35 const uint16 kServerPort = 80;
37 // CryptoFramerVisitor is a framer visitor that records handshake messages.
38 class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
39 public:
40 CryptoFramerVisitor()
41 : error_(false) {
44 virtual void OnError(CryptoFramer* framer) OVERRIDE { error_ = true; }
46 virtual void OnHandshakeMessage(
47 const CryptoHandshakeMessage& message) OVERRIDE {
48 messages_.push_back(message);
51 bool error() const {
52 return error_;
55 const vector<CryptoHandshakeMessage>& messages() const {
56 return messages_;
59 private:
60 bool error_;
61 vector<CryptoHandshakeMessage> messages_;
64 // MovePackets parses crypto handshake messages from packet number
65 // |*inout_packet_index| through to the last packet (or until a packet fails to
66 // decrypt) and has |dest_stream| process them. |*inout_packet_index| is updated
67 // with an index one greater than the last packet processed.
68 void MovePackets(PacketSavingConnection* source_conn,
69 size_t *inout_packet_index,
70 QuicCryptoStream* dest_stream,
71 PacketSavingConnection* dest_conn) {
72 SimpleQuicFramer framer(source_conn->supported_versions());
73 CryptoFramer crypto_framer;
74 CryptoFramerVisitor crypto_visitor;
76 // In order to properly test the code we need to perform encryption and
77 // decryption so that the crypters latch when expected. The crypters are in
78 // |dest_conn|, but we don't want to try and use them there. Instead we swap
79 // them into |framer|, perform the decryption with them, and then swap them
80 // back.
81 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
83 crypto_framer.set_visitor(&crypto_visitor);
85 size_t index = *inout_packet_index;
86 for (; index < source_conn->encrypted_packets_.size(); index++) {
87 if (!framer.ProcessPacket(*source_conn->encrypted_packets_[index])) {
88 // The framer will be unable to decrypt forward-secure packets sent after
89 // the handshake is complete. Don't treat them as handshake packets.
90 break;
93 for (vector<QuicStreamFrame>::const_iterator
94 i = framer.stream_frames().begin();
95 i != framer.stream_frames().end(); ++i) {
96 scoped_ptr<string> frame_data(i->GetDataAsString());
97 ASSERT_TRUE(crypto_framer.ProcessInput(*frame_data));
98 ASSERT_FALSE(crypto_visitor.error());
101 *inout_packet_index = index;
103 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
105 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
107 for (vector<CryptoHandshakeMessage>::const_iterator
108 i = crypto_visitor.messages().begin();
109 i != crypto_visitor.messages().end(); ++i) {
110 dest_stream->OnHandshakeMessage(*i);
114 // HexChar parses |c| as a hex character. If valid, it sets |*value| to the
115 // value of the hex character and returns true. Otherwise it returns false.
116 bool HexChar(char c, uint8* value) {
117 if (c >= '0' && c <= '9') {
118 *value = c - '0';
119 return true;
121 if (c >= 'a' && c <= 'f') {
122 *value = c - 'a' + 10;
123 return true;
125 if (c >= 'A' && c <= 'F') {
126 *value = c - 'A' + 10;
127 return true;
129 return false;
132 // A ChannelIDSource that works in asynchronous mode unless the |callback|
133 // argument to GetChannelIDKey is NULL.
134 class AsyncTestChannelIDSource : public ChannelIDSource,
135 public CryptoTestUtils::CallbackSource {
136 public:
137 // Takes ownership of |sync_source|, a synchronous ChannelIDSource.
138 explicit AsyncTestChannelIDSource(ChannelIDSource* sync_source)
139 : sync_source_(sync_source) {}
140 virtual ~AsyncTestChannelIDSource() {}
142 // ChannelIDSource implementation.
143 virtual QuicAsyncStatus GetChannelIDKey(
144 const string& hostname,
145 scoped_ptr<ChannelIDKey>* channel_id_key,
146 ChannelIDSourceCallback* callback) OVERRIDE {
147 // Synchronous mode.
148 if (!callback) {
149 return sync_source_->GetChannelIDKey(hostname, channel_id_key, NULL);
152 // Asynchronous mode.
153 QuicAsyncStatus status =
154 sync_source_->GetChannelIDKey(hostname, &channel_id_key_, NULL);
155 if (status != QUIC_SUCCESS) {
156 return QUIC_FAILURE;
158 callback_.reset(callback);
159 return QUIC_PENDING;
162 // CallbackSource implementation.
163 virtual void RunPendingCallbacks() OVERRIDE {
164 if (callback_.get()) {
165 callback_->Run(&channel_id_key_);
166 callback_.reset();
170 private:
171 scoped_ptr<ChannelIDSource> sync_source_;
172 scoped_ptr<ChannelIDSourceCallback> callback_;
173 scoped_ptr<ChannelIDKey> channel_id_key_;
176 } // anonymous namespace
178 CryptoTestUtils::FakeClientOptions::FakeClientOptions()
179 : dont_verify_certs(false),
180 channel_id_enabled(false),
181 channel_id_source_async(false) {
184 // static
185 int CryptoTestUtils::HandshakeWithFakeServer(
186 PacketSavingConnection* client_conn,
187 QuicCryptoClientStream* client) {
188 PacketSavingConnection* server_conn =
189 new PacketSavingConnection(true, client_conn->supported_versions());
190 TestSession server_session(server_conn, DefaultQuicConfig());
191 server_session.InitializeSession();
192 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
193 QuicRandom::GetInstance());
195 SetupCryptoServerConfigForTest(
196 server_session.connection()->clock(),
197 server_session.connection()->random_generator(),
198 server_session.config(), &crypto_config);
200 QuicCryptoServerStream server(crypto_config, &server_session);
201 server_session.SetCryptoStream(&server);
203 // The client's handshake must have been started already.
204 CHECK_NE(0u, client_conn->packets_.size());
206 CommunicateHandshakeMessages(client_conn, client, server_conn, &server);
208 CompareClientAndServerKeys(client, &server);
210 return client->num_sent_client_hellos();
213 // static
214 int CryptoTestUtils::HandshakeWithFakeClient(
215 PacketSavingConnection* server_conn,
216 QuicCryptoServerStream* server,
217 const FakeClientOptions& options) {
218 PacketSavingConnection* client_conn = new PacketSavingConnection(false);
219 TestClientSession client_session(client_conn, DefaultQuicConfig());
220 QuicCryptoClientConfig crypto_config;
222 client_session.config()->SetDefaults();
223 crypto_config.SetDefaults();
224 if (!options.dont_verify_certs) {
225 // TODO(wtc): replace this with ProofVerifierForTesting() when we have
226 // a working ProofSourceForTesting().
227 crypto_config.SetProofVerifier(FakeProofVerifierForTesting());
229 bool is_https = false;
230 AsyncTestChannelIDSource* async_channel_id_source = NULL;
231 if (options.channel_id_enabled) {
232 is_https = true;
234 ChannelIDSource* source = ChannelIDSourceForTesting();
235 if (options.channel_id_source_async) {
236 async_channel_id_source = new AsyncTestChannelIDSource(source);
237 source = async_channel_id_source;
239 crypto_config.SetChannelIDSource(source);
241 QuicServerId server_id(kServerHostname, kServerPort, is_https,
242 PRIVACY_MODE_DISABLED);
243 QuicCryptoClientStream client(server_id, &client_session,
244 ProofVerifyContextForTesting(),
245 &crypto_config);
246 client_session.SetCryptoStream(&client);
248 CHECK(client.CryptoConnect());
249 CHECK_EQ(1u, client_conn->packets_.size());
251 CommunicateHandshakeMessagesAndRunCallbacks(
252 client_conn, &client, server_conn, server, async_channel_id_source);
254 CompareClientAndServerKeys(&client, server);
256 if (options.channel_id_enabled) {
257 scoped_ptr<ChannelIDKey> channel_id_key;
258 QuicAsyncStatus status =
259 crypto_config.channel_id_source()->GetChannelIDKey(kServerHostname,
260 &channel_id_key,
261 NULL);
262 EXPECT_EQ(QUIC_SUCCESS, status);
263 EXPECT_EQ(channel_id_key->SerializeKey(),
264 server->crypto_negotiated_params().channel_id);
265 EXPECT_EQ(options.channel_id_source_async,
266 client.WasChannelIDSourceCallbackRun());
269 return client.num_sent_client_hellos();
272 // static
273 void CryptoTestUtils::SetupCryptoServerConfigForTest(
274 const QuicClock* clock,
275 QuicRandom* rand,
276 QuicConfig* config,
277 QuicCryptoServerConfig* crypto_config) {
278 config->SetDefaults();
279 QuicCryptoServerConfig::ConfigOptions options;
280 options.channel_id_enabled = true;
281 scoped_ptr<CryptoHandshakeMessage> scfg(
282 crypto_config->AddDefaultConfig(rand, clock, options));
285 // static
286 void CryptoTestUtils::CommunicateHandshakeMessages(
287 PacketSavingConnection* a_conn,
288 QuicCryptoStream* a,
289 PacketSavingConnection* b_conn,
290 QuicCryptoStream* b) {
291 CommunicateHandshakeMessagesAndRunCallbacks(a_conn, a, b_conn, b, NULL);
294 // static
295 void CryptoTestUtils::CommunicateHandshakeMessagesAndRunCallbacks(
296 PacketSavingConnection* a_conn,
297 QuicCryptoStream* a,
298 PacketSavingConnection* b_conn,
299 QuicCryptoStream* b,
300 CallbackSource* callback_source) {
301 size_t a_i = 0, b_i = 0;
302 while (!a->handshake_confirmed()) {
303 ASSERT_GT(a_conn->packets_.size(), a_i);
304 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
305 << " packets a->b";
306 MovePackets(a_conn, &a_i, b, b_conn);
307 if (callback_source) {
308 callback_source->RunPendingCallbacks();
311 ASSERT_GT(b_conn->packets_.size(), b_i);
312 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
313 << " packets b->a";
314 MovePackets(b_conn, &b_i, a, a_conn);
315 if (callback_source) {
316 callback_source->RunPendingCallbacks();
321 // static
322 pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
323 PacketSavingConnection* a_conn,
324 QuicCryptoStream* a,
325 size_t a_i,
326 PacketSavingConnection* b_conn,
327 QuicCryptoStream* b,
328 size_t b_i) {
329 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
330 << " packets a->b";
331 MovePackets(a_conn, &a_i, b, b_conn);
333 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
334 << " packets b->a";
335 if (b_conn->packets_.size() - b_i == 2) {
336 LOG(INFO) << "here";
338 MovePackets(b_conn, &b_i, a, a_conn);
340 return make_pair(a_i, b_i);
343 // static
344 string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
345 QuicTag tag) {
346 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
347 if (it == message.tag_value_map().end()) {
348 return string();
350 return it->second;
353 class MockCommonCertSets : public CommonCertSets {
354 public:
355 MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
356 : cert_(cert.as_string()),
357 hash_(hash),
358 index_(index) {
361 virtual StringPiece GetCommonHashes() const OVERRIDE {
362 CHECK(false) << "not implemented";
363 return StringPiece();
366 virtual StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE {
367 if (hash == hash_ && index == index_) {
368 return cert_;
370 return StringPiece();
373 virtual bool MatchCert(StringPiece cert,
374 StringPiece common_set_hashes,
375 uint64* out_hash,
376 uint32* out_index) const OVERRIDE {
377 if (cert != cert_) {
378 return false;
381 if (common_set_hashes.size() % sizeof(uint64) != 0) {
382 return false;
384 bool client_has_set = false;
385 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) {
386 uint64 hash;
387 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
388 if (hash == hash_) {
389 client_has_set = true;
390 break;
394 if (!client_has_set) {
395 return false;
398 *out_hash = hash_;
399 *out_index = index_;
400 return true;
403 private:
404 const string cert_;
405 const uint64 hash_;
406 const uint32 index_;
409 CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
410 uint64 hash,
411 uint32 index) {
412 return new class MockCommonCertSets(cert, hash, index);
415 void CryptoTestUtils::CompareClientAndServerKeys(
416 QuicCryptoClientStream* client,
417 QuicCryptoServerStream* server) {
418 const QuicEncrypter* client_encrypter(
419 client->session()->connection()->encrypter(ENCRYPTION_INITIAL));
420 const QuicDecrypter* client_decrypter(
421 client->session()->connection()->decrypter());
422 const QuicEncrypter* client_forward_secure_encrypter(
423 client->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
424 const QuicDecrypter* client_forward_secure_decrypter(
425 client->session()->connection()->alternative_decrypter());
426 const QuicEncrypter* server_encrypter(
427 server->session()->connection()->encrypter(ENCRYPTION_INITIAL));
428 const QuicDecrypter* server_decrypter(
429 server->session()->connection()->decrypter());
430 const QuicEncrypter* server_forward_secure_encrypter(
431 server->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
432 const QuicDecrypter* server_forward_secure_decrypter(
433 server->session()->connection()->alternative_decrypter());
435 StringPiece client_encrypter_key = client_encrypter->GetKey();
436 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
437 StringPiece client_decrypter_key = client_decrypter->GetKey();
438 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
439 StringPiece client_forward_secure_encrypter_key =
440 client_forward_secure_encrypter->GetKey();
441 StringPiece client_forward_secure_encrypter_iv =
442 client_forward_secure_encrypter->GetNoncePrefix();
443 StringPiece client_forward_secure_decrypter_key =
444 client_forward_secure_decrypter->GetKey();
445 StringPiece client_forward_secure_decrypter_iv =
446 client_forward_secure_decrypter->GetNoncePrefix();
447 StringPiece server_encrypter_key = server_encrypter->GetKey();
448 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
449 StringPiece server_decrypter_key = server_decrypter->GetKey();
450 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
451 StringPiece server_forward_secure_encrypter_key =
452 server_forward_secure_encrypter->GetKey();
453 StringPiece server_forward_secure_encrypter_iv =
454 server_forward_secure_encrypter->GetNoncePrefix();
455 StringPiece server_forward_secure_decrypter_key =
456 server_forward_secure_decrypter->GetKey();
457 StringPiece server_forward_secure_decrypter_iv =
458 server_forward_secure_decrypter->GetNoncePrefix();
460 StringPiece client_subkey_secret =
461 client->crypto_negotiated_params().subkey_secret;
462 StringPiece server_subkey_secret =
463 server->crypto_negotiated_params().subkey_secret;
466 const char kSampleLabel[] = "label";
467 const char kSampleContext[] = "context";
468 const size_t kSampleOutputLength = 32;
469 string client_key_extraction;
470 string server_key_extraction;
471 EXPECT_TRUE(client->ExportKeyingMaterial(kSampleLabel,
472 kSampleContext,
473 kSampleOutputLength,
474 &client_key_extraction));
475 EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel,
476 kSampleContext,
477 kSampleOutputLength,
478 &server_key_extraction));
480 CompareCharArraysWithHexError("client write key",
481 client_encrypter_key.data(),
482 client_encrypter_key.length(),
483 server_decrypter_key.data(),
484 server_decrypter_key.length());
485 CompareCharArraysWithHexError("client write IV",
486 client_encrypter_iv.data(),
487 client_encrypter_iv.length(),
488 server_decrypter_iv.data(),
489 server_decrypter_iv.length());
490 CompareCharArraysWithHexError("server write key",
491 server_encrypter_key.data(),
492 server_encrypter_key.length(),
493 client_decrypter_key.data(),
494 client_decrypter_key.length());
495 CompareCharArraysWithHexError("server write IV",
496 server_encrypter_iv.data(),
497 server_encrypter_iv.length(),
498 client_decrypter_iv.data(),
499 client_decrypter_iv.length());
500 CompareCharArraysWithHexError("client forward secure write key",
501 client_forward_secure_encrypter_key.data(),
502 client_forward_secure_encrypter_key.length(),
503 server_forward_secure_decrypter_key.data(),
504 server_forward_secure_decrypter_key.length());
505 CompareCharArraysWithHexError("client forward secure write IV",
506 client_forward_secure_encrypter_iv.data(),
507 client_forward_secure_encrypter_iv.length(),
508 server_forward_secure_decrypter_iv.data(),
509 server_forward_secure_decrypter_iv.length());
510 CompareCharArraysWithHexError("server forward secure write key",
511 server_forward_secure_encrypter_key.data(),
512 server_forward_secure_encrypter_key.length(),
513 client_forward_secure_decrypter_key.data(),
514 client_forward_secure_decrypter_key.length());
515 CompareCharArraysWithHexError("server forward secure write IV",
516 server_forward_secure_encrypter_iv.data(),
517 server_forward_secure_encrypter_iv.length(),
518 client_forward_secure_decrypter_iv.data(),
519 client_forward_secure_decrypter_iv.length());
520 CompareCharArraysWithHexError("subkey secret",
521 client_subkey_secret.data(),
522 client_subkey_secret.length(),
523 server_subkey_secret.data(),
524 server_subkey_secret.length());
525 CompareCharArraysWithHexError("sample key extraction",
526 client_key_extraction.data(),
527 client_key_extraction.length(),
528 server_key_extraction.data(),
529 server_key_extraction.length());
532 // static
533 QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
534 const size_t len = strlen(tagstr);
535 CHECK_NE(0u, len);
537 QuicTag tag = 0;
539 if (tagstr[0] == '#') {
540 CHECK_EQ(static_cast<size_t>(1 + 2*4), len);
541 tagstr++;
543 for (size_t i = 0; i < 8; i++) {
544 tag <<= 4;
546 uint8 v = 0;
547 CHECK(HexChar(tagstr[i], &v));
548 tag |= v;
551 return tag;
554 CHECK_LE(len, 4u);
555 for (size_t i = 0; i < 4; i++) {
556 tag >>= 8;
557 if (i < len) {
558 tag |= static_cast<uint32>(tagstr[i]) << 24;
562 return tag;
565 // static
566 CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
567 va_list ap;
568 va_start(ap, message_tag);
570 CryptoHandshakeMessage message = BuildMessage(message_tag, ap);
571 va_end(ap);
572 return message;
575 // static
576 CryptoHandshakeMessage CryptoTestUtils::BuildMessage(const char* message_tag,
577 va_list ap) {
578 CryptoHandshakeMessage msg;
579 msg.set_tag(ParseTag(message_tag));
581 for (;;) {
582 const char* tagstr = va_arg(ap, const char*);
583 if (tagstr == NULL) {
584 break;
587 if (tagstr[0] == '$') {
588 // Special value.
589 const char* const special = tagstr + 1;
590 if (strcmp(special, "padding") == 0) {
591 const int min_bytes = va_arg(ap, int);
592 msg.set_minimum_size(min_bytes);
593 } else {
594 CHECK(false) << "Unknown special value: " << special;
597 continue;
600 const QuicTag tag = ParseTag(tagstr);
601 const char* valuestr = va_arg(ap, const char*);
603 size_t len = strlen(valuestr);
604 if (len > 0 && valuestr[0] == '#') {
605 valuestr++;
606 len--;
608 CHECK_EQ(0u, len % 2);
609 scoped_ptr<uint8[]> buf(new uint8[len/2]);
611 for (size_t i = 0; i < len/2; i++) {
612 uint8 v = 0;
613 CHECK(HexChar(valuestr[i*2], &v));
614 buf[i] = v << 4;
615 CHECK(HexChar(valuestr[i*2 + 1], &v));
616 buf[i] |= v;
619 msg.SetStringPiece(
620 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len/2));
621 continue;
624 msg.SetStringPiece(tag, valuestr);
627 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
628 // that any padding is included.
629 scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
630 scoped_ptr<CryptoHandshakeMessage> parsed(
631 CryptoFramer::ParseMessage(bytes->AsStringPiece()));
632 CHECK(parsed.get());
634 return *parsed;
637 } // namespace test
638 } // namespace net