manually specialize the CSPRNG cache

pull/50/head
Daniel Micay 2018-08-26 00:02:35 -04:00
parent c41e659383
commit 700e06c2db
2 changed files with 20 additions and 25 deletions

View File

@ -48,33 +48,24 @@ void random_state_init(struct random_state *state) {
state->reseed = 0; state->reseed = 0;
} }
void get_random_bytes(struct random_state *state, void *buf, size_t size) { static void refill(struct random_state *state) {
if (size > RANDOM_CACHE_SIZE / 2) { if (state->reseed < RANDOM_RESEED_SIZE) {
chacha_keystream_bytes(&state->ctx, state->cache, RANDOM_CACHE_SIZE); chacha_keystream_bytes(&state->ctx, state->cache, RANDOM_CACHE_SIZE);
return; state->index = 0;
} state->reseed += RANDOM_CACHE_SIZE;
} else {
while (size) { random_state_init(state);
if (state->index == RANDOM_CACHE_SIZE) {
if (state->reseed >= RANDOM_RESEED_SIZE) {
random_state_init(state);
} else {
chacha_keystream_bytes(&state->ctx, state->cache, RANDOM_CACHE_SIZE);
state->index = 0;
state->reseed += RANDOM_CACHE_SIZE;
}
}
size_t remaining = RANDOM_CACHE_SIZE - state->index;
size_t copy_size = size < remaining ? size : remaining;
memcpy(buf, state->cache + state->index, copy_size);
state->index += copy_size;
size -= copy_size;
} }
} }
uint16_t get_random_u16(struct random_state *state) { uint16_t get_random_u16(struct random_state *state) {
uint16_t value; uint16_t value;
get_random_bytes(state, &value, sizeof(value)); size_t remaining = RANDOM_CACHE_SIZE - state->index;
if (remaining < sizeof(value)) {
refill(state);
}
memcpy(&value, state->cache + state->index, sizeof(value));
state->index += sizeof(value);
return value; return value;
} }
@ -89,14 +80,19 @@ uint16_t get_random_u16_uniform(struct random_state *state, uint16_t bound) {
uint16_t r; uint16_t r;
do { do {
r = get_random_u16(state); r = get_random_u16(state);
} while (r < min); } while (unlikely(r < min));
return r % bound; return r % bound;
} }
uint64_t get_random_u64(struct random_state *state) { uint64_t get_random_u64(struct random_state *state) {
uint64_t value; uint64_t value;
get_random_bytes(state, &value, sizeof(value)); size_t remaining = RANDOM_CACHE_SIZE - state->index;
if (remaining < sizeof(value)) {
refill(state);
}
memcpy(&value, state->cache + state->index, sizeof(value));
state->index += sizeof(value);
return value; return value;
} }
@ -111,7 +107,7 @@ uint64_t get_random_u64_uniform(struct random_state *state, uint64_t bound) {
uint64_t r; uint64_t r;
do { do {
r = get_random_u64(state); r = get_random_u64(state);
} while (r < min); } while (unlikely(r < min));
return r % bound; return r % bound;
} }

View File

@ -16,7 +16,6 @@ struct random_state {
}; };
void random_state_init(struct random_state *state); void random_state_init(struct random_state *state);
void get_random_bytes(struct random_state *state, void *buf, size_t size);
uint16_t get_random_u16(struct random_state *state); uint16_t get_random_u16(struct random_state *state);
uint16_t get_random_u16_uniform(struct random_state *state, uint16_t bound); uint16_t get_random_u16_uniform(struct random_state *state, uint16_t bound);
uint64_t get_random_u64(struct random_state *state); uint64_t get_random_u64(struct random_state *state);