summary refs log tree commit diff stats
path: root/libotr/libgcrypt-1.8.7/random/rndjent.c
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2021-04-09 07:19:03 -0300
committerSoniEx2 <endermoneymod@gmail.com>2021-04-09 07:19:03 -0300
commit0e752a6e215aee21dc73da097c3225495d54a5b6 (patch)
treeb81be02cbf2f06aebf322ac4a5d014b44176bba5 /libotr/libgcrypt-1.8.7/random/rndjent.c
parent7754076c715285173311a1b6811ce377950e18a6 (diff)
Add libotr/etc sources
Diffstat (limited to 'libotr/libgcrypt-1.8.7/random/rndjent.c')
-rw-r--r--libotr/libgcrypt-1.8.7/random/rndjent.c372
1 files changed, 372 insertions, 0 deletions
diff --git a/libotr/libgcrypt-1.8.7/random/rndjent.c b/libotr/libgcrypt-1.8.7/random/rndjent.c
new file mode 100644
index 0000000..3740ddd
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/random/rndjent.c
@@ -0,0 +1,372 @@
+/* rndjent.c  - Driver for the jitterentropy module.
+ * Copyright (C) 2017 g10 Code GmbH
+ * Copyright (C) 2017 Bundesamt für Sicherheit in der Informationstechnik
+ * Copyright (C) 2013 Stephan Mueller <smueller@chronox.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include "types.h"
+#include "g10lib.h"
+#include "../cipher/bithelp.h"
+#include "rand-internal.h"
+
+/*
+ * Decide whether we can support jent at compile time.
+ */
+#undef USE_JENT
+#define JENT_USES_RDTSC 1
+#define JENT_USES_GETTIME 2
+#define JENT_USES_READ_REAL_TIME 3
+#ifdef ENABLE_JENT_SUPPORT
+# if defined (__i386__) || defined(__x86_64__)
+#   define USE_JENT JENT_USES_RDTSC
+# elif defined (HAVE_CLOCK_GETTIME)
+#  if _AIX
+#   define USE_JENT JENT_USES_READ_REAL_TIME
+#  else
+#   define USE_JENT JENT_USES_GETTIME
+#  endif
+# endif
+#endif /*ENABLE_JENT_SUPPORT*/
+
+
+#ifdef USE_JENT
+
+#undef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
+/* Uncomment the next line to build with statistics.  */
+/* #define CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT 1 */
+
+
+/* Note that we source include the actual jitter entropy code.
+ * Platform dependent code is indirectly included from our own
+ * jitterentropy-user-base.h file.   */
+
+/* Tell jitterentropy* that all functions shall be static.  */
+#define JENT_PRIVATE_COMPILE 1
+
+#include "jitterentropy-base.c"
+
+
+/* This is the lock we use to serialize access to this RNG.  The extra
+ * integer variable is only used to check the locking state; that is,
+ * it is not meant to be thread-safe but merely as a failsafe feature
+ * to assert proper locking.  */
+GPGRT_LOCK_DEFINE (jent_rng_lock);
+static int jent_rng_is_locked;
+
+/* This flag tracks whether the RNG has been initialized - either
+ * with error or with success.  Protected by JENT_RNG_LOCK. */
+static int jent_rng_is_initialized;
+
+/* Our collector.  The RNG is in a working state if its value is not
+ * NULL.  Protected by JENT_RNG_LOCK.  */
+struct rand_data *jent_rng_collector;
+
+/* The number of times the core entropy function has been called and
+ * the number of random bytes retrieved.  */
+static unsigned long jent_rng_totalcalls;
+static unsigned long jent_rng_totalbytes;
+
+
+
+/* JENT statistic helper code.  */
+#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
+
+static void
+jent_init_statistic (struct rand_data *rand_data)
+{
+  /* int i; */
+  /* struct entropy_stat *stat = &rand_data->entropy_stat; */
+
+  /* for (i = 0; i < 64; i++) */
+  /*   { */
+  /*     stat->bitslot[i] = 0; */
+  /*     stat->bitvar[i] = 0; */
+  /*   } */
+
+  /* jent_get_nstime (&stat->collection_begin); */
+}
+
+static void
+jent_bit_count (struct rand_data *rand_data, u64 prev_data)
+{
+  /* int i; */
+
+  /* if (!rand_data->entropy_stat.enable_bit_test) */
+  /*   return; */
+
+  /* for (i = 0; i < 64; i++) */
+  /*   { */
+  /*     /\* collect the count of set bits per bit position in the */
+  /*      * current ->data field *\/ */
+  /*     rand_data->entropy_stat.bitslot[i] += (rand_data->data & 1<<i) ? 1:0; */
+
+  /*     /\* collect the count of bit changes between the current */
+  /*      * and the previous random data value per bit position *\/ */
+  /*     if ((rand_data->data & 1<<i) != (prev_data & 1<<i)) */
+  /*       rand_data->entropy_stat.bitvar[i] += 1; */
+  /*   } */
+}
+
+
+static void
+jent_statistic_copy_stat (struct entropy_stat *src, struct entropy_stat *dst)
+{
+  /* /\* not copying bitslot and bitvar as they are not needed for */
+  /*  * statistic printout *\/ */
+  /* dst->collection_begin = src->collection_begin; */
+  /* dst->collection_end	= src->collection_end; */
+  /* dst->old_delta	= src->old_delta; */
+  /* dst->setbits		= src->setbits; */
+  /* dst->varbits		= src->varbits; */
+  /* dst->obsbits		= src->obsbits; */
+  /* dst->collection_loop_cnt= src->collection_loop_cnt; */
+}
+
+
+/*
+ * Assessment of statistical behavior of the generated output and returning
+ * the information to the caller by filling the target value.
+ *
+ * Details about the bit statistics are given in chapter 4 of the doc.
+ * Chapter 5 documents the timer analysis and the resulting entropy.
+ */
+static void
+jent_calc_statistic (struct rand_data *rand_data,
+                     struct entropy_stat *target, unsigned int loop_cnt)
+{
+  /* int i; */
+  /* struct entropy_stat *stat = &rand_data->entropy_stat; */
+
+  /* jent_get_nstime(&stat->collection_end); */
+
+  /* stat->collection_loop_cnt = loop_cnt; */
+
+  /* stat->setbits = 0; */
+  /* stat->varbits = 0; */
+  /* stat->obsbits = 0; */
+
+  /* for (i = 0; i < DATA_SIZE_BITS; i++) */
+  /*   { */
+  /*     stat->setbits += stat->bitslot[i]; */
+  /*     stat->varbits += stat->bitvar[i]; */
+
+  /*     /\* This is the sum of set bits in the current observation */
+  /*      * of the random data. *\/ */
+  /*     stat->obsbits += (rand_data->data & 1<<i) ? 1:0; */
+  /*   } */
+
+  /* jent_statistic_copy_stat(stat, target); */
+
+  /* stat->old_delta = (stat->collection_end - stat->collection_begin); */
+}
+
+#endif /*CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT*/
+
+
+/* Acquire the jent_rng_lock.  */
+static void
+lock_rng (void)
+{
+  gpg_err_code_t rc;
+
+  rc = gpgrt_lock_lock (&jent_rng_lock);
+  if (rc)
+    log_fatal ("failed to acquire the Jent RNG lock: %s\n",
+               gpg_strerror (rc));
+  jent_rng_is_locked = 1;
+}
+
+
+/* Release the jent_rng_lock.  */
+static void
+unlock_rng (void)
+{
+  gpg_err_code_t rc;
+
+  jent_rng_is_locked = 0;
+  rc = gpgrt_lock_unlock (&jent_rng_lock);
+  if (rc)
+    log_fatal ("failed to release the Jent RNG lock: %s\n",
+               gpg_strerror (rc));
+}
+
+
+/* Return true if the JENT RNG code can be run.  It may not yet been
+ * initialized, though.  */
+static int
+is_rng_available (void)
+{
+#if USE_JENT == JENT_USES_RDTSC
+  return !!(_gcry_get_hw_features () & HWF_INTEL_RDTSC);
+#elif USE_JENT == JENT_USES_GETTIME
+  return 2;
+#elif USE_JENT == JENT_USES_READ_REAL_TIME
+  return 3;
+#else  /* Ooops  */
+  return 0;
+#endif
+}
+
+#endif /* USE_JENT */
+
+
+/*
+ * The API used by the high level code.
+ */
+
+/* Read up to LENGTH bytes from a jitter RNG and return the number of
+ * bytes actually read.  */
+size_t
+_gcry_rndjent_poll (void (*add)(const void*, size_t, enum random_origins),
+                    enum random_origins origin, size_t length)
+{
+  size_t nbytes = 0;
+
+#ifdef USE_JENT
+  if ( is_rng_available () )
+    {
+      lock_rng ();
+
+      if (!jent_rng_is_initialized)
+        {
+          /* Auto-initialize.  */
+          jent_rng_is_initialized = 1;
+          jent_entropy_collector_free (jent_rng_collector);
+          jent_rng_collector = NULL;
+          if ( !(_gcry_random_read_conf () & RANDOM_CONF_DISABLE_JENT))
+            {
+              if (!jent_entropy_init ())
+                jent_rng_collector = jent_entropy_collector_alloc (1, 0);
+            }
+        }
+
+      if (jent_rng_collector && add)
+        {
+          /* We have a working JENT and it has not been disabled.  */
+          char buffer[32];
+
+          while (length)
+            {
+              int rc;
+              size_t n = length < sizeof(buffer)? length : sizeof (buffer);
+
+              jent_rng_totalcalls++;
+              rc = jent_read_entropy (jent_rng_collector, buffer, n);
+              if (rc < 0)
+                break;
+              /* We need to hash the output to conform to the BSI
+               * NTG.1 specs.  */
+              _gcry_md_hash_buffer (GCRY_MD_SHA256, buffer, buffer, rc);
+              n = rc < 32? rc : 32;
+              (*add) (buffer, n, origin);
+              length -= n;
+              nbytes += n;
+              jent_rng_totalbytes += n;
+            }
+          wipememory (buffer, sizeof buffer);
+        }
+
+      unlock_rng ();
+    }
+
+#else
+
+  (void)add;
+  (void)origin;
+
+#endif
+
+  return nbytes;
+}
+
+
+/* Return the version number of the JENT RNG.  If the RNG is not
+ * initialized or usable 0 is returned.  If R_ACTIVE is not NULL the
+ * jitter RNG will be initialized and true is stored at R_ACTIVE if
+ * the initialization succeeded.  */
+unsigned int
+_gcry_rndjent_get_version (int *r_active)
+{
+  if (r_active)
+    *r_active = 0;
+#ifdef USE_JENT
+  if ( is_rng_available () )
+    {
+      if (r_active)
+        {
+          /* Make sure the RNG is initialized.  */
+          _gcry_rndjent_poll (NULL, 0, 0);
+
+          lock_rng ();
+          /* To ease debugging we store 2 for a clock_gettime based
+           * implementation and 1 for a rdtsc based code.  */
+          *r_active = jent_rng_collector? is_rng_available () : 0;
+          unlock_rng ();
+        }
+      return jent_version ();
+    }
+  else
+    return 0;
+#else
+  return 0;
+#endif
+}
+
+
+/* Log statistical informantion about the use of this module.  */
+void
+_gcry_rndjent_dump_stats (void)
+{
+  /* In theory we would need to lock the stats here.  However this
+   * function is usually called during cleanup and then we _might_ run
+   * into problems.  */
+
+#ifdef USE_JENT
+  if ( is_rng_available () )
+    {
+      log_info ("rndjent stat: collector=%p calls=%lu bytes=%lu\n",
+                jent_rng_collector, jent_rng_totalcalls, jent_rng_totalbytes);
+
+    }
+#endif /*USE_JENT*/
+}