-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathhash_cache.cpp
134 lines (109 loc) · 3.51 KB
/
hash_cache.cpp
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
130
131
132
133
134
/**
* SHA1 hash support for NSEC3
*
*/
#include "hash_cache.h"
#include "hash.h"
#include "settings.h"
#include <functional>
#include <openssl/sha.h>
#include <stdio.h>
#include <string.h>
#include <unordered_map>
struct hash_cache_key {
int iterations;
unsigned char salt[256];
int saltlength;
unsigned char in[256];
int inlength;
const bool operator==(const hash_cache_key& h) const
{
if (iterations != h.iterations)
return false;
if (saltlength != h.saltlength)
return false;
if (inlength != h.inlength)
return false;
if (memcmp(salt, h.salt, saltlength) != 0)
return false;
if (memcmp(in, h.in, inlength) != 0)
return false;
return true;
}
};
struct hash_cache_entry {
unsigned char hash[SHA_DIGEST_LENGTH];
};
class hash_cache_key_hash_functor : public std::unary_function<hash_cache_key, size_t> {
public:
size_t operator()(const hash_cache_key& q) const
{
size_t hash = 5381;
for (int i = 0; i < q.saltlength; ++i)
hash = ((hash << 5) + hash) + q.salt[i];
for (int i = 0; i < q.inlength; ++i)
hash = ((hash << 5) + hash) + q.in[i];
return ((hash << 5) + hash) + q.iterations;
}
};
// trickery so we can do a forward declare, speeding up compiliation times
typedef std::unordered_map<hash_cache_key, hash_cache_entry, hash_cache_key_hash_functor> hash_cache_base_t;
typedef hash_cache_base_t::iterator hash_cache_iter_t;
class hash_cache_t : public hash_cache_base_t {
};
hash_cache::hash_cache()
{
cacheMap = new hash_cache_t;
}
hash_cache::~hash_cache()
{
delete cacheMap;
}
int hash_cache::get_iterated_hash(unsigned char out[HASH_OUT_LEN],
const unsigned char* salt, int saltlength,
const unsigned char* in, int inlength, int iterations)
{
bool should_use_cache = true;
hash_cache_key key;
if (should_use_cache) {
// built our cache key
key.iterations = iterations;
key.inlength = inlength;
key.saltlength = saltlength;
memcpy(key.salt, salt, saltlength);
memcpy(key.in, in, inlength);
// check the per-thread cache for the existance of our hash
const hash_cache_iter_t& iter = cacheMap->find(key);
if (iter != cacheMap->end()) {
memcpy(out, iter->second.hash, SHA_DIGEST_LENGTH);
return SHA_DIGEST_LENGTH;
}
}
int result = iterated_hash(out, salt, saltlength, in, inlength, iterations);
if (should_use_cache) {
// if our cache is full, half it
if (cacheMap->size() >= dnssec_nsec3_hash_cache_size) {
cacheMap->clear();
/*
hash_cache_iter_t start = cacheMap->begin();
hash_cache_iter_t mid = start + (cacheMap->size() / 2);
cacheMap->erase(start, mid);
*/
}
// add our calculated hash to the cache
hash_cache_entry entry;
memcpy(entry.hash, out, SHA_DIGEST_LENGTH);
cacheMap->insert(std::make_pair(key, entry));
}
return result;
}
int iterated_cached_hash(hash_cache* cache, unsigned char out[HASH_OUT_LEN],
const unsigned char* salt, int saltlength,
const unsigned char* in, int inlength, int iterations)
{
if (cache != NULL && dnssec_nsec3_hash_cache_size > 0) {
return cache->get_iterated_hash(out, salt, saltlength, in, inlength, iterations);
} else {
return iterated_hash(out, salt, saltlength, in, inlength, iterations);
}
}