tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

crypto_rand_numeric.c (5797B)


      1 /**
      2 * \file crypto_rand_numeric.c
      3 *
      4 * \brief Functions for retrieving uniformly distributed numbers
      5 *   from our PRNGs.
      6 **/
      7 
      8 #include "lib/crypt_ops/crypto_rand.h"
      9 #include "lib/log/util_bug.h"
     10 
     11 /**
     12 * Implementation macro: yields code that returns a uniform unbiased
     13 * random number between 0 and limit.  "type" is the type of the number to
     14 * return; "maxval" is the largest possible value of "type"; and "fill_stmt"
     15 * is a code snippet that fills an object named "val" with random bits.
     16 **/
     17 #define IMPLEMENT_RAND_UNSIGNED(type, maxval, limit, fill_stmt)         \
     18  do {                                                                  \
     19    type val;                                                           \
     20    type cutoff;                                                        \
     21    tor_assert((limit) > 0);                                            \
     22                                                                        \
     23    /* We ignore any values that are >= 'cutoff,' to avoid biasing */   \
     24    /* the distribution with clipping at the upper end of the type's */ \
     25    /* range. */                                                        \
     26    cutoff = (maxval) - ((maxval)%(limit));                             \
     27    while (1) {                                                         \
     28      fill_stmt;                                                        \
     29      if (val < cutoff)                                                 \
     30        return val % (limit);                                           \
     31    }                                                                   \
     32  } while (0)
     33 
     34 /**
     35 * Return a pseudorandom integer chosen uniformly from the values between 0
     36 * and <b>limit</b>-1 inclusive. limit must be strictly greater than 0, and
     37 * less than UINT_MAX. */
     38 unsigned
     39 crypto_rand_uint(unsigned limit)
     40 {
     41  tor_assert(limit < UINT_MAX);
     42  IMPLEMENT_RAND_UNSIGNED(unsigned, UINT_MAX, limit,
     43                          crypto_rand((char*)&val, sizeof(val)));
     44 }
     45 
     46 /**
     47 * Return a pseudorandom integer, chosen uniformly from the values
     48 * between 0 and <b>max</b>-1 inclusive.  <b>max</b> must be between 1 and
     49 * INT_MAX+1, inclusive.
     50 */
     51 int
     52 crypto_rand_int(unsigned int max)
     53 {
     54  /* We can't use IMPLEMENT_RAND_UNSIGNED directly, since we're trying
     55   * to return a signed type. Instead we make sure that the range is
     56   * reasonable for a nonnegative int, use crypto_rand_uint(), and cast.
     57   */
     58  tor_assert(max <= ((unsigned int)INT_MAX)+1);
     59 
     60  return (int)crypto_rand_uint(max);
     61 }
     62 
     63 /**
     64 * Return a pseudorandom integer, chosen uniformly from the values i such
     65 * that min <= i < max.
     66 *
     67 * <b>min</b> MUST be in range [0, <b>max</b>).
     68 * <b>max</b> MUST be in range (min, INT_MAX].
     69 **/
     70 int
     71 crypto_rand_int_range(unsigned int min, unsigned int max)
     72 {
     73  tor_assert(min < max);
     74  tor_assert(max <= INT_MAX);
     75 
     76  /* The overflow is avoided here because crypto_rand_int() returns a value
     77   * between 0 and (max - min) inclusive. */
     78  return min + crypto_rand_int(max - min);
     79 }
     80 
     81 /**
     82 * As crypto_rand_int_range, but supports uint64_t.
     83 **/
     84 uint64_t
     85 crypto_rand_uint64_range(uint64_t min, uint64_t max)
     86 {
     87  tor_assert(min < max);
     88  return min + crypto_rand_uint64(max - min);
     89 }
     90 
     91 /**
     92 * As crypto_rand_int_range, but supports time_t.
     93 **/
     94 time_t
     95 crypto_rand_time_range(time_t min, time_t max)
     96 {
     97  tor_assert(min < max);
     98  return min + (time_t)crypto_rand_uint64(max - min);
     99 }
    100 
    101 /**
    102 * Return a pseudorandom 64-bit integer, chosen uniformly from the values
    103 * between 0 and <b>max</b>-1 inclusive.
    104 **/
    105 uint64_t
    106 crypto_rand_uint64(uint64_t max)
    107 {
    108  tor_assert(max < UINT64_MAX);
    109  IMPLEMENT_RAND_UNSIGNED(uint64_t, UINT64_MAX, max,
    110                          crypto_rand((char*)&val, sizeof(val)));
    111 }
    112 
    113 #if SIZEOF_INT == 4
    114 #define UINT_MAX_AS_DOUBLE 4294967296.0
    115 #elif SIZEOF_INT == 8
    116 #define UINT_MAX_AS_DOUBLE 1.8446744073709552e+19
    117 #else
    118 #error SIZEOF_INT is neither 4 nor 8
    119 #endif /* SIZEOF_INT == 4 || ... */
    120 
    121 /**
    122 * Return a pseudorandom double d, chosen uniformly from the range
    123 * 0.0 <= d < 1.0.
    124 **/
    125 double
    126 crypto_rand_double(void)
    127 {
    128  /* We just use an unsigned int here; we don't really care about getting
    129   * more than 32 bits of resolution */
    130  unsigned int u;
    131  crypto_rand((char*)&u, sizeof(u));
    132  return ((double)u) / UINT_MAX_AS_DOUBLE;
    133 }
    134 
    135 /**
    136 * As crypto_rand_uint, but extract the result from a crypto_fast_rng_t
    137 */
    138 unsigned
    139 crypto_fast_rng_get_uint(crypto_fast_rng_t *rng, unsigned limit)
    140 {
    141  tor_assert(limit < UINT_MAX);
    142  IMPLEMENT_RAND_UNSIGNED(unsigned, UINT_MAX, limit,
    143                  crypto_fast_rng_getbytes(rng, (void*)&val, sizeof(val)));
    144 }
    145 
    146 /**
    147 * As crypto_rand_uint64, but extract the result from a crypto_fast_rng_t.
    148 */
    149 uint64_t
    150 crypto_fast_rng_get_uint64(crypto_fast_rng_t *rng, uint64_t limit)
    151 {
    152  tor_assert(limit < UINT64_MAX);
    153  IMPLEMENT_RAND_UNSIGNED(uint64_t, UINT64_MAX, limit,
    154                  crypto_fast_rng_getbytes(rng, (void*)&val, sizeof(val)));
    155 }
    156 
    157 /**
    158 * As crypto_rand_u32, but extract the result from a crypto_fast_rng_t.
    159 */
    160 uint32_t
    161 crypto_fast_rng_get_u32(crypto_fast_rng_t *rng)
    162 {
    163  uint32_t val;
    164  crypto_fast_rng_getbytes(rng, (void*)&val, sizeof(val));
    165  return val;
    166 }
    167 
    168 /**
    169 * As crypto_rand_uint64_range(), but extract the result from a
    170 * crypto_fast_rng_t.
    171 */
    172 uint64_t
    173 crypto_fast_rng_uint64_range(crypto_fast_rng_t *rng,
    174                             uint64_t min, uint64_t max)
    175 {
    176  /* Handle corrupted input */
    177  if (BUG(min >= max)) {
    178    return min;
    179  }
    180 
    181  return min + crypto_fast_rng_get_uint64(rng, max - min);
    182 }
    183 
    184 /**
    185 * As crypto_rand_get_double() but extract the result from a crypto_fast_rng_t.
    186 */
    187 double
    188 crypto_fast_rng_get_double(crypto_fast_rng_t *rng)
    189 {
    190  unsigned int u;
    191  crypto_fast_rng_getbytes(rng, (void*)&u, sizeof(u));
    192  return ((double)u) / UINT_MAX_AS_DOUBLE;
    193 }