manually specialize the CSPRNG cache
parent
c41e659383
commit
700e06c2db
44
random.c
44
random.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
1
random.h
1
random.h
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue