GNUnet  0.11.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 
74 
75 #endif
76 
82 static double
84 {
85  return((double) random () / RAND_MAX);
86 }
87 
88 
95 void
97 {
98  srandom (seed);
99 }
100 
101 
110 void
111 GNUNET_CRYPTO_zero_keys (void *buffer, size_t length)
112 {
113 #if HAVE_MEMSET_S
114  memset_s (buffer, length, 0, length);
115 #elif HAVE_EXPLICIT_BZERO
116  explicit_bzero (buffer, length);
117 #else
118  volatile unsigned char *p = buffer;
119  while (length--)
120  *p++ = 0;
121 #endif
122 }
123 
124 
133 void
135  void *buffer,
136  size_t length)
137 {
138 #ifdef gcry_fast_random_poll
139  static unsigned int invokeCount;
140 #endif
141  switch (mode)
142  {
144  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
145 #ifdef gcry_fast_random_poll
146  if ((invokeCount++ % 256) == 0)
147  gcry_fast_random_poll ();
148 #endif
149  gcry_randomize (buffer, length, GCRY_STRONG_RANDOM);
150  return;
151 
153  gcry_create_nonce (buffer, length);
154  return;
155 
157  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
158 #ifdef gcry_fast_random_poll
159  if ((invokeCount++ % 256) == 0)
160  gcry_fast_random_poll ();
161 #endif
162  gcry_randomize (buffer, length, GCRY_WEAK_RANDOM);
163  return;
164 
165  default:
166  GNUNET_assert (0);
167  }
168 }
169 
170 
178 uint32_t
180 {
181 #ifdef gcry_fast_random_poll
182  static unsigned int invokeCount;
183 #endif
184  uint32_t ret;
185  uint32_t ul;
186 
187  GNUNET_assert (i > 0);
188 
189  switch (mode)
190  {
192  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
193 #ifdef gcry_fast_random_poll
194  if ((invokeCount++ % 256) == 0)
195  gcry_fast_random_poll ();
196 #endif
197  ul = UINT32_MAX - (UINT32_MAX % i);
198  do
199  {
200  gcry_randomize ((unsigned char *) &ret,
201  sizeof(uint32_t),
202  GCRY_STRONG_RANDOM);
203  }
204  while (ret >= ul);
205  return ret % i;
206 
208  ul = UINT32_MAX - (UINT32_MAX % i);
209  do
210  {
211  gcry_create_nonce (&ret, sizeof(ret));
212  }
213  while (ret >= ul);
214  return ret % i;
215 
217  ret = i * get_weak_random ();
218  if (ret >= i)
219  ret = i - 1;
220  return ret;
221 
222  default:
223  GNUNET_assert (0);
224  }
225  return 0;
226 }
227 
228 
237 unsigned int *
239 {
240  unsigned int *ret;
241  unsigned int i;
242  unsigned int tmp;
243  uint32_t x;
244 
245  GNUNET_assert (n > 0);
246  ret = GNUNET_malloc (n * sizeof(unsigned int));
247  for (i = 0; i < n; i++)
248  ret[i] = i;
249  for (i = n - 1; i > 0; i--)
250  {
251  x = GNUNET_CRYPTO_random_u32 (mode, i + 1);
252  tmp = ret[x];
253  ret[x] = ret[i];
254  ret[i] = tmp;
255  }
256  return ret;
257 }
258 
259 
267 uint64_t
269 {
270  uint64_t ret;
271  uint64_t ul;
272 
273  GNUNET_assert (max > 0);
274  switch (mode)
275  {
277  ul = UINT64_MAX - (UINT64_MAX % max);
278  do
279  {
280  gcry_randomize ((unsigned char *) &ret,
281  sizeof(uint64_t),
282  GCRY_STRONG_RANDOM);
283  }
284  while (ret >= ul);
285  return ret % max;
286 
288  ul = UINT64_MAX - (UINT64_MAX % max);
289  do
290  {
291  gcry_create_nonce (&ret, sizeof(ret));
292  }
293  while (ret >= ul);
294 
295  return ret % max;
296 
298  ret = max * get_weak_random ();
299  if (ret >= max)
300  ret = max - 1;
301  return ret;
302 
303  default:
304  GNUNET_assert (0);
305  }
306  return 0;
307 }
308 
309 
314 static void *
315 w_malloc (size_t n)
316 {
317  return calloc (n, 1);
318 }
319 
320 
325 static int
326 w_check (const void *p)
327 {
328  (void) p;
329  return 0; /* not secure memory */
330 }
331 
332 
336 void __attribute__ ((constructor))
337 GNUNET_CRYPTO_random_init ()
338 {
339  gcry_error_t rc;
340 
341  if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
342  {
343  fprintf (
344  stderr,
345  _ ("libgcrypt has not the expected version (version %s is required).\n"),
346  NEED_LIBGCRYPT_VERSION);
347  GNUNET_assert (0);
348  }
349  /* set custom allocators */
350  gcry_set_allocation_handler (&w_malloc, &w_malloc, &w_check, &realloc, &free);
351  /* Disable use of secure memory */
352  if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0)))
353  fprintf (stderr,
354  "Failed to set libgcrypt option %s: %s\n",
355  "DISABLE_SECMEM",
356  gcry_strerror (rc));
357  /* Otherwise gnunet-ecc takes forever to complete, besides
358  we are fine with "just" using GCRY_STRONG_RANDOM */
359  if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0)))
360  fprintf (stderr,
361  "Failed to set libgcrypt option %s: %s\n",
362  "ENABLE_QUICK_RANDOM",
363  gcry_strerror (rc));
364  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
365  gcry_fast_random_poll ();
367  time (NULL)
369 }
370 
371 
375 void __attribute__ ((destructor))
376 GNUNET_CRYPTO_random_fini ()
377 {
378  gcry_set_progress_handler (NULL, NULL);
379 #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
380  (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
381 #endif
382 }
383 
384 
385 /* end of crypto_random.c */
#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
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.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
GNUNET_CRYPTO_Quality
Desired quality level for random numbers.
static enum @8 mode
Should we do a PUT (mode = 0) or GET (mode = 1);.
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:181
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:96
static double get_weak_random()
Create a cryptographically weak pseudo-random number in the interval of 0 to 1.
Definition: crypto_random.c:83
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
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
High-quality operations are desired.