1 // Copyright 2013 The Chromium Authors
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 "components/nacl/browser/nacl_validation_cache.h"
6
7 #include "base/containers/span.h"
8 #include "base/pickle.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace nacl {
12
13 const char key1[65] =
14 "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
15 const char key2[65] =
16 "a 64-byte string of various junk................................";
17 const char sig1[33] = "0123456789ABCDEF0123456789ABCDEF";
18 const char sig2[33] = "a 32-byte string of various junk";
19
20 class NaClValidationCacheTest : public ::testing::Test {
21 protected:
22 NaClValidationCache cache1;
23 NaClValidationCache cache2;
24
SetUp()25 void SetUp() override {
26 // The compiler chokes if std::string(key1) is passed directly as an arg.
27 std::string key(key1);
28 cache1.SetValidationCacheKey(key);
29 cache2.SetValidationCacheKey(key);
30 }
31
IsIdentical(const NaClValidationCache & a,const NaClValidationCache & b) const32 bool IsIdentical(const NaClValidationCache& a,
33 const NaClValidationCache& b) const {
34 if (a.GetValidationCacheKey() != b.GetValidationCacheKey())
35 return false;
36 if (a.size() != b.size())
37 return false;
38 return a.GetContents() == b.GetContents();
39 }
40 };
41
TEST_F(NaClValidationCacheTest,Sanity)42 TEST_F(NaClValidationCacheTest, Sanity) {
43 ASSERT_EQ(0u, cache1.size());
44 ASSERT_FALSE(cache1.QueryKnownToValidate(sig1, true));
45 ASSERT_FALSE(cache1.QueryKnownToValidate(sig2, true));
46 }
47
TEST_F(NaClValidationCacheTest,Sig1)48 TEST_F(NaClValidationCacheTest, Sig1) {
49 cache1.SetKnownToValidate(sig1);
50 ASSERT_EQ(1, (int) cache1.size());
51 ASSERT_TRUE(cache1.QueryKnownToValidate(sig1, true));
52 ASSERT_FALSE(cache1.QueryKnownToValidate(sig2, true));
53 }
54
TEST_F(NaClValidationCacheTest,Sig2)55 TEST_F(NaClValidationCacheTest, Sig2) {
56 cache1.SetKnownToValidate(sig2);
57 ASSERT_EQ(1, (int) cache1.size());
58 ASSERT_FALSE(cache1.QueryKnownToValidate(sig1, true));
59 ASSERT_TRUE(cache1.QueryKnownToValidate(sig2, true));
60 }
61
TEST_F(NaClValidationCacheTest,SigBoth)62 TEST_F(NaClValidationCacheTest, SigBoth) {
63 cache1.SetKnownToValidate(sig1);
64 cache1.SetKnownToValidate(sig2);
65 ASSERT_EQ(2, (int) cache1.size());
66 ASSERT_TRUE(cache1.QueryKnownToValidate(sig1, true));
67 ASSERT_TRUE(cache1.QueryKnownToValidate(sig2, true));
68 }
69
TEST_F(NaClValidationCacheTest,DoubleSet)70 TEST_F(NaClValidationCacheTest, DoubleSet) {
71 cache1.SetKnownToValidate(sig1);
72 cache1.SetKnownToValidate(sig1);
73 ASSERT_EQ(1, (int) cache1.size());
74 ASSERT_TRUE(cache1.QueryKnownToValidate(sig1, true));
75 }
76
TEST_F(NaClValidationCacheTest,EmptyIdentical)77 TEST_F(NaClValidationCacheTest, EmptyIdentical) {
78 ASSERT_TRUE(IsIdentical(cache1, cache2));
79 }
80
TEST_F(NaClValidationCacheTest,DifferentKeysNotIdentical)81 TEST_F(NaClValidationCacheTest, DifferentKeysNotIdentical) {
82 std::string key(key2);
83 cache2.SetValidationCacheKey(key);
84 ASSERT_FALSE(IsIdentical(cache1, cache2));
85 }
86
87
TEST_F(NaClValidationCacheTest,DifferentSizesNotIdentical)88 TEST_F(NaClValidationCacheTest, DifferentSizesNotIdentical) {
89 cache1.SetKnownToValidate(sig1);
90
91 ASSERT_FALSE(IsIdentical(cache1, cache2));
92 }
93
TEST_F(NaClValidationCacheTest,SameSigsIdentical)94 TEST_F(NaClValidationCacheTest, SameSigsIdentical) {
95 cache1.SetKnownToValidate(sig1);
96
97 cache2.SetKnownToValidate(sig1);
98
99 ASSERT_TRUE(IsIdentical(cache1, cache2));
100 }
101
TEST_F(NaClValidationCacheTest,DifferentSigsNotIdentical)102 TEST_F(NaClValidationCacheTest, DifferentSigsNotIdentical) {
103 cache1.SetKnownToValidate(sig1);
104
105 cache2.SetKnownToValidate(sig2);
106
107 ASSERT_FALSE(IsIdentical(cache1, cache2));
108 }
109
TEST_F(NaClValidationCacheTest,InOrderIdentical)110 TEST_F(NaClValidationCacheTest, InOrderIdentical) {
111 cache1.SetKnownToValidate(sig1);
112 cache1.SetKnownToValidate(sig2);
113
114 cache2.SetKnownToValidate(sig1);
115 cache2.SetKnownToValidate(sig2);
116
117 ASSERT_TRUE(IsIdentical(cache1, cache2));
118 }
119
TEST_F(NaClValidationCacheTest,QueryReorders)120 TEST_F(NaClValidationCacheTest, QueryReorders) {
121 cache1.SetKnownToValidate(sig1);
122 cache1.SetKnownToValidate(sig2);
123
124 cache2.SetKnownToValidate(sig2);
125 cache2.SetKnownToValidate(sig1);
126
127 ASSERT_FALSE(IsIdentical(cache1, cache2));
128 cache2.QueryKnownToValidate(sig2, true);
129 ASSERT_TRUE(IsIdentical(cache1, cache2));
130 }
131
TEST_F(NaClValidationCacheTest,ForceNoReorder)132 TEST_F(NaClValidationCacheTest, ForceNoReorder) {
133 cache1.SetKnownToValidate(sig1);
134 cache1.SetKnownToValidate(sig2);
135
136 cache2.SetKnownToValidate(sig2);
137 cache2.SetKnownToValidate(sig1);
138
139 cache2.QueryKnownToValidate(sig2, false);
140 ASSERT_FALSE(IsIdentical(cache1, cache2));
141 }
142
TEST_F(NaClValidationCacheTest,SerializeDeserialize)143 TEST_F(NaClValidationCacheTest, SerializeDeserialize) {
144 std::string key(key2);
145 cache1.SetValidationCacheKey(key);
146 cache1.SetKnownToValidate(sig1);
147 cache1.SetKnownToValidate(sig2);
148
149 base::Pickle pickle;
150 cache1.Serialize(&pickle);
151 ASSERT_TRUE(cache2.Deserialize(&pickle));
152 ASSERT_EQ(2, (int) cache2.size());
153 ASSERT_TRUE(IsIdentical(cache1, cache2));
154 }
155
TEST_F(NaClValidationCacheTest,SerializeDeserializeTruncated)156 TEST_F(NaClValidationCacheTest, SerializeDeserializeTruncated) {
157 std::string key(key2);
158 cache1.SetValidationCacheKey(key);
159 cache1.SetKnownToValidate(sig1);
160 cache1.SetKnownToValidate(sig2);
161
162 base::Pickle pickle;
163 cache1.Serialize(&pickle);
164 base::span<const uint8_t> full_payload = base::make_span(pickle);
165 base::span<const uint8_t> truncated_payload =
166 full_payload.subspan(0, full_payload.size() - 20);
167 base::Pickle truncated = base::Pickle::WithUnownedBuffer(truncated_payload);
168 ASSERT_FALSE(cache2.Deserialize(&truncated));
169 ASSERT_EQ(0u, cache2.size());
170 }
171
TEST_F(NaClValidationCacheTest,DeserializeBadKey)172 TEST_F(NaClValidationCacheTest, DeserializeBadKey) {
173 std::string key(sig1); // Too short, will cause the deserialization to error.
174 cache1.SetValidationCacheKey(key);
175 cache1.SetKnownToValidate(sig1);
176 cache1.SetKnownToValidate(sig2);
177
178 base::Pickle pickle;
179 cache1.Serialize(&pickle);
180 ASSERT_FALSE(cache2.Deserialize(&pickle));
181 ASSERT_EQ(0u, cache2.size());
182 }
183
TEST_F(NaClValidationCacheTest,DeserializeNothing)184 TEST_F(NaClValidationCacheTest, DeserializeNothing) {
185 cache1.SetKnownToValidate(sig1);
186 base::Pickle pickle =
187 base::Pickle::WithUnownedBuffer(base::as_byte_span(std::string()));
188 ASSERT_FALSE(cache1.Deserialize(&pickle));
189 ASSERT_EQ(0u, cache1.size());
190 }
191
TEST_F(NaClValidationCacheTest,DeserializeJunk)192 TEST_F(NaClValidationCacheTest, DeserializeJunk) {
193 cache1.SetKnownToValidate(sig1);
194 base::Pickle pickle =
195 base::Pickle::WithUnownedBuffer(base::as_byte_span(key1));
196 ASSERT_FALSE(cache1.Deserialize(&pickle));
197 ASSERT_EQ(0u, cache1.size());
198 }
199
200 }
201