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 :
|