summaryrefslogtreecommitdiff
path: root/system/libgcrypt/lock-error.patch
diff options
context:
space:
mode:
authorA. Wilcox <AWilcox@Wilcox-Tech.com>2018-06-27 04:03:52 -0500
committerA. Wilcox <AWilcox@Wilcox-Tech.com>2018-06-27 04:07:07 -0500
commit6085739b0c3aaaaa565835c010b15c12353f1f0e (patch)
tree9262cb2c0e980846698e7f5ca8a70c04a08861d2 /system/libgcrypt/lock-error.patch
parent1586a3f2895d37b650ea1e9093fff5d12856e159 (diff)
downloadpackages-6085739b0c3aaaaa565835c010b15c12353f1f0e.tar.gz
packages-6085739b0c3aaaaa565835c010b15c12353f1f0e.tar.bz2
packages-6085739b0c3aaaaa565835c010b15c12353f1f0e.tar.xz
packages-6085739b0c3aaaaa565835c010b15c12353f1f0e.zip
system/libgcrypt: fix lock behaviour
Diffstat (limited to 'system/libgcrypt/lock-error.patch')
-rw-r--r--system/libgcrypt/lock-error.patch378
1 files changed, 378 insertions, 0 deletions
diff --git a/system/libgcrypt/lock-error.patch b/system/libgcrypt/lock-error.patch
new file mode 100644
index 000000000..505907335
--- /dev/null
+++ b/system/libgcrypt/lock-error.patch
@@ -0,0 +1,378 @@
+diff --git a/random/rndjent.c b/random/rndjent.c
+index 0c5a820..3740ddd 100644
+--- a/random/rndjent.c
++++ b/random/rndjent.c
+@@ -1,371 +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)
+ {
+- lock_rng ();
+ /* 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*/
+ }