diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2015-03-08 11:10:45 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2015-03-08 11:10:45 +0100 |
commit | 6c50033dfb7a4dc7094d96f9339459b08b4efac9 (patch) | |
tree | b3c8032d95620c2eb009273adb675c699b8a5a94 /src/kernel/core/prng.c | |
parent | 88636d28b812e425c51be2d4d24d16a504dae147 (diff) | |
download | kogata-6c50033dfb7a4dc7094d96f9339459b08b4efac9.tar.gz kogata-6c50033dfb7a4dc7094d96f9339459b08b4efac9.zip |
Add PRNG
Diffstat (limited to 'src/kernel/core/prng.c')
-rw-r--r-- | src/kernel/core/prng.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/src/kernel/core/prng.c b/src/kernel/core/prng.c new file mode 100644 index 0000000..d4307b6 --- /dev/null +++ b/src/kernel/core/prng.c @@ -0,0 +1,38 @@ +#include <prng.h> + +#define EPOOLSIZE 2048 + +static uint32_t x = 211; +static int n = 0; +static char entropy[EPOOLSIZE]; +static int entropy_count = 0; +static const uint32_t a = 16807; +static const uint32_t m = 0x7FFFFFFF; + +uint16_t prng_word() { + if (++n == 100) { + n = 0; + if (entropy_count) { + entropy_count--; + x += entropy[entropy_count]; + } + } + x = (x * a) % m; + return x & 0xFFFF; +} + +void prng_bytes(uint8_t* out, size_t nbytes) { + uint16_t *d = (uint16_t*)out; + for (size_t i = 0; i < nbytes / 2; i++) { + d[i] = prng_word(); + } + if (nbytes & 1) out[nbytes-1] = prng_word() & 0xFF; +} + +void prng_add_entropy(const uint8_t* ptr, size_t nbytes) { + while (nbytes-- && entropy_count < EPOOLSIZE - 1) { + entropy[entropy_count++] = *(ptr++); + } +} + +/* vim: set ts=4 sw=4 tw=0 noet :*/ |