summaryrefslogtreecommitdiff
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.c284
1 files changed, 142 insertions, 142 deletions
diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c
index d16ba2412..f70763757 100644
--- a/src/util/crypto_random.c
+++ b/src/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,40 +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 149
150 case GNUNET_CRYPTO_QUALITY_NONCE: 150 case GNUNET_CRYPTO_QUALITY_NONCE:
151 gcry_create_nonce(buffer, length); 151 gcry_create_nonce (buffer, length);
152 return; 152 return;
153 153
154 case GNUNET_CRYPTO_QUALITY_WEAK: 154 case GNUNET_CRYPTO_QUALITY_WEAK:
155 /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ 155 /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
156#ifdef gcry_fast_random_poll 156#ifdef gcry_fast_random_poll
157 if ((invokeCount++ % 256) == 0) 157 if ((invokeCount++ % 256) == 0)
158 gcry_fast_random_poll(); 158 gcry_fast_random_poll ();
159#endif 159#endif
160 gcry_randomize(buffer, length, GCRY_WEAK_RANDOM); 160 gcry_randomize (buffer, length, GCRY_WEAK_RANDOM);
161 return; 161 return;
162 162
163 default: 163 default:
164 GNUNET_assert(0); 164 GNUNET_assert (0);
165 } 165 }
166} 166}
167 167
168 168
@@ -174,7 +174,7 @@ GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode,
174 * @return a random value in the interval [0,i[. 174 * @return a random value in the interval [0,i[.
175 */ 175 */
176uint32_t 176uint32_t
177GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i) 177GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i)
178{ 178{
179#ifdef gcry_fast_random_poll 179#ifdef gcry_fast_random_poll
180 static unsigned int invokeCount; 180 static unsigned int invokeCount;
@@ -182,44 +182,44 @@ GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
182 uint32_t ret; 182 uint32_t ret;
183 uint32_t ul; 183 uint32_t ul;
184 184
185 GNUNET_assert(i > 0); 185 GNUNET_assert (i > 0);
186 186
187 switch (mode) 187 switch (mode)
188 { 188 {
189 case GNUNET_CRYPTO_QUALITY_STRONG: 189 case GNUNET_CRYPTO_QUALITY_STRONG:
190 /* 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 */
191#ifdef gcry_fast_random_poll 191#ifdef gcry_fast_random_poll
192 if ((invokeCount++ % 256) == 0) 192 if ((invokeCount++ % 256) == 0)
193 gcry_fast_random_poll(); 193 gcry_fast_random_poll ();
194#endif 194#endif
195 ul = UINT32_MAX - (UINT32_MAX % i); 195 ul = UINT32_MAX - (UINT32_MAX % i);
196 do 196 do
197 { 197 {
198 gcry_randomize((unsigned char *)&ret, 198 gcry_randomize ((unsigned char *) &ret,
199 sizeof(uint32_t), 199 sizeof(uint32_t),
200 GCRY_STRONG_RANDOM); 200 GCRY_STRONG_RANDOM);
201 }
202 while (ret >= ul);
203 return ret % i;
204
205 case GNUNET_CRYPTO_QUALITY_NONCE:
206 ul = UINT32_MAX - (UINT32_MAX % i);
207 do
208 {
209 gcry_create_nonce(&ret, sizeof(ret));
210 }
211 while (ret >= ul);
212 return ret % i;
213
214 case GNUNET_CRYPTO_QUALITY_WEAK:
215 ret = i * get_weak_random();
216 if (ret >= i)
217 ret = i - 1;
218 return ret;
219
220 default:
221 GNUNET_assert(0);
222 } 201 }
202 while (ret >= ul);
203 return ret % i;
204
205 case GNUNET_CRYPTO_QUALITY_NONCE:
206 ul = UINT32_MAX - (UINT32_MAX % i);
207 do
208 {
209 gcry_create_nonce (&ret, sizeof(ret));
210 }
211 while (ret >= ul);
212 return ret % i;
213
214 case GNUNET_CRYPTO_QUALITY_WEAK:
215 ret = i * get_weak_random ();
216 if (ret >= i)
217 ret = i - 1;
218 return ret;
219
220 default:
221 GNUNET_assert (0);
222 }
223 return 0; 223 return 0;
224} 224}
225 225
@@ -233,24 +233,24 @@ GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
233 * @return the permutation array (allocated from heap) 233 * @return the permutation array (allocated from heap)
234 */ 234 */
235unsigned int * 235unsigned int *
236GNUNET_CRYPTO_random_permute(enum GNUNET_CRYPTO_Quality mode, unsigned int n) 236GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n)
237{ 237{
238 unsigned int *ret; 238 unsigned int *ret;
239 unsigned int i; 239 unsigned int i;
240 unsigned int tmp; 240 unsigned int tmp;
241 uint32_t x; 241 uint32_t x;
242 242
243 GNUNET_assert(n > 0); 243 GNUNET_assert (n > 0);
244 ret = GNUNET_malloc(n * sizeof(unsigned int)); 244 ret = GNUNET_malloc (n * sizeof(unsigned int));
245 for (i = 0; i < n; i++) 245 for (i = 0; i < n; i++)
246 ret[i] = i; 246 ret[i] = i;
247 for (i = n - 1; i > 0; i--) 247 for (i = n - 1; i > 0; i--)
248 { 248 {
249 x = GNUNET_CRYPTO_random_u32(mode, i + 1); 249 x = GNUNET_CRYPTO_random_u32 (mode, i + 1);
250 tmp = ret[x]; 250 tmp = ret[x];
251 ret[x] = ret[i]; 251 ret[x] = ret[i];
252 ret[i] = tmp; 252 ret[i] = tmp;
253 } 253 }
254 return ret; 254 return ret;
255} 255}
256 256
@@ -263,44 +263,44 @@ GNUNET_CRYPTO_random_permute(enum GNUNET_CRYPTO_Quality mode, unsigned int n)
263 * @return random 64-bit number 263 * @return random 64-bit number
264 */ 264 */
265uint64_t 265uint64_t
266GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max) 266GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max)
267{ 267{
268 uint64_t ret; 268 uint64_t ret;
269 uint64_t ul; 269 uint64_t ul;
270 270
271 GNUNET_assert(max > 0); 271 GNUNET_assert (max > 0);
272 switch (mode) 272 switch (mode)
273 {
274 case GNUNET_CRYPTO_QUALITY_STRONG:
275 ul = UINT64_MAX - (UINT64_MAX % max);
276 do
273 { 277 {
274 case GNUNET_CRYPTO_QUALITY_STRONG: 278 gcry_randomize ((unsigned char *) &ret,
275 ul = UINT64_MAX - (UINT64_MAX % max); 279 sizeof(uint64_t),
276 do 280 GCRY_STRONG_RANDOM);
277 {
278 gcry_randomize((unsigned char *)&ret,
279 sizeof(uint64_t),
280 GCRY_STRONG_RANDOM);
281 }
282 while (ret >= ul);
283 return ret % max;
284
285 case GNUNET_CRYPTO_QUALITY_NONCE:
286 ul = UINT64_MAX - (UINT64_MAX % max);
287 do
288 {
289 gcry_create_nonce(&ret, sizeof(ret));
290 }
291 while (ret >= ul);
292
293 return ret % max;
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 } 281 }
282 while (ret >= ul);
283 return ret % max;
284
285 case GNUNET_CRYPTO_QUALITY_NONCE:
286 ul = UINT64_MAX - (UINT64_MAX % max);
287 do
288 {
289 gcry_create_nonce (&ret, sizeof(ret));
290 }
291 while (ret >= ul);
292
293 return ret % max;
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 }
304 return 0; 304 return 0;
305} 305}
306 306
@@ -310,9 +310,9 @@ GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
310 * strategy of libgcrypt implementation. 310 * strategy of libgcrypt implementation.
311 */ 311 */
312static void * 312static void *
313w_malloc(size_t n) 313w_malloc (size_t n)
314{ 314{
315 return calloc(n, 1); 315 return calloc (n, 1);
316} 316}
317 317
318 318
@@ -321,9 +321,9 @@ w_malloc(size_t n)
321 * strategy of libgcrypt implementation. 321 * strategy of libgcrypt implementation.
322 */ 322 */
323static int 323static int
324w_check(const void *p) 324w_check (const void *p)
325{ 325{
326 (void)p; 326 (void) p;
327 return 0; /* not secure memory */ 327 return 0; /* not secure memory */
328} 328}
329 329
@@ -331,49 +331,49 @@ w_check(const void *p)
331/** 331/**
332 * Initialize libgcrypt. 332 * Initialize libgcrypt.
333 */ 333 */
334void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init() 334void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init ()
335{ 335{
336 gcry_error_t rc; 336 gcry_error_t rc;
337 337
338 if (!gcry_check_version(NEED_LIBGCRYPT_VERSION)) 338 if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
339 { 339 {
340 fprintf( 340 fprintf (
341 stderr, 341 stderr,
342 _("libgcrypt has not the expected version (version %s is required).\n"), 342 _ ("libgcrypt has not the expected version (version %s is required).\n"),
343 NEED_LIBGCRYPT_VERSION); 343 NEED_LIBGCRYPT_VERSION);
344 GNUNET_assert(0); 344 GNUNET_assert (0);
345 } 345 }
346 /* set custom allocators */ 346 /* set custom allocators */
347 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);
348 /* Disable use of secure memory */ 348 /* Disable use of secure memory */
349 if ((rc = gcry_control(GCRYCTL_DISABLE_SECMEM, 0))) 349 if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0)))
350 fprintf(stderr, 350 fprintf (stderr,
351 "Failed to set libgcrypt option %s: %s\n", 351 "Failed to set libgcrypt option %s: %s\n",
352 "DISABLE_SECMEM", 352 "DISABLE_SECMEM",
353 gcry_strerror(rc)); 353 gcry_strerror (rc));
354 /* Otherwise gnunet-ecc takes forever to complete, besides 354 /* Otherwise gnunet-ecc takes forever to complete, besides
355 we are fine with "just" using GCRY_STRONG_RANDOM */ 355 we are fine with "just" using GCRY_STRONG_RANDOM */
356 if ((rc = gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0))) 356 if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0)))
357 fprintf(stderr, 357 fprintf (stderr,
358 "Failed to set libgcrypt option %s: %s\n", 358 "Failed to set libgcrypt option %s: %s\n",
359 "ENABLE_QUICK_RANDOM", 359 "ENABLE_QUICK_RANDOM",
360 gcry_strerror(rc)); 360 gcry_strerror (rc));
361 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); 361 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
362 gcry_fast_random_poll(); 362 gcry_fast_random_poll ();
363 GNUNET_CRYPTO_seed_weak_random( 363 GNUNET_CRYPTO_seed_weak_random (
364 time(NULL) ^ 364 time (NULL)
365 GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX)); 365 ^ GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
366} 366}
367 367
368 368
369/** 369/**
370 * Nicely shut down libgcrypt. 370 * Nicely shut down libgcrypt.
371 */ 371 */
372void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini() 372void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini ()
373{ 373{
374 gcry_set_progress_handler(NULL, NULL); 374 gcry_set_progress_handler (NULL, NULL);
375#ifdef GCRYCTL_CLOSE_RANDOM_DEVICE 375#ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
376 (void)gcry_control(GCRYCTL_CLOSE_RANDOM_DEVICE, 0); 376 (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
377#endif 377#endif
378} 378}
379 379