tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / util / crypto_random.c
index d3200d2bb5fd0e7c2525824baa3442bf2141a5d7..8bb5f0587e548f2449adaa0a42849759bf62ad37 100644 (file)
@@ -3,7 +3,7 @@
      (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
+     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.
 
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      Affero General Public License for more details.
 
+     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
+
 */
 
 /**
@@ -91,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.
@@ -100,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;
@@ -141,7 +176,7 @@ GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, void *buffer, size_
  */
 uint32_t
 GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode,
-                         uint32_t i)
+                          uint32_t i)
 {
 #ifdef gcry_fast_random_poll
   static unsigned int invokeCount;
@@ -197,7 +232,7 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode,
  */
 unsigned int *
 GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode,
-                             unsigned int n)
+                              unsigned int n)
 {
   unsigned int *ret;
   unsigned int i;
@@ -227,7 +262,8 @@ GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode,
  * @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;
@@ -265,6 +301,28 @@ 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.
  */
@@ -280,6 +338,13 @@ GNUNET_CRYPTO_random_init ()
              NEED_LIBGCRYPT_VERSION);
     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",