1 // Copyright (c) 2013 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 "quiche/quic/core/crypto/cert_compressor.h"
6
7 #include <memory>
8 #include <string>
9
10 #include "absl/strings/escaping.h"
11 #include "absl/strings/string_view.h"
12 #include "quiche/quic/core/quic_utils.h"
13 #include "quiche/quic/platform/api/quic_test.h"
14 #include "quiche/quic/test_tools/crypto_test_utils.h"
15
16 namespace quic {
17 namespace test {
18
19 class CertCompressorTest : public QuicTest {};
20
TEST_F(CertCompressorTest,EmptyChain)21 TEST_F(CertCompressorTest, EmptyChain) {
22 std::vector<std::string> chain;
23 const std::string compressed =
24 CertCompressor::CompressChain(chain, absl::string_view());
25 EXPECT_EQ("00", absl::BytesToHexString(compressed));
26
27 std::vector<std::string> chain2, cached_certs;
28 ASSERT_TRUE(
29 CertCompressor::DecompressChain(compressed, cached_certs, &chain2));
30 EXPECT_EQ(chain.size(), chain2.size());
31 }
32
TEST_F(CertCompressorTest,Compressed)33 TEST_F(CertCompressorTest, Compressed) {
34 std::vector<std::string> chain;
35 chain.push_back("testcert");
36 const std::string compressed =
37 CertCompressor::CompressChain(chain, absl::string_view());
38 ASSERT_GE(compressed.size(), 2u);
39 EXPECT_EQ("0100", absl::BytesToHexString(compressed.substr(0, 2)));
40
41 std::vector<std::string> chain2, cached_certs;
42 ASSERT_TRUE(
43 CertCompressor::DecompressChain(compressed, cached_certs, &chain2));
44 EXPECT_EQ(chain.size(), chain2.size());
45 EXPECT_EQ(chain[0], chain2[0]);
46 }
47
TEST_F(CertCompressorTest,Common)48 TEST_F(CertCompressorTest, Common) {
49 std::vector<std::string> chain;
50 chain.push_back("testcert");
51 static const uint64_t set_hash = 42;
52 const std::string compressed = CertCompressor::CompressChain(
53 chain, absl::string_view(reinterpret_cast<const char*>(&set_hash),
54 sizeof(set_hash)));
55 ASSERT_GE(compressed.size(), 2u);
56 // 01 is the prefix for a zlib "compressed" cert not common or cached.
57 EXPECT_EQ("0100", absl::BytesToHexString(compressed.substr(0, 2)));
58
59 std::vector<std::string> chain2, cached_certs;
60 ASSERT_TRUE(
61 CertCompressor::DecompressChain(compressed, cached_certs, &chain2));
62 EXPECT_EQ(chain.size(), chain2.size());
63 EXPECT_EQ(chain[0], chain2[0]);
64 }
65
TEST_F(CertCompressorTest,Cached)66 TEST_F(CertCompressorTest, Cached) {
67 std::vector<std::string> chain;
68 chain.push_back("testcert");
69 uint64_t hash = QuicUtils::FNV1a_64_Hash(chain[0]);
70 absl::string_view hash_bytes(reinterpret_cast<char*>(&hash), sizeof(hash));
71 const std::string compressed =
72 CertCompressor::CompressChain(chain, hash_bytes);
73
74 EXPECT_EQ("02" /* cached */ + absl::BytesToHexString(hash_bytes) +
75 "00" /* end of list */,
76 absl::BytesToHexString(compressed));
77
78 std::vector<std::string> cached_certs, chain2;
79 cached_certs.push_back(chain[0]);
80 ASSERT_TRUE(
81 CertCompressor::DecompressChain(compressed, cached_certs, &chain2));
82 EXPECT_EQ(chain.size(), chain2.size());
83 EXPECT_EQ(chain[0], chain2[0]);
84 }
85
TEST_F(CertCompressorTest,BadInputs)86 TEST_F(CertCompressorTest, BadInputs) {
87 std::vector<std::string> cached_certs, chain;
88
89 EXPECT_FALSE(CertCompressor::DecompressChain(
90 absl::BytesToHexString("04") /* bad entry type */, cached_certs, &chain));
91
92 EXPECT_FALSE(CertCompressor::DecompressChain(
93 absl::BytesToHexString("01") /* no terminator */, cached_certs, &chain));
94
95 EXPECT_FALSE(CertCompressor::DecompressChain(
96 absl::BytesToHexString("0200") /* hash truncated */, cached_certs,
97 &chain));
98
99 EXPECT_FALSE(CertCompressor::DecompressChain(
100 absl::BytesToHexString("0300") /* hash and index truncated */,
101 cached_certs, &chain));
102
103 /* without a CommonCertSets */
104 EXPECT_FALSE(
105 CertCompressor::DecompressChain(absl::BytesToHexString("03"
106 "0000000000000000"
107 "00000000"),
108 cached_certs, &chain));
109
110 /* incorrect hash and index */
111 EXPECT_FALSE(
112 CertCompressor::DecompressChain(absl::BytesToHexString("03"
113 "a200000000000000"
114 "00000000"),
115 cached_certs, &chain));
116 }
117
118 } // namespace test
119 } // namespace quic
120