blob: b95954170ed0bf9e7fff29b76ce2e1238a40d82e [file] [log] [blame]
// 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_protocol.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/test/disabled_if_big_endian.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) {
}
~TestCryptoVisitor() {}
virtual void OnError(CryptoFramer* framer) {
LOG(ERROR) << "CryptoFramer Error: " << framer->error();
error_count_++;
}
virtual void OnHandshakeMessage(const CryptoHandshakeMessage& message) {
message_tags_.push_back(message.tag);
message_maps_.push_back(map<CryptoTag, string>());
CryptoTagValueMap::const_iterator it = message.tag_value_map.begin();
while (it != message.tag_value_map.end()) {
message_maps_.back()[it->first] = it->second.as_string();
++it;
}
}
CryptoFramer framer_;
// Counters from the visitor callbacks.
int error_count_;
CryptoTagVector message_tags_;
vector<map<CryptoTag, string> > message_maps_;
};
} // namespace test
TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ConstructHandshakeMessage)) {
CryptoHandshakeMessage message;
message.tag = 0xFFAA7733;
message.tag_value_map[0x12345678] = "abcdef";
message.tag_value_map[0x12345679] = "ghijk";
message.tag_value_map[0x1234567A] = "lmnopqr";
unsigned char packet[] = {
// tag
0x33, 0x77, 0xAA, 0xFF,
// num entries
0x03, 0x00,
// tag 1
0x78, 0x56, 0x34, 0x12,
// tag 2
0x79, 0x56, 0x34, 0x12,
// tag 3
0x7A, 0x56, 0x34, 0x12,
// len 1
0x06, 0x00,
// len 2
0x05, 0x00,
// len 3
0x07, 0x00,
// padding
0xAB, 0xAB,
// 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,
DISABLED_IF_BIG_ENDIAN(ConstructHandshakeMessageWithTwoKeys)) {
CryptoHandshakeMessage message;
message.tag = 0xFFAA7733;
message.tag_value_map[0x12345678] = "abcdef";
message.tag_value_map[0x12345679] = "ghijk";
unsigned char packet[] = {
// tag
0x33, 0x77, 0xAA, 0xFF,
// num entries
0x02, 0x00,
// tag 1
0x78, 0x56, 0x34, 0x12,
// tag 2
0x79, 0x56, 0x34, 0x12,
// len 1
0x06, 0x00,
// len 2
0x05, 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, ConstructHandshakeMessageTooManyEntries) {
CryptoHandshakeMessage message;
message.tag = 0xFFAA7733;
for (uint32 key = 1; key <= kMaxEntries + 1; ++key) {
message.tag_value_map[key] = "abcdef";
}
CryptoFramer framer;
scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
EXPECT_TRUE(data.get() == NULL);
}
TEST(CryptoFramerTest, ConstructHandshakeMessageInvalidLength) {
CryptoHandshakeMessage message;
message.tag = 0xFFAA7733;
message.tag_value_map[0x12345678] = "";
CryptoFramer framer;
scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
EXPECT_TRUE(data.get() == NULL);
}
TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ProcessInput)) {
test::TestCryptoVisitor visitor;
CryptoFramer framer;
framer.set_visitor(&visitor);
unsigned char input[] = {
// tag
0x33, 0x77, 0xAA, 0xFF,
// num entries
0x02, 0x00,
// tag 1
0x78, 0x56, 0x34, 0x12,
// tag 2
0x79, 0x56, 0x34, 0x12,
// len 1
0x06, 0x00,
// len 2
0x05, 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))));
ASSERT_EQ(1u, visitor.message_tags_.size());
EXPECT_EQ(0xFFAA7733, visitor.message_tags_[0]);
EXPECT_EQ(2u, visitor.message_maps_[0].size());
EXPECT_EQ("abcdef",visitor.message_maps_[0][0x12345678]);
EXPECT_EQ("ghijk", visitor.message_maps_[0][0x12345679]);
}
TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ProcessInputIncrementally)) {
test::TestCryptoVisitor visitor;
CryptoFramer framer;
framer.set_visitor(&visitor);
unsigned char input[] = {
// tag
0x33, 0x77, 0xAA, 0xFF,
// num entries
0x02, 0x00,
// tag 1
0x78, 0x56, 0x34, 0x12,
// tag 2
0x79, 0x56, 0x34, 0x12,
// len 1
0x06, 0x00,
// len 2
0x05, 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)));
}
ASSERT_EQ(1u, visitor.message_tags_.size());
EXPECT_EQ(0xFFAA7733, visitor.message_tags_[0]);
EXPECT_EQ(2u, visitor.message_maps_[0].size());
EXPECT_EQ("abcdef",visitor.message_maps_[0][0x12345678]);
EXPECT_EQ("ghijk", visitor.message_maps_[0][0x12345679]);
}
TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ProcessInputTagsOutOfOrder)) {
test::TestCryptoVisitor visitor;
CryptoFramer framer;
framer.set_visitor(&visitor);
unsigned char input[] = {
// tag
0x33, 0x77, 0xAA, 0xFF,
// num entries
0x02, 0x00,
// tag 1
0x79, 0x56, 0x34, 0x12,
// tag 2
0x78, 0x56, 0x34, 0x12,
};
EXPECT_FALSE(framer.ProcessInput(StringPiece(AsChars(input),
arraysize(input))));
EXPECT_EQ(QUIC_CRYPTO_TAGS_OUT_OF_ORDER, framer.error());
}
TEST(CryptoFramerTest, ProcessInputTooManyEntries) {
test::TestCryptoVisitor visitor;
CryptoFramer framer;
framer.set_visitor(&visitor);
unsigned char input[] = {
// tag
0x33, 0x77, 0xAA, 0xFF,
// num entries
0xA0, 0x00,
};
EXPECT_FALSE(framer.ProcessInput(StringPiece(AsChars(input),
arraysize(input))));
EXPECT_EQ(QUIC_CRYPTO_TOO_MANY_ENTRIES, framer.error());
}
TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ProcessInputInvalidLength)) {
test::TestCryptoVisitor visitor;
CryptoFramer framer;
framer.set_visitor(&visitor);
unsigned char input[] = {
// tag
0x33, 0x77, 0xAA, 0xFF,
// num entries
0x02, 0x00,
// tag 1
0x78, 0x56, 0x34, 0x12,
// tag 2
0x79, 0x56, 0x34, 0x12,
// len 1
0x00, 0x00,
// len 2
0x05, 0x00,
};
EXPECT_FALSE(framer.ProcessInput(StringPiece(AsChars(input),
arraysize(input))));
EXPECT_EQ(QUIC_CRYPTO_INVALID_VALUE_LENGTH, framer.error());
}
} // namespace net