diff --git a/random.c b/random.c index f58740e..ae242c4 100644 --- a/random.c +++ b/random.c @@ -18,7 +18,7 @@ static ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) { #endif static void get_random_seed(void *buf, size_t size) { - while (size > 0) { + while (size) { ssize_t r; do { @@ -54,6 +54,28 @@ static void refill(struct random_state *state) { } } +void get_random_bytes(struct random_state *state, void *buf, size_t size) { + // avoid needless copying to and from the cache as an optimization + if (size > RANDOM_CACHE_SIZE / 2) { + chacha_keystream_bytes(&state->ctx, buf, size); + return; + } + + while (size) { + if (state->index == RANDOM_CACHE_SIZE) { + refill(state); + } + + size_t remaining = RANDOM_CACHE_SIZE - state->index; + size_t copy_size = min(size, remaining); + memcpy(buf, state->cache + state->index, copy_size); + state->index += copy_size; + + buf = (char *)buf + copy_size; + size -= copy_size; + } +} + u16 get_random_u16(struct random_state *state) { u16 value; unsigned remaining = RANDOM_CACHE_SIZE - state->index; diff --git a/random.h b/random.h index 420797d..629b18a 100644 --- a/random.h +++ b/random.h @@ -15,6 +15,7 @@ struct random_state { }; void random_state_init(struct random_state *state); +void get_random_bytes(struct random_state *state, void *buf, size_t size); u16 get_random_u16(struct random_state *state); u16 get_random_u16_uniform(struct random_state *state, u16 bound); u64 get_random_u64(struct random_state *state);