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