Tor  0.4.3.0-alpha-dev
crypto_rand_numeric.c
Go to the documentation of this file.
1 /**
2  * \file crypto_rand_numeric.c
3  *
4  * \brief Functions for retrieving uniformly distributed numbers
5  * from our PRNGs.
6  **/
7 
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 between 0 and
37  * 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
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
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
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
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
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
189 {
190  unsigned int u;
191  crypto_fast_rng_getbytes(rng, (void*)&u, sizeof(u));
192  return ((double)u) / UINT_MAX_AS_DOUBLE;
193 }
194 
unsigned crypto_fast_rng_get_uint(crypto_fast_rng_t *rng, unsigned limit)
void crypto_rand(char *to, size_t n)
Definition: crypto_rand.c:477
Common functions for using (pseudo-)random number generators.
unsigned crypto_rand_uint(unsigned limit)
#define IMPLEMENT_RAND_UNSIGNED(type, maxval, limit, fill_stmt)
uint64_t crypto_fast_rng_uint64_range(crypto_fast_rng_t *rng, uint64_t min, uint64_t max)
double crypto_rand_double(void)
time_t crypto_rand_time_range(time_t min, time_t max)
uint64_t crypto_fast_rng_get_uint64(crypto_fast_rng_t *rng, uint64_t limit)
#define tor_assert(expr)
Definition: util_bug.h:102
uint64_t crypto_rand_uint64(uint64_t max)
int crypto_rand_int_range(unsigned int min, unsigned int max)
void crypto_fast_rng_getbytes(crypto_fast_rng_t *rng, uint8_t *out, size_t n)
int crypto_rand_int(unsigned int max)
uint32_t crypto_fast_rng_get_u32(crypto_fast_rng_t *rng)
double crypto_fast_rng_get_double(crypto_fast_rng_t *rng)
uint64_t crypto_rand_uint64_range(uint64_t min, uint64_t max)
Macros to manage assertions, fatal and non-fatal.