#include #include #include #include #include #include #include #include #include #include #include "structs.h" static struct rng_state global_rng_state; __attribute__((visibility("default"))) bool initialize_states(){ assert( (sizeof(uint32_t) * CHAR_BIT) == 32 ); memset( (void*)&global_rng_state, 0, sizeof(struct rng_state) ); ssize_t state_bytes_read = 0; if ( (state_bytes_read = getrandom((void*)&global_rng_state.states, 16 * sizeof(uint32_t), GRND_NONBLOCK)) == -1 ) return false; if ( (size_t)state_bytes_read < (16 * sizeof(uint32_t)) ){ errno = EIO; return false; } global_rng_state.state_idx = global_rng_state.states[7] & 0x0f; errno = 0; return true; } __attribute__((visibility("default"))) uint32_t get_random_output(){ size_t use_state = global_rng_state.state_idx; global_rng_state.state_idx = global_rng_state.states[use_state] & 0x0f; if ( global_rng_state.gen_period_ctr >= 0xffffffff ){ global_rng_state.period_end_ctr++; if ( global_rng_state.period_end_ctr >= 16 ){ assert( initialize_states() == true ); global_rng_state.period_end_ctr = 0; } global_rng_state.gen_period_ctr = 0; } global_rng_state.gen_period_ctr++; global_rng_state.states[use_state] ^= global_rng_state.states[use_state] >> 11; global_rng_state.states[use_state] ^= global_rng_state.states[use_state] << 7; global_rng_state.states[use_state] ^= global_rng_state.states[use_state] >> 16; return global_rng_state.states[use_state] * OUTPUT_MULTIPLIER; } __attribute__((visibility("default"))) uint32_t get_uniform_uint( uint32_t min, uint32_t max ){ if ( max <= min ) return min; uint32_t ncount = (max - min) + 1; uint32_t upper_bound = 0xffffffff - (0xffffffff % ncount); uint32_t gen_output = get_random_output(); if ( gen_output > upper_bound ){ while ( gen_output > upper_bound ) gen_output = get_random_output(); } return (gen_output % max) + min; } __attribute__((visibility("default"))) void clear_rng_state(){ memset( (void*)&global_rng_state, 0, sizeof(struct rng_state) ); return; }