diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2018-06-27 04:03:52 -0500 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2018-06-27 04:07:07 -0500 |
commit | 6085739b0c3aaaaa565835c010b15c12353f1f0e (patch) | |
tree | 9262cb2c0e980846698e7f5ca8a70c04a08861d2 /system/libgcrypt/lock-error.patch | |
parent | 1586a3f2895d37b650ea1e9093fff5d12856e159 (diff) | |
download | packages-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.patch | 378 |
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*/ + } |