Home | History | Annotate | Download | only in nacl_host
      1 // Copyright (c) 2012 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 "chrome/browser/nacl_host/nacl_validation_cache.h"
      6 
      7 #include "base/pickle.h"
      8 #include "base/rand_util.h"
      9 
     10 namespace {
     11 
     12 // For the moment, choose an arbitrary cache size.
     13 const size_t kValidationCacheCacheSize = 200;
     14 // Key size is equal to the block size (not the digest size) of SHA256.
     15 const size_t kValidationCacheKeySize = 64;
     16 // Entry size is equal to the digest size of SHA256.
     17 const size_t kValidationCacheEntrySize = 32;
     18 
     19 const char kValidationCacheBeginMagic[] = "NaCl";
     20 const char kValidationCacheEndMagic[] = "Done";
     21 
     22 }  // namespace
     23 
     24 NaClValidationCache::NaClValidationCache()
     25     : validation_cache_(kValidationCacheCacheSize) {
     26   // Make sure the cache key is unpredictable, even if the cache has not
     27   // been loaded.
     28   Reset();
     29 }
     30 
     31 NaClValidationCache::~NaClValidationCache() {
     32   // Make clang's style checking happy by adding a destructor.
     33 }
     34 
     35 bool NaClValidationCache::QueryKnownToValidate(const std::string& signature,
     36                                                bool reorder) {
     37   if (signature.length() == kValidationCacheEntrySize) {
     38     ValidationCacheType::iterator iter;
     39     if (reorder) {
     40       iter = validation_cache_.Get(signature);
     41     } else {
     42       iter = validation_cache_.Peek(signature);
     43     }
     44     if (iter != validation_cache_.end()) {
     45       return iter->second;
     46     }
     47   }
     48   return false;
     49 }
     50 
     51 void NaClValidationCache::SetKnownToValidate(const std::string& signature) {
     52   if (signature.length() == kValidationCacheEntrySize) {
     53     validation_cache_.Put(signature, true);
     54   }
     55 }
     56 
     57 void NaClValidationCache::Serialize(Pickle* pickle) const {
     58   // Mark the beginning of the data stream.
     59   pickle->WriteString(kValidationCacheBeginMagic);
     60   pickle->WriteString(validation_cache_key_);
     61   pickle->WriteInt(validation_cache_.size());
     62 
     63   // Serialize the cache in reverse order so that deserializing it can easily
     64   // preserve the MRU order.  (Last item deserialized => most recently used.)
     65   ValidationCacheType::const_reverse_iterator iter;
     66   for (iter = validation_cache_.rbegin();
     67        iter != validation_cache_.rend();
     68        ++iter) {
     69     pickle->WriteString(iter->first);
     70   }
     71 
     72   // Mark the end of the data stream.
     73   pickle->WriteString(kValidationCacheEndMagic);
     74 }
     75 
     76 void NaClValidationCache::Reset() {
     77   validation_cache_key_ = base::RandBytesAsString(kValidationCacheKeySize);
     78   validation_cache_.Clear();
     79 }
     80 
     81 bool NaClValidationCache::Deserialize(const Pickle* pickle) {
     82   bool success = DeserializeImpl(pickle);
     83   if (!success) {
     84     Reset();
     85   }
     86   return success;
     87 }
     88 
     89 bool NaClValidationCache::DeserializeImpl(const Pickle* pickle) {
     90   PickleIterator iter(*pickle);
     91   std::string buffer;
     92   int count;
     93 
     94   // Magic
     95   if (!iter.ReadString(&buffer))
     96     return false;
     97   if (0 != buffer.compare(kValidationCacheBeginMagic))
     98     return false;
     99 
    100   // Key
    101   if (!iter.ReadString(&buffer))
    102     return false;
    103   if (buffer.size() != kValidationCacheKeySize)
    104     return false;
    105 
    106   validation_cache_key_ = buffer;
    107   validation_cache_.Clear();
    108 
    109   // Cache entries
    110   if (!iter.ReadInt(&count))
    111     return false;
    112   for (int i = 0; i < count; ++i) {
    113     if (!iter.ReadString(&buffer))
    114       return false;
    115     if (buffer.size() != kValidationCacheEntrySize)
    116       return false;
    117     validation_cache_.Put(buffer, true);
    118   }
    119 
    120   // Magic
    121   if (!iter.ReadString(&buffer))
    122     return false;
    123   if (0 != buffer.compare(kValidationCacheEndMagic))
    124     return false;
    125 
    126   // Success!
    127   return true;
    128 }
    129 
    130