- add sources.
[platform/framework/web/crosswalk.git] / src / net / quic / test_tools / crypto_test_utils.cc
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.
4
5 #include "net/quic/test_tools/crypto_test_utils.h"
6
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/test_tools/quic_connection_peer.h"
19 #include "net/quic/test_tools/quic_test_utils.h"
20 #include "net/quic/test_tools/simple_quic_framer.h"
21
22 using base::StringPiece;
23 using std::string;
24 using std::vector;
25
26 namespace net {
27 namespace test {
28
29 namespace {
30
31 // CryptoFramerVisitor is a framer visitor that records handshake messages.
32 class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
33  public:
34   CryptoFramerVisitor()
35       : error_(false) {
36   }
37
38   virtual void OnError(CryptoFramer* framer) OVERRIDE {
39     error_ = true;
40   }
41
42   virtual void OnHandshakeMessage(
43       const CryptoHandshakeMessage& message) OVERRIDE {
44     messages_.push_back(message);
45   }
46
47   bool error() const {
48     return error_;
49   }
50
51   const vector<CryptoHandshakeMessage>& messages() const {
52     return messages_;
53   }
54
55  private:
56   bool error_;
57   vector<CryptoHandshakeMessage> messages_;
58 };
59
60 // MovePackets parses crypto handshake messages from packet number
61 // |*inout_packet_index| through to the last packet and has |dest_stream|
62 // process them. |*inout_packet_index| is updated with an index one greater
63 // than the last packet processed.
64 void MovePackets(PacketSavingConnection* source_conn,
65                  size_t *inout_packet_index,
66                  QuicCryptoStream* dest_stream,
67                  PacketSavingConnection* dest_conn) {
68   SimpleQuicFramer framer;
69   CryptoFramer crypto_framer;
70   CryptoFramerVisitor crypto_visitor;
71
72   // In order to properly test the code we need to perform encryption and
73   // decryption so that the crypters latch when expected. The crypters are in
74   // |dest_conn|, but we don't want to try and use them there. Instead we swap
75   // them into |framer|, perform the decryption with them, and then swap them
76   // back.
77   QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
78
79   crypto_framer.set_visitor(&crypto_visitor);
80
81   size_t index = *inout_packet_index;
82   for (; index < source_conn->encrypted_packets_.size(); index++) {
83     ASSERT_TRUE(framer.ProcessPacket(*source_conn->encrypted_packets_[index]));
84     for (vector<QuicStreamFrame>::const_iterator
85          i =  framer.stream_frames().begin();
86          i != framer.stream_frames().end(); ++i) {
87       ASSERT_TRUE(crypto_framer.ProcessInput(i->data));
88       ASSERT_FALSE(crypto_visitor.error());
89     }
90   }
91   *inout_packet_index = index;
92
93   QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
94
95   ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
96
97   for (vector<CryptoHandshakeMessage>::const_iterator
98        i = crypto_visitor.messages().begin();
99        i != crypto_visitor.messages().end(); ++i) {
100     dest_stream->OnHandshakeMessage(*i);
101   }
102 }
103
104 // HexChar parses |c| as a hex character. If valid, it sets |*value| to the
105 // value of the hex character and returns true. Otherwise it returns false.
106 bool HexChar(char c, uint8* value) {
107   if (c >= '0' && c <= '9') {
108     *value = c - '0';
109     return true;
110   }
111   if (c >= 'a' && c <= 'f') {
112     *value = c - 'a' + 10;
113     return true;
114   }
115   if (c >= 'A' && c <= 'F') {
116     *value = c - 'A' + 10;
117     return true;
118   }
119   return false;
120 }
121
122 }  // anonymous namespace
123
124 CryptoTestUtils::FakeClientOptions::FakeClientOptions()
125     : dont_verify_certs(false),
126       channel_id_enabled(false) {
127 }
128
129 // static
130 int CryptoTestUtils::HandshakeWithFakeServer(
131     PacketSavingConnection* client_conn,
132     QuicCryptoClientStream* client) {
133   QuicGuid guid(1);
134   IPAddressNumber ip;
135   CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
136   IPEndPoint addr = IPEndPoint(ip, 1);
137   PacketSavingConnection* server_conn =
138       new PacketSavingConnection(guid, addr, true);
139   TestSession server_session(server_conn, DefaultQuicConfig(), true);
140
141   QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
142                                        QuicRandom::GetInstance());
143   SetupCryptoServerConfigForTest(
144       server_session.connection()->clock(),
145       server_session.connection()->random_generator(),
146       server_session.config(), &crypto_config);
147
148   QuicCryptoServerStream server(crypto_config, &server_session);
149   server_session.SetCryptoStream(&server);
150
151   // The client's handshake must have been started already.
152   CHECK_NE(0u, client_conn->packets_.size());
153
154   CommunicateHandshakeMessages(client_conn, client, server_conn, &server);
155
156   CompareClientAndServerKeys(client, &server);
157
158   return client->num_sent_client_hellos();
159 }
160
161 // static
162 int CryptoTestUtils::HandshakeWithFakeClient(
163     PacketSavingConnection* server_conn,
164     QuicCryptoServerStream* server,
165     const FakeClientOptions& options) {
166   QuicGuid guid(1);
167   IPAddressNumber ip;
168   CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
169   IPEndPoint addr = IPEndPoint(ip, 1);
170   PacketSavingConnection* client_conn =
171       new PacketSavingConnection(guid, addr, false);
172   TestSession client_session(client_conn, DefaultQuicConfig(), false);
173   QuicCryptoClientConfig crypto_config;
174
175   client_session.config()->SetDefaults();
176   crypto_config.SetDefaults();
177   // TODO(rtenneti): Enable testing of ProofVerifier.
178   // if (!options.dont_verify_certs) {
179   //   crypto_config.SetProofVerifier(ProofVerifierForTesting());
180   // }
181   if (options.channel_id_enabled) {
182     crypto_config.SetChannelIDSigner(ChannelIDSignerForTesting());
183   }
184   QuicCryptoClientStream client("test.example.com", &client_session,
185                                 &crypto_config);
186   client_session.SetCryptoStream(&client);
187
188   CHECK(client.CryptoConnect());
189   CHECK_EQ(1u, client_conn->packets_.size());
190
191   CommunicateHandshakeMessages(client_conn, &client, server_conn, server);
192
193   CompareClientAndServerKeys(&client, server);
194
195   if (options.channel_id_enabled) {
196     EXPECT_EQ(crypto_config.channel_id_signer()->GetKeyForHostname(
197                   "test.example.com"),
198               server->crypto_negotiated_params().channel_id);
199   }
200
201   return client.num_sent_client_hellos();
202 }
203
204 // static
205 void CryptoTestUtils::SetupCryptoServerConfigForTest(
206     const QuicClock* clock,
207     QuicRandom* rand,
208     QuicConfig* config,
209     QuicCryptoServerConfig* crypto_config) {
210   config->SetDefaults();
211   QuicCryptoServerConfig::ConfigOptions options;
212   options.channel_id_enabled = true;
213   scoped_ptr<CryptoHandshakeMessage> scfg(
214       crypto_config->AddDefaultConfig(rand, clock, options));
215 }
216
217 // static
218 void CryptoTestUtils::CommunicateHandshakeMessages(
219     PacketSavingConnection* a_conn,
220     QuicCryptoStream* a,
221     PacketSavingConnection* b_conn,
222     QuicCryptoStream* b) {
223   size_t a_i = 0, b_i = 0;
224   while (!a->handshake_confirmed()) {
225     ASSERT_GT(a_conn->packets_.size(), a_i);
226     LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
227               << " packets a->b";
228     MovePackets(a_conn, &a_i, b, b_conn);
229
230     ASSERT_GT(b_conn->packets_.size(), b_i);
231     LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
232               << " packets b->a";
233     if (b_conn->packets_.size() - b_i == 2) {
234       LOG(INFO) << "here";
235     }
236     MovePackets(b_conn, &b_i, a, a_conn);
237   }
238 }
239
240 // static
241 string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
242                                        QuicTag tag) {
243   QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
244   if (it == message.tag_value_map().end()) {
245     return string();
246   }
247   return it->second;
248 }
249
250 class MockCommonCertSets : public CommonCertSets {
251  public:
252   MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
253       : cert_(cert.as_string()),
254         hash_(hash),
255         index_(index) {
256   }
257
258   virtual StringPiece GetCommonHashes() const OVERRIDE {
259     CHECK(false) << "not implemented";
260     return StringPiece();
261   }
262
263   virtual StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE {
264     if (hash == hash_ && index == index_) {
265       return cert_;
266     }
267     return StringPiece();
268   }
269
270   virtual bool MatchCert(StringPiece cert,
271                          StringPiece common_set_hashes,
272                          uint64* out_hash,
273                          uint32* out_index) const OVERRIDE {
274     if (cert != cert_) {
275       return false;
276     }
277
278     if (common_set_hashes.size() % sizeof(uint64) != 0) {
279       return false;
280     }
281     bool client_has_set = false;
282     for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) {
283       uint64 hash;
284       memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
285       if (hash == hash_) {
286         client_has_set = true;
287         break;
288       }
289     }
290
291     if (!client_has_set) {
292       return false;
293     }
294
295     *out_hash = hash_;
296     *out_index = index_;
297     return true;
298   }
299
300  private:
301   const string cert_;
302   const uint64 hash_;
303   const uint32 index_;
304 };
305
306 CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
307                                                     uint64 hash,
308                                                     uint32 index) {
309   return new class MockCommonCertSets(cert, hash, index);
310 }
311
312 void CryptoTestUtils::CompareClientAndServerKeys(
313     QuicCryptoClientStream* client,
314     QuicCryptoServerStream* server) {
315   const QuicEncrypter* client_encrypter(
316       client->session()->connection()->encrypter(ENCRYPTION_INITIAL));
317   const QuicDecrypter* client_decrypter(
318       client->session()->connection()->decrypter());
319   const QuicEncrypter* client_forward_secure_encrypter(
320       client->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
321   const QuicDecrypter* client_forward_secure_decrypter(
322       client->session()->connection()->alternative_decrypter());
323   const QuicEncrypter* server_encrypter(
324       server->session()->connection()->encrypter(ENCRYPTION_INITIAL));
325   const QuicDecrypter* server_decrypter(
326       server->session()->connection()->decrypter());
327   const QuicEncrypter* server_forward_secure_encrypter(
328       server->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
329   const QuicDecrypter* server_forward_secure_decrypter(
330       server->session()->connection()->alternative_decrypter());
331
332   StringPiece client_encrypter_key = client_encrypter->GetKey();
333   StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
334   StringPiece client_decrypter_key = client_decrypter->GetKey();
335   StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
336   StringPiece client_forward_secure_encrypter_key =
337       client_forward_secure_encrypter->GetKey();
338   StringPiece client_forward_secure_encrypter_iv =
339       client_forward_secure_encrypter->GetNoncePrefix();
340   StringPiece client_forward_secure_decrypter_key =
341       client_forward_secure_decrypter->GetKey();
342   StringPiece client_forward_secure_decrypter_iv =
343       client_forward_secure_decrypter->GetNoncePrefix();
344   StringPiece server_encrypter_key = server_encrypter->GetKey();
345   StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
346   StringPiece server_decrypter_key = server_decrypter->GetKey();
347   StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
348   StringPiece server_forward_secure_encrypter_key =
349       server_forward_secure_encrypter->GetKey();
350   StringPiece server_forward_secure_encrypter_iv =
351       server_forward_secure_encrypter->GetNoncePrefix();
352   StringPiece server_forward_secure_decrypter_key =
353       server_forward_secure_decrypter->GetKey();
354   StringPiece server_forward_secure_decrypter_iv =
355       server_forward_secure_decrypter->GetNoncePrefix();
356
357   CompareCharArraysWithHexError("client write key",
358                                 client_encrypter_key.data(),
359                                 client_encrypter_key.length(),
360                                 server_decrypter_key.data(),
361                                 server_decrypter_key.length());
362   CompareCharArraysWithHexError("client write IV",
363                                 client_encrypter_iv.data(),
364                                 client_encrypter_iv.length(),
365                                 server_decrypter_iv.data(),
366                                 server_decrypter_iv.length());
367   CompareCharArraysWithHexError("server write key",
368                                 server_encrypter_key.data(),
369                                 server_encrypter_key.length(),
370                                 client_decrypter_key.data(),
371                                 client_decrypter_key.length());
372   CompareCharArraysWithHexError("server write IV",
373                                 server_encrypter_iv.data(),
374                                 server_encrypter_iv.length(),
375                                 client_decrypter_iv.data(),
376                                 client_decrypter_iv.length());
377   CompareCharArraysWithHexError("client forward secure write key",
378                                 client_forward_secure_encrypter_key.data(),
379                                 client_forward_secure_encrypter_key.length(),
380                                 server_forward_secure_decrypter_key.data(),
381                                 server_forward_secure_decrypter_key.length());
382   CompareCharArraysWithHexError("client forward secure write IV",
383                                 client_forward_secure_encrypter_iv.data(),
384                                 client_forward_secure_encrypter_iv.length(),
385                                 server_forward_secure_decrypter_iv.data(),
386                                 server_forward_secure_decrypter_iv.length());
387   CompareCharArraysWithHexError("server forward secure write key",
388                                 server_forward_secure_encrypter_key.data(),
389                                 server_forward_secure_encrypter_key.length(),
390                                 client_forward_secure_decrypter_key.data(),
391                                 client_forward_secure_decrypter_key.length());
392   CompareCharArraysWithHexError("server forward secure write IV",
393                                 server_forward_secure_encrypter_iv.data(),
394                                 server_forward_secure_encrypter_iv.length(),
395                                 client_forward_secure_decrypter_iv.data(),
396                                 client_forward_secure_decrypter_iv.length());
397 }
398
399 // static
400 QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
401   const size_t len = strlen(tagstr);
402   CHECK_NE(0u, len);
403
404   QuicTag tag = 0;
405
406   if (tagstr[0] == '#') {
407     CHECK_EQ(static_cast<size_t>(1 + 2*4), len);
408     tagstr++;
409
410     for (size_t i = 0; i < 8; i++) {
411       tag <<= 4;
412
413       uint8 v = 0;
414       CHECK(HexChar(tagstr[i], &v));
415       tag |= v;
416     }
417
418     return tag;
419   }
420
421   CHECK_LE(len, 4u);
422   for (size_t i = 0; i < 4; i++) {
423     tag >>= 8;
424     if (i < len) {
425       tag |= static_cast<uint32>(tagstr[i]) << 24;
426     }
427   }
428
429   return tag;
430 }
431
432 // static
433 CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
434   va_list ap;
435   va_start(ap, message_tag);
436
437   CryptoHandshakeMessage message = BuildMessage(message_tag, ap);
438   va_end(ap);
439   return message;
440 }
441
442 // static
443 CryptoHandshakeMessage CryptoTestUtils::BuildMessage(const char* message_tag,
444                                                      va_list ap) {
445   CryptoHandshakeMessage msg;
446   msg.set_tag(ParseTag(message_tag));
447
448   for (;;) {
449     const char* tagstr = va_arg(ap, const char*);
450     if (tagstr == NULL) {
451       break;
452     }
453
454     if (tagstr[0] == '$') {
455       // Special value.
456       const char* const special = tagstr + 1;
457       if (strcmp(special, "padding") == 0) {
458         const int min_bytes = va_arg(ap, int);
459         msg.set_minimum_size(min_bytes);
460       } else {
461         CHECK(false) << "Unknown special value: " << special;
462       }
463
464       continue;
465     }
466
467     const QuicTag tag = ParseTag(tagstr);
468     const char* valuestr = va_arg(ap, const char*);
469
470     size_t len = strlen(valuestr);
471     if (len > 0 && valuestr[0] == '#') {
472       valuestr++;
473       len--;
474
475       CHECK(len % 2 == 0);
476       scoped_ptr<uint8[]> buf(new uint8[len/2]);
477
478       for (size_t i = 0; i < len/2; i++) {
479         uint8 v = 0;
480         CHECK(HexChar(valuestr[i*2], &v));
481         buf[i] = v << 4;
482         CHECK(HexChar(valuestr[i*2 + 1], &v));
483         buf[i] |= v;
484       }
485
486       msg.SetStringPiece(
487           tag, StringPiece(reinterpret_cast<char*>(buf.get()), len/2));
488       continue;
489     }
490
491     msg.SetStringPiece(tag, valuestr);
492   }
493
494   // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
495   // that any padding is included.
496   scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
497   scoped_ptr<CryptoHandshakeMessage> parsed(
498       CryptoFramer::ParseMessage(bytes->AsStringPiece()));
499   CHECK(parsed.get());
500
501   return *parsed;
502 }
503
504 }  // namespace test
505 }  // namespace net