diff options
Diffstat (limited to 'contrib/libottery')
-rw-r--r-- | contrib/libottery/CMakeLists.txt | 9 | ||||
-rw-r--r-- | contrib/libottery/chacha_cryptobox.c | 64 | ||||
-rw-r--r-- | contrib/libottery/ottery-internal.h | 8 | ||||
-rw-r--r-- | contrib/libottery/ottery-threading.h | 5 | ||||
-rw-r--r-- | contrib/libottery/ottery.c | 321 |
5 files changed, 245 insertions, 162 deletions
diff --git a/contrib/libottery/CMakeLists.txt b/contrib/libottery/CMakeLists.txt index a2b3d8c0a..3ea5658f3 100644 --- a/contrib/libottery/CMakeLists.txt +++ b/contrib/libottery/CMakeLists.txt @@ -2,8 +2,11 @@ SET(OTTERYSRC chacha_merged.c ottery.c ottery_cpuinfo.c ottery_entropy.c - ottery_global.c) + ottery_global.c chacha_cryptobox.c) ADD_LIBRARY(ottery STATIC ${OTTERYSRC}) + +SET(OTTERY_CFLAGS "-DBUILD_RSPAMD") if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") - set_target_properties(ottery PROPERTIES COMPILER_FLAGS "-O3") -endif ()
\ No newline at end of file + SET(OTTERY_CFLAGS "${OTTERY_CFLAGS} -O3") +endif () +set_target_properties(ottery PROPERTIES COMPILE_FLAGS "${OTTERY_CFLAGS}")
\ No newline at end of file diff --git a/contrib/libottery/chacha_cryptobox.c b/contrib/libottery/chacha_cryptobox.c new file mode 100644 index 000000000..ecbcccaf3 --- /dev/null +++ b/contrib/libottery/chacha_cryptobox.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ottery-internal.h" +#include "libcryptobox/chacha20/chacha.h" + +#define STATE_LEN (sizeof(chacha_state)) +#define STATE_BYTES 40 + +#define IDX_STEP 16 +#define OUTPUT_LEN (IDX_STEP * 64) + +static void +chacha_cryptobox_state_setup (void *state_, const uint8_t *bytes) +{ + chacha_state *x = state_; + chacha_init (x, (chacha_key *)bytes, (chacha_iv *)(bytes + 32), 20); +} + +static void +chacha20_cryptobox_generate (void *state_, uint8_t *output, uint32_t idx) +{ + chacha_state *x = state_; + + memset (output, 0, OUTPUT_LEN); + memcpy (output, &idx, sizeof (idx)); + chacha_update (x, output, output, OUTPUT_LEN); +} + +#define PRF_CHACHA(r) { \ + "CHACHA" #r, \ + "CHACHA" #r "-NOSIMD", \ + "CHACHA" #r "-NOSIMD-DEFAULT", \ + STATE_LEN, \ + STATE_BYTES, \ + OUTPUT_LEN, \ + 0, \ + chacha_cryptobox_state_setup, \ + chacha ## r ## _cryptobox_generate \ +} + +const struct ottery_prf ottery_prf_chacha20_cryptobox_ = PRF_CHACHA(20); diff --git a/contrib/libottery/ottery-internal.h b/contrib/libottery/ottery-internal.h index 24279043e..145c5e4a9 100644 --- a/contrib/libottery/ottery-internal.h +++ b/contrib/libottery/ottery-internal.h @@ -15,7 +15,11 @@ #define OTTERY_INTERNAL_H_HEADER_INCLUDED_ #include <stdint.h> #include <sys/types.h> + +#ifdef BUILD_RSPAMD #include "config.h" +#endif + #include "ottery-threading.h" @@ -300,6 +304,10 @@ void ottery_disable_cpu_capabilities_(uint32_t disable); extern const struct ottery_prf ottery_prf_chacha8_merged_; extern const struct ottery_prf ottery_prf_chacha12_merged_; extern const struct ottery_prf ottery_prf_chacha20_merged_; + +#ifdef BUILD_RSPAMD +extern const struct ottery_prf ottery_prf_chacha20_cryptobox_; +#endif /**@}*/ /** diff --git a/contrib/libottery/ottery-threading.h b/contrib/libottery/ottery-threading.h index 383d9cd83..c5427adae 100644 --- a/contrib/libottery/ottery-threading.h +++ b/contrib/libottery/ottery-threading.h @@ -14,6 +14,11 @@ #ifndef OTTERY_LOCKING_H_HEADER_INCLUDED_ #define OTTERY_LOCKING_H_HEADER_INCLUDED_ +/* We don't need locks when building rspamd */ +#ifdef BUILD_RSPAMD +#define OTTERY_NO_LOCKS +#endif + /* Locks */ #ifdef OTTERY_NO_LOCKS /* Nothing here. */ diff --git a/contrib/libottery/ottery.c b/contrib/libottery/ottery.c index fd20b1132..0b466c641 100644 --- a/contrib/libottery/ottery.c +++ b/contrib/libottery/ottery.c @@ -183,59 +183,62 @@ ottery_get_impl(const char *impl) &ottery_prf_chacha12_krovetz_1_, &ottery_prf_chacha8_krovetz_1_, #endif - &ottery_prf_chacha20_merged_, - &ottery_prf_chacha12_merged_, - &ottery_prf_chacha8_merged_, +#ifdef BUILD_RSPAMD + &ottery_prf_chacha20_cryptobox_, +#endif + &ottery_prf_chacha20_merged_, + &ottery_prf_chacha12_merged_, + &ottery_prf_chacha8_merged_, - NULL, + NULL, }; const uint32_t cap = ottery_get_cpu_capabilities_(); for (i = 0; ALL_PRFS[i]; ++i) { - const struct ottery_prf *prf = ALL_PRFS[i]; - if ((prf->required_cpucap & cap) != prf->required_cpucap) - continue; - if (impl == NULL) - return prf; - if (!strcmp(impl, prf->name)) - return prf; - if (!strcmp(impl, prf->impl)) - return prf; - if (!strcmp(impl, prf->flav)) - return prf; + const struct ottery_prf *prf = ALL_PRFS[i]; + if ((prf->required_cpucap & cap) != prf->required_cpucap) + continue; + if (impl == NULL) + return prf; + if (!strcmp(impl, prf->name)) + return prf; + if (!strcmp(impl, prf->impl)) + return prf; + if (!strcmp(impl, prf->flav)) + return prf; } return NULL; } int ottery_config_force_implementation(struct ottery_config *cfg, - const char *impl) + const char *impl) { const struct ottery_prf *prf = ottery_get_impl(impl); if (prf) { - cfg->impl = prf; - return 0; + cfg->impl = prf; + return 0; } return OTTERY_ERR_INVALID_ARGUMENT; } void ottery_config_set_manual_prf_(struct ottery_config *cfg, - const struct ottery_prf *prf) + const struct ottery_prf *prf) { cfg->impl = prf; } void ottery_config_set_urandom_device(struct ottery_config *cfg, - const char *fname) + const char *fname) { cfg->entropy_config.urandom_fname = fname; } void ottery_config_set_urandom_fd(struct ottery_config *cfg, - int fd) + int fd) { cfg->entropy_config.urandom_fd = fd; cfg->entropy_config.urandom_fd_is_set = (fd >= 0); @@ -243,8 +246,8 @@ ottery_config_set_urandom_fd(struct ottery_config *cfg, void ottery_config_set_egd_socket(struct ottery_config *cfg, - const struct sockaddr *addr, - int len) + const struct sockaddr *addr, + int len) { cfg->entropy_config.egd_sockaddr = addr; cfg->entropy_config.egd_socklen = len; @@ -252,18 +255,18 @@ ottery_config_set_egd_socket(struct ottery_config *cfg, void ottery_config_disable_entropy_sources(struct ottery_config *cfg, - uint32_t disabled_sources) + uint32_t disabled_sources) { cfg->entropy_config.disabled_sources = - (disabled_sources & OTTERY_ENTROPY_ALL_SOURCES); + (disabled_sources & OTTERY_ENTROPY_ALL_SOURCES); } void ottery_config_mark_entropy_sources_weak(struct ottery_config *cfg, - uint32_t disabled_sources) + uint32_t disabled_sources) { cfg->entropy_config.weak_sources = - (disabled_sources & OTTERY_ENTROPY_ALL_SOURCES); + (disabled_sources & OTTERY_ENTROPY_ALL_SOURCES); } /** @@ -307,8 +310,8 @@ ottery_st_nextblock_nolock(struct ottery_state_nolock *st) */ static int ottery_st_initialize(struct ottery_state *st, - const struct ottery_config *config, - int locked) + const struct ottery_config *config, + int locked) { const struct ottery_prf *prf = NULL; struct ottery_config cfg_tmp; @@ -317,46 +320,46 @@ ottery_st_initialize(struct ottery_state *st, * error now, and not a crash when the SIMD instructions start to fail. */ if (((uintptr_t)st) & 0xf) - return OTTERY_ERR_STATE_ALIGNMENT; + return OTTERY_ERR_STATE_ALIGNMENT; if (!config) { - ottery_config_init(&cfg_tmp); - config = &cfg_tmp; + ottery_config_init(&cfg_tmp); + config = &cfg_tmp; } prf = config->impl; if (!prf) - prf = ottery_get_impl(NULL); + prf = ottery_get_impl(NULL); memset(st, 0, sizeof(*st)); if (locked) { - /* Now set up the spinlock or mutex or hybrid thing. */ - if (INIT_LOCK(&st->mutex)) - return OTTERY_ERR_LOCK_INIT; + /* Now set up the spinlock or mutex or hybrid thing. */ + if (INIT_LOCK(&st->mutex)) + return OTTERY_ERR_LOCK_INIT; } /* Check invariants for PRF, in case we wrote some bad code. */ if ((prf->state_len > MAX_STATE_LEN) || - (prf->state_bytes > MAX_STATE_BYTES) || - (prf->state_bytes > prf->output_len) || - (prf->output_len > MAX_OUTPUT_LEN)) - return OTTERY_ERR_INTERNAL; + (prf->state_bytes > MAX_STATE_BYTES) || + (prf->state_bytes > prf->output_len) || + (prf->output_len > MAX_OUTPUT_LEN)) + return OTTERY_ERR_INTERNAL; /* Check whether some of our structure size assumptions are right. */ if ((sizeof(struct ottery_state) > OTTERY_STATE_DUMMY_SIZE_) || - (sizeof(struct ottery_config) > OTTERY_CONFIG_DUMMY_SIZE_)) - return OTTERY_ERR_INTERNAL; + (sizeof(struct ottery_config) > OTTERY_CONFIG_DUMMY_SIZE_)) + return OTTERY_ERR_INTERNAL; memcpy(&st->entropy_config, &config->entropy_config, - sizeof(struct ottery_entropy_config)); + sizeof(struct ottery_entropy_config)); /* Copy the PRF into place. */ memcpy(&st->prf, prf, sizeof(*prf)); if ((err = ottery_st_reseed(st))) - return err; + return err; /* Set the magic number last, or else we might look like we succeeded * when we didn't */ @@ -378,24 +381,24 @@ ottery_st_reseed(struct ottery_state *st) size_t buflen = ottery_get_entropy_bufsize_(st->prf.state_bytes); uint8_t *buf = alloca(buflen); if (!buf) - return OTTERY_ERR_INIT_STRONG_RNG; + return OTTERY_ERR_INIT_STRONG_RNG; if ((err = ottery_get_entropy_(&st->entropy_config, &st->entropy_state, 0, - buf, st->prf.state_bytes, - &buflen, - &flags))) - return err; + buf, st->prf.state_bytes, + &buflen, + &flags))) + return err; if (buflen < st->prf.state_bytes) - return OTTERY_ERR_ACCESS_STRONG_RNG; + return OTTERY_ERR_ACCESS_STRONG_RNG; /* The first state_bytes bytes become the initial key. */ st->prf.setup(st->state, buf); /* If there are more bytes, we mix them into the key with add_seed */ if (buflen > st->prf.state_bytes) - ottery_st_add_seed_impl(st, - buf + st->prf.state_bytes, - buflen - st->prf.state_bytes, - 0, - 0); + ottery_st_add_seed_impl(st, + buf + st->prf.state_bytes, + buflen - st->prf.state_bytes, + 0, + 0); ottery_memclear_(buf, buflen); st->last_entropy_flags = flags; st->entropy_src_flags = flags; @@ -415,7 +418,7 @@ ottery_st_init(struct ottery_state *st, const struct ottery_config *cfg) int ottery_st_init_nolock(struct ottery_state_nolock *st, - const struct ottery_config *cfg) + const struct ottery_config *cfg) { return ottery_st_initialize(st, cfg, 0); } @@ -425,8 +428,8 @@ ottery_st_add_seed_impl(struct ottery_state *st, const uint8_t *seed, size_t n, { #ifndef OTTERY_NO_INIT_CHECK if (check_magic && UNLIKELY(st->magic != MAGIC(st))) { - ottery_fatal_error_(OTTERY_ERR_STATE_INIT); - return OTTERY_ERR_STATE_INIT; + ottery_fatal_error_(OTTERY_ERR_STATE_INIT); + return OTTERY_ERR_STATE_INIT; } #endif @@ -437,40 +440,40 @@ ottery_st_add_seed_impl(struct ottery_state *st, const uint8_t *seed, size_t n, uint32_t flags = 0; if (!seed || !n) { - int err; - tmp_seed_len = ottery_get_entropy_bufsize_(st->prf.state_bytes); - tmp_seed = alloca(tmp_seed_len); - if (!tmp_seed) - return OTTERY_ERR_INIT_STRONG_RNG; - n = tmp_seed_len; - if ((err = ottery_get_entropy_(&st->entropy_config, &st->entropy_state, 0, - tmp_seed, st->prf.state_bytes, - &n, - &flags))) - return err; - if (n < st->prf.state_bytes) - return OTTERY_ERR_ACCESS_STRONG_RNG; - seed = tmp_seed; + int err; + tmp_seed_len = ottery_get_entropy_bufsize_(st->prf.state_bytes); + tmp_seed = alloca(tmp_seed_len); + if (!tmp_seed) + return OTTERY_ERR_INIT_STRONG_RNG; + n = tmp_seed_len; + if ((err = ottery_get_entropy_(&st->entropy_config, &st->entropy_state, 0, + tmp_seed, st->prf.state_bytes, + &n, + &flags))) + return err; + if (n < st->prf.state_bytes) + return OTTERY_ERR_ACCESS_STRONG_RNG; + seed = tmp_seed; } if (locking) - LOCK(st); + LOCK(st); /* The algorithm here is really easy. We grab a block of output from the * PRNG, that the first (state_bytes) bytes of that, XOR it with up to * (state_bytes) bytes of our new seed data, and use that to set our new * state. We do this over and over until we have no more seed data to add. */ while (n) { - unsigned i; - size_t m = n > st->prf.state_bytes/2 ? st->prf.state_bytes/2 : n; - ottery_st_nextblock_nolock_norekey(st); - for (i = 0; i < m; ++i) { - st->buffer[i] ^= seed[i]; - } - st->prf.setup(st->state, st->buffer); - st->block_counter = 0; - n -= m; - seed += m; + unsigned i; + size_t m = n > st->prf.state_bytes/2 ? st->prf.state_bytes/2 : n; + ottery_st_nextblock_nolock_norekey(st); + for (i = 0; i < m; ++i) { + st->buffer[i] ^= seed[i]; + } + st->prf.setup(st->state, st->buffer); + st->block_counter = 0; + n -= m; + seed += m; } /* Now make sure that st->buffer is set up with the new state. */ @@ -480,11 +483,11 @@ ottery_st_add_seed_impl(struct ottery_state *st, const uint8_t *seed, size_t n, st->last_entropy_flags = flags; if (locking) - UNLOCK(st); + UNLOCK(st); /* If we used stack-allocated seed material, wipe it. */ if (tmp_seed) - ottery_memclear_(tmp_seed, tmp_seed_len); + ottery_memclear_(tmp_seed, tmp_seed_len); return 0; } @@ -541,9 +544,9 @@ void ottery_fatal_error_(int error) { if (ottery_fatal_handler) - ottery_fatal_handler(error); + ottery_fatal_handler(error); else - abort(); + abort(); } void @@ -561,8 +564,8 @@ ottery_st_rand_check_init(struct ottery_state *st) { #ifndef OTTERY_NO_INIT_CHECK if (UNLIKELY(st->magic != MAGIC(st))) { - ottery_fatal_error_(OTTERY_ERR_STATE_INIT); - return -1; + ottery_fatal_error_(OTTERY_ERR_STATE_INIT); + return -1; } #else (void)st; @@ -576,12 +579,12 @@ ottery_st_rand_check_pid(struct ottery_state *st) { #ifndef OTTERY_NO_PID_CHECK if (UNLIKELY(st->pid != getpid())) { - int err; - if ((err = ottery_st_reseed(st))) { - ottery_fatal_error_(OTTERY_ERR_FLAG_POSTFORK_RESEED|err); - return -1; - } - st->pid = getpid(); + int err; + if ((err = ottery_st_reseed(st))) { + ottery_fatal_error_(OTTERY_ERR_FLAG_POSTFORK_RESEED|err); + return -1; + } + st->pid = getpid(); } #else (void) st; @@ -593,11 +596,11 @@ static inline int ottery_st_rand_lock_and_check(struct ottery_state *st) { if (ottery_st_rand_check_init(st)) - return -1; + return -1; LOCK(st); if (ottery_st_rand_check_pid(st)) { - UNLOCK(st); - return -1; + UNLOCK(st); + return -1; } return 0; } @@ -606,9 +609,9 @@ static inline int ottery_st_rand_check_nolock(struct ottery_state_nolock *st) { if (ottery_st_rand_check_init(st)) - return -1; + return -1; if (ottery_st_rand_check_pid(st)) - return -1; + return -1; return 0; } @@ -624,36 +627,36 @@ ottery_st_rand_check_nolock(struct ottery_state_nolock *st) */ static inline void ottery_st_rand_bytes_from_buf(struct ottery_state *st, uint8_t *out, - size_t n) + size_t n) { if (n + st->pos < st->prf.output_len) { - memcpy(out, st->buffer+st->pos, n); - CLEARBUF(st->buffer+st->pos, n); - st->pos += n; + memcpy(out, st->buffer+st->pos, n); + CLEARBUF(st->buffer+st->pos, n); + st->pos += n; } else { - unsigned cpy = st->prf.output_len - st->pos; - memcpy(out, st->buffer+st->pos, cpy); - n -= cpy; - out += cpy; - ottery_st_nextblock_nolock(st); - memcpy(out, st->buffer+st->pos, n); - CLEARBUF(st->buffer, n); - st->pos += n; - assert(st->pos < st->prf.output_len); + unsigned cpy = st->prf.output_len - st->pos; + memcpy(out, st->buffer+st->pos, cpy); + n -= cpy; + out += cpy; + ottery_st_nextblock_nolock(st); + memcpy(out, st->buffer+st->pos, n); + CLEARBUF(st->buffer, n); + st->pos += n; + assert(st->pos < st->prf.output_len); } } static void ottery_st_rand_bytes_impl(struct ottery_state *st, void *out_, - size_t n) + size_t n) { uint8_t *out = out_; size_t cpy; if (n + st->pos < st->prf.output_len * 2 - st->prf.state_bytes - 1) { - /* Fulfill it all from the buffer simply if possible. */ - ottery_st_rand_bytes_from_buf(st, out, n); - return; + /* Fulfill it all from the buffer simply if possible. */ + ottery_st_rand_bytes_from_buf(st, out, n); + return; } /* Okay. That's not going to happen. Well, take what we can... */ @@ -664,15 +667,15 @@ ottery_st_rand_bytes_impl(struct ottery_state *st, void *out_, /* Then take whole blocks so long as we need them, without stirring... */ while (n >= st->prf.output_len) { - /* (We could save a memcpy here if we generated the block directly at out - * rather than doing the memcpy here. First we'd need to make sure that we - * had gotten the block aligned to a 16-byte boundary, though, and we'd - * have some other tricky bookkeeping to do. Let's call this good enough - * for now.) */ - ottery_st_nextblock_nolock_norekey(st); - memcpy(out, st->buffer, st->prf.output_len); - out += st->prf.output_len; - n -= st->prf.output_len; + /* (We could save a memcpy here if we generated the block directly at out + * rather than doing the memcpy here. First we'd need to make sure that we + * had gotten the block aligned to a 16-byte boundary, though, and we'd + * have some other tricky bookkeeping to do. Let's call this good enough + * for now.) */ + ottery_st_nextblock_nolock_norekey(st); + memcpy(out, st->buffer, st->prf.output_len); + out += st->prf.output_len; + n -= st->prf.output_len; } /* Then stir for the last part. */ @@ -684,7 +687,7 @@ void ottery_st_rand_bytes(struct ottery_state *st, void *out_, size_t n) { if (ottery_st_rand_lock_and_check(st)) - return; + return; ottery_st_rand_bytes_impl(st, out_, n); UNLOCK(st); } @@ -693,7 +696,7 @@ void ottery_st_rand_bytes_nolock(struct ottery_state_nolock *st, void *out_, size_t n) { if (ottery_st_rand_check_nolock(st)) - return; + return; ottery_st_rand_bytes_impl(st, out_, n); } @@ -705,7 +708,7 @@ ottery_st_rand_bytes_nolock(struct ottery_state_nolock *st, void *out_, size_t n * @param p a pointer to the bytes to read from. **/ #define INT_ASSIGN_PTR(type, r, p) do { \ - memcpy(&r, p, sizeof(type)); \ + memcpy(&r, p, sizeof(type)); \ } while (0) /** @@ -715,38 +718,38 @@ ottery_st_rand_bytes_nolock(struct ottery_state_nolock *st, void *out_, size_t n * @param inttype The type of integer to generate. **/ #define OTTERY_RETURN_RAND_INTTYPE_IMPL(st, inttype, unlock) do { \ - inttype result; \ - if (sizeof(inttype) + (st)->pos <= (st)->prf.output_len) { \ - INT_ASSIGN_PTR(inttype, result, (st)->buffer + (st)->pos); \ - CLEARBUF((st)->buffer + (st)->pos, sizeof(inttype)); \ - (st)->pos += sizeof(inttype); \ - if (st->pos == (st)->prf.output_len) { \ - ottery_st_nextblock_nolock(st); \ - } \ - } else { \ - /* Our handling of this case here is significantly simpler */ \ - /* than that of ottery_st_rand_bytes_from_buf, at the expense */ \ - /* of wasting up to sizeof(inttype)-1 bytes. Since inttype */ \ - /* is at most 8 bytes long, that's not such a big deal. */ \ - ottery_st_nextblock_nolock(st); \ - INT_ASSIGN_PTR(inttype, result, (st)->buffer + (st)->pos); \ - CLEARBUF((st)->buffer, sizeof(inttype)); \ - (st)->pos += sizeof(inttype); \ - } \ - unlock; \ - return result; \ + inttype result; \ + if (sizeof(inttype) + (st)->pos <= (st)->prf.output_len) { \ + INT_ASSIGN_PTR(inttype, result, (st)->buffer + (st)->pos); \ + CLEARBUF((st)->buffer + (st)->pos, sizeof(inttype)); \ + (st)->pos += sizeof(inttype); \ + if (st->pos == (st)->prf.output_len) { \ + ottery_st_nextblock_nolock(st); \ + } \ + } else { \ + /* Our handling of this case here is significantly simpler */ \ + /* than that of ottery_st_rand_bytes_from_buf, at the expense */ \ + /* of wasting up to sizeof(inttype)-1 bytes. Since inttype */ \ + /* is at most 8 bytes long, that's not such a big deal. */ \ + ottery_st_nextblock_nolock(st); \ + INT_ASSIGN_PTR(inttype, result, (st)->buffer + (st)->pos); \ + CLEARBUF((st)->buffer, sizeof(inttype)); \ + (st)->pos += sizeof(inttype); \ + } \ + unlock; \ + return result; \ } while (0) #define OTTERY_RETURN_RAND_INTTYPE(st, inttype) do { \ - if (ottery_st_rand_lock_and_check(st)) \ - return (inttype)0; \ - OTTERY_RETURN_RAND_INTTYPE_IMPL(st, inttype, UNLOCK(st)); \ + if (ottery_st_rand_lock_and_check(st)) \ + return (inttype)0; \ + OTTERY_RETURN_RAND_INTTYPE_IMPL(st, inttype, UNLOCK(st)); \ } while (0) #define OTTERY_RETURN_RAND_INTTYPE_NOLOCK(st, inttype) do { \ - if (ottery_st_rand_check_nolock(st)) \ - return (inttype)0; \ - OTTERY_RETURN_RAND_INTTYPE_IMPL(st, inttype, ); \ + if (ottery_st_rand_check_nolock(st)) \ + return (inttype)0; \ + OTTERY_RETURN_RAND_INTTYPE_IMPL(st, inttype, ); \ } while (0) unsigned @@ -792,7 +795,7 @@ ottery_st_rand_range_nolock(struct ottery_state_nolock *st, unsigned upper) unsigned divisor = lim ? (UINT_MAX / lim) : 1; unsigned n; do { - n = (ottery_st_rand_unsigned_nolock(st) / divisor); + n = (ottery_st_rand_unsigned_nolock(st) / divisor); } while (n > upper); return n; @@ -805,7 +808,7 @@ ottery_st_rand_range64_nolock(struct ottery_state_nolock *st, uint64_t upper) uint64_t divisor = lim ? (UINT64_MAX / lim) : 1; uint64_t n; do { - n = (ottery_st_rand_uint64_nolock(st) / divisor); + n = (ottery_st_rand_uint64_nolock(st) / divisor); } while (n > upper); return n; @@ -816,7 +819,7 @@ ottery_st_rand_range(struct ottery_state *state, unsigned upper) { unsigned n; if (ottery_st_rand_check_init(state)) - return 0; + return 0; LOCK(state); n = ottery_st_rand_range_nolock(state, upper); UNLOCK(state); @@ -828,7 +831,7 @@ ottery_st_rand_range64(struct ottery_state *state, uint64_t upper) { uint64_t n; if (ottery_st_rand_check_init(state)) - return 0; + return 0; LOCK(state); n = ottery_st_rand_range64_nolock(state, upper); UNLOCK(state); |