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
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;
149 
151  gcry_create_nonce(buffer, length);
152  return;
153 
155  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
156 #ifdef gcry_fast_random_poll
157  if ((invokeCount++ % 256) == 0)
158  gcry_fast_random_poll();
159 #endif
160  gcry_randomize(buffer, length, GCRY_WEAK_RANDOM);
161  return;
162 
163  default:
164  GNUNET_assert(0);
165  }
166 }
167 
168 
176 uint32_t
178 {
179 #ifdef gcry_fast_random_poll
180  static unsigned int invokeCount;
181 #endif
182  uint32_t ret;
183  uint32_t ul;
184 
185  GNUNET_assert(i > 0);
186 
187  switch (mode)
188  {
190  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
191 #ifdef gcry_fast_random_poll
192  if ((invokeCount++ % 256) == 0)
193  gcry_fast_random_poll();
194 #endif
195  ul = UINT32_MAX - (UINT32_MAX % i);
196  do
197  {
198  gcry_randomize((unsigned char *)&ret,
199  sizeof(uint32_t),
200  GCRY_STRONG_RANDOM);
201  }
202  while (ret >= ul);
203  return ret % i;
204 
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 
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;
224 }
225 
226 
235 unsigned int *
237 {
238  unsigned int *ret;
239  unsigned int i;
240  unsigned int tmp;
241  uint32_t x;
242 
243  GNUNET_assert(n > 0);
244  ret = GNUNET_malloc(n * sizeof(unsigned int));
245  for (i = 0; i < n; i++)
246  ret[i] = i;
247  for (i = n - 1; i > 0; i--)
248  {
249  x = GNUNET_CRYPTO_random_u32(mode, i + 1);
250  tmp = ret[x];
251  ret[x] = ret[i];
252  ret[i] = tmp;
253  }
254  return ret;
255 }
256 
257 
265 uint64_t
267 {
268  uint64_t ret;
269  uint64_t ul;
270 
271  GNUNET_assert(max > 0);
272  switch (mode)
273  {
275  ul = UINT64_MAX - (UINT64_MAX % max);
276  do
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 
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 
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;
305 }
306 
307 
312 static void *
313 w_malloc(size_t n)
314 {
315  return calloc(n, 1);
316 }
317 
318 
323 static int
324 w_check(const void *p)
325 {
326  (void)p;
327  return 0; /* not secure memory */
328 }
329 
330 
334 void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init()
335 {
336  gcry_error_t rc;
337 
338  if (!gcry_check_version(NEED_LIBGCRYPT_VERSION))
339  {
340  fprintf(
341  stderr,
342  _("libgcrypt has not the expected version (version %s is required).\n"),
343  NEED_LIBGCRYPT_VERSION);
344  GNUNET_assert(0);
345  }
346  /* set custom allocators */
347  gcry_set_allocation_handler(&w_malloc, &w_malloc, &w_check, &realloc, &free);
348  /* Disable use of secure memory */
349  if ((rc = gcry_control(GCRYCTL_DISABLE_SECMEM, 0)))
350  fprintf(stderr,
351  "Failed to set libgcrypt option %s: %s\n",
352  "DISABLE_SECMEM",
353  gcry_strerror(rc));
354  /* Otherwise gnunet-ecc takes forever to complete, besides
355  we are fine with "just" using GCRY_STRONG_RANDOM */
356  if ((rc = gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0)))
357  fprintf(stderr,
358  "Failed to set libgcrypt option %s: %s\n",
359  "ENABLE_QUICK_RANDOM",
360  gcry_strerror(rc));
361  gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
362  gcry_fast_random_poll();
364  time(NULL) ^
366 }
367 
368 
372 void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini()
373 {
374  gcry_set_progress_handler(NULL, NULL);
375 #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
376  (void)gcry_control(GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
377 #endif
378 }
379 
380 
381 /* 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.
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: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: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
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.