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/loader/nacl_validation_query.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10
11 #include "components/nacl/loader/nacl_validation_db.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 // This test makes sure that validation signature generation is performed
15 // correctly. In effect, this means that we are checking all of the data
16 // (and no other data) we are passing the signature generator affects the final
17 // signature. To avoid tying the tests to a particular implementation, each
18 // test generates two signatures and compares them rather than trying to compare
19 // against a specified signature.
20
21 namespace {
22
23 const char kKey[] = "bogus key for HMAC...";
24 const char kKeyAlt[] = "bogus key for HMAC!!!";
25
26 const char kVersion[] = "bogus version";
27 const char kVersionAlt[] = "bogus!version";
28
29
30 const char kShortData[] = "Short data 1234567890";
31 const char kAltShortData[] = "Short!data 1234567890";
32
33 const char kLongData[] = "Long data."
34 "1234567890123456789012345678901234567890123456789012345678901234567890"
35 "1234567890123456789012345678901234567890123456789012345678901234567890"
36 "1234567890123456789012345678901234567890123456789012345678901234567890"
37 "1234567890123456789012345678901234567890123456789012345678901234567890";
38
39 class MockValidationDB : public NaClValidationDB {
40 public:
MockValidationDB()41 MockValidationDB()
42 : did_query_(false),
43 did_set_(false),
44 status_(true) {
45 }
46
QueryKnownToValidate(const std::string & signature)47 bool QueryKnownToValidate(const std::string& signature) override {
48 // The typecast is needed to work around gtest trying to take the address
49 // of a constant.
50 EXPECT_EQ((int) NaClValidationQuery::kDigestLength,
51 (int) signature.length());
52 EXPECT_FALSE(did_query_);
53 EXPECT_FALSE(did_set_);
54 did_query_ = true;
55 memcpy(query_signature_, signature.data(),
56 NaClValidationQuery::kDigestLength);
57 return status_;
58 }
59
SetKnownToValidate(const std::string & signature)60 void SetKnownToValidate(const std::string& signature) override {
61 // The typecast is needed to work around gtest trying to take the address
62 // of a constant.
63 ASSERT_EQ((int) NaClValidationQuery::kDigestLength,
64 (int) signature.length());
65 EXPECT_TRUE(did_query_);
66 EXPECT_FALSE(did_set_);
67 did_set_ = true;
68 memcpy(set_signature_, signature.data(),
69 NaClValidationQuery::kDigestLength);
70 // Signatures should be the same.
71 EXPECT_EQ(0, memcmp(query_signature_, set_signature_,
72 NaClValidationQuery::kDigestLength));
73 }
74
75 bool did_query_;
76 bool did_set_;
77 bool status_;
78
79 uint8_t query_signature_[NaClValidationQuery::kDigestLength];
80 uint8_t set_signature_[NaClValidationQuery::kDigestLength];
81 };
82
83 class TestQuery {
84 public:
TestQuery(const char * key,const char * version)85 TestQuery(const char* key, const char* version) {
86 db = std::make_unique<MockValidationDB>();
87 context =
88 std::make_unique<NaClValidationQueryContext>(db.get(), key, version);
89 query.reset(context->CreateQuery());
90 }
91
92 std::unique_ptr<MockValidationDB> db;
93 std::unique_ptr<NaClValidationQueryContext> context;
94 std::unique_ptr<NaClValidationQuery> query;
95 };
96
97 class NaClValidationQueryTest : public ::testing::Test {
98 protected:
99 std::unique_ptr<TestQuery> query1;
100 std::unique_ptr<TestQuery> query2;
101
SetUp()102 void SetUp() override {
103 query1 = std::make_unique<TestQuery>(kKey, kVersion);
104 query2 = std::make_unique<TestQuery>(kKey, kVersion);
105 }
106
AssertQuerySame()107 void AssertQuerySame() {
108 ASSERT_TRUE(query1->db->did_query_);
109 ASSERT_TRUE(query2->db->did_query_);
110 ASSERT_EQ(0, memcmp(query1->db->query_signature_,
111 query2->db->query_signature_,
112 NaClValidationQuery::kDigestLength));
113 }
114
AssertQueryDifferent()115 void AssertQueryDifferent() {
116 ASSERT_TRUE(query1->db->did_query_);
117 ASSERT_TRUE(query2->db->did_query_);
118 ASSERT_NE(0, memcmp(query1->db->query_signature_,
119 query2->db->query_signature_,
120 NaClValidationQuery::kDigestLength));
121 }
122 };
123
TEST_F(NaClValidationQueryTest,Sanity)124 TEST_F(NaClValidationQueryTest, Sanity) {
125 query1->query->AddData(kShortData, sizeof(kShortData));
126 ASSERT_FALSE(query1->db->did_query_);
127 ASSERT_FALSE(query1->db->did_set_);
128 ASSERT_EQ(1, query1->query->QueryKnownToValidate());
129 ASSERT_TRUE(query1->db->did_query_);
130 ASSERT_FALSE(query1->db->did_set_);
131 query1->query->SetKnownToValidate();
132 ASSERT_TRUE(query1->db->did_query_);
133 ASSERT_TRUE(query1->db->did_set_);
134 }
135
TEST_F(NaClValidationQueryTest,ConsistentShort)136 TEST_F(NaClValidationQueryTest, ConsistentShort) {
137 query1->query->AddData(kShortData, sizeof(kShortData));
138 query1->query->QueryKnownToValidate();
139
140 query2->query->AddData(kShortData, sizeof(kShortData));
141 query2->query->QueryKnownToValidate();
142
143 AssertQuerySame();
144 }
145
TEST_F(NaClValidationQueryTest,InconsistentShort)146 TEST_F(NaClValidationQueryTest, InconsistentShort) {
147 query1->query->AddData(kShortData, sizeof(kShortData));
148 query1->query->QueryKnownToValidate();
149
150 query2->query->AddData(kAltShortData, sizeof(kAltShortData));
151 query2->query->QueryKnownToValidate();
152
153 AssertQueryDifferent();
154 }
155
156 // Test for a bug caught during development where AddData would accidently
157 // overwrite previously written data and add uninitialzied memory to the hash.
TEST_F(NaClValidationQueryTest,ConsistentShortBug)158 TEST_F(NaClValidationQueryTest, ConsistentShortBug) {
159 query1->query->AddData(kShortData, sizeof(kShortData));
160 query1->query->AddData(kShortData, sizeof(kShortData));
161 query1->query->QueryKnownToValidate();
162
163 query2->query->AddData(kShortData, sizeof(kShortData));
164 query2->query->AddData(kShortData, sizeof(kShortData));
165 query2->query->QueryKnownToValidate();
166
167 AssertQuerySame();
168 }
169
170 // Test for a bug caught during development where AddData would accidently
171 // overwrite previously written data and add uninitialzed memory to the hash.
TEST_F(NaClValidationQueryTest,InconsistentShortBug1)172 TEST_F(NaClValidationQueryTest, InconsistentShortBug1) {
173 query1->query->AddData(kShortData, sizeof(kShortData));
174 query1->query->AddData(kShortData, sizeof(kShortData));
175 query1->query->QueryKnownToValidate();
176
177 query2->query->AddData(kAltShortData, sizeof(kAltShortData));
178 query2->query->AddData(kShortData, sizeof(kShortData));
179 query2->query->QueryKnownToValidate();
180
181 AssertQueryDifferent();
182 }
183
184 // Make sure we don't ignore the second bit of data.
TEST_F(NaClValidationQueryTest,InconsistentShort2)185 TEST_F(NaClValidationQueryTest, InconsistentShort2) {
186 query1->query->AddData(kShortData, sizeof(kShortData));
187 query1->query->AddData(kShortData, sizeof(kShortData));
188 query1->query->QueryKnownToValidate();
189
190 query2->query->AddData(kShortData, sizeof(kShortData));
191 query2->query->AddData(kAltShortData, sizeof(kAltShortData));
192 query2->query->QueryKnownToValidate();
193
194 AssertQueryDifferent();
195 }
196
TEST_F(NaClValidationQueryTest,InconsistentZeroSizedAdd)197 TEST_F(NaClValidationQueryTest, InconsistentZeroSizedAdd) {
198 query1->query->AddData(kShortData, sizeof(kShortData));
199 query1->query->QueryKnownToValidate();
200
201 query2->query->AddData(kShortData, sizeof(kShortData));
202 query2->query->AddData(kShortData, 0);
203 query2->query->QueryKnownToValidate();
204
205 AssertQueryDifferent();
206 }
207
TEST_F(NaClValidationQueryTest,ConsistentZeroSizedAdd)208 TEST_F(NaClValidationQueryTest, ConsistentZeroSizedAdd) {
209 query1->query->AddData(kShortData, sizeof(kShortData));
210 query1->query->AddData("a", 0);
211 query1->query->QueryKnownToValidate();
212
213 query2->query->AddData(kShortData, sizeof(kShortData));
214 query2->query->AddData("b", 0);
215 query2->query->QueryKnownToValidate();
216
217 AssertQuerySame();
218 }
219
TEST_F(NaClValidationQueryTest,ConsistentRepeatedShort)220 TEST_F(NaClValidationQueryTest, ConsistentRepeatedShort) {
221 for (int i = 0; i < 30; i++) {
222 query1->query->AddData(kShortData, sizeof(kShortData));
223 }
224 query1->query->QueryKnownToValidate();
225
226 for (int i = 0; i < 30; i++) {
227 query2->query->AddData(kShortData, sizeof(kShortData));
228 }
229 query2->query->QueryKnownToValidate();
230
231 AssertQuerySame();
232 }
233
TEST_F(NaClValidationQueryTest,ConsistentLong)234 TEST_F(NaClValidationQueryTest, ConsistentLong) {
235 query1->query->AddData(kLongData, sizeof(kLongData));
236 query1->query->QueryKnownToValidate();
237
238 query2->query->AddData(kLongData, sizeof(kLongData));
239 query2->query->QueryKnownToValidate();
240
241 AssertQuerySame();
242 }
243
TEST_F(NaClValidationQueryTest,ConsistentRepeatedLong)244 TEST_F(NaClValidationQueryTest, ConsistentRepeatedLong) {
245 for (int i = 0; i < 30; i++) {
246 query1->query->AddData(kLongData, sizeof(kLongData));
247 }
248 query1->query->QueryKnownToValidate();
249
250 for (int i = 0; i < 30; i++) {
251 query2->query->AddData(kLongData, sizeof(kLongData));
252 }
253 query2->query->QueryKnownToValidate();
254
255 AssertQuerySame();
256 }
257
TEST_F(NaClValidationQueryTest,PerturbKey)258 TEST_F(NaClValidationQueryTest, PerturbKey) {
259 query2 = std::make_unique<TestQuery>(kKeyAlt, kVersion);
260
261 query1->query->AddData(kShortData, sizeof(kShortData));
262 query1->query->QueryKnownToValidate();
263
264 query2->query->AddData(kShortData, sizeof(kShortData));
265 query2->query->QueryKnownToValidate();
266
267 AssertQueryDifferent();
268 }
269
TEST_F(NaClValidationQueryTest,PerturbVersion)270 TEST_F(NaClValidationQueryTest, PerturbVersion) {
271 query2 = std::make_unique<TestQuery>(kKey, kVersionAlt);
272
273 query1->query->AddData(kShortData, sizeof(kShortData));
274 query1->query->QueryKnownToValidate();
275
276 query2->query->AddData(kShortData, sizeof(kShortData));
277 query2->query->QueryKnownToValidate();
278
279 AssertQueryDifferent();
280 }
281
282 }
283