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 = 500; 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 NaClValidationCache()22NaClValidationCache::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 ~NaClValidationCache()29NaClValidationCache::~NaClValidationCache() { 30 // Make clang's style checking happy by adding a destructor. 31 } 32 QueryKnownToValidate(const std::string & signature,bool reorder)33bool 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 SetKnownToValidate(const std::string & signature)49void NaClValidationCache::SetKnownToValidate(const std::string& signature) { 50 if (signature.length() == kValidationCacheEntrySize) { 51 validation_cache_.Put(signature, true); 52 } 53 } 54 Serialize(base::Pickle * pickle) const55void NaClValidationCache::Serialize(base::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 Reset()74void NaClValidationCache::Reset() { 75 validation_cache_key_ = base::RandBytesAsString(kValidationCacheKeySize); 76 validation_cache_.Clear(); 77 } 78 Deserialize(const base::Pickle * pickle)79bool NaClValidationCache::Deserialize(const base::Pickle* pickle) { 80 bool success = DeserializeImpl(pickle); 81 if (!success) { 82 Reset(); 83 } 84 return success; 85 } 86 DeserializeImpl(const base::Pickle * pickle)87bool NaClValidationCache::DeserializeImpl(const base::Pickle* pickle) { 88 base::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