Skip to content

Commit

Permalink
rng: Reduce seeding iterations, re-seed regularly
Browse files Browse the repository at this point in the history
  • Loading branch information
fwsGonzo committed Mar 25, 2019
1 parent 021a35e commit 3b26db0
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 28 deletions.
5 changes: 3 additions & 2 deletions api/kernel/rng.hpp
Expand Up @@ -22,15 +22,16 @@

#include <cstdlib>
#include <cstdint>
#include <delegate>

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

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

// Try to reseed the RNG state somehow
extern void rng_reseed();
// Try to reseed the RNG state
extern void rng_reseed_init(delegate<void(uint64_t*)>, int rounds);

// Extract 32 bit integer from system RNG
inline uint32_t rng_extract_uint32()
Expand Down
33 changes: 31 additions & 2 deletions src/kernel/rng.cpp
Expand Up @@ -22,12 +22,18 @@
#include <algorithm>
#include <cstring>
#include <smp>
#define SHAKE_128_RATE (1600-256)/8

struct alignas(SMP_ALIGN) rng_state
{
uint64_t state[25];
int64_t reseed_counter = 0;
int32_t reseed_rounds = 0;
delegate<void(uint64_t*)> reseed_callback = nullptr;
};
static SMP::Array<rng_state> rng;
// every RESEED_RATE bytes entropy is refilled
static const int RESEED_RATE = 4096;

static inline uint64_t rotate_left(uint64_t input, size_t rot) {
return (input << rot) | (input >> (64-rot));
Expand Down Expand Up @@ -114,8 +120,6 @@ static void keccak_1600_p(uint64_t A[25]) {
}
}

#define SHAKE_128_RATE (1600-256)/8

static inline void xor_bytes(const uint8_t* in, uint8_t* out, size_t bytes)
{
for(size_t i = 0; i != bytes; ++i)
Expand All @@ -137,7 +141,17 @@ void rng_absorb(const void* input, size_t bytes)
keccak_1600_p(PER_CPU(rng).state);
absorbed += absorbing;
}
PER_CPU(rng).reseed_counter += RESEED_RATE * bytes;
}

static void reseed_now()
{
uint64_t value;
for (int i = 0; i < PER_CPU(rng).reseed_rounds; i++) {
PER_CPU(rng).reseed_callback(&value);
rng_absorb(&value, sizeof(value));
}
}

void rng_extract(void* output, size_t bytes)
{
Expand All @@ -150,4 +164,19 @@ void rng_extract(void* output, size_t bytes)
keccak_1600_p(PER_CPU(rng).state);
copied += copying;
}
// don't reseed if no callback to do so
if (PER_CPU(rng).reseed_callback == nullptr) return;
PER_CPU(rng).reseed_counter -= bytes;
// reseed when below certain entropy
if (PER_CPU(rng).reseed_counter < 0) {
PER_CPU(rng).reseed_counter = 0;
reseed_now();
}
}

void rng_reseed_init(delegate<void(uint64_t*)> func, int rounds)
{
PER_CPU(rng).reseed_callback = func;
PER_CPU(rng).reseed_rounds = rounds;
reseed_now();
}
41 changes: 17 additions & 24 deletions src/platform/x86_pc/rand.cpp
Expand Up @@ -3,40 +3,33 @@
#include <kernel/os.hpp>
#include <arch.hpp>
#include <kprint>
extern "C" void intel_rdrand(void*);
extern "C" void intel_rdseed(void*);
extern "C" void intel_rdrand(uint64_t*);
extern "C" void intel_rdseed(uint64_t*);

static void fallback_entropy(uint64_t* res)
{
uint64_t clock = (uint64_t) res;
// this is horrible, better solution needed here
for (int i = 0; i < 64; ++i) {
clock += OS::cycles_since_boot();
asm volatile("cpuid" ::: "memory", "eax", "ebx", "ecx", "edx");
}
// here we need to add our own bits
*res = clock;
}

// used to generate initial
// entropy for a cryptographic randomness generator
void RNG::init()
{
if (CPUID::has_feature(CPUID::Feature::RDSEED)) {
for (int i = 0; i < 64 * 2; i++)
{
uintptr_t rdseed;
intel_rdseed(&rdseed);
rng_absorb(&rdseed, sizeof(rdseed));
}
rng_reseed_init(intel_rdseed, 2);
}
else if (CPUID::has_feature(CPUID::Feature::RDRAND)) {
for (int i = 0; i < 64 * 5; i++)
{
uintptr_t rdrand;
intel_rdrand(&rdrand);
rng_absorb(&rdrand, sizeof(rdrand));
}
rng_reseed_init(intel_rdrand, 65);
}
else {
for (int i = 0; i < 64 * 16; i++)
{
uint64_t clock = 0;
// this is horrible, better solution needed here
for (int i = 0; i < 64; ++i) {
clock += OS::cycles_since_boot();
asm volatile("cpuid" ::: "memory", "eax", "ebx", "ecx", "edx");
}
rng_absorb(&clock, sizeof(clock));
}
rng_reseed_init(fallback_entropy, 64*16);
return;
}
assert(0 && "No randomness fallback");
Expand Down

0 comments on commit 3b26db0

Please sign in to comment.