LCOV - code coverage report
Current view: top level - lib/crypt_ops - crypto_rand_numeric.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 40 41 97.6 %
Date: 2021-11-24 03:28:48 Functions: 12 12 100.0 %

          Line data    Source code
       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       72701 : crypto_rand_uint(unsigned limit)
      40             : {
      41       72701 :   tor_assert(limit < UINT_MAX);
      42       72790 :   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       72701 : 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       72701 :   tor_assert(max <= ((unsigned int)INT_MAX)+1);
      59             : 
      60       72701 :   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        5008 : crypto_rand_int_range(unsigned int min, unsigned int max)
      72             : {
      73        5008 :   tor_assert(min < max);
      74        5008 :   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        5008 :   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        1000 : crypto_rand_uint64_range(uint64_t min, uint64_t max)
      86             : {
      87        1000 :   tor_assert(min < max);
      88        1000 :   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        7131 : crypto_rand_time_range(time_t min, time_t max)
      96             : {
      97        7131 :   tor_assert(min < max);
      98        7131 :   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       60287 : crypto_rand_uint64(uint64_t max)
     107             : {
     108       60287 :   tor_assert(max < UINT64_MAX);
     109       60397 :   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        4202 : 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        4202 :   unsigned int u;
     131        4202 :   crypto_rand((char*)&u, sizeof(u));
     132        4202 :   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       71076 : crypto_fast_rng_get_uint(crypto_fast_rng_t *rng, unsigned limit)
     140             : {
     141       71076 :   tor_assert(limit < UINT_MAX);
     142       71076 :   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         336 : crypto_fast_rng_get_uint64(crypto_fast_rng_t *rng, uint64_t limit)
     151             : {
     152         336 :   tor_assert(limit < UINT64_MAX);
     153         336 :   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    12602642 : crypto_fast_rng_get_u32(crypto_fast_rng_t *rng)
     162             : {
     163    12602642 :   uint32_t val;
     164    12602642 :   crypto_fast_rng_getbytes(rng, (void*)&val, sizeof(val));
     165    12602642 :   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          36 : crypto_fast_rng_uint64_range(crypto_fast_rng_t *rng,
     174             :                              uint64_t min, uint64_t max)
     175             : {
     176             :   /* Handle corrupted input */
     177          36 :   if (BUG(min >= max)) {
     178           0 :     return min;
     179             :   }
     180             : 
     181          36 :   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         128 : crypto_fast_rng_get_double(crypto_fast_rng_t *rng)
     189             : {
     190         128 :   unsigned int u;
     191         128 :   crypto_fast_rng_getbytes(rng, (void*)&u, sizeof(u));
     192         128 :   return ((double)u) / UINT_MAX_AS_DOUBLE;
     193             : }
     194             : 

Generated by: LCOV version 1.14