GNUnet  0.10.x
crypto_random.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet. Copyright (C) 2001-2014 Christian Grothoff
3  (and other contributing authors)
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 
20 */
21 
27 #include "platform.h"
28 #include "gnunet_crypto_lib.h"
29 #include <gcrypt.h>
30 
31 #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-random", __VA_ARGS__)
32 
33 #define LOG_STRERROR(kind, syscall) \
34  GNUNET_log_from_strerror (kind, "util-crypto-random", syscall)
35 
36 
37 /* TODO: ndurner, move this to plibc? */
38 /* The code is derived from glibc, obviously */
39 #if ! HAVE_RANDOM || ! HAVE_SRANDOM
40 #ifdef RANDOM
41 #undef RANDOM
42 #endif
43 #ifdef SRANDOM
44 #undef SRANDOM
45 #endif
46 #define RANDOM() glibc_weak_rand32 ()
47 #define SRANDOM(s) glibc_weak_srand32 (s)
48 #if defined(RAND_MAX)
49 #undef RAND_MAX
50 #endif
51 #define RAND_MAX 0x7fffffff /* Hopefully this is correct */
52 
53 
54 static int32_t glibc_weak_rand32_state = 1;
55 
56 
57 void
58 glibc_weak_srand32 (int32_t s)
59 {
61 }
62 
63 
64 int32_t
66 {
67  int32_t val = glibc_weak_rand32_state;
68 
69  val = ((glibc_weak_rand32_state * 1103515245) + 12345) & 0x7fffffff;
71  return val;
72 }
73 #endif
74 
80 static double
82 {
83  return ((double) RANDOM () / RAND_MAX);
84 }
85 
86 
93 void
95 {
96  SRANDOM (seed);
97 }
98 
99 
108 void
109 GNUNET_CRYPTO_zero_keys (void *buffer, size_t length)
110 {
111 #if HAVE_MEMSET_S
112  memset_s (buffer, length, 0, length);
113 #elif HAVE_EXPLICIT_BZERO
114  explicit_bzero (buffer, length);
115 #else
116  volatile unsigned char *p = buffer;
117  while (length--)
118  *p++ = 0;
119 #endif
120 }
121 
122 
131 void
133  void *buffer,
134  size_t length)
135 {
136 #ifdef gcry_fast_random_poll
137  static unsigned int invokeCount;
138 #endif
139  switch (mode)
140  {
142  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
143 #ifdef gcry_fast_random_poll
144  if ((invokeCount++ % 256) == 0)
145  gcry_fast_random_poll ();
146 #endif
147  gcry_randomize (buffer, length, GCRY_STRONG_RANDOM);
148  return;
150  gcry_create_nonce (buffer, length);
151  return;
153  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
154 #ifdef gcry_fast_random_poll
155  if ((invokeCount++ % 256) == 0)
156  gcry_fast_random_poll ();
157 #endif
158  gcry_randomize (buffer, length, GCRY_WEAK_RANDOM);
159  return;
160  default:
161  GNUNET_assert (0);
162  }
163 }
164 
165 
173 uint32_t
175 {
176 #ifdef gcry_fast_random_poll
177  static unsigned int invokeCount;
178 #endif
179  uint32_t ret;
180  uint32_t ul;
181 
182  GNUNET_assert (i > 0);
183 
184  switch (mode)
185  {
187  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
188 #ifdef gcry_fast_random_poll
189  if ((invokeCount++ % 256) == 0)
190  gcry_fast_random_poll ();
191 #endif
192  ul = UINT32_MAX - (UINT32_MAX % i);
193  do
194  {
195  gcry_randomize ((unsigned char *) &ret,
196  sizeof (uint32_t),
197  GCRY_STRONG_RANDOM);
198  } while (ret >= ul);
199  return ret % i;
201  ul = UINT32_MAX - (UINT32_MAX % i);
202  do
203  {
204  gcry_create_nonce (&ret, sizeof (ret));
205  } while (ret >= ul);
206  return ret % i;
208  ret = i * get_weak_random ();
209  if (ret >= i)
210  ret = i - 1;
211  return ret;
212  default:
213  GNUNET_assert (0);
214  }
215  return 0;
216 }
217 
218 
227 unsigned int *
229 {
230  unsigned int *ret;
231  unsigned int i;
232  unsigned int tmp;
233  uint32_t x;
234 
235  GNUNET_assert (n > 0);
236  ret = GNUNET_malloc (n * sizeof (unsigned int));
237  for (i = 0; i < n; i++)
238  ret[i] = i;
239  for (i = n - 1; i > 0; i--)
240  {
241  x = GNUNET_CRYPTO_random_u32 (mode, i + 1);
242  tmp = ret[x];
243  ret[x] = ret[i];
244  ret[i] = tmp;
245  }
246  return ret;
247 }
248 
249 
257 uint64_t
259 {
260  uint64_t ret;
261  uint64_t ul;
262 
263  GNUNET_assert (max > 0);
264  switch (mode)
265  {
267  ul = UINT64_MAX - (UINT64_MAX % max);
268  do
269  {
270  gcry_randomize ((unsigned char *) &ret,
271  sizeof (uint64_t),
272  GCRY_STRONG_RANDOM);
273  } while (ret >= ul);
274  return ret % max;
276  ul = UINT64_MAX - (UINT64_MAX % max);
277  do
278  {
279  gcry_create_nonce (&ret, sizeof (ret));
280  } while (ret >= ul);
281 
282  return ret % max;
284  ret = max * get_weak_random ();
285  if (ret >= max)
286  ret = max - 1;
287  return ret;
288  default:
289  GNUNET_assert (0);
290  }
291  return 0;
292 }
293 
294 
299 static void *
300 w_malloc (size_t n)
301 {
302  return calloc (n, 1);
303 }
304 
305 
310 static int
311 w_check (const void *p)
312 {
313  (void) p;
314  return 0; /* not secure memory */
315 }
316 
317 
321 void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init ()
322 {
323  gcry_error_t rc;
324 
325  if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
326  {
327  FPRINTF (
328  stderr,
329  _ ("libgcrypt has not the expected version (version %s is required).\n"),
330  NEED_LIBGCRYPT_VERSION);
331  GNUNET_assert (0);
332  }
333  /* set custom allocators */
334  gcry_set_allocation_handler (&w_malloc, &w_malloc, &w_check, &realloc, &free);
335  /* Disable use of secure memory */
336  if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0)))
337  FPRINTF (stderr,
338  "Failed to set libgcrypt option %s: %s\n",
339  "DISABLE_SECMEM",
340  gcry_strerror (rc));
341  /* Otherwise gnunet-ecc takes forever to complete, besides
342  we are fine with "just" using GCRY_STRONG_RANDOM */
343  if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0)))
344  FPRINTF (stderr,
345  "Failed to set libgcrypt option %s: %s\n",
346  "ENABLE_QUICK_RANDOM",
347  gcry_strerror (rc));
348  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
349  gcry_fast_random_poll ();
351  time (NULL) ^
353 }
354 
355 
359 void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini ()
360 {
361  gcry_set_progress_handler (NULL, NULL);
362 #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
363  (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
364 #endif
365 }
366 
367 
368 /* end of crypto_random.c */
#define RANDOM()
Definition: crypto_random.c:46
#define RAND_MAX
Definition: crypto_random.c:51
unsigned int * GNUNET_CRYPTO_random_permute(enum GNUNET_CRYPTO_Quality mode, unsigned int n)
Get an array with a random permutation of the numbers 0...n-1.
void glibc_weak_srand32(int32_t s)
Definition: crypto_random.c:58
#define FPRINTF
Definition: plibc.h:683
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate random unsigned 64-bit value.
static void * w_malloc(size_t n)
Allocation wrapper for libgcrypt, used to avoid bad locking strategy of libgcrypt implementation...
static int w_check(const void *p)
Allocation wrapper for libgcrypt, used to avoid bad locking strategy of libgcrypt implementation...
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random unsigned 32-bit number modulo i.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
GNUNET_CRYPTO_Quality
Desired quality level for random numbers.
static int ret
Final status code.
Definition: gnunet-arm.c:89
void GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
Zero out buffer, securely against compiler optimizations.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
cryptographic primitives for GNUnet
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
int32_t glibc_weak_rand32()
Definition: crypto_random.c:65
Randomness for IVs etc.
unsigned char * buffer
IO buffer.
void GNUNET_CRYPTO_seed_weak_random(int32_t seed)
Seed a weak random generator.
Definition: crypto_random.c:94
static double get_weak_random()
Create a cryptographically weak pseudo-random number in the interval of 0 to 1.
Definition: crypto_random.c:81
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
void __attribute__((constructor))
Initialize libgcrypt.
static int32_t glibc_weak_rand32_state
Definition: crypto_random.c:54
#define SRANDOM(s)
Definition: crypto_random.c:47
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
static enum @11 mode
Should we do a PUT (mode = 0) or GET (mode = 1);.
High-quality operations are desired.