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 #ifdef OPENBSD
100  srandom_deterministic (seed);
101 #else
102  srandom (seed);
103 #endif
104 }
105 
106 
115 void
116 GNUNET_CRYPTO_zero_keys (void *buffer, size_t length)
117 {
118 #if HAVE_MEMSET_S
119  memset_s (buffer, length, 0, length);
120 #elif HAVE_EXPLICIT_BZERO
121  explicit_bzero (buffer, length);
122 #else
123  volatile unsigned char *p = buffer;
124  while (length--)
125  *p++ = 0;
126 #endif
127 }
128 
129 
138 void
140  void *buffer,
141  size_t length)
142 {
143 #ifdef gcry_fast_random_poll
144  static unsigned int invokeCount;
145 #endif
146  switch (mode)
147  {
149  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
150 #ifdef gcry_fast_random_poll
151  if ((invokeCount++ % 256) == 0)
152  gcry_fast_random_poll ();
153 #endif
154  gcry_randomize (buffer, length, GCRY_STRONG_RANDOM);
155  return;
156 
158  gcry_create_nonce (buffer, length);
159  return;
160 
162  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
163 #ifdef gcry_fast_random_poll
164  if ((invokeCount++ % 256) == 0)
165  gcry_fast_random_poll ();
166 #endif
167  gcry_randomize (buffer, length, GCRY_WEAK_RANDOM);
168  return;
169 
170  default:
171  GNUNET_assert (0);
172  }
173 }
174 
175 
183 uint32_t
185  uint32_t i)
186 {
187 #ifdef gcry_fast_random_poll
188  static unsigned int invokeCount;
189 #endif
190  uint32_t ret;
191  uint32_t ul;
192 
193  GNUNET_assert (i > 0);
194 
195  switch (mode)
196  {
198  /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
199 #ifdef gcry_fast_random_poll
200  if ((invokeCount++ % 256) == 0)
201  gcry_fast_random_poll ();
202 #endif
203  ul = UINT32_MAX - (UINT32_MAX % i);
204  do
205  {
206  gcry_randomize ((unsigned char *) &ret,
207  sizeof(uint32_t),
208  GCRY_STRONG_RANDOM);
209  }
210  while (ret >= ul);
211  return ret % i;
212 
214  ul = UINT32_MAX - (UINT32_MAX % i);
215  do
216  {
217  gcry_create_nonce (&ret, sizeof(ret));
218  }
219  while (ret >= ul);
220  return ret % i;
221 
223  ret = i * get_weak_random ();
224  if (ret >= i)
225  ret = i - 1;
226  return ret;
227 
228  default:
229  GNUNET_assert (0);
230  }
231  return 0;
232 }
233 
234 
243 unsigned int *
245  unsigned int n)
246 {
247  unsigned int *ret;
248  unsigned int i;
249  unsigned int tmp;
250  uint32_t x;
251 
252  GNUNET_assert (n > 0);
253  ret = GNUNET_malloc (n * sizeof(unsigned int));
254  for (i = 0; i < n; i++)
255  ret[i] = i;
256  for (i = n - 1; i > 0; i--)
257  {
258  x = GNUNET_CRYPTO_random_u32 (mode, i + 1);
259  tmp = ret[x];
260  ret[x] = ret[i];
261  ret[i] = tmp;
262  }
263  return ret;
264 }
265 
266 
274 uint64_t
276  uint64_t max)
277 {
278  uint64_t ret;
279  uint64_t ul;
280 
281  GNUNET_assert (max > 0);
282  switch (mode)
283  {
285  ul = UINT64_MAX - (UINT64_MAX % max);
286  do
287  {
288  gcry_randomize ((unsigned char *) &ret,
289  sizeof(uint64_t),
290  GCRY_STRONG_RANDOM);
291  }
292  while (ret >= ul);
293  return ret % max;
294 
296  ul = UINT64_MAX - (UINT64_MAX % max);
297  do
298  {
299  gcry_create_nonce (&ret, sizeof(ret));
300  }
301  while (ret >= ul);
302 
303  return ret % max;
304 
306  ret = max * get_weak_random ();
307  if (ret >= max)
308  ret = max - 1;
309  return ret;
310 
311  default:
312  GNUNET_assert (0);
313  }
314  return 0;
315 }
316 
317 
328 void
330  struct GNUNET_Uuid *uuid)
331 {
332  struct GNUNET_TIME_Absolute now;
333  uint64_t ms;
334  uint64_t be;
335  char *base;
336 
338  uuid,
339  sizeof (struct GNUNET_Uuid));
340  now = GNUNET_TIME_absolute_get ();
341  ms = now.abs_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
342  be = GNUNET_htonll (ms);
343  base = (char *) &be;
344  memcpy (uuid,
345  base + 2,
346  sizeof (be) - 2);
347 }
348 
349 
354 static void *
355 w_malloc (size_t n)
356 {
357  return calloc (n, 1);
358 }
359 
360 
365 static int
366 w_check (const void *p)
367 {
368  (void) p;
369  return 0; /* not secure memory */
370 }
371 
372 
376 void __attribute__ ((constructor))
377 GNUNET_CRYPTO_random_init ()
378 {
379  gcry_error_t rc;
380 
381  if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
382  {
383  fprintf (
384  stderr,
385  _ ("libgcrypt has not the expected version (version %s is required).\n"),
386  NEED_LIBGCRYPT_VERSION);
387  GNUNET_assert (0);
388  }
389  /* set custom allocators */
390  gcry_set_allocation_handler (&w_malloc, &w_malloc, &w_check, &realloc, &free);
391  /* Disable use of secure memory */
392  if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0)))
393  fprintf (stderr,
394  "Failed to set libgcrypt option %s: %s\n",
395  "DISABLE_SECMEM",
396  gcry_strerror (rc));
397  /* Otherwise gnunet-ecc takes forever to complete, besides
398  we are fine with "just" using GCRY_STRONG_RANDOM */
399  if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0)))
400  fprintf (stderr,
401  "Failed to set libgcrypt option %s: %s\n",
402  "ENABLE_QUICK_RANDOM",
403  gcry_strerror (rc));
404  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
405  gcry_fast_random_poll ();
407  time (NULL)
409 }
410 
411 
415 void __attribute__ ((destructor))
416 GNUNET_CRYPTO_random_fini ()
417 {
418  gcry_set_progress_handler (NULL, NULL);
419 #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
420  (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
421 #endif
422 }
423 
424 
425 /* 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-uri.c:37
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:110
#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.