diff options
Diffstat (limited to 'chromium/net/quic/crypto/crypto_framer_test.cc')
-rw-r--r-- | chromium/net/quic/crypto/crypto_framer_test.cc | 485 |
1 files changed, 485 insertions, 0 deletions
diff --git a/chromium/net/quic/crypto/crypto_framer_test.cc b/chromium/net/quic/crypto/crypto_framer_test.cc new file mode 100644 index 00000000000..4486f595eee --- /dev/null +++ b/chromium/net/quic/crypto/crypto_framer_test.cc @@ -0,0 +1,485 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <map> +#include <vector> + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "net/quic/crypto/crypto_framer.h" +#include "net/quic/crypto/crypto_handshake.h" +#include "net/quic/crypto/crypto_protocol.h" +#include "net/quic/quic_protocol.h" +#include "net/quic/test_tools/crypto_test_utils.h" +#include "net/quic/test_tools/quic_test_utils.h" + +using base::StringPiece; +using std::map; +using std::string; +using std::vector; + +namespace net { + +namespace { + +char* AsChars(unsigned char* data) { return reinterpret_cast<char*>(data); } + +} // namespace + +namespace test { + +class TestCryptoVisitor : public ::net::CryptoFramerVisitorInterface { + public: + TestCryptoVisitor() : error_count_(0) {} + + virtual void OnError(CryptoFramer* framer) OVERRIDE { + DLOG(ERROR) << "CryptoFramer Error: " << framer->error(); + ++error_count_; + } + + virtual void OnHandshakeMessage( + const CryptoHandshakeMessage& message) OVERRIDE { + messages_.push_back(message); + } + + // Counters from the visitor callbacks. + int error_count_; + + vector<CryptoHandshakeMessage> messages_; +}; + +TEST(CryptoFramerTest, ConstructHandshakeMessage) { + CryptoHandshakeMessage message; + message.set_tag(0xFFAA7733); + message.SetStringPiece(0x12345678, "abcdef"); + message.SetStringPiece(0x12345679, "ghijk"); + message.SetStringPiece(0x1234567A, "lmnopqr"); + + unsigned char packet[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x03, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x78, 0x56, 0x34, 0x12, + // end offset 1 + 0x06, 0x00, 0x00, 0x00, + // tag 2 + 0x79, 0x56, 0x34, 0x12, + // end offset 2 + 0x0b, 0x00, 0x00, 0x00, + // tag 3 + 0x7A, 0x56, 0x34, 0x12, + // end offset 3 + 0x12, 0x00, 0x00, 0x00, + // value 1 + 'a', 'b', 'c', 'd', + 'e', 'f', + // value 2 + 'g', 'h', 'i', 'j', + 'k', + // value 3 + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', + }; + + CryptoFramer framer; + scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message)); + ASSERT_TRUE(data.get() != NULL); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); +} + +TEST(CryptoFramerTest, ConstructHandshakeMessageWithTwoKeys) { + CryptoHandshakeMessage message; + message.set_tag(0xFFAA7733); + message.SetStringPiece(0x12345678, "abcdef"); + message.SetStringPiece(0x12345679, "ghijk"); + + unsigned char packet[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x02, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x78, 0x56, 0x34, 0x12, + // end offset 1 + 0x06, 0x00, 0x00, 0x00, + // tag 2 + 0x79, 0x56, 0x34, 0x12, + // end offset 2 + 0x0b, 0x00, 0x00, 0x00, + // value 1 + 'a', 'b', 'c', 'd', + 'e', 'f', + // value 2 + 'g', 'h', 'i', 'j', + 'k', + }; + + CryptoFramer framer; + scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message)); + ASSERT_TRUE(data.get() != NULL); + + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); +} + +TEST(CryptoFramerTest, ConstructHandshakeMessageZeroLength) { + CryptoHandshakeMessage message; + message.set_tag(0xFFAA7733); + message.SetStringPiece(0x12345678, ""); + + unsigned char packet[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x01, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x78, 0x56, 0x34, 0x12, + // end offset 1 + 0x00, 0x00, 0x00, 0x00, + }; + + CryptoFramer framer; + scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message)); + ASSERT_TRUE(data.get() != NULL); + + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); +} + +TEST(CryptoFramerTest, ConstructHandshakeMessageTooManyEntries) { + CryptoHandshakeMessage message; + message.set_tag(0xFFAA7733); + for (uint32 key = 1; key <= kMaxEntries + 1; ++key) { + message.SetStringPiece(key, "abcdef"); + } + + CryptoFramer framer; + scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message)); + EXPECT_TRUE(data.get() == NULL); +} + +TEST(CryptoFramerTest, ConstructHandshakeMessageMinimumSize) { + CryptoHandshakeMessage message; + message.set_tag(0xFFAA7733); + message.SetStringPiece(0x01020304, "test"); + message.set_minimum_size(64); + + unsigned char packet[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x02, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 'P', 'A', 'D', 0, + // end offset 1 + 0x24, 0x00, 0x00, 0x00, + // tag 2 + 0x04, 0x03, 0x02, 0x01, + // end offset 2 + 0x28, 0x00, 0x00, 0x00, + // 36 bytes of padding. + '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', + // value 2 + 't', 'e', 's', 't', + }; + + CryptoFramer framer; + scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message)); + ASSERT_TRUE(data.get() != NULL); + + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); +} + +TEST(CryptoFramerTest, ConstructHandshakeMessageMinimumSizePadLast) { + CryptoHandshakeMessage message; + message.set_tag(0xFFAA7733); + message.SetStringPiece(1, ""); + message.set_minimum_size(64); + + unsigned char packet[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x02, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x01, 0x00, 0x00, 0x00, + // end offset 1 + 0x00, 0x00, 0x00, 0x00, + // tag 2 + 'P', 'A', 'D', 0, + // end offset 2 + 0x28, 0x00, 0x00, 0x00, + // 40 bytes of padding. + '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', + }; + + CryptoFramer framer; + scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message)); + ASSERT_TRUE(data.get() != NULL); + + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); +} + +TEST(CryptoFramerTest, ProcessInput) { + test::TestCryptoVisitor visitor; + CryptoFramer framer; + framer.set_visitor(&visitor); + + unsigned char input[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x02, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x78, 0x56, 0x34, 0x12, + // end offset 1 + 0x06, 0x00, 0x00, 0x00, + // tag 2 + 0x79, 0x56, 0x34, 0x12, + // end offset 2 + 0x0b, 0x00, 0x00, 0x00, + // value 1 + 'a', 'b', 'c', 'd', + 'e', 'f', + // value 2 + 'g', 'h', 'i', 'j', + 'k', + }; + + EXPECT_TRUE( + framer.ProcessInput(StringPiece(AsChars(input), arraysize(input)))); + EXPECT_EQ(0u, framer.InputBytesRemaining()); + EXPECT_EQ(0, visitor.error_count_); + ASSERT_EQ(1u, visitor.messages_.size()); + const CryptoHandshakeMessage& message = visitor.messages_[0]; + EXPECT_EQ(0xFFAA7733, message.tag()); + EXPECT_EQ(2u, message.tag_value_map().size()); + EXPECT_EQ("abcdef", CryptoTestUtils::GetValueForTag(message, 0x12345678)); + EXPECT_EQ("ghijk", CryptoTestUtils::GetValueForTag(message, 0x12345679)); +} + +TEST(CryptoFramerTest, ProcessInputWithThreeKeys) { + test::TestCryptoVisitor visitor; + CryptoFramer framer; + framer.set_visitor(&visitor); + + unsigned char input[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x03, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x78, 0x56, 0x34, 0x12, + // end offset 1 + 0x06, 0x00, 0x00, 0x00, + // tag 2 + 0x79, 0x56, 0x34, 0x12, + // end offset 2 + 0x0b, 0x00, 0x00, 0x00, + // tag 3 + 0x7A, 0x56, 0x34, 0x12, + // end offset 3 + 0x12, 0x00, 0x00, 0x00, + // value 1 + 'a', 'b', 'c', 'd', + 'e', 'f', + // value 2 + 'g', 'h', 'i', 'j', + 'k', + // value 3 + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', + }; + + EXPECT_TRUE( + framer.ProcessInput(StringPiece(AsChars(input), arraysize(input)))); + EXPECT_EQ(0u, framer.InputBytesRemaining()); + EXPECT_EQ(0, visitor.error_count_); + ASSERT_EQ(1u, visitor.messages_.size()); + const CryptoHandshakeMessage& message = visitor.messages_[0]; + EXPECT_EQ(0xFFAA7733, message.tag()); + EXPECT_EQ(3u, message.tag_value_map().size()); + EXPECT_EQ("abcdef", CryptoTestUtils::GetValueForTag(message, 0x12345678)); + EXPECT_EQ("ghijk", CryptoTestUtils::GetValueForTag(message, 0x12345679)); + EXPECT_EQ("lmnopqr", CryptoTestUtils::GetValueForTag(message, 0x1234567A)); +} + +TEST(CryptoFramerTest, ProcessInputIncrementally) { + test::TestCryptoVisitor visitor; + CryptoFramer framer; + framer.set_visitor(&visitor); + + unsigned char input[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x02, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x78, 0x56, 0x34, 0x12, + // end offset 1 + 0x06, 0x00, 0x00, 0x00, + // tag 2 + 0x79, 0x56, 0x34, 0x12, + // end offset 2 + 0x0b, 0x00, 0x00, 0x00, + // value 1 + 'a', 'b', 'c', 'd', + 'e', 'f', + // value 2 + 'g', 'h', 'i', 'j', + 'k', + }; + + for (size_t i = 0; i < arraysize(input); i++) { + EXPECT_TRUE(framer.ProcessInput(StringPiece(AsChars(input) + i, 1))); + } + EXPECT_EQ(0u, framer.InputBytesRemaining()); + ASSERT_EQ(1u, visitor.messages_.size()); + const CryptoHandshakeMessage& message = visitor.messages_[0]; + EXPECT_EQ(0xFFAA7733, message.tag()); + EXPECT_EQ(2u, message.tag_value_map().size()); + EXPECT_EQ("abcdef", CryptoTestUtils::GetValueForTag(message, 0x12345678)); + EXPECT_EQ("ghijk", CryptoTestUtils::GetValueForTag(message, 0x12345679)); +} + +TEST(CryptoFramerTest, ProcessInputTagsOutOfOrder) { + test::TestCryptoVisitor visitor; + CryptoFramer framer; + framer.set_visitor(&visitor); + + unsigned char input[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x02, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x78, 0x56, 0x34, 0x13, + // end offset 1 + 0x01, 0x00, 0x00, 0x00, + // tag 2 + 0x79, 0x56, 0x34, 0x12, + // end offset 2 + 0x02, 0x00, 0x00, 0x00, + }; + + EXPECT_FALSE( + framer.ProcessInput(StringPiece(AsChars(input), arraysize(input)))); + EXPECT_EQ(QUIC_CRYPTO_TAGS_OUT_OF_ORDER, framer.error()); + EXPECT_EQ(1, visitor.error_count_); +} + +TEST(CryptoFramerTest, ProcessEndOffsetsOutOfOrder) { + test::TestCryptoVisitor visitor; + CryptoFramer framer; + framer.set_visitor(&visitor); + + unsigned char input[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x02, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x79, 0x56, 0x34, 0x12, + // end offset 1 + 0x01, 0x00, 0x00, 0x00, + // tag 2 + 0x78, 0x56, 0x34, 0x13, + // end offset 2 + 0x00, 0x00, 0x00, 0x00, + }; + + EXPECT_FALSE( + framer.ProcessInput(StringPiece(AsChars(input), arraysize(input)))); + EXPECT_EQ(QUIC_CRYPTO_TAGS_OUT_OF_ORDER, framer.error()); + EXPECT_EQ(1, visitor.error_count_); +} + +TEST(CryptoFramerTest, ProcessInputTooManyEntries) { + test::TestCryptoVisitor visitor; + CryptoFramer framer; + framer.set_visitor(&visitor); + + unsigned char input[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0xA0, 0x00, + // padding + 0x00, 0x00, + }; + + EXPECT_FALSE( + framer.ProcessInput(StringPiece(AsChars(input), arraysize(input)))); + EXPECT_EQ(QUIC_CRYPTO_TOO_MANY_ENTRIES, framer.error()); + EXPECT_EQ(1, visitor.error_count_); +} + +TEST(CryptoFramerTest, ProcessInputZeroLength) { + test::TestCryptoVisitor visitor; + CryptoFramer framer; + framer.set_visitor(&visitor); + + unsigned char input[] = { + // tag + 0x33, 0x77, 0xAA, 0xFF, + // num entries + 0x02, 0x00, + // padding + 0x00, 0x00, + // tag 1 + 0x78, 0x56, 0x34, 0x12, + // end offset 1 + 0x00, 0x00, 0x00, 0x00, + // tag 2 + 0x79, 0x56, 0x34, 0x12, + // end offset 2 + 0x05, 0x00, 0x00, 0x00, + }; + + EXPECT_TRUE( + framer.ProcessInput(StringPiece(AsChars(input), arraysize(input)))); + EXPECT_EQ(0, visitor.error_count_); +} + +} // namespace test + +} // namespace net |