Home | History | Annotate | Download | only in crypto
      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 <map>
      6 #include <vector>
      7 
      8 #include "base/logging.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "net/quic/crypto/crypto_framer.h"
     11 #include "net/quic/crypto/crypto_handshake.h"
     12 #include "net/quic/crypto/crypto_protocol.h"
     13 #include "net/quic/quic_protocol.h"
     14 #include "net/quic/test_tools/crypto_test_utils.h"
     15 #include "net/quic/test_tools/quic_test_utils.h"
     16 
     17 using base::StringPiece;
     18 using std::map;
     19 using std::string;
     20 using std::vector;
     21 
     22 namespace net {
     23 
     24 namespace {
     25 
     26 char* AsChars(unsigned char* data) { return reinterpret_cast<char*>(data); }
     27 
     28 }  // namespace
     29 
     30 namespace test {
     31 
     32 class TestCryptoVisitor : public ::net::CryptoFramerVisitorInterface {
     33  public:
     34   TestCryptoVisitor() : error_count_(0) {}
     35 
     36   virtual void OnError(CryptoFramer* framer) OVERRIDE {
     37     DLOG(ERROR) << "CryptoFramer Error: " << framer->error();
     38     ++error_count_;
     39   }
     40 
     41   virtual void OnHandshakeMessage(
     42       const CryptoHandshakeMessage& message) OVERRIDE {
     43     messages_.push_back(message);
     44   }
     45 
     46   // Counters from the visitor callbacks.
     47   int error_count_;
     48 
     49   vector<CryptoHandshakeMessage> messages_;
     50 };
     51 
     52 TEST(CryptoFramerTest, ConstructHandshakeMessage) {
     53   CryptoHandshakeMessage message;
     54   message.set_tag(0xFFAA7733);
     55   message.SetStringPiece(0x12345678, "abcdef");
     56   message.SetStringPiece(0x12345679, "ghijk");
     57   message.SetStringPiece(0x1234567A, "lmnopqr");
     58 
     59   unsigned char packet[] = {
     60     // tag
     61     0x33, 0x77, 0xAA, 0xFF,
     62     // num entries
     63     0x03, 0x00,
     64     // padding
     65     0x00, 0x00,
     66     // tag 1
     67     0x78, 0x56, 0x34, 0x12,
     68     // end offset 1
     69     0x06, 0x00, 0x00, 0x00,
     70     // tag 2
     71     0x79, 0x56, 0x34, 0x12,
     72     // end offset 2
     73     0x0b, 0x00, 0x00, 0x00,
     74     // tag 3
     75     0x7A, 0x56, 0x34, 0x12,
     76     // end offset 3
     77     0x12, 0x00, 0x00, 0x00,
     78     // value 1
     79     'a',  'b',  'c',  'd',
     80     'e',  'f',
     81     // value 2
     82     'g',  'h',  'i',  'j',
     83     'k',
     84     // value 3
     85     'l',  'm',  'n',  'o',
     86     'p',  'q',  'r',
     87   };
     88 
     89   CryptoFramer framer;
     90   scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
     91   ASSERT_TRUE(data.get() != NULL);
     92   test::CompareCharArraysWithHexError("constructed packet", data->data(),
     93                                       data->length(), AsChars(packet),
     94                                       arraysize(packet));
     95 }
     96 
     97 TEST(CryptoFramerTest, ConstructHandshakeMessageWithTwoKeys) {
     98   CryptoHandshakeMessage message;
     99   message.set_tag(0xFFAA7733);
    100   message.SetStringPiece(0x12345678, "abcdef");
    101   message.SetStringPiece(0x12345679, "ghijk");
    102 
    103   unsigned char packet[] = {
    104     // tag
    105     0x33, 0x77, 0xAA, 0xFF,
    106     // num entries
    107     0x02, 0x00,
    108     // padding
    109     0x00, 0x00,
    110     // tag 1
    111     0x78, 0x56, 0x34, 0x12,
    112     // end offset 1
    113     0x06, 0x00, 0x00, 0x00,
    114     // tag 2
    115     0x79, 0x56, 0x34, 0x12,
    116     // end offset 2
    117     0x0b, 0x00, 0x00, 0x00,
    118     // value 1
    119     'a',  'b',  'c',  'd',
    120     'e',  'f',
    121     // value 2
    122     'g',  'h',  'i',  'j',
    123     'k',
    124   };
    125 
    126   CryptoFramer framer;
    127   scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
    128   ASSERT_TRUE(data.get() != NULL);
    129 
    130   test::CompareCharArraysWithHexError("constructed packet", data->data(),
    131                                       data->length(), AsChars(packet),
    132                                       arraysize(packet));
    133 }
    134 
    135 TEST(CryptoFramerTest, ConstructHandshakeMessageZeroLength) {
    136   CryptoHandshakeMessage message;
    137   message.set_tag(0xFFAA7733);
    138   message.SetStringPiece(0x12345678, "");
    139 
    140   unsigned char packet[] = {
    141     // tag
    142     0x33, 0x77, 0xAA, 0xFF,
    143     // num entries
    144     0x01, 0x00,
    145     // padding
    146     0x00, 0x00,
    147     // tag 1
    148     0x78, 0x56, 0x34, 0x12,
    149     // end offset 1
    150     0x00, 0x00, 0x00, 0x00,
    151   };
    152 
    153   CryptoFramer framer;
    154   scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
    155   ASSERT_TRUE(data.get() != NULL);
    156 
    157   test::CompareCharArraysWithHexError("constructed packet", data->data(),
    158                                       data->length(), AsChars(packet),
    159                                       arraysize(packet));
    160 }
    161 
    162 TEST(CryptoFramerTest, ConstructHandshakeMessageTooManyEntries) {
    163   CryptoHandshakeMessage message;
    164   message.set_tag(0xFFAA7733);
    165   for (uint32 key = 1; key <= kMaxEntries + 1; ++key) {
    166     message.SetStringPiece(key, "abcdef");
    167   }
    168 
    169   CryptoFramer framer;
    170   scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
    171   EXPECT_TRUE(data.get() == NULL);
    172 }
    173 
    174 TEST(CryptoFramerTest, ConstructHandshakeMessageMinimumSize) {
    175   CryptoHandshakeMessage message;
    176   message.set_tag(0xFFAA7733);
    177   message.SetStringPiece(0x01020304, "test");
    178   message.set_minimum_size(64);
    179 
    180   unsigned char packet[] = {
    181     // tag
    182     0x33, 0x77, 0xAA, 0xFF,
    183     // num entries
    184     0x02, 0x00,
    185     // padding
    186     0x00, 0x00,
    187     // tag 1
    188     'P', 'A', 'D', 0,
    189     // end offset 1
    190     0x24, 0x00, 0x00, 0x00,
    191     // tag 2
    192     0x04, 0x03, 0x02, 0x01,
    193     // end offset 2
    194     0x28, 0x00, 0x00, 0x00,
    195     // 36 bytes of padding.
    196     '-', '-', '-', '-', '-', '-', '-', '-',
    197     '-', '-', '-', '-', '-', '-', '-', '-',
    198     '-', '-', '-', '-', '-', '-', '-', '-',
    199     '-', '-', '-', '-', '-', '-', '-', '-',
    200     '-', '-', '-', '-',
    201     // value 2
    202     't', 'e', 's', 't',
    203   };
    204 
    205   CryptoFramer framer;
    206   scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
    207   ASSERT_TRUE(data.get() != NULL);
    208 
    209   test::CompareCharArraysWithHexError("constructed packet", data->data(),
    210                                       data->length(), AsChars(packet),
    211                                       arraysize(packet));
    212 }
    213 
    214 TEST(CryptoFramerTest, ConstructHandshakeMessageMinimumSizePadLast) {
    215   CryptoHandshakeMessage message;
    216   message.set_tag(0xFFAA7733);
    217   message.SetStringPiece(1, "");
    218   message.set_minimum_size(64);
    219 
    220   unsigned char packet[] = {
    221     // tag
    222     0x33, 0x77, 0xAA, 0xFF,
    223     // num entries
    224     0x02, 0x00,
    225     // padding
    226     0x00, 0x00,
    227     // tag 1
    228     0x01, 0x00, 0x00, 0x00,
    229     // end offset 1
    230     0x00, 0x00, 0x00, 0x00,
    231     // tag 2
    232     'P', 'A', 'D', 0,
    233     // end offset 2
    234     0x28, 0x00, 0x00, 0x00,
    235     // 40 bytes of padding.
    236     '-', '-', '-', '-', '-', '-', '-', '-',
    237     '-', '-', '-', '-', '-', '-', '-', '-',
    238     '-', '-', '-', '-', '-', '-', '-', '-',
    239     '-', '-', '-', '-', '-', '-', '-', '-',
    240     '-', '-', '-', '-', '-', '-', '-', '-',
    241   };
    242 
    243   CryptoFramer framer;
    244   scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
    245   ASSERT_TRUE(data.get() != NULL);
    246 
    247   test::CompareCharArraysWithHexError("constructed packet", data->data(),
    248                                       data->length(), AsChars(packet),
    249                                       arraysize(packet));
    250 }
    251 
    252 TEST(CryptoFramerTest, ProcessInput) {
    253   test::TestCryptoVisitor visitor;
    254   CryptoFramer framer;
    255   framer.set_visitor(&visitor);
    256 
    257   unsigned char input[] = {
    258     // tag
    259     0x33, 0x77, 0xAA, 0xFF,
    260     // num entries
    261     0x02, 0x00,
    262     // padding
    263     0x00, 0x00,
    264     // tag 1
    265     0x78, 0x56, 0x34, 0x12,
    266     // end offset 1
    267     0x06, 0x00, 0x00, 0x00,
    268     // tag 2
    269     0x79, 0x56, 0x34, 0x12,
    270     // end offset 2
    271     0x0b, 0x00, 0x00, 0x00,
    272     // value 1
    273     'a',  'b',  'c',  'd',
    274     'e',  'f',
    275     // value 2
    276     'g',  'h',  'i',  'j',
    277     'k',
    278   };
    279 
    280   EXPECT_TRUE(
    281       framer.ProcessInput(StringPiece(AsChars(input), arraysize(input))));
    282   EXPECT_EQ(0u, framer.InputBytesRemaining());
    283   EXPECT_EQ(0, visitor.error_count_);
    284   ASSERT_EQ(1u, visitor.messages_.size());
    285   const CryptoHandshakeMessage& message = visitor.messages_[0];
    286   EXPECT_EQ(0xFFAA7733, message.tag());
    287   EXPECT_EQ(2u, message.tag_value_map().size());
    288   EXPECT_EQ("abcdef", CryptoTestUtils::GetValueForTag(message, 0x12345678));
    289   EXPECT_EQ("ghijk", CryptoTestUtils::GetValueForTag(message, 0x12345679));
    290 }
    291 
    292 TEST(CryptoFramerTest, ProcessInputWithThreeKeys) {
    293   test::TestCryptoVisitor visitor;
    294   CryptoFramer framer;
    295   framer.set_visitor(&visitor);
    296 
    297   unsigned char input[] = {
    298     // tag
    299     0x33, 0x77, 0xAA, 0xFF,
    300     // num entries
    301     0x03, 0x00,
    302     // padding
    303     0x00, 0x00,
    304     // tag 1
    305     0x78, 0x56, 0x34, 0x12,
    306     // end offset 1
    307     0x06, 0x00, 0x00, 0x00,
    308     // tag 2
    309     0x79, 0x56, 0x34, 0x12,
    310     // end offset 2
    311     0x0b, 0x00, 0x00, 0x00,
    312     // tag 3
    313     0x7A, 0x56, 0x34, 0x12,
    314     // end offset 3
    315     0x12, 0x00, 0x00, 0x00,
    316     // value 1
    317     'a',  'b',  'c',  'd',
    318     'e',  'f',
    319     // value 2
    320     'g',  'h',  'i',  'j',
    321     'k',
    322     // value 3
    323     'l',  'm',  'n',  'o',
    324     'p',  'q',  'r',
    325   };
    326 
    327   EXPECT_TRUE(
    328       framer.ProcessInput(StringPiece(AsChars(input), arraysize(input))));
    329   EXPECT_EQ(0u, framer.InputBytesRemaining());
    330   EXPECT_EQ(0, visitor.error_count_);
    331   ASSERT_EQ(1u, visitor.messages_.size());
    332   const CryptoHandshakeMessage& message = visitor.messages_[0];
    333   EXPECT_EQ(0xFFAA7733, message.tag());
    334   EXPECT_EQ(3u, message.tag_value_map().size());
    335   EXPECT_EQ("abcdef", CryptoTestUtils::GetValueForTag(message, 0x12345678));
    336   EXPECT_EQ("ghijk", CryptoTestUtils::GetValueForTag(message, 0x12345679));
    337   EXPECT_EQ("lmnopqr", CryptoTestUtils::GetValueForTag(message, 0x1234567A));
    338 }
    339 
    340 TEST(CryptoFramerTest, ProcessInputIncrementally) {
    341   test::TestCryptoVisitor visitor;
    342   CryptoFramer framer;
    343   framer.set_visitor(&visitor);
    344 
    345   unsigned char input[] = {
    346     // tag
    347     0x33, 0x77, 0xAA, 0xFF,
    348     // num entries
    349     0x02, 0x00,
    350     // padding
    351     0x00, 0x00,
    352     // tag 1
    353     0x78, 0x56, 0x34, 0x12,
    354     // end offset 1
    355     0x06, 0x00, 0x00, 0x00,
    356     // tag 2
    357     0x79, 0x56, 0x34, 0x12,
    358     // end offset 2
    359     0x0b, 0x00, 0x00, 0x00,
    360     // value 1
    361     'a',  'b',  'c',  'd',
    362     'e',  'f',
    363     // value 2
    364     'g',  'h',  'i',  'j',
    365     'k',
    366   };
    367 
    368   for (size_t i = 0; i < arraysize(input); i++) {
    369     EXPECT_TRUE(framer.ProcessInput(StringPiece(AsChars(input) + i, 1)));
    370   }
    371   EXPECT_EQ(0u, framer.InputBytesRemaining());
    372   ASSERT_EQ(1u, visitor.messages_.size());
    373   const CryptoHandshakeMessage& message = visitor.messages_[0];
    374   EXPECT_EQ(0xFFAA7733, message.tag());
    375   EXPECT_EQ(2u, message.tag_value_map().size());
    376   EXPECT_EQ("abcdef", CryptoTestUtils::GetValueForTag(message, 0x12345678));
    377   EXPECT_EQ("ghijk", CryptoTestUtils::GetValueForTag(message, 0x12345679));
    378 }
    379 
    380 TEST(CryptoFramerTest, ProcessInputTagsOutOfOrder) {
    381   test::TestCryptoVisitor visitor;
    382   CryptoFramer framer;
    383   framer.set_visitor(&visitor);
    384 
    385   unsigned char input[] = {
    386     // tag
    387     0x33, 0x77, 0xAA, 0xFF,
    388     // num entries
    389     0x02, 0x00,
    390     // padding
    391     0x00, 0x00,
    392     // tag 1
    393     0x78, 0x56, 0x34, 0x13,
    394     // end offset 1
    395     0x01, 0x00, 0x00, 0x00,
    396     // tag 2
    397     0x79, 0x56, 0x34, 0x12,
    398     // end offset 2
    399     0x02, 0x00, 0x00, 0x00,
    400   };
    401 
    402   EXPECT_FALSE(
    403       framer.ProcessInput(StringPiece(AsChars(input), arraysize(input))));
    404   EXPECT_EQ(QUIC_CRYPTO_TAGS_OUT_OF_ORDER, framer.error());
    405   EXPECT_EQ(1, visitor.error_count_);
    406 }
    407 
    408 TEST(CryptoFramerTest, ProcessEndOffsetsOutOfOrder) {
    409   test::TestCryptoVisitor visitor;
    410   CryptoFramer framer;
    411   framer.set_visitor(&visitor);
    412 
    413   unsigned char input[] = {
    414     // tag
    415     0x33, 0x77, 0xAA, 0xFF,
    416     // num entries
    417     0x02, 0x00,
    418     // padding
    419     0x00, 0x00,
    420     // tag 1
    421     0x79, 0x56, 0x34, 0x12,
    422     // end offset 1
    423     0x01, 0x00, 0x00, 0x00,
    424     // tag 2
    425     0x78, 0x56, 0x34, 0x13,
    426     // end offset 2
    427     0x00, 0x00, 0x00, 0x00,
    428   };
    429 
    430   EXPECT_FALSE(
    431       framer.ProcessInput(StringPiece(AsChars(input), arraysize(input))));
    432   EXPECT_EQ(QUIC_CRYPTO_TAGS_OUT_OF_ORDER, framer.error());
    433   EXPECT_EQ(1, visitor.error_count_);
    434 }
    435 
    436 TEST(CryptoFramerTest, ProcessInputTooManyEntries) {
    437   test::TestCryptoVisitor visitor;
    438   CryptoFramer framer;
    439   framer.set_visitor(&visitor);
    440 
    441   unsigned char input[] = {
    442     // tag
    443     0x33, 0x77, 0xAA, 0xFF,
    444     // num entries
    445     0xA0, 0x00,
    446     // padding
    447     0x00, 0x00,
    448   };
    449 
    450   EXPECT_FALSE(
    451       framer.ProcessInput(StringPiece(AsChars(input), arraysize(input))));
    452   EXPECT_EQ(QUIC_CRYPTO_TOO_MANY_ENTRIES, framer.error());
    453   EXPECT_EQ(1, visitor.error_count_);
    454 }
    455 
    456 TEST(CryptoFramerTest, ProcessInputZeroLength) {
    457   test::TestCryptoVisitor visitor;
    458   CryptoFramer framer;
    459   framer.set_visitor(&visitor);
    460 
    461   unsigned char input[] = {
    462     // tag
    463     0x33, 0x77, 0xAA, 0xFF,
    464     // num entries
    465     0x02, 0x00,
    466     // padding
    467     0x00, 0x00,
    468     // tag 1
    469     0x78, 0x56, 0x34, 0x12,
    470     // end offset 1
    471     0x00, 0x00, 0x00, 0x00,
    472     // tag 2
    473     0x79, 0x56, 0x34, 0x12,
    474     // end offset 2
    475     0x05, 0x00, 0x00, 0x00,
    476   };
    477 
    478   EXPECT_TRUE(
    479       framer.ProcessInput(StringPiece(AsChars(input), arraysize(input))));
    480   EXPECT_EQ(0, visitor.error_count_);
    481 }
    482 
    483 }  // namespace test
    484 
    485 }  // namespace net
    486