• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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