aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_random.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/crypto_random.c')
-rw-r--r--src/util/crypto_random.c283
1 files changed, 148 insertions, 135 deletions
diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c
index 58cab082e..d16ba2412 100644
--- a/src/util/crypto_random.c
+++ b/src/util/crypto_random.c
@@ -17,7 +17,7 @@
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19 19
20*/ 20 */
21 21
22/** 22/**
23 * @file util/crypto_random.c 23 * @file util/crypto_random.c
@@ -28,23 +28,23 @@
28#include "gnunet_crypto_lib.h" 28#include "gnunet_crypto_lib.h"
29#include <gcrypt.h> 29#include <gcrypt.h>
30 30
31#define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-random", __VA_ARGS__) 31#define LOG(kind, ...) GNUNET_log_from(kind, "util-crypto-random", __VA_ARGS__)
32 32
33#define LOG_STRERROR(kind, syscall) \ 33#define LOG_STRERROR(kind, syscall) \
34 GNUNET_log_from_strerror (kind, "util-crypto-random", syscall) 34 GNUNET_log_from_strerror(kind, "util-crypto-random", syscall)
35 35
36 36
37/* TODO: ndurner, move this to plibc? */ 37/* TODO: ndurner, move this to plibc? */
38/* The code is derived from glibc, obviously */ 38/* The code is derived from glibc, obviously */
39#if ! HAVE_RANDOM || ! HAVE_SRANDOM 39#if !HAVE_RANDOM || !HAVE_SRANDOM
40#ifdef RANDOM 40#ifdef RANDOM
41#undef RANDOM 41#undef RANDOM
42#endif 42#endif
43#ifdef SRANDOM 43#ifdef SRANDOM
44#undef SRANDOM 44#undef SRANDOM
45#endif 45#endif
46#define RANDOM() glibc_weak_rand32 () 46#define RANDOM() glibc_weak_rand32()
47#define SRANDOM(s) glibc_weak_srand32 (s) 47#define SRANDOM(s) glibc_weak_srand32(s)
48#if defined(RAND_MAX) 48#if defined(RAND_MAX)
49#undef RAND_MAX 49#undef RAND_MAX
50#endif 50#endif
@@ -55,14 +55,14 @@ static int32_t glibc_weak_rand32_state = 1;
55 55
56 56
57void 57void
58glibc_weak_srand32 (int32_t s) 58glibc_weak_srand32(int32_t s)
59{ 59{
60 glibc_weak_rand32_state = s; 60 glibc_weak_rand32_state = s;
61} 61}
62 62
63 63
64int32_t 64int32_t
65glibc_weak_rand32 () 65glibc_weak_rand32()
66{ 66{
67 int32_t val = glibc_weak_rand32_state; 67 int32_t val = glibc_weak_rand32_state;
68 68
@@ -78,9 +78,9 @@ glibc_weak_rand32 ()
78 * @return number between 0 and 1. 78 * @return number between 0 and 1.
79 */ 79 */
80static double 80static double
81get_weak_random () 81get_weak_random()
82{ 82{
83 return ((double) random () / RAND_MAX); 83 return((double)random() / RAND_MAX);
84} 84}
85 85
86 86
@@ -91,9 +91,9 @@ get_weak_random ()
91 * @param seed the seed to use 91 * @param seed the seed to use
92 */ 92 */
93void 93void
94GNUNET_CRYPTO_seed_weak_random (int32_t seed) 94GNUNET_CRYPTO_seed_weak_random(int32_t seed)
95{ 95{
96 srandom (seed); 96 srandom(seed);
97} 97}
98 98
99 99
@@ -106,12 +106,12 @@ GNUNET_CRYPTO_seed_weak_random (int32_t seed)
106 * @param length buffer length 106 * @param length buffer length
107 */ 107 */
108void 108void
109GNUNET_CRYPTO_zero_keys (void *buffer, size_t length) 109GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
110{ 110{
111#if HAVE_MEMSET_S 111#if HAVE_MEMSET_S
112 memset_s (buffer, length, 0, length); 112 memset_s(buffer, length, 0, length);
113#elif HAVE_EXPLICIT_BZERO 113#elif HAVE_EXPLICIT_BZERO
114 explicit_bzero (buffer, length); 114 explicit_bzero(buffer, length);
115#else 115#else
116 volatile unsigned char *p = buffer; 116 volatile unsigned char *p = buffer;
117 while (length--) 117 while (length--)
@@ -129,37 +129,40 @@ GNUNET_CRYPTO_zero_keys (void *buffer, size_t length)
129 * @param length buffer length 129 * @param length buffer length
130 */ 130 */
131void 131void
132GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, 132GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode,
133 void *buffer, 133 void *buffer,
134 size_t length) 134 size_t length)
135{ 135{
136#ifdef gcry_fast_random_poll 136#ifdef gcry_fast_random_poll
137 static unsigned int invokeCount; 137 static unsigned int invokeCount;
138#endif 138#endif
139 switch (mode) 139 switch (mode)
140 { 140 {
141 case GNUNET_CRYPTO_QUALITY_STRONG: 141 case GNUNET_CRYPTO_QUALITY_STRONG:
142 /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ 142 /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
143#ifdef gcry_fast_random_poll 143#ifdef gcry_fast_random_poll
144 if ((invokeCount++ % 256) == 0) 144 if ((invokeCount++ % 256) == 0)
145 gcry_fast_random_poll (); 145 gcry_fast_random_poll();
146#endif 146#endif
147 gcry_randomize (buffer, length, GCRY_STRONG_RANDOM); 147 gcry_randomize(buffer, length, GCRY_STRONG_RANDOM);
148 return; 148 return;
149 case GNUNET_CRYPTO_QUALITY_NONCE: 149
150 gcry_create_nonce (buffer, length); 150 case GNUNET_CRYPTO_QUALITY_NONCE:
151 return; 151 gcry_create_nonce(buffer, length);
152 case GNUNET_CRYPTO_QUALITY_WEAK: 152 return;
153 /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ 153
154 case GNUNET_CRYPTO_QUALITY_WEAK:
155 /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
154#ifdef gcry_fast_random_poll 156#ifdef gcry_fast_random_poll
155 if ((invokeCount++ % 256) == 0) 157 if ((invokeCount++ % 256) == 0)
156 gcry_fast_random_poll (); 158 gcry_fast_random_poll();
157#endif 159#endif
158 gcry_randomize (buffer, length, GCRY_WEAK_RANDOM); 160 gcry_randomize(buffer, length, GCRY_WEAK_RANDOM);
159 return; 161 return;
160 default: 162
161 GNUNET_assert (0); 163 default:
162 } 164 GNUNET_assert(0);
165 }
163} 166}
164 167
165 168
@@ -171,7 +174,7 @@ GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode,
171 * @return a random value in the interval [0,i[. 174 * @return a random value in the interval [0,i[.
172 */ 175 */
173uint32_t 176uint32_t
174GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i) 177GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
175{ 178{
176#ifdef gcry_fast_random_poll 179#ifdef gcry_fast_random_poll
177 static unsigned int invokeCount; 180 static unsigned int invokeCount;
@@ -179,39 +182,44 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i)
179 uint32_t ret; 182 uint32_t ret;
180 uint32_t ul; 183 uint32_t ul;
181 184
182 GNUNET_assert (i > 0); 185 GNUNET_assert(i > 0);
183 186
184 switch (mode) 187 switch (mode)
185 { 188 {
186 case GNUNET_CRYPTO_QUALITY_STRONG: 189 case GNUNET_CRYPTO_QUALITY_STRONG:
187 /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ 190 /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
188#ifdef gcry_fast_random_poll 191#ifdef gcry_fast_random_poll
189 if ((invokeCount++ % 256) == 0) 192 if ((invokeCount++ % 256) == 0)
190 gcry_fast_random_poll (); 193 gcry_fast_random_poll();
191#endif 194#endif
192 ul = UINT32_MAX - (UINT32_MAX % i); 195 ul = UINT32_MAX - (UINT32_MAX % i);
193 do 196 do
194 { 197 {
195 gcry_randomize ((unsigned char *) &ret, 198 gcry_randomize((unsigned char *)&ret,
196 sizeof (uint32_t), 199 sizeof(uint32_t),
197 GCRY_STRONG_RANDOM); 200 GCRY_STRONG_RANDOM);
198 } while (ret >= ul); 201 }
199 return ret % i; 202 while (ret >= ul);
200 case GNUNET_CRYPTO_QUALITY_NONCE: 203 return ret % i;
201 ul = UINT32_MAX - (UINT32_MAX % i); 204
202 do 205 case GNUNET_CRYPTO_QUALITY_NONCE:
203 { 206 ul = UINT32_MAX - (UINT32_MAX % i);
204 gcry_create_nonce (&ret, sizeof (ret)); 207 do
205 } while (ret >= ul); 208 {
206 return ret % i; 209 gcry_create_nonce(&ret, sizeof(ret));
207 case GNUNET_CRYPTO_QUALITY_WEAK: 210 }
208 ret = i * get_weak_random (); 211 while (ret >= ul);
209 if (ret >= i) 212 return ret % i;
210 ret = i - 1; 213
211 return ret; 214 case GNUNET_CRYPTO_QUALITY_WEAK:
212 default: 215 ret = i * get_weak_random();
213 GNUNET_assert (0); 216 if (ret >= i)
214 } 217 ret = i - 1;
218 return ret;
219
220 default:
221 GNUNET_assert(0);
222 }
215 return 0; 223 return 0;
216} 224}
217 225
@@ -225,24 +233,24 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i)
225 * @return the permutation array (allocated from heap) 233 * @return the permutation array (allocated from heap)
226 */ 234 */
227unsigned int * 235unsigned int *
228GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n) 236GNUNET_CRYPTO_random_permute(enum GNUNET_CRYPTO_Quality mode, unsigned int n)
229{ 237{
230 unsigned int *ret; 238 unsigned int *ret;
231 unsigned int i; 239 unsigned int i;
232 unsigned int tmp; 240 unsigned int tmp;
233 uint32_t x; 241 uint32_t x;
234 242
235 GNUNET_assert (n > 0); 243 GNUNET_assert(n > 0);
236 ret = GNUNET_malloc (n * sizeof (unsigned int)); 244 ret = GNUNET_malloc(n * sizeof(unsigned int));
237 for (i = 0; i < n; i++) 245 for (i = 0; i < n; i++)
238 ret[i] = i; 246 ret[i] = i;
239 for (i = n - 1; i > 0; i--) 247 for (i = n - 1; i > 0; i--)
240 { 248 {
241 x = GNUNET_CRYPTO_random_u32 (mode, i + 1); 249 x = GNUNET_CRYPTO_random_u32(mode, i + 1);
242 tmp = ret[x]; 250 tmp = ret[x];
243 ret[x] = ret[i]; 251 ret[x] = ret[i];
244 ret[i] = tmp; 252 ret[i] = tmp;
245 } 253 }
246 return ret; 254 return ret;
247} 255}
248 256
@@ -255,39 +263,44 @@ GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n)
255 * @return random 64-bit number 263 * @return random 64-bit number
256 */ 264 */
257uint64_t 265uint64_t
258GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) 266GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
259{ 267{
260 uint64_t ret; 268 uint64_t ret;
261 uint64_t ul; 269 uint64_t ul;
262 270
263 GNUNET_assert (max > 0); 271 GNUNET_assert(max > 0);
264 switch (mode) 272 switch (mode)
265 {
266 case GNUNET_CRYPTO_QUALITY_STRONG:
267 ul = UINT64_MAX - (UINT64_MAX % max);
268 do
269 { 273 {
270 gcry_randomize ((unsigned char *) &ret, 274 case GNUNET_CRYPTO_QUALITY_STRONG:
271 sizeof (uint64_t), 275 ul = UINT64_MAX - (UINT64_MAX % max);
272 GCRY_STRONG_RANDOM); 276 do
273 } while (ret >= ul); 277 {
274 return ret % max; 278 gcry_randomize((unsigned char *)&ret,
275 case GNUNET_CRYPTO_QUALITY_NONCE: 279 sizeof(uint64_t),
276 ul = UINT64_MAX - (UINT64_MAX % max); 280 GCRY_STRONG_RANDOM);
277 do 281 }
278 { 282 while (ret >= ul);
279 gcry_create_nonce (&ret, sizeof (ret)); 283 return ret % max;
280 } while (ret >= ul); 284
281 285 case GNUNET_CRYPTO_QUALITY_NONCE:
282 return ret % max; 286 ul = UINT64_MAX - (UINT64_MAX % max);
283 case GNUNET_CRYPTO_QUALITY_WEAK: 287 do
284 ret = max * get_weak_random (); 288 {
285 if (ret >= max) 289 gcry_create_nonce(&ret, sizeof(ret));
286 ret = max - 1; 290 }
287 return ret; 291 while (ret >= ul);
288 default: 292
289 GNUNET_assert (0); 293 return ret % max;
290 } 294
295 case GNUNET_CRYPTO_QUALITY_WEAK:
296 ret = max * get_weak_random();
297 if (ret >= max)
298 ret = max - 1;
299 return ret;
300
301 default:
302 GNUNET_assert(0);
303 }
291 return 0; 304 return 0;
292} 305}
293 306
@@ -297,9 +310,9 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max)
297 * strategy of libgcrypt implementation. 310 * strategy of libgcrypt implementation.
298 */ 311 */
299static void * 312static void *
300w_malloc (size_t n) 313w_malloc(size_t n)
301{ 314{
302 return calloc (n, 1); 315 return calloc(n, 1);
303} 316}
304 317
305 318
@@ -308,9 +321,9 @@ w_malloc (size_t n)
308 * strategy of libgcrypt implementation. 321 * strategy of libgcrypt implementation.
309 */ 322 */
310static int 323static int
311w_check (const void *p) 324w_check(const void *p)
312{ 325{
313 (void) p; 326 (void)p;
314 return 0; /* not secure memory */ 327 return 0; /* not secure memory */
315} 328}
316 329
@@ -318,49 +331,49 @@ w_check (const void *p)
318/** 331/**
319 * Initialize libgcrypt. 332 * Initialize libgcrypt.
320 */ 333 */
321void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init () 334void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init()
322{ 335{
323 gcry_error_t rc; 336 gcry_error_t rc;
324 337
325 if (! gcry_check_version (NEED_LIBGCRYPT_VERSION)) 338 if (!gcry_check_version(NEED_LIBGCRYPT_VERSION))
326 { 339 {
327 fprintf ( 340 fprintf(
328 stderr, 341 stderr,
329 _ ("libgcrypt has not the expected version (version %s is required).\n"), 342 _("libgcrypt has not the expected version (version %s is required).\n"),
330 NEED_LIBGCRYPT_VERSION); 343 NEED_LIBGCRYPT_VERSION);
331 GNUNET_assert (0); 344 GNUNET_assert(0);
332 } 345 }
333 /* set custom allocators */ 346 /* set custom allocators */
334 gcry_set_allocation_handler (&w_malloc, &w_malloc, &w_check, &realloc, &free); 347 gcry_set_allocation_handler(&w_malloc, &w_malloc, &w_check, &realloc, &free);
335 /* Disable use of secure memory */ 348 /* Disable use of secure memory */
336 if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0))) 349 if ((rc = gcry_control(GCRYCTL_DISABLE_SECMEM, 0)))
337 fprintf (stderr, 350 fprintf(stderr,
338 "Failed to set libgcrypt option %s: %s\n", 351 "Failed to set libgcrypt option %s: %s\n",
339 "DISABLE_SECMEM", 352 "DISABLE_SECMEM",
340 gcry_strerror (rc)); 353 gcry_strerror(rc));
341 /* Otherwise gnunet-ecc takes forever to complete, besides 354 /* Otherwise gnunet-ecc takes forever to complete, besides
342 we are fine with "just" using GCRY_STRONG_RANDOM */ 355 we are fine with "just" using GCRY_STRONG_RANDOM */
343 if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0))) 356 if ((rc = gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0)))
344 fprintf (stderr, 357 fprintf(stderr,
345 "Failed to set libgcrypt option %s: %s\n", 358 "Failed to set libgcrypt option %s: %s\n",
346 "ENABLE_QUICK_RANDOM", 359 "ENABLE_QUICK_RANDOM",
347 gcry_strerror (rc)); 360 gcry_strerror(rc));
348 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); 361 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
349 gcry_fast_random_poll (); 362 gcry_fast_random_poll();
350 GNUNET_CRYPTO_seed_weak_random ( 363 GNUNET_CRYPTO_seed_weak_random(
351 time (NULL) ^ 364 time(NULL) ^
352 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX)); 365 GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
353} 366}
354 367
355 368
356/** 369/**
357 * Nicely shut down libgcrypt. 370 * Nicely shut down libgcrypt.
358 */ 371 */
359void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini () 372void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini()
360{ 373{
361 gcry_set_progress_handler (NULL, NULL); 374 gcry_set_progress_handler(NULL, NULL);
362#ifdef GCRYCTL_CLOSE_RANDOM_DEVICE 375#ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
363 (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0); 376 (void)gcry_control(GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
364#endif 377#endif
365} 378}
366 379