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 "gnunet_time_lib.h"
30 #include <gcrypt.h>
31 
32 #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-random", __VA_ARGS__)
33 
34 #define LOG_STRERROR(kind, syscall) \
35  GNUNET_log_from_strerror (kind, "util-crypto-random", syscall)
36 
37 
38 /* TODO: ndurner, move this to plibc? */
39 /* The code is derived from glibc, obviously */
40 #if ! HAVE_RANDOM || ! HAVE_SRANDOM
41 #ifdef RANDOM
42 #undef RANDOM
43 #endif
44 #ifdef SRANDOM
45 #undef SRANDOM
46 #endif
47 #define RANDOM() glibc_weak_rand32 ()
48 #define SRANDOM(s) glibc_weak_srand32 (s)
49 #if defined(RAND_MAX)
50 #undef RAND_MAX
51 #endif
52 #define RAND_MAX 0x7fffffff /* Hopefully this is correct */
53 
54 
55 static int32_t glibc_weak_rand32_state = 1;
56 
57 
58 void
59 glibc_weak_srand32 (int32_t s)
60 {
62 }
63 
64 
65 int32_t
67 {
68  int32_t val = glibc_weak_rand32_state;
69 
70  val = ((glibc_weak_rand32_state * 1103515245) + 12345) & 0x7fffffff;
72  return val;
73 }
74 
75 
76 #endif
77 
83 static double
85 {
86  return((double) random () / RAND_MAX);
87 }
88 
89 
96 void
98 {
99  srandom (seed);
100 }
101 
102 
111 void
112 GNUNET_CRYPTO_zero_keys (void *buffer, size_t length)
113 {
114 #if HAVE_MEMSET_S
115  memset_s (buffer, length, 0, length);
116 #elif HAVE_EXPLICIT_BZERO
117  explicit_bzero (buffer, length);
118 #else
119  volatile unsigned char *p = buffer;
120  while (length--)
121  *p++ = 0;
122 #endif
123 }
124 
125 
134 void
136  void *buffer,
137  size_t length)
138 {
139 #ifdef gcry_fast_random_poll
140  static unsigned int invokeCount;
141 #endif
142  switch (mode)
143  {
145  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
146 #ifdef gcry_fast_random_poll
147  if ((invokeCount++ % 256) == 0)
148  gcry_fast_random_poll ();
149 #endif
150  gcry_randomize (buffer, length, GCRY_STRONG_RANDOM);
151  return;
152 
154  gcry_create_nonce (buffer, length);
155  return;
156 
158  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
159 #ifdef gcry_fast_random_poll
160  if ((invokeCount++ % 256) == 0)
161  gcry_fast_random_poll ();
162 #endif
163  gcry_randomize (buffer, length, GCRY_WEAK_RANDOM);
164  return;
165 
166  default:
167  GNUNET_assert (0);
168  }
169 }
170 
171 
179 uint32_t
181  uint32_t i)
182 {
183 #ifdef gcry_fast_random_poll
184  static unsigned int invokeCount;
185 #endif
186  uint32_t ret;
187  uint32_t ul;
188 
189  GNUNET_assert (i > 0);
190 
191  switch (mode)
192  {
194  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
195 #ifdef gcry_fast_random_poll
196  if ((invokeCount++ % 256) == 0)
197  gcry_fast_random_poll ();
198 #endif
199  ul = UINT32_MAX - (UINT32_MAX % i);
200  do
201  {
202  gcry_randomize ((unsigned char *) &ret,
203  sizeof(uint32_t),
204  GCRY_STRONG_RANDOM);
205  }
206  while (ret >= ul);
207  return ret % i;
208 
210  ul = UINT32_MAX - (UINT32_MAX % i);
211  do
212  {
213  gcry_create_nonce (&ret, sizeof(ret));
214  }
215  while (ret >= ul);
216  return ret % i;
217 
219  ret = i * get_weak_random ();
220  if (ret >= i)
221  ret = i - 1;
222  return ret;
223 
224  default:
225  GNUNET_assert (0);
226  }
227  return 0;
228 }
229 
230 
239 unsigned int *
241  unsigned int n)
242 {
243  unsigned int *ret;
244  unsigned int i;
245  unsigned int tmp;
246  uint32_t x;
247 
248  GNUNET_assert (n > 0);
249  ret = GNUNET_malloc (n * sizeof(unsigned int));
250  for (i = 0; i < n; i++)
251  ret[i] = i;
252  for (i = n - 1; i > 0; i--)
253  {
254  x = GNUNET_CRYPTO_random_u32 (mode, i + 1);
255  tmp = ret[x];
256  ret[x] = ret[i];
257  ret[i] = tmp;
258  }
259  return ret;
260 }
261 
262 
270 uint64_t
272  uint64_t max)
273 {
274  uint64_t ret;
275  uint64_t ul;
276 
277  GNUNET_assert (max > 0);
278  switch (mode)
279  {
281  ul = UINT64_MAX - (UINT64_MAX % max);
282  do
283  {
284  gcry_randomize ((unsigned char *) &ret,
285  sizeof(uint64_t),
286  GCRY_STRONG_RANDOM);
287  }
288  while (ret >= ul);
289  return ret % max;
290 
292  ul = UINT64_MAX - (UINT64_MAX % max);
293  do
294  {
295  gcry_create_nonce (&ret, sizeof(ret));
296  }
297  while (ret >= ul);
298 
299  return ret % max;
300 
302  ret = max * get_weak_random ();
303  if (ret >= max)
304  ret = max - 1;
305  return ret;
306 
307  default:
308  GNUNET_assert (0);
309  }
310  return 0;
311 }
312 
313 
324 void
326  struct GNUNET_Uuid *uuid)
327 {
328  struct GNUNET_TIME_Absolute now;
329  uint64_t ms;
330  uint64_t be;
331  char *base;
332 
334  uuid,
335  sizeof (struct GNUNET_Uuid));
336  now = GNUNET_TIME_absolute_get ();
337  ms = now.abs_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
338  be = GNUNET_htonll (ms);
339  base = (char *) &be;
340  memcpy (uuid,
341  base + 2,
342  sizeof (be) - 2);
343 }
344 
345 
350 static void *
351 w_malloc (size_t n)
352 {
353  return calloc (n, 1);
354 }
355 
356 
361 static int
362 w_check (const void *p)
363 {
364  (void) p;
365  return 0; /* not secure memory */
366 }
367 
368 
372 void __attribute__ ((constructor))
373 GNUNET_CRYPTO_random_init ()
374 {
375  gcry_error_t rc;
376 
377  if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
378  {
379  fprintf (
380  stderr,
381  _ ("libgcrypt has not the expected version (version %s is required).\n"),
382  NEED_LIBGCRYPT_VERSION);
383  GNUNET_assert (0);
384  }
385  /* set custom allocators */
386  gcry_set_allocation_handler (&w_malloc, &w_malloc, &w_check, &realloc, &free);
387  /* Disable use of secure memory */
388  if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0)))
389  fprintf (stderr,
390  "Failed to set libgcrypt option %s: %s\n",
391  "DISABLE_SECMEM",
392  gcry_strerror (rc));
393  /* Otherwise gnunet-ecc takes forever to complete, besides
394  we are fine with "just" using GCRY_STRONG_RANDOM */
395  if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0)))
396  fprintf (stderr,
397  "Failed to set libgcrypt option %s: %s\n",
398  "ENABLE_QUICK_RANDOM",
399  gcry_strerror (rc));
400  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
401  gcry_fast_random_poll ();
403  time (NULL)
405 }
406 
407 
411 void __attribute__ ((destructor))
412 GNUNET_CRYPTO_random_fini ()
413 {
414  gcry_set_progress_handler (NULL, NULL);
415 #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
416  (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
417 #endif
418 }
419 
420 
421 /* end of crypto_random.c */
static int32_t glibc_weak_rand32_state
Definition: crypto_random.c:55
void glibc_weak_srand32(int32_t s)
Definition: crypto_random.c:59
#define RAND_MAX
Definition: crypto_random.c:52
int32_t glibc_weak_rand32()
Definition: crypto_random.c:66
static void * w_malloc(size_t n)
Allocation wrapper for libgcrypt, used to avoid bad locking strategy of libgcrypt implementation.
static double get_weak_random(void)
Create a cryptographically weak pseudo-random number in the interval of 0 to 1.
Definition: crypto_random.c:84
static int w_check(const void *p)
Allocation wrapper for libgcrypt, used to avoid bad locking strategy of libgcrypt implementation.
void __attribute__((constructor))
Initialize libgcrypt.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:36
cryptographic primitives for GNUnet
static enum @8 mode
Should we do a PUT (mode = 0) or GET (mode = 1);.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate random unsigned 64-bit value.
void GNUNET_CRYPTO_random_timeflake(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_Uuid *uuid)
Fill UUID with a timeflake pseudo-random value.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
GNUNET_CRYPTO_Quality
Desired quality level for random numbers.
void GNUNET_CRYPTO_seed_weak_random(int32_t seed)
Seed a weak random generator.
Definition: crypto_random.c:97
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random unsigned 32-bit number modulo i.
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 GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
Zero out buffer, securely against compiler optimizations.
@ GNUNET_CRYPTO_QUALITY_STRONG
High-quality operations are desired.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
#define max(x, y)
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
A UUID, a 128 bit "random" value.