Skip to content

Commit 3b26db0

Browse files
committed
rng: Reduce seeding iterations, re-seed regularly
1 parent 021a35e commit 3b26db0

3 files changed

Lines changed: 51 additions & 28 deletions

File tree

api/kernel/rng.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,16 @@
2222

2323
#include <cstdlib>
2424
#include <cstdint>
25+
#include <delegate>
2526

2627
// Incorporate seed data into the system RNG state
2728
extern void rng_absorb(const void* input, size_t bytes);
2829

2930
// Extract output from the system RNG
3031
extern void rng_extract(void* output, size_t bytes);
3132

32-
// Try to reseed the RNG state somehow
33-
extern void rng_reseed();
33+
// Try to reseed the RNG state
34+
extern void rng_reseed_init(delegate<void(uint64_t*)>, int rounds);
3435

3536
// Extract 32 bit integer from system RNG
3637
inline uint32_t rng_extract_uint32()

src/kernel/rng.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,18 @@
2222
#include <algorithm>
2323
#include <cstring>
2424
#include <smp>
25+
#define SHAKE_128_RATE (1600-256)/8
2526

2627
struct alignas(SMP_ALIGN) rng_state
2728
{
2829
uint64_t state[25];
30+
int64_t reseed_counter = 0;
31+
int32_t reseed_rounds = 0;
32+
delegate<void(uint64_t*)> reseed_callback = nullptr;
2933
};
3034
static SMP::Array<rng_state> rng;
35+
// every RESEED_RATE bytes entropy is refilled
36+
static const int RESEED_RATE = 4096;
3137

3238
static inline uint64_t rotate_left(uint64_t input, size_t rot) {
3339
return (input << rot) | (input >> (64-rot));
@@ -114,8 +120,6 @@ static void keccak_1600_p(uint64_t A[25]) {
114120
}
115121
}
116122

117-
#define SHAKE_128_RATE (1600-256)/8
118-
119123
static inline void xor_bytes(const uint8_t* in, uint8_t* out, size_t bytes)
120124
{
121125
for(size_t i = 0; i != bytes; ++i)
@@ -137,7 +141,17 @@ void rng_absorb(const void* input, size_t bytes)
137141
keccak_1600_p(PER_CPU(rng).state);
138142
absorbed += absorbing;
139143
}
144+
PER_CPU(rng).reseed_counter += RESEED_RATE * bytes;
145+
}
146+
147+
static void reseed_now()
148+
{
149+
uint64_t value;
150+
for (int i = 0; i < PER_CPU(rng).reseed_rounds; i++) {
151+
PER_CPU(rng).reseed_callback(&value);
152+
rng_absorb(&value, sizeof(value));
140153
}
154+
}
141155

142156
void rng_extract(void* output, size_t bytes)
143157
{
@@ -150,4 +164,19 @@ void rng_extract(void* output, size_t bytes)
150164
keccak_1600_p(PER_CPU(rng).state);
151165
copied += copying;
152166
}
167+
// don't reseed if no callback to do so
168+
if (PER_CPU(rng).reseed_callback == nullptr) return;
169+
PER_CPU(rng).reseed_counter -= bytes;
170+
// reseed when below certain entropy
171+
if (PER_CPU(rng).reseed_counter < 0) {
172+
PER_CPU(rng).reseed_counter = 0;
173+
reseed_now();
174+
}
153175
}
176+
177+
void rng_reseed_init(delegate<void(uint64_t*)> func, int rounds)
178+
{
179+
PER_CPU(rng).reseed_callback = func;
180+
PER_CPU(rng).reseed_rounds = rounds;
181+
reseed_now();
182+
}

src/platform/x86_pc/rand.cpp

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,33 @@
33
#include <kernel/os.hpp>
44
#include <arch.hpp>
55
#include <kprint>
6-
extern "C" void intel_rdrand(void*);
7-
extern "C" void intel_rdseed(void*);
6+
extern "C" void intel_rdrand(uint64_t*);
7+
extern "C" void intel_rdseed(uint64_t*);
8+
9+
static void fallback_entropy(uint64_t* res)
10+
{
11+
uint64_t clock = (uint64_t) res;
12+
// this is horrible, better solution needed here
13+
for (int i = 0; i < 64; ++i) {
14+
clock += OS::cycles_since_boot();
15+
asm volatile("cpuid" ::: "memory", "eax", "ebx", "ecx", "edx");
16+
}
17+
// here we need to add our own bits
18+
*res = clock;
19+
}
820

921
// used to generate initial
1022
// entropy for a cryptographic randomness generator
1123
void RNG::init()
1224
{
1325
if (CPUID::has_feature(CPUID::Feature::RDSEED)) {
14-
for (int i = 0; i < 64 * 2; i++)
15-
{
16-
uintptr_t rdseed;
17-
intel_rdseed(&rdseed);
18-
rng_absorb(&rdseed, sizeof(rdseed));
19-
}
26+
rng_reseed_init(intel_rdseed, 2);
2027
}
2128
else if (CPUID::has_feature(CPUID::Feature::RDRAND)) {
22-
for (int i = 0; i < 64 * 5; i++)
23-
{
24-
uintptr_t rdrand;
25-
intel_rdrand(&rdrand);
26-
rng_absorb(&rdrand, sizeof(rdrand));
27-
}
29+
rng_reseed_init(intel_rdrand, 65);
2830
}
2931
else {
30-
for (int i = 0; i < 64 * 16; i++)
31-
{
32-
uint64_t clock = 0;
33-
// this is horrible, better solution needed here
34-
for (int i = 0; i < 64; ++i) {
35-
clock += OS::cycles_since_boot();
36-
asm volatile("cpuid" ::: "memory", "eax", "ebx", "ecx", "edx");
37-
}
38-
rng_absorb(&clock, sizeof(clock));
39-
}
32+
rng_reseed_init(fallback_entropy, 64*16);
4033
return;
4134
}
4235
assert(0 && "No randomness fallback");

0 commit comments

Comments
 (0)