128 lines
3.5 KiB
C++
128 lines
3.5 KiB
C++
// Copyright 2013 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "components/nacl/browser/nacl_validation_cache.h"
|
|
|
|
#include "base/containers/adapters.h"
|
|
#include "base/pickle.h"
|
|
#include "base/rand_util.h"
|
|
|
|
namespace nacl {
|
|
|
|
// For the moment, choose an arbitrary cache size.
|
|
const size_t kValidationCacheCacheSize = 500;
|
|
// Key size is equal to the block size (not the digest size) of SHA256.
|
|
const size_t kValidationCacheKeySize = 64;
|
|
// Entry size is equal to the digest size of SHA256.
|
|
const size_t kValidationCacheEntrySize = 32;
|
|
|
|
const char kValidationCacheBeginMagic[] = "NaCl";
|
|
const char kValidationCacheEndMagic[] = "Done";
|
|
|
|
NaClValidationCache::NaClValidationCache()
|
|
: validation_cache_(kValidationCacheCacheSize) {
|
|
// Make sure the cache key is unpredictable, even if the cache has not
|
|
// been loaded.
|
|
Reset();
|
|
}
|
|
|
|
NaClValidationCache::~NaClValidationCache() {
|
|
// Make clang's style checking happy by adding a destructor.
|
|
}
|
|
|
|
bool NaClValidationCache::QueryKnownToValidate(const std::string& signature,
|
|
bool reorder) {
|
|
if (signature.length() == kValidationCacheEntrySize) {
|
|
ValidationCacheType::iterator iter;
|
|
if (reorder) {
|
|
iter = validation_cache_.Get(signature);
|
|
} else {
|
|
iter = validation_cache_.Peek(signature);
|
|
}
|
|
if (iter != validation_cache_.end()) {
|
|
return iter->second;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void NaClValidationCache::SetKnownToValidate(const std::string& signature) {
|
|
if (signature.length() == kValidationCacheEntrySize) {
|
|
validation_cache_.Put(signature, true);
|
|
}
|
|
}
|
|
|
|
void NaClValidationCache::Serialize(base::Pickle* pickle) const {
|
|
// Mark the beginning of the data stream.
|
|
pickle->WriteString(kValidationCacheBeginMagic);
|
|
pickle->WriteString(validation_cache_key_);
|
|
pickle->WriteInt(validation_cache_.size());
|
|
|
|
// Serialize the cache in reverse order so that deserializing it can easily
|
|
// preserve the MRU order. (Last item deserialized => most recently used.)
|
|
ValidationCacheType::const_reverse_iterator iter;
|
|
for (const auto& [signature, value] : base::Reversed(validation_cache_)) {
|
|
pickle->WriteString(signature);
|
|
}
|
|
|
|
// Mark the end of the data stream.
|
|
pickle->WriteString(kValidationCacheEndMagic);
|
|
}
|
|
|
|
void NaClValidationCache::Reset() {
|
|
validation_cache_key_ = base::RandBytesAsString(kValidationCacheKeySize);
|
|
validation_cache_.Clear();
|
|
}
|
|
|
|
bool NaClValidationCache::Deserialize(const base::Pickle* pickle) {
|
|
bool success = DeserializeImpl(pickle);
|
|
if (!success) {
|
|
Reset();
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool NaClValidationCache::DeserializeImpl(const base::Pickle* pickle) {
|
|
base::PickleIterator iter(*pickle);
|
|
std::string buffer;
|
|
int count;
|
|
|
|
// Magic
|
|
if (!iter.ReadString(&buffer))
|
|
return false;
|
|
if (0 != buffer.compare(kValidationCacheBeginMagic))
|
|
return false;
|
|
|
|
// Key
|
|
if (!iter.ReadString(&buffer))
|
|
return false;
|
|
if (buffer.size() != kValidationCacheKeySize)
|
|
return false;
|
|
|
|
validation_cache_key_ = buffer;
|
|
validation_cache_.Clear();
|
|
|
|
// Cache entries
|
|
if (!iter.ReadInt(&count))
|
|
return false;
|
|
for (int i = 0; i < count; ++i) {
|
|
if (!iter.ReadString(&buffer))
|
|
return false;
|
|
if (buffer.size() != kValidationCacheEntrySize)
|
|
return false;
|
|
validation_cache_.Put(buffer, true);
|
|
}
|
|
|
|
// Magic
|
|
if (!iter.ReadString(&buffer))
|
|
return false;
|
|
if (0 != buffer.compare(kValidationCacheEndMagic))
|
|
return false;
|
|
|
|
// Success!
|
|
return true;
|
|
}
|
|
|
|
} // namespace nacl
|