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
|
#pragma once
#include <Exceptions.h>
#include <tomcrypt.h>
namespace Balau {
template<const struct ltc_prng_descriptor * desc>
class PRNG {
public:
PRNG() { start(); }
~PRNG() { done(); }
void reset() {
done();
start();
}
void setKey(const uint8_t * key, size_t len) {
int r = desc->add_entropy(key, len, &m_state);
IAssert(r == CRYPT_OK, "add_entropy for %s returned %i", desc->name, r);
r = desc->ready(&m_state);
IAssert(r == CRYPT_OK, "ready for %s returned %i", desc->name, r);
}
size_t generate(uint8_t * out, size_t len) {
size_t actualLen = desc->read(out, len, &m_state);
IAssert(len == actualLen, "Couldn't get enough bytes for %s", desc->name);
return actualLen;
}
template<size_t L>
void setKey(const char (&key)[L]) { setKey((const uint8_t *) key, L - 1); }
void setKey(const String & key) { setKey((const uint8_t *) key.to_charp(), key.strlen()); }
template<size_t L>
void generate(const uint8_t (&out)[L]) { generate(out, L); }
static const char * name() { return desc->name; }
private:
void start() {
int r = desc->start(&m_state);
IAssert(r == CRYPT_OK, "start for %s returned %i", desc->name, r);
}
void done() {
int r = desc->done(&m_state);
IAssert(r == CRYPT_OK, "done for %s returned %i", desc->name, r);
}
prng_state m_state;
};
template<class PRNG, size_t BlockLen = 64>
class Cypher : public PRNG {
public:
void process(uint8_t * buf, size_t len) {
while (len) {
if (!m_len) {
m_ptr = m_buffer;
m_len = BlockLen;
generate(m_buffer, BlockLen);
}
ssize_t chunkLen = std::min(m_len, len);
m_len -= chunkLen;
len -= chunkLen;
if ((((uintptr_t) m_ptr) & 7) && (((uintptr_t) buf) & 7)) {
uint64_t * buf64 = (uint64_t *) buf;
uint64_t * ptr64 = (uint64_t *) m_ptr;
chunkLen -= 7;
while (chunkLen > 0) {
chunkLen -= 8;
*buf64++ ^= *ptr64++;
}
m_ptr = (uint8_t *) ptr64;
buf = (uint8_t *) buf64;
chunkLen += 7;
}
if ((((uintptr_t) m_ptr) & 3) && (((uintptr_t) buf) & 3)) {
uint64_t * buf32 = (uint32_t *) buf;
uint64_t * ptr32 = (uint32_t *) m_ptr;
chunkLen -= 3;
while (chunkLen > 0) {
chunkLen -= 4;
*buf32++ ^= *ptr32++;
}
m_ptr = (uint8_t *) ptr32;
buf = (uint8_t *) buf32;
chunkLen += 3;
}
while (chunkLen--)
*buf++ ^= *m_ptr++;
}
}
private:
uint8_t m_buffer[BlockLen], * m_ptr = m_buffer;
size_t m_len = 0;
};
typedef PRNG<&yarrow_desc> Yarrow;
typedef PRNG<&fortuna_desc> Fortuna;
typedef PRNG<&rc4_desc> RC4;
typedef PRNG<&sprng_desc> SPRNG;
typedef PRNG<&sober128_desc> Sober128;
};
|