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