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