tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / util / crypto_random.c
index 6840445d19f7d51846421add1325a8ce178059fb..8bb5f0587e548f2449adaa0a42849759bf62ad37 100644 (file)
@@ -1,21 +1,21 @@
 /*
-     This file is part of GNUnet.
-     (C) 2001-2013 Christian Grothoff (and other contributing authors)
+     This file is part of GNUnet.  Copyright (C) 2001-2014 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 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
+     Affero General Public License for more details.
 
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
 
 */
 
  * @author Christian Grothoff
  */
 #include "platform.h"
-#include "gnunet_util_lib.h"
+#include "gnunet_crypto_lib.h"
 #include <gcrypt.h>
 
-#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-random", __VA_ARGS__)
 
-#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
+#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-crypto-random", syscall)
 
 
 /* TODO: ndurner, move this to plibc? */
@@ -84,7 +84,7 @@ get_weak_random ()
 
 
 /**
- * Seed a weak random generator. Only GNUNET_CRYPTO_QUALITY_WEAK-mode generator
+ * Seed a weak random generator. Only #GNUNET_CRYPTO_QUALITY_WEAK-mode generator
  * can be seeded.
  *
  * @param seed the seed to use
@@ -96,6 +96,34 @@ GNUNET_CRYPTO_seed_weak_random (int32_t seed)
 }
 
 
+/**
+ * @ingroup crypto
+ * Zero out @a buffer, securely against compiler optimizations.
+ * Used to delete key material.
+ *
+ * @param buffer the buffer to zap
+ * @param length buffer length
+ */
+void
+GNUNET_CRYPTO_zero_keys (void *buffer,
+                         size_t length)
+{
+#if HAVE_MEMSET_S
+  memset_s (buffer,
+            length,
+            0,
+            length);
+#elif HAVE_EXPLICIT_BZERO
+  explicit_bzero (buffer,
+                  length);
+#else
+  volatile unsigned char *p = buffer;
+  while (length--)
+    *p++ = 0;
+#endif
+}
+
+
 /**
  * @ingroup crypto
  * Fill block with a random values.
@@ -105,7 +133,9 @@ GNUNET_CRYPTO_seed_weak_random (int32_t seed)
  * @param length buffer length
  */
 void
-GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
+GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode,
+                            void *buffer,
+                            size_t length)
 {
 #ifdef gcry_fast_random_poll
   static unsigned int invokeCount;
@@ -138,14 +168,15 @@ GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, void *buffer, size_
 
 
 /**
- * Produce a random value.
+ * Produce a random unsigned 32-bit number modulo @a i.
  *
  * @param mode desired quality of the random number
  * @param i the upper limit (exclusive) for the random number
  * @return a random value in the interval [0,i[.
  */
 uint32_t
-GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i)
+GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode,
+                          uint32_t i)
 {
 #ifdef gcry_fast_random_poll
   static unsigned int invokeCount;
@@ -194,13 +225,14 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i)
 /**
  * Get an array with a random permutation of the
  * numbers 0...n-1.
- * @param mode GNUNET_RANDOM_QUALITY_STRONG if the strong (but expensive)
- *        PRNG should be used, GNUNET_RANDOM_QUALITY_WEAK otherwise
+ * @param mode #GNUNET_RANDOM_QUALITY_STRONG if the strong (but expensive)
+ *        PRNG should be used, #GNUNET_RANDOM_QUALITY_WEAK otherwise
  * @param n the size of the array
  * @return the permutation array (allocated from heap)
  */
 unsigned int *
-GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n)
+GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode,
+                              unsigned int n)
 {
   unsigned int *ret;
   unsigned int i;
@@ -223,15 +255,15 @@ GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n)
 
 
 /**
- * Random on unsigned 64-bit values.
- *
+ * Generate random unsigned 64-bit value.
  *
  * @param mode desired quality of the random number
  * @param max value returned will be in range [0,max) (exclusive)
  * @return random 64-bit number
  */
 uint64_t
-GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max)
+GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode,
+                          uint64_t max)
 {
   uint64_t ret;
   uint64_t ul;
@@ -269,6 +301,31 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max)
 }
 
 
+/**
+ * Allocation wrapper for libgcrypt, used to avoid bad locking
+ * strategy of libgcrypt implementation.
+ */
+static void *
+w_malloc (size_t n)
+{
+  return calloc (n, 1);
+}
+
+
+/**
+ * Allocation wrapper for libgcrypt, used to avoid bad locking
+ * strategy of libgcrypt implementation.
+ */
+static int
+w_check (const void *p)
+{
+  return 0; /* not secure memory */
+}
+
+
+/**
+ * Initialize libgcrypt.
+ */
 void __attribute__ ((constructor))
 GNUNET_CRYPTO_random_init ()
 {
@@ -279,19 +336,26 @@ GNUNET_CRYPTO_random_init ()
     FPRINTF (stderr,
              _("libgcrypt has not the expected version (version %s is required).\n"),
              NEED_LIBGCRYPT_VERSION);
-    GNUNET_abort ();
+    GNUNET_assert (0);
   }
+  /* set custom allocators */
+  gcry_set_allocation_handler (&w_malloc,
+                               &w_malloc,
+                               &w_check,
+                               &realloc,
+                               &free);
+  /* Disable use of secure memory */
   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,
+  /* Otherwise gnunet-ecc takes forever to complete, besides
      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",
+            "Failed to set libgcrypt option %s: %s\n",
+            "ENABLE_QUICK_RANDOM",
             gcry_strerror (rc));
   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
   gcry_fast_random_poll ();
@@ -301,11 +365,16 @@ GNUNET_CRYPTO_random_init ()
 }
 
 
+/**
+ * Nicely shut down libgcrypt.
+ */
 void __attribute__ ((destructor))
 GNUNET_CRYPTO_random_fini ()
 {
   gcry_set_progress_handler (NULL, NULL);
+#ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
   (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
+#endif
 }