X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcrypto_random.c;h=6840445d19f7d51846421add1325a8ce178059fb;hb=267f7c5a9a354b8959607c7bc031906c02b61be4;hp=a1485029e3551ab6d1221dd7aeb06a5610fe9840;hpb=55ac5056bd7f3997f67bc7a478f3e1d01ffb0e52;p=oweals%2Fgnunet.git diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c index a1485029e..6840445d1 100644 --- a/src/util/crypto_random.c +++ b/src/util/crypto_random.c @@ -1,10 +1,10 @@ /* This file is part of GNUnet. - (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors) + (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but @@ -25,38 +25,46 @@ * @author Christian Grothoff */ #include "platform.h" -#include "gnunet_common.h" -#include "gnunet_crypto_lib.h" -#include "gnunet_os_lib.h" +#include "gnunet_util_lib.h" #include #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) + /* TODO: ndurner, move this to plibc? */ /* The code is derived from glibc, obviously */ -#if MINGW +#if !HAVE_RANDOM || !HAVE_SRANDOM #ifdef RANDOM -# undef RANDOM +#undef RANDOM #endif #ifdef SRANDOM -# undef SRANDOM +#undef SRANDOM #endif #define RANDOM() glibc_weak_rand32() #define SRANDOM(s) glibc_weak_srand32(s) +#if defined(RAND_MAX) +#undef RAND_MAX +#endif +#define RAND_MAX 0x7fffffff /* Hopefully this is correct */ + + static int32_t glibc_weak_rand32_state = 1; + void glibc_weak_srand32 (int32_t s) { glibc_weak_rand32_state = s; } + int32_t glibc_weak_rand32 () { int32_t val = glibc_weak_rand32_state; + val = ((glibc_weak_rand32_state * 1103515245) + 12345) & 0x7fffffff; glibc_weak_rand32_state = val; return val; @@ -69,11 +77,12 @@ glibc_weak_rand32 () * @return number between 0 and 1. */ static double -weak_random () +get_weak_random () { return ((double) RANDOM () / RAND_MAX); } + /** * Seed a weak random generator. Only GNUNET_CRYPTO_QUALITY_WEAK-mode generator * can be seeded. @@ -86,6 +95,48 @@ GNUNET_CRYPTO_seed_weak_random (int32_t seed) SRANDOM (seed); } + +/** + * @ingroup crypto + * Fill block with a random values. + * + * @param mode desired quality of the random number + * @param buffer the buffer to fill + * @param length buffer length + */ +void +GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length) +{ +#ifdef gcry_fast_random_poll + static unsigned int invokeCount; +#endif + switch (mode) + { + case GNUNET_CRYPTO_QUALITY_STRONG: + /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ +#ifdef gcry_fast_random_poll + if ((invokeCount++ % 256) == 0) + gcry_fast_random_poll (); +#endif + gcry_randomize (buffer, length, GCRY_STRONG_RANDOM); + return; + case GNUNET_CRYPTO_QUALITY_NONCE: + gcry_create_nonce (buffer, length); + return; + case GNUNET_CRYPTO_QUALITY_WEAK: + /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ +#ifdef gcry_fast_random_poll + if ((invokeCount++ % 256) == 0) + gcry_fast_random_poll (); +#endif + gcry_randomize (buffer, length, GCRY_WEAK_RANDOM); + return; + default: + GNUNET_assert (0); + } +} + + /** * Produce a random value. * @@ -129,7 +180,7 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i) while (ret >= ul); return ret % i; case GNUNET_CRYPTO_QUALITY_WEAK: - ret = i * weak_random (); + ret = i * get_weak_random (); if (ret >= i) ret = i - 1; return ret; @@ -170,6 +221,7 @@ GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n) return ret; } + /** * Random on unsigned 64-bit values. * @@ -206,7 +258,7 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) return ret % max; case GNUNET_CRYPTO_QUALITY_WEAK: - ret = max * weak_random (); + ret = max * get_weak_random (); if (ret >= max) ret = max - 1; return ret; @@ -216,111 +268,44 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) return 0; } -/** - * This function should only be called in testcases - * where strong entropy gathering is not desired - * (for example, for hostkey generation). - */ -void -GNUNET_CRYPTO_random_disable_entropy_gathering () -{ - gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); -} - - -/** - * Process ID of the "find" process that we use for - * entropy gathering. - */ -static struct GNUNET_OS_Process *genproc; - -/** - * Function called by libgcrypt whenever we are - * blocked gathering entropy. - */ -static void -entropy_generator (void *cls, const char *what, int printchar, int current, - int total) -{ - unsigned long code; - enum GNUNET_OS_ProcessStatusType type; - int ret; - - if (0 != strcmp (what, "need_entropy")) - return; - if (current == total) - { - if (genproc != NULL) - { - if (0 != GNUNET_OS_process_kill (genproc, SIGTERM)) - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "kill"); - GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (genproc)); - GNUNET_OS_process_close (genproc); - genproc = NULL; - } - return; - } - if (genproc != NULL) - { - ret = GNUNET_OS_process_status (genproc, &type, &code); - if (ret == GNUNET_NO) - return; /* still running */ - if (ret == GNUNET_SYSERR) - { - GNUNET_break (0); - return; - } - if (0 != GNUNET_OS_process_kill (genproc, SIGTERM)) - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "kill"); - GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (genproc)); - GNUNET_OS_process_close (genproc); - genproc = NULL; - } - LOG (GNUNET_ERROR_TYPE_INFO, _("Starting `%s' process to generate entropy\n"), - "find"); - genproc = - GNUNET_OS_start_process (NULL, NULL, "sh", "sh", "-c", - "exec find / -mount -type f -exec cp {} /dev/null \\; 2>/dev/null", - NULL); -} - -static void -killfind () +void __attribute__ ((constructor)) +GNUNET_CRYPTO_random_init () { - if (genproc != NULL) - { - GNUNET_OS_process_kill (genproc, SIGKILL); - GNUNET_OS_process_close (genproc); - genproc = NULL; - } -} + gcry_error_t rc; - -void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init () -{ - gcry_control (GCRYCTL_DISABLE_SECMEM, 0); - if (!gcry_check_version (GCRYPT_VERSION)) + if (! gcry_check_version (NEED_LIBGCRYPT_VERSION)) { - fprintf (stderr, - _ - ("libgcrypt has not the expected version (version %s is required).\n"), - GCRYPT_VERSION); + FPRINTF (stderr, + _("libgcrypt has not the expected version (version %s is required).\n"), + NEED_LIBGCRYPT_VERSION); GNUNET_abort (); } -#ifdef gcry_fast_random_poll + if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0))) + FPRINTF (stderr, + "Failed to set libgcrypt option %s: %s\n", + "DISABLE_SECMEM", + gcry_strerror (rc)); + /* we only generate ephemeral keys in-process; for those, + we are fine with "just" using GCRY_STRONG_RANDOM */ + if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0))) + FPRINTF (stderr, + "Failed to set libgcrypt option %s: %s\n", + "ENABLE_QUICK_RANDOM", + gcry_strerror (rc)); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); gcry_fast_random_poll (); -#endif - gcry_set_progress_handler (&entropy_generator, NULL); - atexit (&killfind); GNUNET_CRYPTO_seed_weak_random (time (NULL) ^ - GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX)); + GNUNET_CRYPTO_random_u32 + (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX)); } -void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini () +void __attribute__ ((destructor)) +GNUNET_CRYPTO_random_fini () { gcry_set_progress_handler (NULL, NULL); + (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0); }