This repository has been archived by the owner. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathentropy.c
executable file
·138 lines (112 loc) · 3.51 KB
/
entropy.c
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
135
136
137
#include <assert.h>
#include <stdlib.h> // for NULL
#include "params.h"
#include "entropy.h"
#include "sha3.h"
/* Increment the seed
* (we treat it as an array of bytes/little-endian) */
static void increment_seed(entropy_t *entropy) {
uint32_t i;
for (i=0; i<SHA3_512_DIGEST_LENGTH; i++) {
entropy->seed[i] ++;
if (entropy->seed[i] > 0) {
break;
}
}
}
/* Store random bits into the hash array.
* Then increment the entropy->seed. *
* - hash must be an array of n * SHA3_512_DIGEST_LENGTH bytes (i.e., n * 64 bytes) */
static void refresh(entropy_t *entropy, uint8_t *hash, uint32_t n) {
assert(n > 0);
while (n > 0) {
//SHA3_512(hash, entropy->seed, SHA3_512_DIGEST_LENGTH);
// sha3_512(hash, entropy->seed, SHA3_512_DIGEST_LENGTH);
SHA3_sha3512(hash, entropy->seed, SHA3_512_DIGEST_LENGTH);
increment_seed(entropy);
hash += SHA3_512_DIGEST_LENGTH;
n --;
}
}
static void char_pool_refresh(entropy_t *entropy) {
refresh(entropy, entropy->char_pool, EPOOL_HASH_COUNT);
entropy->char_index = 0;
}
static void int16_pool_refresh(entropy_t *entropy) {
refresh(entropy, (uint8_t *) entropy->int16_pool, EPOOL_HASH_COUNT);
entropy->int16_index = 0;
}
static void int64_pool_refresh(entropy_t *entropy) {
refresh(entropy, (uint8_t *) entropy->int64_pool, EPOOL_HASH_COUNT);
entropy->int64_index = 0;
}
/* Random 64bit integer */
uint64_t entropy_random_uint64(entropy_t *entropy){
assert(entropy != NULL);
if (entropy->int64_index >= HASH_LEN_UINT64 * EPOOL_HASH_COUNT) {
int64_pool_refresh(entropy);
}
assert(entropy->int64_index < HASH_LEN_UINT64 * EPOOL_HASH_COUNT);
return entropy->int64_pool[entropy->int64_index++];
}
/* Random 16bit integer */
uint16_t entropy_random_uint16(entropy_t *entropy){
assert(entropy != NULL);
if (entropy->int16_index >= HASH_LEN_UINT16 * EPOOL_HASH_COUNT) {
int16_pool_refresh(entropy);
}
assert(entropy->int16_index < HASH_LEN_UINT16 * EPOOL_HASH_COUNT);
return entropy->int16_pool[entropy->int16_index++];
}
/* Random byte */
uint8_t entropy_random_uint8(entropy_t *entropy){
assert(entropy != NULL);
if (entropy->char_index >= SHA3_512_DIGEST_LENGTH * EPOOL_HASH_COUNT) {
char_pool_refresh(entropy);
}
assert(entropy->char_index < SHA3_512_DIGEST_LENGTH * EPOOL_HASH_COUNT);
return entropy->char_pool[entropy->char_index++];
}
/* Use previous function to refresh bit pool */
static void bit_pool_refresh(entropy_t *entropy) {
entropy->bit_pool = entropy_random_uint64(entropy);
entropy->bit_index = 0;
}
/* Get a random bit */
bool entropy_random_bit(entropy_t *entropy) {
bool bit;
assert(entropy != NULL);
if (entropy->bit_index >= 64) {
bit_pool_refresh(entropy);
}
bit = entropy->bit_pool & 1;
entropy->bit_pool >>= 1;
entropy->bit_index ++;
return bit;
}
/* Return n random bits
* - n must be no more than 32
* - the n bits are low-order bits of the returned integer. */
uint32_t entropy_random_bits(entropy_t* entropy, uint32_t n) {
uint32_t retval;
assert(entropy != NULL && n <= 32);
retval = 0;
while (n > 0) {
retval <<= 1;
retval |= entropy_random_bit(entropy);
n --;
}
return retval;
}
/* Initialize: with the given seed
* - seed must be an array of SHA3_512_DIGEST_LENGTH bytes */
void entropy_init(entropy_t *entropy, const uint8_t *seed) {
uint32_t i;
for (i=0; i<SHA3_512_DIGEST_LENGTH; i++) {
entropy->seed[i] = seed[i];
}
char_pool_refresh(entropy);
int16_pool_refresh(entropy);
int64_pool_refresh(entropy);
bit_pool_refresh(entropy);
}