blob: d2abfc8b14dcf664931a965e8e907c43278b40c8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/nacl_host/nacl_validation_cache.h"
#include "base/pickle.h"
#include "base/rand_util.h"
namespace {
// For the moment, choose an arbitrary cache size.
const size_t kValidationCacheCacheSize = 200;
// 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";
} // namespace
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(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 (iter = validation_cache_.rbegin();
iter != validation_cache_.rend();
++iter) {
pickle->WriteString(iter->first);
}
// 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 Pickle* pickle) {
bool success = DeserializeImpl(pickle);
if (!success) {
Reset();
}
return success;
}
bool NaClValidationCache::DeserializeImpl(const Pickle* pickle) {
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;
}
|