Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(534)

Unified Diff: net/tools/transport_security_state_generator/trie/trie_writer_unittest.cc

Issue 2660793002: Add transport security state generator tests. (Closed)
Patch Set: export method for tests Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/tools/transport_security_state_generator/trie/trie_writer_unittest.cc
diff --git a/net/tools/transport_security_state_generator/trie/trie_writer_unittest.cc b/net/tools/transport_security_state_generator/trie/trie_writer_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5f6f71667a890a4b80021b616065d10607b37797
--- /dev/null
+++ b/net/tools/transport_security_state_generator/trie/trie_writer_unittest.cc
@@ -0,0 +1,396 @@
+// Copyright 2017 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 <memory>
+
+#include "base/memory/ptr_util.h"
+#include "net/tools/transport_security_state_generator/bit_writer.h"
+#include "net/tools/transport_security_state_generator/huffman/huffman_builder.h"
+#include "net/tools/transport_security_state_generator/transport_security_state_entry.h"
+#include "net/tools/transport_security_state_generator/trie/trie_bit_buffer.h"
+#include "net/tools/transport_security_state_generator/trie/trie_writer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+namespace {
+
+std::vector<uint8_t> StringToVector(const std::string& input) {
+ std::vector<uint8_t> output;
+ for (const auto& character : input) {
+ output.push_back(character);
+ }
+ return output;
+}
+
+void appendEntry(const std::string& hostname,
+ TransportSecurityStateEntries* entries) {
+ std::unique_ptr<TransportSecurityStateEntry> entry =
+ base::MakeUnique<TransportSecurityStateEntry>();
+ entry->hostname = hostname;
+ entry->include_subdomains = true;
+ entry->force_https = true;
+
+ entries->push_back(std::move(entry));
+}
+
+} // namespace
+
+class TrieWriterTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ // Create a Huffman representation that is 8bit ASCII.
+ for (uint8_t i = 0; i <= 127; ++i) {
+ HuffmanRepresentation representation;
+ representation.bits = i;
+ representation.number_of_bits = 8;
+ huffman_table_[i] = representation;
+ }
+
+ domain_ids_map_["BADSSL_COM"] = 1;
+ domain_ids_map_["EXAMPLE_ORG"] = 2;
+ domain_ids_map_["OVERFLOW_TLD"] = 512;
+
+ report_uris_map_["https://report.badssl.com/upload"] = 1;
+ report_uris_map_["https://report.example.org/upload"] = 2;
+ report_uris_map_["https://report.overflow.tld/upload"] = 16;
+
+ pinsets_map_["pinset_a"] = 1;
+ pinsets_map_["pinset_b"] = 2;
+ pinsets_map_["pinset_overflow"] = 16;
+ }
+
+ std::unique_ptr<TrieWriter> GetTrieWriter() {
+ return base::MakeUnique<TrieWriter>(huffman_table_, domain_ids_map_,
+ report_uris_map_, report_uris_map_,
+ pinsets_map_, nullptr);
+ }
+
+ bool TestWriteEntry(TrieWriter* trie_writer,
+ const TransportSecurityStateEntry& entry,
+ std::initializer_list<uint8_t> expected) {
+ TrieBitBuffer buffer;
+ if (!trie_writer->WriteEntry(&entry, &buffer)) {
+ return false;
+ }
+
+ BitWriter bit_writer;
+ buffer.WriteToBitWriter(&bit_writer);
+ bit_writer.Flush();
+
+ EXPECT_EQ(std::vector<uint8_t>(expected), bit_writer.bytes());
+ return true;
+ }
+
+ private:
+ HuffmanRepresentationTable huffman_table_;
+ NameIDMap domain_ids_map_;
+ NameIDMap report_uris_map_;
+ NameIDMap pinsets_map_;
+};
+
+TEST_F(TrieWriterTest, SingleEntryTrie) {
+ TransportSecurityStateEntries entries;
+ appendEntry("hsts.badssl.com", &entries);
+
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+
+ uint32_t root_position;
+ ASSERT_TRUE(trie_writer->WriteEntries(entries, &root_position));
+
+ EXPECT_EQ(0U, root_position);
+ EXPECT_EQ(157U, trie_writer->position());
+
+ trie_writer->Flush();
+ EXPECT_EQ(20U, trie_writer->bytes().size());
+
+ // The expected bits are, starting at |root_position|:
+ // 0xFF 0XFE: 15 ones followed by a zero indicating a prefix of 15 characters.
+ //
+ // The prefix follows immediately (8 bits per character):
+ // 0x6D 0x6F 0x63 0x2E 0x6C 0x73 0x73 0x64 0x61 0x62 0x2E 0x73 0x74 0x73 0x68
+ // and decodes to "moc.lssdab.stsh".
+ //
+ // The prefix is followed by 0x0 (kTerminalValue) which indidicates the end
+ // of the prefix. What follows is the encoded entry for "hsts.badssl.com":
+ // 0xC3 0xF8. The entry (first 5 bits) is followed be 0x7F (kEndOfTabelValue).
+ // The remaining bits are padding.
+ EXPECT_THAT(
+ trie_writer->bytes(),
+ testing::ElementsAreArray({0xFF, 0xFE, 0x6D, 0x6F, 0x63, 0x2E, 0x6C,
+ 0x73, 0x73, 0x64, 0x61, 0x62, 0x2E, 0x73,
+ 0x74, 0x73, 0x68, 0x0, 0xC3, 0xF8}));
+}
+
+TEST_F(TrieWriterTest, MultiPrefixTrie) {
+ TransportSecurityStateEntries entries;
+ appendEntry("hsts.badssl.com", &entries);
+ appendEntry("expect-ct.badssl.com", &entries);
+ appendEntry("expect-staple.badssl.com", &entries);
+
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+
+ uint32_t root_position;
+ ASSERT_TRUE(trie_writer->WriteEntries(entries, &root_position));
+
+ EXPECT_EQ(273U, root_position);
+ EXPECT_EQ(440U, trie_writer->position());
+
+ trie_writer->Flush();
+ EXPECT_EQ(56U, trie_writer->bytes().size());
+
+ EXPECT_THAT(trie_writer->bytes(),
martijnc 2017/02/08 20:58:21 I've verified that these expectations are correct
Ryan Sleevi 2017/02/08 21:45:29 That's a really tough question. You're effectively
+ testing::ElementsAreArray(
+ {0xff, 0xf3, 0x63, 0x83, 0xb, 0xa3, 0x99, 0x6b, 0xa3, 0x1b,
+ 0x2b, 0x83, 0xc3, 0x28, 0x6, 0x1f, 0xf9, 0xd1, 0xcd, 0xa0,
+ 0x3, 0xf, 0xff, 0xe6, 0x32, 0xd7, 0x46, 0x36, 0x57, 0x7,
+ 0x86, 0x50, 0xc, 0x3f, 0xff, 0xf3, 0x6b, 0x7b, 0x19, 0x73,
+ 0x63, 0x9b, 0x9b, 0x23, 0xb, 0x11, 0x73, 0x2a, 0x62, 0x2e,
+ 0x70, 0x82, 0x74, 0x31, 0x7f, 0x0}));
+}
+
+TEST_F(TrieWriterTest, MultiMixedPrefixTrie) {
+ TransportSecurityStateEntries entries;
+ appendEntry("hsts.badssl.com", &entries);
+ appendEntry("expect-ct.badssl.com", &entries);
+ appendEntry("example.org", &entries);
+ appendEntry("badssl.com", &entries);
+
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+
+ uint32_t root_position;
+ ASSERT_TRUE(trie_writer->WriteEntries(entries, &root_position));
+
+ EXPECT_EQ(423U, root_position);
+ EXPECT_EQ(476U, trie_writer->position());
+
+ trie_writer->Flush();
+ EXPECT_EQ(60U, trie_writer->bytes().size());
+
+ EXPECT_THAT(
+ trie_writer->bytes(),
+ testing::ElementsAreArray(
+ {0xff, 0xce, 0x4d, 0xe5, 0xcc, 0xad, 0x8e, 0xd, 0xac, 0x2f,
+ 0xc, 0xa0, 0x18, 0x7f, 0xe7, 0x47, 0x36, 0x80, 0xc, 0x3f,
+ 0xff, 0x98, 0xcb, 0x5d, 0x18, 0xd9, 0x5c, 0x1e, 0x19, 0x40,
+ 0x30, 0xfe, 0x73, 0x44, 0x7b, 0xa1, 0x8b, 0xff, 0xfc, 0xde,
+ 0xc6, 0x5c, 0xd8, 0xe6, 0xe6, 0xc8, 0xc2, 0xc4, 0x1, 0x82,
+ 0xe3, 0x5c, 0xfe, 0x67, 0x4e, 0x9d, 0xb6, 0x32, 0xd7, 0xf0}));
+}
+
+TEST_F(TrieWriterTest, WriteEntryHSTS) {
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+ TransportSecurityStateEntry entry;
+ entry.hostname = "example.org";
+
+ entry.force_https = true;
+ entry.include_subdomains = true;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0xC0}));
+
+ entry.force_https = false;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x80}));
+
+ entry.include_subdomains = false;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x0}));
+
+ entry.force_https = true;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x40}));
+}
+
+TEST_F(TrieWriterTest, WriteEntryHPKP) {
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+ TransportSecurityStateEntry entry;
+ entry.hostname = "example.org";
+
+ entry.pinset = "pinset_a";
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x22, 0x2, 0x0}));
+
+ entry.hpkp_include_subdomains = true;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x22, 0x2, 0x80}));
+
+ // Should ignore |entry.hpkp_include_subdomains|.
+ entry.include_subdomains = true;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0xA2, 0x2, 0x0}));
+
+ // Should result in an "empty" HPKP state.
+ entry.pinset = "";
+ entry.include_subdomains = false;
+ entry.hpkp_include_subdomains = true;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x0}));
+
+ // Unknown pinset.
+ entry.pinset = "not_found";
+ EXPECT_FALSE(TestWriteEntry(trie_writer.get(), entry, {}));
+
+ // Overflow for the pinset ID.
+ entry.pinset = "pinset_overflow";
+ EXPECT_FALSE(TestWriteEntry(trie_writer.get(), entry, {}));
+
+ // Set a valid pinset for the other tests.
+ entry.pinset = "pinset_a";
+
+ // Overflow for the domain ID.
+ entry.hostname = "overflow.tld";
+ EXPECT_FALSE(TestWriteEntry(trie_writer.get(), entry, {}));
+
+ // Unknown domain ID.
+ entry.hostname = "unknown.tld";
+ EXPECT_FALSE(TestWriteEntry(trie_writer.get(), entry, {}));
+}
+
+TEST_F(TrieWriterTest, WriteEntryExpectStaple) {
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+ TransportSecurityStateEntry entry;
+ entry.hostname = "example.org";
+
+ entry.expect_staple = true;
+ entry.expect_staple_report_uri = "https://report.example.org/upload";
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x08, 0x80}));
+
+ entry.expect_staple_include_subdomains = true;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x0C, 0x80}));
+
+ // This should result in an "empty" expect-staple state.
+ entry.expect_staple = false;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x0}));
+
+ // Enable expect-staple for the other tests.
+ entry.expect_staple = true;
+
+ // Invalid report URI ID.
+ entry.expect_staple_report_uri = "https://report.overflow.tld/upload";
+ EXPECT_FALSE(TestWriteEntry(trie_writer.get(), entry, {}));
+
+ // Unknown report URI.
+ entry.expect_staple_report_uri = "https://report.unknown.tld/upload";
+ EXPECT_FALSE(TestWriteEntry(trie_writer.get(), entry, {}));
+}
+
+TEST_F(TrieWriterTest, WriteEntryExpectCT) {
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+ TransportSecurityStateEntry entry;
+ entry.hostname = "example.org";
+
+ entry.expect_ct = true;
+ entry.expect_ct_report_uri = "https://report.example.org/upload";
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x12, 0x0}));
+
+ // This should result in an "empty" expect-staple state.
+ entry.expect_ct = false;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x0}));
+
+ // Enable expect-staple for the other tests.
+ entry.expect_ct = true;
+
+ // Invalid report URI ID.
+ entry.expect_ct_report_uri = "https://report.overflow.tld/upload";
+ EXPECT_FALSE(TestWriteEntry(trie_writer.get(), entry, {}));
+
+ // Unknown report URI.
+ entry.expect_ct_report_uri = "https://report.unknown.tld/upload";
+ EXPECT_FALSE(TestWriteEntry(trie_writer.get(), entry, {}));
+}
+
+TEST_F(TrieWriterTest, WriteEntryCombination) {
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+ TransportSecurityStateEntry entry;
+ entry.hostname = "example.org";
+
+ entry.force_https = true;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0x40}));
+
+ entry.include_subdomains = true;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0xC0}));
+
+ entry.pinset = "pinset_a";
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0xE2, 0x2, 0x0}));
+
+ // Should have no effect.
+ entry.hpkp_include_subdomains = true;
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0xE2, 0x2, 0x0}));
+
+ entry.expect_ct = true;
+ entry.expect_ct_report_uri = "https://report.example.org/upload";
+ EXPECT_TRUE(TestWriteEntry(trie_writer.get(), entry, {0xE2, 0x2, 0x90}));
+
+ entry.expect_staple = true;
+ entry.expect_staple_report_uri = "https://report.example.org/upload";
+ EXPECT_TRUE(
+ TestWriteEntry(trie_writer.get(), entry, {0xE2, 0x2, 0x94, 0x40}));
+
+ entry.expect_staple_include_subdomains = true;
+ EXPECT_TRUE(
+ TestWriteEntry(trie_writer.get(), entry, {0xE2, 0x2, 0x96, 0x40}));
+}
+
+TEST_F(TrieWriterTest, ReverseName) {
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+
+ EXPECT_EQ(StringToVector(std::string("moc.elpmaxe\0", 12)),
+ trie_writer->ReverseName("example.com"));
+ EXPECT_EQ(StringToVector(std::string("moc.lssdab.stsh\0", 16)),
+ trie_writer->ReverseName("hsts.badssl.com"));
+}
+
+TEST_F(TrieWriterTest, LongestCommonPrefix) {
+ std::unique_ptr<TrieWriter> trie_writer = GetTrieWriter();
+
+ TransportSecurityStateEntry entry1;
+ entry1.hostname = "sub.sub.example.com";
+ TransportSecurityStateEntry entry2;
+ entry2.hostname = "sub.example.com";
+ TransportSecurityStateEntry entry3;
+ entry3.hostname = "www.sub.example.com";
+ TransportSecurityStateEntry entry4;
+ entry4.hostname = "example.com";
+ TransportSecurityStateEntry entry5;
+ entry5.hostname = "badssl.com";
+ TransportSecurityStateEntry entry6;
+ entry6.hostname = "example.org";
+
+ ReversedEntries reversed_entries;
+ reversed_entries.push_back(base::MakeUnique<ReversedEntry>(
+ trie_writer->ReverseName(entry1.hostname), &entry1));
+
+ EXPECT_EQ(StringToVector("moc.elpmaxe.bus.bus"),
+ trie_writer->LongestCommonPrefix(reversed_entries.cbegin(),
+ reversed_entries.cend()));
+
+ reversed_entries.push_back(base::MakeUnique<ReversedEntry>(
+ trie_writer->ReverseName(entry2.hostname), &entry2));
+ EXPECT_EQ(StringToVector("moc.elpmaxe.bus"),
+ trie_writer->LongestCommonPrefix(reversed_entries.cbegin(),
+ reversed_entries.cend()));
+
+ reversed_entries.push_back(base::MakeUnique<ReversedEntry>(
+ trie_writer->ReverseName(entry3.hostname), &entry3));
+ EXPECT_EQ(StringToVector("moc.elpmaxe.bus"),
+ trie_writer->LongestCommonPrefix(reversed_entries.cbegin(),
+ reversed_entries.cend()));
+
+ reversed_entries.push_back(base::MakeUnique<ReversedEntry>(
+ trie_writer->ReverseName(entry4.hostname), &entry4));
+ EXPECT_EQ(StringToVector("moc.elpmaxe"),
+ trie_writer->LongestCommonPrefix(reversed_entries.cbegin(),
+ reversed_entries.cend()));
+
+ reversed_entries.push_back(base::MakeUnique<ReversedEntry>(
+ trie_writer->ReverseName(entry5.hostname), &entry5));
+ EXPECT_EQ(StringToVector("moc."),
+ trie_writer->LongestCommonPrefix(reversed_entries.cbegin(),
+ reversed_entries.cend()));
+
+ reversed_entries.push_back(base::MakeUnique<ReversedEntry>(
+ trie_writer->ReverseName(entry6.hostname), &entry6));
+ EXPECT_EQ(StringToVector(""),
+ trie_writer->LongestCommonPrefix(reversed_entries.cbegin(),
+ reversed_entries.cend()));
+}
+
+} // transport_security_state
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698