Path: blob/main/contrib/libfido2/fuzz/uniform_random.c
39586 views
/*1* Copyright (c) 2008, Damien Miller <[email protected]>2*3* Permission to use, copy, modify, and distribute this software for any4* purpose with or without fee is hereby granted, provided that the above5* copyright notice and this permission notice appear in all copies.6*7* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES8* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF9* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR10* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES11* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN12* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF13* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.14*/1516#include <stdint.h>17#include <stdlib.h>1819uint32_t uniform_random(uint32_t);20unsigned long prng_uint32(void);2122/*23* Calculate a uniformly distributed random number less than upper_bound24* avoiding "modulo bias".25*26* Uniformity is achieved by generating new random numbers until the one27* returned is outside the range [0, 2**32 % upper_bound). This28* guarantees the selected random number will be inside29* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)30* after reduction modulo upper_bound.31*/32uint32_t33uniform_random(uint32_t upper_bound)34{35uint32_t r, min;3637if (upper_bound < 2)38return 0;3940/* 2**32 % x == (2**32 - x) % x */41min = -upper_bound % upper_bound;4243/*44* This could theoretically loop forever but each retry has45* p > 0.5 (worst case, usually far better) of selecting a46* number inside the range we need, so it should rarely need47* to re-roll.48*/49for (;;) {50r = (uint32_t)prng_uint32();51if (r >= min)52break;53}5455return r % upper_bound;56}575859