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;
78 * Create a cryptographically weak pseudo-random number in the interval of 0 to 1.
80 * @return number between 0 and 1.
85 return((double) random () / RAND_MAX);
90 * Seed a weak random generator. Only #GNUNET_CRYPTO_QUALITY_WEAK-mode generator
93 * @param seed the seed to use
96 GNUNET_CRYPTO_seed_weak_random (int32_t seed)
104 * Zero out @a buffer, securely against compiler optimizations.
105 * Used to delete key material.
107 * @param buffer the buffer to zap
108 * @param length buffer length
111 GNUNET_CRYPTO_zero_keys (void *buffer, size_t length)
114 memset_s (buffer, length, 0, length);
115 #elif HAVE_EXPLICIT_BZERO
116 explicit_bzero (buffer, length);
118 volatile unsigned char *p = buffer;
127 * Fill block with a random values.
129 * @param mode desired quality of the random number
130 * @param buffer the buffer to fill
131 * @param length buffer length
134 GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode,
138 #ifdef gcry_fast_random_poll
139 static unsigned int invokeCount;
143 case GNUNET_CRYPTO_QUALITY_STRONG:
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 ();
149 gcry_randomize (buffer, length, GCRY_STRONG_RANDOM);
152 case GNUNET_CRYPTO_QUALITY_NONCE:
153 gcry_create_nonce (buffer, length);
156 case GNUNET_CRYPTO_QUALITY_WEAK:
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 ();
162 gcry_randomize (buffer, length, GCRY_WEAK_RANDOM);
172 * Produce a random unsigned 32-bit number modulo @a i.
174 * @param mode desired quality of the random number
175 * @param i the upper limit (exclusive) for the random number
176 * @return a random value in the interval [0,i[.
179 GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i)
181 #ifdef gcry_fast_random_poll
182 static unsigned int invokeCount;
187 GNUNET_assert (i > 0);
191 case GNUNET_CRYPTO_QUALITY_STRONG:
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 ();
197 ul = UINT32_MAX - (UINT32_MAX % i);
200 gcry_randomize ((unsigned char *) &ret,
207 case GNUNET_CRYPTO_QUALITY_NONCE:
208 ul = UINT32_MAX - (UINT32_MAX % i);
211 gcry_create_nonce (&ret, sizeof(ret));
216 case GNUNET_CRYPTO_QUALITY_WEAK:
217 ret = i * get_weak_random ();
230 * Get an array with a random permutation of the
232 * @param mode #GNUNET_RANDOM_QUALITY_STRONG if the strong (but expensive)
233 * PRNG should be used, #GNUNET_RANDOM_QUALITY_WEAK otherwise
234 * @param n the size of the array
235 * @return the permutation array (allocated from heap)
238 GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n)
245 GNUNET_assert (n > 0);
246 ret = GNUNET_malloc (n * sizeof(unsigned int));
247 for (i = 0; i < n; i++)
249 for (i = n - 1; i > 0; i--)
251 x = GNUNET_CRYPTO_random_u32 (mode, i + 1);
261 * Generate random unsigned 64-bit value.
263 * @param mode desired quality of the random number
264 * @param max value returned will be in range [0,max) (exclusive)
265 * @return random 64-bit number
268 GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max)
273 GNUNET_assert (max > 0);
276 case GNUNET_CRYPTO_QUALITY_STRONG:
277 ul = UINT64_MAX - (UINT64_MAX % max);
280 gcry_randomize ((unsigned char *) &ret,
287 case GNUNET_CRYPTO_QUALITY_NONCE:
288 ul = UINT64_MAX - (UINT64_MAX % max);
291 gcry_create_nonce (&ret, sizeof(ret));
297 case GNUNET_CRYPTO_QUALITY_WEAK:
298 ret = max * get_weak_random ();
311 * Allocation wrapper for libgcrypt, used to avoid bad locking
312 * strategy of libgcrypt implementation.
317 return calloc (n, 1);
322 * Allocation wrapper for libgcrypt, used to avoid bad locking
323 * strategy of libgcrypt implementation.
326 w_check (const void *p)
329 return 0; /* not secure memory */
334 * Initialize libgcrypt.
336 void __attribute__ ((constructor))
337 GNUNET_CRYPTO_random_init ()
341 if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
345 _ ("libgcrypt has not the expected version (version %s is required).\n"),
346 NEED_LIBGCRYPT_VERSION);
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)))
354 "Failed to set libgcrypt option %s: %s\n",
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)))
361 "Failed to set libgcrypt option %s: %s\n",
362 "ENABLE_QUICK_RANDOM",
364 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
365 gcry_fast_random_poll ();
366 GNUNET_CRYPTO_seed_weak_random (
368 ^ GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
373 * Nicely shut down libgcrypt.
375 void __attribute__ ((destructor))
376 GNUNET_CRYPTO_random_fini ()
378 gcry_set_progress_handler (NULL, NULL);
379 #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
380 (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
385 /* end of crypto_random.c */