2 This file is part of GNUnet. Copyright (C) 2001-2014 Christian Grothoff
3 (and other contributing authors)
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
23 * @file util/crypto_random.c
24 * @brief functions to gather random numbers
25 * @author Christian Grothoff
28 #include "gnunet_crypto_lib.h"
31 #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-random", __VA_ARGS__)
33 #define LOG_STRERROR(kind, syscall) \
34 GNUNET_log_from_strerror (kind, "util-crypto-random", syscall)
37 /* TODO: ndurner, move this to plibc? */
38 /* The code is derived from glibc, obviously */
39 #if ! HAVE_RANDOM || ! HAVE_SRANDOM
46 #define RANDOM() glibc_weak_rand32 ()
47 #define SRANDOM(s) glibc_weak_srand32 (s)
51 #define RAND_MAX 0x7fffffff /* Hopefully this is correct */
54 static int32_t glibc_weak_rand32_state = 1;
58 glibc_weak_srand32 (int32_t s)
60 glibc_weak_rand32_state = s;
67 int32_t val = glibc_weak_rand32_state;
69 val = ((glibc_weak_rand32_state * 1103515245) + 12345) & 0x7fffffff;
70 glibc_weak_rand32_state = val;
76 * Create a cryptographically weak pseudo-random number in the interval of 0 to 1.
78 * @return number between 0 and 1.
83 return ((double) RANDOM () / RAND_MAX);
88 * Seed a weak random generator. Only #GNUNET_CRYPTO_QUALITY_WEAK-mode generator
91 * @param seed the seed to use
94 GNUNET_CRYPTO_seed_weak_random (int32_t seed)
102 * Zero out @a buffer, securely against compiler optimizations.
103 * Used to delete key material.
105 * @param buffer the buffer to zap
106 * @param length buffer length
109 GNUNET_CRYPTO_zero_keys (void *buffer, size_t length)
112 memset_s (buffer, length, 0, length);
113 #elif HAVE_EXPLICIT_BZERO
114 explicit_bzero (buffer, length);
116 volatile unsigned char *p = buffer;
125 * Fill block with a random values.
127 * @param mode desired quality of the random number
128 * @param buffer the buffer to fill
129 * @param length buffer length
132 GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode,
136 #ifdef gcry_fast_random_poll
137 static unsigned int invokeCount;
141 case GNUNET_CRYPTO_QUALITY_STRONG:
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 ();
147 gcry_randomize (buffer, length, GCRY_STRONG_RANDOM);
149 case GNUNET_CRYPTO_QUALITY_NONCE:
150 gcry_create_nonce (buffer, length);
152 case GNUNET_CRYPTO_QUALITY_WEAK:
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 ();
158 gcry_randomize (buffer, length, GCRY_WEAK_RANDOM);
167 * Produce a random unsigned 32-bit number modulo @a i.
169 * @param mode desired quality of the random number
170 * @param i the upper limit (exclusive) for the random number
171 * @return a random value in the interval [0,i[.
174 GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i)
176 #ifdef gcry_fast_random_poll
177 static unsigned int invokeCount;
182 GNUNET_assert (i > 0);
186 case GNUNET_CRYPTO_QUALITY_STRONG:
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 ();
192 ul = UINT32_MAX - (UINT32_MAX % i);
195 gcry_randomize ((unsigned char *) &ret,
200 case GNUNET_CRYPTO_QUALITY_NONCE:
201 ul = UINT32_MAX - (UINT32_MAX % i);
204 gcry_create_nonce (&ret, sizeof (ret));
207 case GNUNET_CRYPTO_QUALITY_WEAK:
208 ret = i * get_weak_random ();
220 * Get an array with a random permutation of the
222 * @param mode #GNUNET_RANDOM_QUALITY_STRONG if the strong (but expensive)
223 * PRNG should be used, #GNUNET_RANDOM_QUALITY_WEAK otherwise
224 * @param n the size of the array
225 * @return the permutation array (allocated from heap)
228 GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n)
235 GNUNET_assert (n > 0);
236 ret = GNUNET_malloc (n * sizeof (unsigned int));
237 for (i = 0; i < n; i++)
239 for (i = n - 1; i > 0; i--)
241 x = GNUNET_CRYPTO_random_u32 (mode, i + 1);
251 * Generate random unsigned 64-bit value.
253 * @param mode desired quality of the random number
254 * @param max value returned will be in range [0,max) (exclusive)
255 * @return random 64-bit number
258 GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max)
263 GNUNET_assert (max > 0);
266 case GNUNET_CRYPTO_QUALITY_STRONG:
267 ul = UINT64_MAX - (UINT64_MAX % max);
270 gcry_randomize ((unsigned char *) &ret,
275 case GNUNET_CRYPTO_QUALITY_NONCE:
276 ul = UINT64_MAX - (UINT64_MAX % max);
279 gcry_create_nonce (&ret, sizeof (ret));
283 case GNUNET_CRYPTO_QUALITY_WEAK:
284 ret = max * get_weak_random ();
296 * Allocation wrapper for libgcrypt, used to avoid bad locking
297 * strategy of libgcrypt implementation.
302 return calloc (n, 1);
307 * Allocation wrapper for libgcrypt, used to avoid bad locking
308 * strategy of libgcrypt implementation.
311 w_check (const void *p)
314 return 0; /* not secure memory */
319 * Initialize libgcrypt.
321 void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init ()
325 if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
329 _ ("libgcrypt has not the expected version (version %s is required).\n"),
330 NEED_LIBGCRYPT_VERSION);
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)))
338 "Failed to set libgcrypt option %s: %s\n",
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)))
345 "Failed to set libgcrypt option %s: %s\n",
346 "ENABLE_QUICK_RANDOM",
348 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
349 gcry_fast_random_poll ();
350 GNUNET_CRYPTO_seed_weak_random (
352 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
357 * Nicely shut down libgcrypt.
359 void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini ()
361 gcry_set_progress_handler (NULL, NULL);
362 #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
363 (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
368 /* end of crypto_random.c */