Linux cryptographic layer development
 help / color / mirror / Atom feed
* [PATCH v6 3/5] crypto: Linux Random Number Generator
From: Stephan Mueller @ 2016-08-11 12:25 UTC (permalink / raw)
  To: herbert
  Cc: Ted Tso, sandyinchina, Jason Cooper, John Denker, H. Peter Anvin,
	Joe Perches, Pavel Machek, George Spelvin, linux-crypto,
	linux-kernel
In-Reply-To: <4723196.TTQvcXsLCG@positron.chronox.de>

The LRNG with the following properties:

* noise source: interrupts timing with fast boot time seeding

* lockless LFSR to collect raw entropy

* use of kernel crypto API DRBG

* in case kernel crypto API is not compiled, use standalone
  ChaCha20 based RNG

* used cipher types for hashes and DRBG is selectable at
  compile time

* "atomic" seeding of secondary DRBG to ensure full entropy
  transport

* instantiate one DRBG per NUMA node

Further details including the rationale for the design choices and
properties of the LRNG together with testing is provided at [1].
In addition, the documentation explains the conducted regression
tests to verify that the LRNG is API and ABI compatible with the
legacy /dev/random implementation.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/lrng_base.c  | 1960 +++++++++++++++++++++++++++++++++++++++++++++++++++
 crypto/lrng_kcapi.c |  167 +++++
 2 files changed, 2127 insertions(+)
 create mode 100644 crypto/lrng_base.c
 create mode 100644 crypto/lrng_kcapi.c

diff --git a/crypto/lrng_base.c b/crypto/lrng_base.c
new file mode 100644
index 0000000..ab92298
--- /dev/null
+++ b/crypto/lrng_base.c
@@ -0,0 +1,1960 @@
+/*
+ * Linux Random Number Generator (LRNG)
+ *
+ * Documentation and test code: http://www.chronox.de/lrng.html
+ *
+ * Copyright (C) 2016, 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 GPL2
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/timex.h>
+#include <linux/percpu.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/random.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
+#include <linux/cryptohash.h>
+#include <linux/syscalls.h>
+#include <linux/uuid.h>
+#include <linux/fips.h>
+#include <linux/slab.h>
+
+/*
+ * Define a DRBG plus a hash / MAC used to extract data from the entropy pool.
+ * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice
+ * (Note, you should use the suggested selections below -- using SHA-1 or MD5
+ * is not wise). The idea is that the used cipher primitive can be selected to
+ * be the same as used for the DRBG. I.e. the LRNG only uses one cipher
+ * primitive using the same cipher implementation with the options offered in
+ * the following. This means, if the CTR DRBG is selected and AES-NI is present,
+ * both the CTR DRBG and the selected cmac(aes) use AES-NI.
+ *
+ * The security strengths of the DRBGs are taken from SP800-57 section 5.6.1.
+ *
+ * This definition is allowed to be changed.
+ */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+# define LRNG_HASH_NAME "cmac(aes)"
+# if 0
+#  define LRNG_DRBG_BLOCKLEN_BYTES 16
+#  define LRNG_DRBG_SECURITY_STRENGTH_BYTES 16
+#  define LRNG_DRBG_CORE "drbg_nopr_ctr_aes128"		/* CTR DRBG AES-128 */
+# else
+#  define LRNG_DRBG_BLOCKLEN_BYTES 16
+#  define LRNG_DRBG_SECURITY_STRENGTH_BYTES 32
+#  define LRNG_DRBG_CORE "drbg_nopr_ctr_aes256"		/* CTR DRBG AES-256 */
+# endif
+#elif defined CONFIG_CRYPTO_DRBG_HMAC
+# if 0
+#  define LRNG_DRBG_BLOCKLEN_BYTES 32
+#  define LRNG_DRBG_SECURITY_STRENGTH_BYTES 16
+#  define LRNG_DRBG_CORE "drbg_nopr_hmac_sha256"	/* HMAC DRBG SHA-256 */
+#  define LRNG_HASH_NAME "sha256"
+# else
+#  define LRNG_DRBG_BLOCKLEN_BYTES 64
+#  define LRNG_DRBG_SECURITY_STRENGTH_BYTES 32
+#  define LRNG_DRBG_CORE "drbg_nopr_hmac_sha512"	/* HMAC DRBG SHA-512 */
+#  define LRNG_HASH_NAME "sha512"
+# endif
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+# if 0
+#  define LRNG_DRBG_BLOCKLEN_BYTES 32
+#  define LRNG_DRBG_SECURITY_STRENGTH_BYTES 16
+#  define LRNG_DRBG_CORE "drbg_nopr_sha256"		/* Hash DRBG SHA-256 */
+#  define LRNG_HASH_NAME "sha256"
+# else
+#  define LRNG_DRBG_BLOCKLEN_BYTES 64
+#  define LRNG_DRBG_SECURITY_STRENGTH_BYTES 32
+#  define LRNG_DRBG_CORE "drbg_nopr_sha512"		/* Hash DRBG SHA-512 */
+#  define LRNG_HASH_NAME "sha512"
+# endif
+#else
+# define LRNG_DRBG_BLOCKLEN_BYTES 64
+# define LRNG_DRBG_SECURITY_STRENGTH_BYTES 32
+# define LRNG_DRBG_CORE "ChaCha20"			/* ChaCha20 */
+# define LRNG_HASH_NAME "sha1"
+#endif
+
+#define LRNG_DRBG_SECURITY_STRENGTH_BITS (LRNG_DRBG_SECURITY_STRENGTH_BYTES * 8)
+
+/* Alignmask which should cover all cipher implementations */
+#define LRNG_KCAPI_ALIGN 8
+
+/* Primary DRBG state handle */
+struct lrng_pdrbg {
+	void *pdrbg;			/* DRNG handle */
+	bool pdrbg_fully_seeded;	/* Is DRBG fully seeded? */
+	bool pdrbg_min_seeded;		/* Is DRBG minimally seeded? */
+	u32 pdrbg_entropy_bits;		/* Is DRBG entropy level */
+	struct work_struct lrng_seed_work;	/* (re)seed work queue */
+	spinlock_t lock;
+};
+
+/* Secondary DRBG state handle */
+struct lrng_sdrbg {
+	void *sdrbg;			/* DRNG handle */
+	atomic_t requests;		/* Number of DRBG requests */
+	unsigned long last_seeded;	/* Last time it was seeded */
+	bool fully_seeded;		/* Is DRBG fully seeded? */
+	spinlock_t lock;
+};
+
+/*
+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is
+ * considered a safer margin. This applies to secondary DRBG.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRBG_MAX_REQSIZE (1<<12)
+
+/*
+ * SP800-90A defines a maximum number of requests between reseeds of 1<<48.
+ * The given value is considered a much safer margin, balancing requests for
+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be
+ * larger than INT_MAX because it is used in an atomic_t. This applies to
+ * secondary DRBG.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRBG_RESEED_THRESH (1<<12)
+
+/* Status information about IRQ noise source */
+struct lrng_irq_info {
+	atomic_t num_events;	/* Number of non-stuck IRQs since last read */
+	atomic_t num_events_thresh;	/* Reseed threshold */
+	atomic_t last_time;	/* Stuck test: time of previous IRQ */
+	atomic_t last_delta;	/* Stuck test: delta of previous IRQ */
+	atomic_t last_delta2;	/* Stuck test: 2. time derivation of prev IRQ */
+	atomic_t reseed_in_progress;	/* Flag for on executing reseed */
+	atomic_t crngt_ctr;	/* FIPS 140-2 CRNGT counter */
+	bool irq_highres_timer;	/* Is high-resolution timer available? */
+	u32 irq_entropy_bits;	/* LRNG_IRQ_ENTROPY_BITS? */
+};
+
+/*
+ * According to FIPS 140-2 IG 9.8, our C threshold is at 3 back to back stuck
+ * values. It should be highly unlikely that we see three consecutive
+ * identical time stamps.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_FIPS_CRNGT 3
+
+/*
+ * This is the entropy pool used by the slow noise source. Its size should
+ * be at least as large as the interrupt entropy estimate.
+ *
+ * The pool array is aligned to 8 bytes to comfort the kernel crypto API cipher
+ * implementations: for some accelerated implementations, we need an alignment
+ * to avoid a realignment which involes memcpy(). The alignment to 8 bytes
+ * should satisfy all crypto implementations.
+ *
+ * LRNG_POOL_SIZE is allowed to be changed only if the taps for the LFSR are
+ * changed as well. The size must be in powers of 2 due to the mask handling in
+ * lrng_pool_lfsr which uses AND instead of modulo.
+ *
+ * The polynomials for the LFSR are taken from the following URL
+ * which lists primitive polynomials
+ * http://courses.cse.tamu.edu/csce680/walker/lfsr_table.pdf. The first
+ * polynomial is from "Primitive Binary Polynomials" by Wayne Stahnke (1993)
+ * and is primitive as well as irreducible.
+ *
+ * Note, the tap values are smaller by one compared to the documentation because
+ * they are used as an index into an array where the index starts by zero.
+ *
+ * All polynomials were also checked to be primitive with magma.
+ */
+static u32 const lrng_lfsr_polynomial[] =
+	{ 127, 28, 26, 1 };			/* 128 words by Stahnke */
+	/* { 255, 253, 250, 245 }; */		/* 256 words */
+	/* { 511, 509, 506, 503 }; */		/* 512 words */
+	/* { 1023, 1014, 1001, 1000 }; */	/* 1024 words */
+	/* { 2047, 2034, 2033, 2028 }; */	/* 2048 words */
+	/* { 4095, 4094, 4080, 4068 }; */	/* 4096 words */
+struct lrng_pool {
+#define LRNG_POOL_SIZE 128
+#define LRNG_POOL_WORD_BYTES (sizeof(atomic_t))
+#define LRNG_POOL_SIZE_BYTES (LRNG_POOL_SIZE * LRNG_POOL_WORD_BYTES)
+#define LRNG_POOL_SIZE_BITS (LRNG_POOL_SIZE_BYTES * 8)
+#define LRNG_POOL_WORD_BITS (LRNG_POOL_WORD_BYTES * 8)
+	atomic_t pool[LRNG_POOL_SIZE] __aligned(LRNG_KCAPI_ALIGN); /* Pool */
+	atomic_t pool_ptr;	/* Ptr into pool for next IRQ word injection */
+	atomic_t input_rotate;	/* rotate for LFSR */
+	u32 last_numa_node;	/* Last NUMA node */
+	void *lrng_hash;
+	struct lrng_irq_info irq_info;	/* IRQ noise source status info */
+};
+
+/*
+ * Number of interrupts to be recorded to assume that DRBG security strength
+ * bits of entropy are received.
+ * Note: a value below the DRBG security strength should not be defined as this
+ *	 may imply the DRBG can never be fully seeded in case other noise
+ *	 sources are unavailable.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_ENTROPY_BYTES (LRNG_DRBG_SECURITY_STRENGTH_BYTES)
+#define LRNG_IRQ_ENTROPY_BITS (LRNG_IRQ_ENTROPY_BYTES * 8)
+
+/*
+ * Leave given amount of entropy in bits entropy pool to serve /dev/random while
+ * /dev/urandom is stressed.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_EMERG_ENTROPY (LRNG_DRBG_SECURITY_STRENGTH_BITS * 2)
+
+/*
+ * Min required seed entropy is 112 bits as per FIPS 140-2 and AIS20/31.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_MIN_SEED_ENTROPY_BITS 112
+
+#define LRNG_INIT_ENTROPY_BITS 32
+/*
+ * Oversampling factor of IRQ events to obtain
+ * LRNG_DRBG_SECURITY_STRENGTH_BYTES. This factor is used when a
+ * high-resolution time stamp is not available. In this case, jiffies and
+ * register contents are used to fill the entropy pool. These noise sources
+ * are much less entropic than the high-resolution timer. The entropy content
+ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BYTES divided by
+ * LRNG_IRQ_OVERSAMPLING_FACTOR.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_OVERSAMPLING_FACTOR 10
+
+static struct lrng_pdrbg lrng_pdrbg = {
+	.lock = __SPIN_LOCK_UNLOCKED(lrng.pdrbg.lock)
+};
+
+static struct lrng_sdrbg **lrng_sdrbg __read_mostly;
+
+static struct lrng_pool lrng_pool = {
+	.irq_info = {
+		.crngt_ctr = ATOMIC_INIT(LRNG_FIPS_CRNGT),
+	},
+};
+
+static LIST_HEAD(lrng_ready_list);
+static DEFINE_SPINLOCK(lrng_ready_list_lock);
+
+static atomic_t lrng_pdrbg_avail = ATOMIC_INIT(0);
+static atomic_t lrng_initrng_bytes = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(lrng_init_rng_lock);	/* Lock the init RNG state */
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_read_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_pdrbg_init_wait);
+static struct fasync_struct *fasync;
+
+/*
+ * Estimated entropy of data is a 32th of LRNG_DRBG_SECURITY_STRENGTH_BITS.
+ * As we have no ability to review the implementation of those noise sources,
+ * it is prudent to have a conservative estimate here.
+ */
+static u32 archrandom = LRNG_DRBG_SECURITY_STRENGTH_BITS>>5;
+module_param(archrandom, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise source (e.g. RDRAND)");
+
+/*
+ * If the entropy count falls under this number of bits, then we
+ * should wake up processes which are selecting or polling on write
+ * access to /dev/random.
+ */
+static u32 lrng_write_wakeup_bits = LRNG_DRBG_SECURITY_STRENGTH_BITS;
+
+/*
+ * The minimum number of bits of entropy before we wake up a read on
+ * /dev/random.
+ */
+static u32 lrng_read_wakeup_bits = LRNG_POOL_WORD_BITS * 2;
+
+/*
+ * Maximum number of seconds between DRBG reseed intervals of the secondary
+ * DRBG. Note, this is enforced with the next request of random numbers from
+ * the secondary DRBG. Setting this value to zero implies a reseeding attempt
+ * before every generated random number.
+ */
+static int lrng_sdrbg_reseed_max_time = 600;
+
+/************************** Crypto Implementations ***************************/
+
+/**
+ * Allocate DRNG -- the provided integers should be used for sanity checks.
+ * @return: allocated data structure or NULL on error
+ */
+void *lrng_drng_alloc(u8 *drng_name, u32 blocklen_bytes, u32 sec_strength);
+
+/* Deallocate DRNG */
+void lrng_drng_dealloc(void *drng);
+
+/**
+ * Seed the DRNG with data of arbitrary length
+ * @drng: is pointer to data structure allocated with lrng_drng_alloc
+ * @return: >= 0 on success, < 0 on error
+ */
+int lrng_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen);
+
+/**
+ * Generate random numbers from the DRNG with arbitrary length
+ * @return: generated number of bytes, < 0 on error
+ */
+int lrng_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen);
+
+/**
+ * Allocate the hash for reading the entropy pool
+ * @return: allocated data structure (NULL is success too) or ERR_PTR on error
+ */
+void *lrng_hash_alloc(u8 *hashname, u8 *key, u32 keylen);
+
+/**
+ * Return the digestsize for the used hash to read out entropy pool
+ * @hash: is pointer to data structure allocated with lrng_hash_alloc
+ * @return: size of digest of hash in bytes
+ */
+u32 lrng_hash_digestsize(void *hash);
+
+/**
+ * Generate hash
+ * @hash: is pointer to data structure allocated with lrng_hash_alloc
+ * @return: 0 on success, < 0 on error
+ */
+int lrng_hash_buffer(void *hash, u8 *inbuf, u32 inbuflen, u8 *digest);
+
+/********************************** Helper ***********************************/
+
+static inline u32 atomic_read_u32(atomic_t *v)
+{
+	return (u32)atomic_read(v);
+}
+
+static inline u32 atomic_xchg_u32(atomic_t *v, u32 x)
+{
+	return (u32)atomic_xchg(v, x);
+}
+
+static inline u32 lrng_entropy_to_data(u32 entropy_bits)
+{
+	return ((entropy_bits * lrng_pool.irq_info.irq_entropy_bits) /
+		LRNG_DRBG_SECURITY_STRENGTH_BITS);
+}
+
+static inline u32 lrng_data_to_entropy(u32 irqnum)
+{
+	return ((irqnum * LRNG_DRBG_SECURITY_STRENGTH_BITS) /
+		lrng_pool.irq_info.irq_entropy_bits);
+}
+
+static inline u32 lrng_avail_entropy(void)
+{
+	return min_t(u32, LRNG_POOL_SIZE_BITS,
+		     lrng_data_to_entropy(atomic_read_u32(
+					&lrng_pool.irq_info.num_events)));
+}
+
+static inline void lrng_set_entropy_thresh(u32 new)
+{
+	atomic_set(&lrng_pool.irq_info.num_events_thresh,
+		   lrng_entropy_to_data(new));
+}
+
+/* Is the primary DRBG seed level too low? */
+static inline bool lrng_need_entropy(void)
+{
+	return (lrng_pdrbg.pdrbg_entropy_bits < lrng_write_wakeup_bits);
+}
+
+/* Is the entropy pool filled for /dev/random pull or DRBG fully seeded? */
+static inline bool lrng_have_entropy_full(void)
+{
+	return ((lrng_avail_entropy() >= lrng_read_wakeup_bits) ||
+		lrng_pdrbg.pdrbg_entropy_bits >=
+					LRNG_DRBG_SECURITY_STRENGTH_BITS);
+}
+
+/*********************** Fast soise source processing ************************/
+
+/**
+ * Get CPU noise source entropy
+ *
+ * @outbuf: buffer to store entropy of size LRNG_DRBG_SECURITY_STRENGTH_BYTES
+ * @return: > 0 on success where value provides the added entropy in bits
+ *	    0 if no fast source was available
+ */
+static inline u32 lrng_get_arch(u8 *outbuf)
+{
+	u32 i;
+	u32 ent_bits = archrandom;
+
+	/* operate on full blocks */
+	BUILD_BUG_ON(LRNG_DRBG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long));
+
+	if (!ent_bits)
+		return 0;
+
+	for (i = 0; i < LRNG_DRBG_SECURITY_STRENGTH_BYTES;
+	     i += sizeof(unsigned long)) {
+		if (!arch_get_random_long((unsigned long *)(outbuf + i))) {
+			archrandom = 0;
+			return 0;
+		}
+	}
+
+	/* Obtain entropy statement -- cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, LRNG_DRBG_SECURITY_STRENGTH_BITS);
+	pr_debug("obtained %u bits of entropy from CPU RNG noise source\n",
+		 ent_bits);
+	return ent_bits;
+}
+
+/************************ Slow noise source processing ************************/
+
+/*
+ * Implement a (modified) twisted Generalized Feedback Shift Register. (See M.
+ * Matsumoto & Y. Kurita, 1992.  Twisted GFSR generators. ACM Transactions on
+ * Modeling and Computer Simulation 2(3):179-194.  Also see M. Matsumoto & Y.
+ * Kurita, 1994.  Twisted GFSR generators II.  ACM Transactions on Modeling and
+ * Computer Simulation 4:254-266).
+ */
+static u32 const lrng_twist_table[8] = {
+	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
+/**
+ * Hot code path - inject data into entropy pool using LFSR
+ */
+static void lrng_pool_lfsr(const u8 *buf, u32 buflen)
+{
+	u32 mask = (LRNG_POOL_SIZE - 1);
+
+	while (buflen--) {
+		u32 ptr = (u32)atomic_add_return(1, &lrng_pool.pool_ptr) & mask;
+		/*
+		 * Add 7 bits of rotation to the pool. At the beginning of the
+		 * pool, add an extra 7 bits rotation, so that successive passes
+		 * spread the input bits across the pool evenly.
+		 */
+		u32 input_rotate = (u32)atomic_add_return((ptr ? 7 : 14),
+						&lrng_pool.input_rotate) & 31;
+		u32 word = rol32(*buf++, input_rotate);
+
+		BUILD_BUG_ON(LRNG_POOL_SIZE - 1 != lrng_lfsr_polynomial[0]);
+		word ^= atomic_read_u32(&lrng_pool.pool[ptr]);
+		word ^= atomic_read_u32(&lrng_pool.pool[
+				(ptr + lrng_lfsr_polynomial[0]) & mask]);
+		word ^= atomic_read_u32(&lrng_pool.pool[
+				(ptr + lrng_lfsr_polynomial[1]) & mask]);
+		word ^= atomic_read_u32(&lrng_pool.pool[
+				(ptr + lrng_lfsr_polynomial[2]) & mask]);
+		word ^= atomic_read_u32(&lrng_pool.pool[
+				(ptr + lrng_lfsr_polynomial[3]) & mask]);
+
+		word = (word >> 3) ^ lrng_twist_table[word & 7];
+		atomic_set(&lrng_pool.pool[ptr], word);
+	}
+}
+
+/**
+ * Hot code path - Stuck test by checking the:
+ *      1st derivation of the event occurrence (time delta)
+ *      2nd derivation of the event occurrence (delta of time deltas)
+ *      3rd derivation of the event occurrence (delta of delta of time deltas)
+ *
+ * All values must always be non-zero. This is also the FIPS 140-2 CRNGT.
+ *
+ * @irq_info: Reference to IRQ information
+ * @now: Event time
+ * @return: 0 event occurrence not stuck (good bit)
+ *	    1 event occurrence stuck (reject bit)
+ */
+static int lrng_irq_stuck(struct lrng_irq_info *irq_info, u32 now_time)
+{
+	u32 delta = now_time - atomic_xchg_u32(&irq_info->last_time, now_time);
+	int delta2 = delta - atomic_xchg_u32(&irq_info->last_delta, delta);
+	int delta3 = delta2 - atomic_xchg(&irq_info->last_delta2, delta2);
+
+#ifdef CONFIG_CRYPTO_FIPS
+	if (fips_enabled) {
+		if (!delta) {
+			if (atomic_dec_and_test(&irq_info->crngt_ctr))
+				panic("FIPS 140-2 continuous random number generator test failed\n");
+		} else
+			atomic_set(&irq_info->crngt_ctr, LRNG_FIPS_CRNGT);
+	}
+#endif
+
+	if (!delta || !delta2 || !delta3)
+		return 1;
+
+	return 0;
+}
+
+/**
+ * Hot code path - mix data into entropy pool
+ */
+static inline void lrng_pool_mixin(const u8 *buf, u32 buflen, u32 irq_num)
+{
+	lrng_pool_lfsr(buf, buflen);
+
+	/* Should we wake readers? */
+	if (irq_num == lrng_entropy_to_data(lrng_read_wakeup_bits)) {
+		wake_up_interruptible(&lrng_read_wait);
+		kill_fasync(&fasync, SIGIO, POLL_IN);
+	}
+
+	/* Only try to reseed if the DRBG is alive. */
+	if (!atomic_read(&lrng_pdrbg_avail))
+		return;
+
+	/*
+	 * Once all secondary DRBGs are fully seeded, the interrupt noise
+	 * sources will not trigger any reseeding any more.
+	 */
+	if (lrng_sdrbg[lrng_pool.last_numa_node]->fully_seeded)
+		return;
+
+	/* Only trigger the DRBG reseed if we have collected enough IRQs. */
+	if (atomic_read_u32(&lrng_pool.irq_info.num_events) <
+	    atomic_read_u32(&lrng_pool.irq_info.num_events_thresh))
+		return;
+
+	/* Ensure that the seeding only occurs once at any given time. */
+	if (atomic_cmpxchg(&lrng_pool.irq_info.reseed_in_progress, 0, 1))
+		return;
+
+	/* Seed the DRBG with IRQ noise. */
+	schedule_work(&lrng_pdrbg.lrng_seed_work);
+}
+
+/**
+ * Hot code path - Callback for interrupt handler
+ */
+void add_interrupt_randomness(int irq, int irq_flags)
+{
+	u32 now_time = random_get_entropy();
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+	u32 irq_num = (u32)atomic_add_return(1, &irq_info->num_events);
+
+	if (lrng_pool.irq_info.irq_highres_timer) {
+		if (lrng_irq_stuck(irq_info, now_time))
+			return;
+		lrng_pool_mixin((u8 *)&now_time, sizeof(now_time), irq_num);
+	} else {
+		struct pt_regs *regs = get_irq_regs();
+		static atomic_t reg_idx = ATOMIC_INIT(0);
+
+		struct {
+			long jiffies;
+			int irq;
+			int irq_flags;
+			u64 ip;
+			u32 curr_reg;
+		} data;
+
+		data.jiffies = jiffies;
+		data.irq = irq;
+		data.irq_flags = irq_flags;
+		if (regs) {
+			u32 *ptr = (u32 *)regs;
+
+			data.ip = instruction_pointer(regs);
+			if (atomic_read(&reg_idx) >=
+					sizeof(struct pt_regs) / sizeof(u32))
+				atomic_set(&reg_idx, 0);
+			data.curr_reg = *(ptr + atomic_add_return(1, &reg_idx));
+		}
+
+		lrng_pool_mixin((u8 *)&data, sizeof(data), irq_num);
+	}
+}
+EXPORT_SYMBOL(add_interrupt_randomness);
+
+/**
+ * Callback for HID layer
+ */
+void add_input_randomness(unsigned int type, unsigned int code,
+			  unsigned int value)
+{
+	static unsigned char last_value;
+	unsigned int val;
+
+	/* ignore autorepeat and the like */
+	if (value == last_value)
+		return;
+
+	last_value = value;
+
+	val = (type << 4) ^ code ^ (code >> 4) ^ value;
+	lrng_pool_mixin((u8 *)&val, sizeof(val), 0);
+}
+EXPORT_SYMBOL_GPL(add_input_randomness);
+
+/**
+ * Read the entropy pool out for use. The caller must ensure this function
+ * is only called once at a time.
+ *
+ * This function handles the translation from the number of received interrupts
+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BYTES
+ * which defines how many interrupts must be received to obtain 256 bits of
+ * entropy. With this value, the function lrng_data_to_entropy converts a given
+ * data size (received interrupts, requested amount of data, etc.) into an
+ * entropy statement. lrng_entropy_to_data does the reverse.
+ *
+ * Both functions are agnostic about the type of data: when the number of
+ * interrupts is processed by these functions, the resulting entropy value is in
+ * bits as we assume the entropy of interrupts is measured in bits. When data is
+ * processed, the entropy value is in bytes as the data is measured in bytes.
+ *
+ * @outbuf: buffer to store data in with size LRNG_DRBG_SECURITY_STRENGTH_BYTES
+ * @requested_entropy_bits: requested bits of entropy -- the function will
+ *			    return at least this amount of entropy if available
+ * @drain: boolean indicating that that all entropy of pool can be used
+ *	   (otherwise some emergency amount of entropy is left)
+ * @return: estimated entropy from the IRQs that went into the pool since last
+ *	    readout.
+ */
+static u32 lrng_get_pool(u8 *outbuf, u32 requested_entropy_bits, bool drain)
+{
+	u32 i, avail_entropy_bytes, irq_num_events_used, irq_num_event_back;
+	/* How many unused interrupts are in entropy pool? */
+	u32 irq_num_events = atomic_xchg_u32(&lrng_pool.irq_info.num_events, 0);
+	/* Convert available interrupts into entropy statement */
+	u32 avail_entropy_bits = lrng_data_to_entropy(irq_num_events);
+	u32 digestsize = lrng_hash_digestsize(lrng_pool.lrng_hash);
+	u8 digest[digestsize] __aligned(LRNG_KCAPI_ALIGN);
+
+	/* Cap available entropy to pool size */
+	avail_entropy_bits =
+			min_t(u32, avail_entropy_bits, LRNG_POOL_SIZE_BITS);
+
+	/* How much entropy we need to and can we use? */
+	if (drain)
+		avail_entropy_bits = min_t(u32, avail_entropy_bits,
+					   requested_entropy_bits);
+	else
+		avail_entropy_bits = min_t(u32, (avail_entropy_bits -
+			 min_t(u32, LRNG_EMERG_ENTROPY, avail_entropy_bits)),
+						requested_entropy_bits);
+
+	/* Hash is a compression function: we generate entropy amount of data */
+	avail_entropy_bits = round_down(avail_entropy_bits, 8);
+	avail_entropy_bytes = avail_entropy_bits >> 3;
+	BUG_ON(avail_entropy_bytes > LRNG_DRBG_SECURITY_STRENGTH_BYTES);
+
+	/* Hash the entire entropy pool */
+	for (i = 0;
+	     i < LRNG_DRBG_SECURITY_STRENGTH_BYTES && avail_entropy_bytes > 0;
+	     i += digestsize) {
+		u32 tocopy = min3(avail_entropy_bytes, digestsize,
+				  (LRNG_DRBG_SECURITY_STRENGTH_BYTES - i));
+
+		if (lrng_hash_buffer(lrng_pool.lrng_hash, (u8 *)lrng_pool.pool,
+				     LRNG_POOL_SIZE_BYTES, digest))
+			return 0;
+
+		/* Mix read data back into pool for backtracking resistance */
+		lrng_pool_lfsr(digest, digestsize);
+		/* Copy the data out to the caller */
+		memcpy(outbuf + i, digest, tocopy);
+		avail_entropy_bytes -= tocopy;
+	}
+	memzero_explicit(digest, digestsize);
+
+	/* There may be new events that came in while we processed this logic */
+	irq_num_events += atomic_xchg_u32(&lrng_pool.irq_info.num_events, 0);
+	/* Convert used entropy into interrupt number for subtraction */
+	irq_num_events_used = lrng_entropy_to_data(avail_entropy_bits);
+	/* Cap the number of events we say we have left to not reuse events */
+	irq_num_event_back = min_t(u32, irq_num_events - irq_num_events_used,
+				   lrng_entropy_to_data(LRNG_POOL_SIZE_BITS) -
+				    irq_num_events_used);
+	/* Add the unused interrupt number back to the state variable */
+	atomic_add(irq_num_event_back, &lrng_pool.irq_info.num_events);
+
+	/* Obtain entropy statement in bits from the used entropy */
+	pr_debug("obtained %u bits of entropy from %u newly collected interrupts - not using %u interrupts\n",
+		 avail_entropy_bits, irq_num_events_used, irq_num_event_back);
+
+	return avail_entropy_bits;
+}
+
+/****************************** DRBG processing *******************************/
+
+/**
+ * Ping all kernel internal callers waiting until the DRBG is fully
+ * seeded that the DRBG is now fully seeded.
+ */
+static void lrng_process_ready_list(void)
+{
+	unsigned long flags;
+	struct random_ready_callback *rdy, *tmp;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) {
+		struct module *owner = rdy->owner;
+
+		list_del_init(&rdy->list);
+		rdy->func(rdy);
+		module_put(owner);
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+}
+
+/**
+ * Set the slow noise source reseed trigger threshold. The initial threshold
+ * is set to the minimum data size that can be read from the pool: a word. Upon
+ * reaching this value, the next seed threshold of 112 bits is set followed
+ * by 256 bits.
+ *
+ * @entropy_bits: size of entropy currently injected into DRBG
+ */
+static void lrng_pdrbg_init_ops(u32 entropy_bits)
+{
+	if (lrng_pdrbg.pdrbg_fully_seeded)
+		return;
+
+	/* DRBG is seeded with full security strength */
+	if (entropy_bits >= LRNG_DRBG_SECURITY_STRENGTH_BITS) {
+		lrng_pdrbg.pdrbg_fully_seeded = true;
+		lrng_pdrbg.pdrbg_min_seeded = true;
+		pr_info("primary DRBG fully seeded with %u bits of entropy\n",
+			entropy_bits);
+		lrng_process_ready_list();
+		wake_up_all(&lrng_pdrbg_init_wait);
+
+	} else if (!lrng_pdrbg.pdrbg_min_seeded) {
+
+		/* DRBG is seeded with at least 112 bits of entropy */
+		if (entropy_bits >= LRNG_MIN_SEED_ENTROPY_BITS) {
+			lrng_pdrbg.pdrbg_min_seeded = true;
+			pr_info("primary DRBG minimally seeded with %u bits of entropy\n",
+				entropy_bits);
+			lrng_set_entropy_thresh(
+					LRNG_DRBG_SECURITY_STRENGTH_BITS);
+
+		/* DRBG is seeded with at least LRNG_INIT_ENTROPY_BITS bits */
+		} else if (entropy_bits >= LRNG_INIT_ENTROPY_BITS) {
+			pr_info("primary DRBG initially seeded with %u bits of entropy\n",
+				entropy_bits);
+			lrng_set_entropy_thresh(LRNG_MIN_SEED_ENTROPY_BITS);
+		}
+	}
+}
+
+/* Caller must hold lrng_pdrbg.lock */
+static int lrng_pdrbg_generate(u8 *outbuf, u32 outbuflen, bool fullentropy)
+{
+	int ret;
+
+	/* /dev/random only works from a fully seeded DRBG */
+	if (fullentropy && !lrng_pdrbg.pdrbg_fully_seeded)
+		return 0;
+
+	/*
+	 * Only deliver as many bytes as the DRBG is seeded with except during
+	 * initialization to provide a first seed to the secondary DRBG.
+	 */
+	if (lrng_pdrbg.pdrbg_min_seeded)
+		outbuflen = min_t(u32, outbuflen,
+				  lrng_pdrbg.pdrbg_entropy_bits>>3);
+	else
+		outbuflen = min_t(u32, outbuflen,
+				  LRNG_MIN_SEED_ENTROPY_BITS>>3);
+
+	ret = lrng_drng_generate_helper(lrng_pdrbg.pdrbg, outbuf, outbuflen);
+	if (ret != outbuflen) {
+		pr_warn("getting random data from primary DRBG failed (%d)\n",
+			ret);
+		return ret;
+	}
+
+	if (lrng_pdrbg.pdrbg_entropy_bits > (u32)(ret<<3))
+		lrng_pdrbg.pdrbg_entropy_bits -= ret<<3;
+	else
+		lrng_pdrbg.pdrbg_entropy_bits = 0;
+	pr_debug("obtained %d bytes of random data from primary DRBG\n", ret);
+	pr_debug("primary DRBG entropy level at %u bits\n",
+		 lrng_pdrbg.pdrbg_entropy_bits);
+
+	return ret;
+}
+
+/**
+ * Inject data into the primary DRBG with a given entropy value. The function
+ * calls the DRBG's update function. This function also generates random data
+ * if requested by caller. The caller is only returned the amount of random
+ * data that is at most equal to the amount of entropy that just seeded the
+ * DRBG.
+ *
+ * Note, this function seeds the primary DRBG and generates data from it
+ * in an atomic operation.
+ *
+ * @inbuf: buffer to inject
+ * @inbuflen: length of inbuf
+ * @entropy_bits: entropy value of the data in inbuf in bits
+ * @outbuf: buffer to fill immediately after seeding to get full entropy
+ * @outbuflen: length of outbuf
+ * @fullentropy: start /dev/random output only after the DRBG was fully seeded
+ * @return: number of bytes written to outbuf, 0 if outbuf is not supplied,
+ *	    or < 0 in case of error
+ */
+static int lrng_pdrbg_inject(const u8 *inbuf, u32 inbuflen, u32 entropy_bits,
+			     u8 *outbuf, u32 outbuflen, bool fullentropy)
+{
+	int ret;
+	unsigned long flags;
+
+	/* cap the maximum entropy value to the provided data length */
+	entropy_bits = min_t(u32, entropy_bits, inbuflen<<3);
+
+	spin_lock_irqsave(&lrng_pdrbg.lock, flags);
+	ret = lrng_drng_seed_helper(lrng_pdrbg.pdrbg, inbuf, inbuflen);
+	if (ret < 0) {
+		pr_warn("(re)seeding of primary DRBG failed\n");
+		goto unlock;
+	}
+	pr_debug("inject %u bytes with %u bits of entropy into primary DRBG\n",
+		 inbuflen, entropy_bits);
+
+	/* Adjust the fill level indicator to at most the DRBG sec strength */
+	lrng_pdrbg.pdrbg_entropy_bits =
+		min_t(u32, lrng_pdrbg.pdrbg_entropy_bits + entropy_bits,
+		      LRNG_DRBG_SECURITY_STRENGTH_BITS);
+	lrng_pdrbg_init_ops(lrng_pdrbg.pdrbg_entropy_bits);
+
+	if (outbuf && outbuflen)
+		ret = lrng_pdrbg_generate(outbuf, outbuflen, fullentropy);
+
+unlock:
+	spin_unlock_irqrestore(&lrng_pdrbg.lock, flags);
+
+	if (lrng_have_entropy_full()) {
+		/* Wake readers */
+		wake_up_interruptible(&lrng_read_wait);
+		kill_fasync(&fasync, SIGIO, POLL_IN);
+	}
+
+	return ret;
+}
+
+/**
+ * Seed the DRBG from the internal noise sources.
+ */
+static int lrng_pdrbg_seed_internal(u8 *outbuf, u32 outbuflen, bool fullentropy,
+				    bool drain)
+{
+	u32 total_entropy_bits, now;
+	u8 entropy_buf[(LRNG_DRBG_SECURITY_STRENGTH_BYTES * 2) + sizeof(now)]
+						__aligned(LRNG_KCAPI_ALIGN);
+	int ret;
+
+	/* No reseeding if sufficient entropy in primary DRBG */
+	if (lrng_pdrbg.pdrbg_entropy_bits >= outbuflen<<3) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&lrng_pdrbg.lock, flags);
+		ret = lrng_pdrbg_generate(outbuf, outbuflen, fullentropy);
+		spin_unlock_irqrestore(&lrng_pdrbg.lock, flags);
+		if (ret == outbuflen)
+			goto out;
+	}
+
+	/*
+	 * drain the pool completely during init and when /dev/random calls.
+	 *
+	 * lrng_get_pool must be guaranteed to be called with multiples of 8
+	 * (bits) of entropy as it can only operate byte-wise.
+	 */
+	total_entropy_bits = lrng_get_pool(entropy_buf,
+					   LRNG_DRBG_SECURITY_STRENGTH_BITS,
+					   drain);
+
+	/*
+	 * Prevent domination of fast noise sources over slow noise sources
+	 * in case /dev/random calls. Only when the slow noise sources have
+	 * some entropy, pull from the fast noise sources and inject all
+	 * into the DRBG.
+	 */
+	if (!total_entropy_bits && drain) {
+		ret = 0;
+		goto memzero;
+	}
+
+	/*
+	 * Concatenate the output of the noise sources. This would be the
+	 * spot to add an entropy extractor logic if desired. Note, this
+	 * entirety should have the ability to collect entropy equal or larger
+	 * than the DRBG strength to be able to feed /dev/random.
+	 */
+	total_entropy_bits += lrng_get_arch(entropy_buf +
+					    LRNG_DRBG_SECURITY_STRENGTH_BYTES);
+
+	pr_debug("reseed primary DRBG from internal noise sources with %u bits of entropy\n",
+		 total_entropy_bits);
+
+	/* also reseed the DRBG with the current time stamp */
+	now = random_get_entropy();
+	memcpy(entropy_buf + (LRNG_DRBG_SECURITY_STRENGTH_BYTES * 2), &now,
+	       sizeof(now));
+
+	ret = lrng_pdrbg_inject(entropy_buf, sizeof(entropy_buf),
+				total_entropy_bits,
+				outbuf, outbuflen, fullentropy);
+
+memzero:
+	memzero_explicit(entropy_buf, sizeof(entropy_buf));
+
+	/*
+	 * Shall we wake up user space writers? This location covers
+	 * /dev/urandom as well, but also ensures that the user space provider
+	 * does not dominate the internal noise sources since in case the
+	 * first call of this function finds sufficient entropy in the primary
+	 * DRBG, it will not trigger the wakeup. This implies that when the next
+	 * /dev/urandom read happens, the primary DRBG is drained and the
+	 * internal noise sources are asked to feed the primary DRBG.
+	 */
+	if (lrng_need_entropy()) {
+		wake_up_interruptible(&lrng_write_wait);
+		kill_fasync(&fasync, SIGIO, POLL_OUT);
+	}
+
+out:
+	/* Allow the seeding operation to be called again */
+	atomic_set(&lrng_pool.irq_info.reseed_in_progress, 0);
+
+	return ret;
+}
+
+/**
+ * Inject a data buffer into the secondary DRBG
+ *
+ * @sdrbg: reference to secondary DRBG
+ * @inbuf: buffer with data to inject
+ * @inbuflen: buffer length
+ * @internal: did random data originate from internal sources? Update the
+ *	      reseed threshold and the reseed timer when seeded with entropic
+ *	      data from noise sources to prevent unprivileged users from
+ *	      stopping reseeding the secondary DRBG with entropic data.
+ */
+static void lrng_sdrbg_inject(struct lrng_sdrbg *sdrbg,
+			      u8 *inbuf, u32 inbuflen, bool internal)
+{
+	unsigned long flags;
+
+	BUILD_BUG_ON(LRNG_DRBG_RESEED_THRESH > INT_MAX);
+	pr_debug("seeding secondary DRBG with %u bytes\n", inbuflen);
+	spin_lock_irqsave(&sdrbg->lock, flags);
+	if (lrng_drng_seed_helper(sdrbg->sdrbg, inbuf, inbuflen) < 0) {
+		pr_warn("seeding of secondary DRBG failed\n");
+		atomic_set(&sdrbg->requests, 1);
+	} else if (internal) {
+		pr_debug("secondary DRBG stats since last seeding: %lu secs; generate calls: %d\n",
+			 (jiffies - sdrbg->last_seeded) / HZ,
+			 (LRNG_DRBG_RESEED_THRESH -
+			  atomic_read(&sdrbg->requests)));
+		sdrbg->last_seeded = jiffies;
+		atomic_set(&sdrbg->requests, LRNG_DRBG_RESEED_THRESH);
+	}
+	spin_unlock_irqrestore(&sdrbg->lock, flags);
+}
+
+/**
+ * Try to seed the secondary DRBG
+ *
+ * @sdrbg: reference to secondary DRBG
+ * @seedfunc: function to use to seed and obtain random data from primary DRBG
+ */
+static void lrng_sdrbg_seed(struct lrng_sdrbg *sdrbg,
+	int (*seed_func)(u8 *outbuf, u32 outbuflen, bool fullentropy,
+			 bool drain))
+{
+	u8 seedbuf[LRNG_DRBG_SECURITY_STRENGTH_BYTES];
+	int ret;
+
+	BUILD_BUG_ON(LRNG_MIN_SEED_ENTROPY_BITS >
+		     LRNG_DRBG_SECURITY_STRENGTH_BITS);
+
+	pr_debug("reseed of secondary DRBG triggered\n");
+	ret = seed_func(seedbuf, LRNG_DRBG_SECURITY_STRENGTH_BYTES, false,
+			!sdrbg->fully_seeded);
+	/* Update the DRBG state even though we received zero random data */
+	if (ret < 0) {
+		/*
+		 * Try to reseed at next round - note if EINPROGRESS is returned
+		 * the request counter may fall below zero in case of parallel
+		 * operations. We accept such "underflow" temporarily as the
+		 * counter will be set back to a positive number in the course
+		 * of the reseed. For these few generate operations under
+		 * heavy parallel strain of /dev/urandom we therefore exceed
+		 * the LRNG_DRBG_RESEED_THRESH threshold.
+		 */
+		if (ret != -EINPROGRESS)
+			atomic_set(&sdrbg->requests, 1);
+		return;
+	}
+
+	lrng_sdrbg_inject(sdrbg, seedbuf, ret, true);
+	memzero_explicit(seedbuf, ret);
+
+	if (ret >= LRNG_DRBG_SECURITY_STRENGTH_BYTES)
+		sdrbg->fully_seeded = true;
+}
+
+/**
+ * DRBG reseed trigger: Kernel thread handler triggered by the schedule_work()
+ */
+static void lrng_pdrbg_seed_work(struct work_struct *dummy)
+{
+	u32 node;
+
+	for (node = 0; node <= lrng_pool.last_numa_node; node++) {
+		struct lrng_sdrbg *sdrbg = lrng_sdrbg[node];
+
+		if (!sdrbg->fully_seeded) {
+			pr_debug("reseed triggered by interrupt noise source for secondary DRBG on NUMA node %d\n", node);
+			lrng_sdrbg_seed(sdrbg, lrng_pdrbg_seed_internal);
+			if (node && sdrbg->fully_seeded) {
+				/* Prevent reseed storm */
+				sdrbg->last_seeded += node * 100 * HZ;
+				/* Prevent draining of pool on idle systems */
+				lrng_sdrbg_reseed_max_time += 100;
+			}
+			return;
+		}
+	}
+}
+
+/**
+ * DRBG reseed trigger: Synchronous reseed request
+ */
+static int lrng_pdrbg_seed(u8 *outbuf, u32 outbuflen, bool fullentropy,
+			   bool drain)
+{
+	/* Ensure that the seeding only occurs once at any given time */
+	if (atomic_cmpxchg(&lrng_pool.irq_info.reseed_in_progress, 0, 1))
+		return -EINPROGRESS;
+	return lrng_pdrbg_seed_internal(outbuf, outbuflen, fullentropy, drain);
+}
+
+/**
+ * Obtain random data from DRBG with information theoretical entropy by
+ * triggering a reseed. The primary DRBG will only return as many random
+ * bytes as it was seeded with.
+ *
+ * @outbuf: buffer to store the random data in
+ * @outbuflen: length of outbuf
+ * @return: < 0 on error
+ *	    >= 0 the number of bytes that were obtained
+ */
+static int lrng_pdrbg_get(u8 *outbuf, u32 outbuflen)
+{
+	int ret;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	/* DRBG is not yet available */
+	if (!atomic_read(&lrng_pdrbg_avail))
+		return 0;
+
+	ret = lrng_pdrbg_seed(outbuf, outbuflen, true, true);
+	pr_debug("read %u bytes of full entropy data from primary DRBG\n", ret);
+
+	return ret;
+}
+
+/**
+ * Initial RNG provides random data with as much entropy as we have
+ * at boot time until the DRBG becomes available during late_initcall() but
+ * before user space boots. When the DRBG is initialized, the initial RNG
+ * is retired.
+ *
+ * Note: until retirement of this RNG, the system did not generate too much
+ * entropy yet. Hence, a proven DRNG like a DRBG is not necessary here anyway.
+ *
+ * The RNG is using the following as noise source:
+ *	* high resolution time stamps
+ *	* the collected IRQ state
+ *	* CPU noise source if available
+ *
+ * Input/output: it is a drop-in replacement for lrng_sdrbg_get.
+ */
+static u32 lrng_init_state[SHA_WORKSPACE_WORDS];
+static int lrng_init_rng(u8 *outbuf, u32 outbuflen)
+{
+	u32 hash[SHA_DIGEST_WORDS];
+	u32 outbuflen_orig = outbuflen;
+	u32 workspace[SHA_WORKSPACE_WORDS];
+
+	BUILD_BUG_ON(sizeof(lrng_init_state[0]) != LRNG_POOL_WORD_BYTES);
+
+	sha_init(hash);
+	while (outbuflen) {
+		unsigned int arch;
+		u32 i;
+		u32 todo = min_t(u32, outbuflen,
+				 SHA_WORKSPACE_WORDS * sizeof(u32));
+
+		/* Update init RNG state with CPU RNG and timer data */
+		for (i = 0; i < SHA_WORKSPACE_WORDS; i++) {
+			if (arch_get_random_int(&arch))
+				lrng_init_state[i] ^= arch;
+			lrng_init_state[i] ^= random_get_entropy();
+		}
+		/* SHA-1 update using the init RNG state */
+		sha_transform(hash, (u8 *)&lrng_init_state, workspace);
+
+		/* SHA-1 update with all words of the entropy pool */
+		BUILD_BUG_ON(LRNG_POOL_SIZE % 16);
+		for (i = 0; i < LRNG_POOL_SIZE; i += 16)
+			sha_transform(hash, (u8 *)(lrng_pool.pool + i),
+				      workspace);
+
+		/* Mix generated data into state for backtracking resistance */
+		for (i = 0; i < SHA_DIGEST_WORDS; i++)
+			lrng_init_state[i] ^= hash[i];
+
+		memcpy(outbuf, hash, todo);
+		outbuf += todo;
+		outbuflen -= todo;
+		atomic_add(todo, &lrng_initrng_bytes);
+	}
+	memzero_explicit(hash, sizeof(hash));
+	memzero_explicit(workspace, sizeof(workspace));
+
+	return outbuflen_orig;
+}
+
+static inline struct lrng_sdrbg *lrng_get_current_sdrbg(void)
+{
+	struct lrng_sdrbg *sdrbg = lrng_sdrbg[numa_node_id()];
+
+	return (sdrbg->fully_seeded) ? sdrbg : lrng_sdrbg[0];
+}
+
+/**
+ * Get random data out of the secondary DRBG which is reseeded frequently. In
+ * the worst case, the DRBG may generate random numbers without being reseeded
+ * for LRNG_DRBG_RESEED_THRESH requests times LRNG_DRBG_MAX_REQSIZE bytes.
+ *
+ * If the DRBG is not yet initialized, use the initial RNG output.
+ *
+ * @outbuf: buffer for storing random data
+ * @outbuflen: length of outbuf
+ * @return: < 0 in error case (DRBG generation or update failed)
+ *	    >=0 returning the returned number of bytes
+ */
+static int lrng_sdrbg_get(u8 *outbuf, u32 outbuflen)
+{
+	u32 processed = 0;
+	struct lrng_sdrbg *sdrbg;
+	unsigned long flags;
+	int ret;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	outbuflen = min_t(size_t, outbuflen, INT_MAX);
+
+	/* DRBG is not yet available */
+	if (!atomic_read(&lrng_pdrbg_avail)) {
+		spin_lock_irqsave(&lrng_init_rng_lock, flags);
+		/* Prevent race with lrng_init */
+		if (!atomic_read(&lrng_pdrbg_avail)) {
+			ret = lrng_init_rng(outbuf, outbuflen);
+			spin_unlock_irqrestore(&lrng_init_rng_lock, flags);
+			return ret;
+		}
+		spin_unlock_irqrestore(&lrng_init_rng_lock, flags);
+	}
+
+	sdrbg = lrng_get_current_sdrbg();
+	while (outbuflen) {
+		unsigned long now = jiffies;
+		u32 todo = min_t(u32, outbuflen, LRNG_DRBG_MAX_REQSIZE);
+
+		if (atomic_dec_and_test(&sdrbg->requests) ||
+		    time_after(now, sdrbg->last_seeded +
+			       lrng_sdrbg_reseed_max_time * HZ))
+			lrng_sdrbg_seed(sdrbg, lrng_pdrbg_seed);
+
+		spin_lock_irqsave(&sdrbg->lock, flags);
+		ret = lrng_drng_generate_helper(sdrbg->sdrbg,
+						outbuf + processed, todo);
+		spin_unlock_irqrestore(&sdrbg->lock, flags);
+		if (ret <= 0) {
+			pr_warn("getting random data from secondary DRBG failed (%d)\n",
+				ret);
+			return -EFAULT;
+		}
+		processed += ret;
+		outbuflen -= ret;
+	}
+
+	return processed;
+}
+
+static int lrng_drngs_alloc(void)
+{
+	unsigned long flags;
+	struct drbg_state *pdrbg;
+	u32 node;
+	u32 num_nodes = num_possible_nodes();
+
+	pdrbg = lrng_drng_alloc(LRNG_DRBG_CORE, LRNG_DRBG_BLOCKLEN_BYTES,
+				LRNG_DRBG_SECURITY_STRENGTH_BYTES);
+	if (!pdrbg)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&lrng_pdrbg.lock, flags);
+	if (lrng_pdrbg.pdrbg) {
+		lrng_drng_dealloc(pdrbg);
+		kfree(pdrbg);
+	} else {
+		lrng_pdrbg.pdrbg = pdrbg;
+		INIT_WORK(&lrng_pdrbg.lrng_seed_work, lrng_pdrbg_seed_work);
+		pr_info("primary DRBG allocated\n");
+	}
+
+	lrng_pool.last_numa_node = num_nodes - 1;
+
+	spin_unlock_irqrestore(&lrng_pdrbg.lock, flags);
+
+	lrng_sdrbg = kmalloc_array(num_nodes, sizeof(void *),
+				   GFP_KERNEL|__GFP_NOFAIL);
+	for (node = 0; node < num_nodes; node++) {
+		struct lrng_sdrbg *sdrbg;
+
+		sdrbg = kmalloc_node(sizeof(struct lrng_sdrbg),
+				     GFP_KERNEL|__GFP_NOFAIL, node);
+		if (!sdrbg)
+			goto err;
+		memset(sdrbg, 0, sizeof(lrng_sdrbg));
+		lrng_sdrbg[node] = sdrbg;
+
+		sdrbg->sdrbg = lrng_drng_alloc(LRNG_DRBG_CORE,
+					       LRNG_DRBG_BLOCKLEN_BYTES,
+					LRNG_DRBG_SECURITY_STRENGTH_BYTES);
+		if (!sdrbg->sdrbg)
+			goto err;
+
+		atomic_set(&sdrbg->requests, 1);
+		spin_lock_init(&sdrbg->lock);
+		sdrbg->last_seeded = jiffies;
+		sdrbg->fully_seeded = false;
+
+		pr_info("secondary DRBG for NUMA node %d allocated\n", node);
+	}
+
+	return 0;
+
+err:
+	for (node = 0; node < num_nodes; node++) {
+		struct lrng_sdrbg *sdrbg = lrng_sdrbg[node];
+
+		if (sdrbg) {
+			if (sdrbg->sdrbg)
+				lrng_drng_dealloc(sdrbg->sdrbg);
+			kfree(sdrbg);
+		}
+	}
+	kfree(lrng_sdrbg);
+
+	lrng_drng_dealloc(pdrbg);
+	kfree(pdrbg);
+
+	return -ENOMEM;
+}
+
+static int lrng_alloc(void)
+{
+	u8 key[LRNG_DRBG_SECURITY_STRENGTH_BYTES] __aligned(LRNG_KCAPI_ALIGN);
+	int ret = lrng_drngs_alloc();
+
+	if (ret)
+		return ret;
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	lrng_init_rng(key, sizeof(key));
+	lrng_pool.lrng_hash = lrng_hash_alloc(LRNG_HASH_NAME, key, sizeof(key));
+	memzero_explicit(key, sizeof(key));
+	if (IS_ERR(lrng_pool.lrng_hash))
+		return -PTR_ERR(lrng_pool.lrng_hash);
+
+	return 0;
+}
+
+/************************** LRNG kernel interfaces ***************************/
+
+void get_random_bytes(void *buf, int nbytes)
+{
+	lrng_sdrbg_get((u8 *)buf, (u32)nbytes);
+}
+EXPORT_SYMBOL(get_random_bytes);
+
+/**
+ * This function will use the architecture-specific hardware random
+ * number generator if it is available.  The arch-specific hw RNG will
+ * almost certainly be faster than what we can do in software, but it
+ * is impossible to verify that it is implemented securely (as
+ * opposed, to, say, the AES encryption of a sequence number using a
+ * key known by the NSA).  So it's useful if we need the speed, but
+ * only if we're willing to trust the hardware manufacturer not to
+ * have put in a back door.
+ *
+ * @buf: buffer allocated by caller to store the random data in
+ * @nbytes: length of outbuf
+ */
+void get_random_bytes_arch(void *buf, int nbytes)
+{
+	u8 *p = buf;
+
+	while (nbytes) {
+		unsigned long v;
+		int chunk = min_t(int, nbytes, sizeof(unsigned long));
+
+		if (!arch_get_random_long(&v))
+			break;
+
+		memcpy(p, &v, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+
+	if (nbytes)
+		lrng_sdrbg_get((u8 *)p, (u32)nbytes);
+}
+EXPORT_SYMBOL(get_random_bytes_arch);
+
+/**
+ * Interface for in-kernel drivers of true hardware RNGs.
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
+ *
+ * @buffer: buffer holding the entropic data from HW noise sources to be used to
+ *	    (re)seed the DRBG.
+ * @count: length of buffer
+ * @entropy_bits: amount of entropy in buffer (value is in bits)
+ */
+void add_hwgenerator_randomness(const char *buffer, size_t count,
+				size_t entropy_bits)
+{
+	/* DRBG is not yet online */
+	if (!atomic_read(&lrng_pdrbg_avail))
+		return;
+	/*
+	 * Suspend writing if we are fully loaded with entropy.
+	 * We'll be woken up again once below lrng_write_wakeup_thresh,
+	 * or when the calling thread is about to terminate.
+	 */
+	wait_event_interruptible(lrng_write_wait,
+				 kthread_should_stop() || lrng_need_entropy());
+	lrng_pdrbg_inject(buffer, count, entropy_bits, NULL, 0, false);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+/**
+ * Delete a previously registered readiness callback function.
+ */
+void del_random_ready_callback(struct random_ready_callback *rdy)
+{
+	unsigned long flags;
+	struct module *owner = NULL;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (!list_empty(&rdy->list)) {
+		list_del_init(&rdy->list);
+		owner = rdy->owner;
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+}
+EXPORT_SYMBOL(del_random_ready_callback);
+
+/**
+ * Add a callback function that will be invoked when the DRBG is fully seeded.
+ *
+ * @return: 0 if callback is successfully added
+ *          -EALREADY if pool is already initialised (callback not called)
+ *	    -ENOENT if module for callback is not alive
+ */
+int add_random_ready_callback(struct random_ready_callback *rdy)
+{
+	struct module *owner;
+	unsigned long flags;
+	int err = -EALREADY;
+
+	if (likely(lrng_pdrbg.pdrbg_fully_seeded))
+		return err;
+
+	owner = rdy->owner;
+	if (!try_module_get(owner))
+		return -ENOENT;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (lrng_pdrbg.pdrbg_fully_seeded)
+		goto out;
+
+	owner = NULL;
+
+	list_add(&rdy->list, &lrng_ready_list);
+	err = 0;
+
+out:
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+
+	return err;
+}
+EXPORT_SYMBOL(add_random_ready_callback);
+
+/************************ LRNG user space interfaces *************************/
+
+static ssize_t lrng_read_common(char __user *buf, size_t nbytes,
+			int (*lrng_read_random)(u8 *outbuf, u32 outbuflen))
+{
+	ssize_t ret = 0;
+	u8 tmpbuf[64] __aligned(LRNG_KCAPI_ALIGN);
+	u8 *tmp_large = NULL;
+	u8 *tmp = tmpbuf;
+	u32 tmplen = sizeof(tmpbuf);
+
+	if (nbytes == 0)
+		return 0;
+
+	/*
+	 * Satisfy large read requests -- as the common case are smaller
+	 * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for
+	 * those by using the stack variable of tmpbuf.
+	 */
+	if (nbytes > 64) {
+		tmplen = min_t(u32, nbytes, LRNG_DRBG_MAX_REQSIZE);
+		tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL);
+		if (!tmp_large)
+			tmplen = sizeof(tmpbuf);
+		else
+			tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN);
+	}
+
+	while (nbytes) {
+		u32 todo = min_t(u32, nbytes, tmplen);
+		int rc = 0;
+
+		if (tmp_large && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		rc = lrng_read_random(tmp, todo);
+		if (rc <= 0)
+			break;
+		if (copy_to_user(buf, tmp, rc)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= rc;
+		buf += rc;
+		ret += rc;
+	}
+
+	/* Wipe data just returned from memory */
+	if (tmp_large)
+		kzfree(tmp_large);
+	else
+		memzero_explicit(tmpbuf, sizeof(tmpbuf));
+
+	return ret;
+}
+
+static ssize_t
+lrng_pdrbg_read_common(int nonblock, char __user *buf, size_t nbytes)
+{
+	if (nbytes == 0)
+		return 0;
+
+	nbytes = min_t(u32, nbytes, LRNG_DRBG_BLOCKLEN_BYTES);
+	while (1) {
+		ssize_t n;
+
+		n = lrng_read_common(buf, nbytes, lrng_pdrbg_get);
+		if (n < 0)
+			return n;
+		if (n > 0)
+			return n;
+
+		/* No entropy available.  Maybe wait and retry. */
+		if (nonblock)
+			return -EAGAIN;
+
+		wait_event_interruptible(lrng_read_wait,
+					 lrng_have_entropy_full());
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+}
+
+static ssize_t lrng_pdrbg_read(struct file *file, char __user *buf,
+			       size_t nbytes, loff_t *ppos)
+{
+	return lrng_pdrbg_read_common(file->f_flags & O_NONBLOCK, buf, nbytes);
+}
+
+static unsigned int lrng_pdrbg_poll(struct file *file, poll_table *wait)
+{
+	unsigned int mask;
+
+	poll_wait(file, &lrng_read_wait, wait);
+	poll_wait(file, &lrng_write_wait, wait);
+	mask = 0;
+	if (lrng_have_entropy_full())
+		mask |= POLLIN | POLLRDNORM;
+	if (lrng_need_entropy())
+		mask |= POLLOUT | POLLWRNORM;
+	return mask;
+}
+
+static ssize_t lrng_drbg_write_common(const char __user *buffer, size_t count,
+				      u32 entropy_bits, bool sdrbg)
+{
+	ssize_t ret = 0;
+	u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
+	const char __user *p = buffer;
+
+	if (!atomic_read(&lrng_pdrbg_avail))
+		return -EAGAIN;
+
+	count = min_t(size_t, count, INT_MAX);
+	while (count > 0) {
+		size_t bytes = min_t(size_t, count, sizeof(buf));
+		u32 ent = min_t(u32, bytes<<3, entropy_bits);
+
+		if (copy_from_user(&buf, p, bytes))
+			return -EFAULT;
+		/* Inject data into primary DRBG */
+		lrng_pdrbg_inject(buf, bytes, ent, NULL, 0, false);
+		/* Data from /dev/[|u]random is injected into secondary DRBG */
+		if (sdrbg) {
+			u32 node;
+			int num_nodes = num_possible_nodes();
+
+			for (node = 0; node < num_nodes; node++)
+				lrng_sdrbg_inject(lrng_sdrbg[node], buf, bytes,
+						  false);
+		}
+
+		count -= bytes;
+		p += bytes;
+		ret += bytes;
+		entropy_bits -= ent;
+
+		cond_resched();
+	}
+
+	return ret;
+}
+
+static ssize_t lrng_sdrbg_read(struct file *file, char __user *buf,
+			       size_t nbytes, loff_t *ppos)
+{
+	return lrng_read_common(buf, nbytes, lrng_sdrbg_get);
+}
+
+static ssize_t lrng_drbg_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	return lrng_drbg_write_common(buffer, count, 0, true);
+}
+
+static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	int size, ent_count_bits;
+	int __user *p = (int __user *)arg;
+
+	switch (cmd) {
+	case RNDGETENTCNT:
+		ent_count_bits = lrng_avail_entropy();
+		if (put_user(ent_count_bits, p))
+			return -EFAULT;
+		return 0;
+	case RNDADDTOENTCNT:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p))
+			return -EFAULT;
+		ent_count_bits = (int)lrng_avail_entropy() + ent_count_bits;
+		if (ent_count_bits < 0)
+			ent_count_bits = 0;
+		if (ent_count_bits > LRNG_POOL_SIZE_BITS)
+			ent_count_bits = LRNG_POOL_SIZE_BITS;
+		atomic_set(&lrng_pool.irq_info.num_events,
+			   lrng_entropy_to_data(ent_count_bits));
+		return 0;
+	case RNDADDENTROPY:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p++))
+			return -EFAULT;
+		if (ent_count_bits < 0)
+			return -EINVAL;
+		if (get_user(size, p++))
+			return -EFAULT;
+		if (size < 0)
+			return -EINVAL;
+		/* there cannot be more entropy than data */
+		ent_count_bits = min(ent_count_bits, size<<3);
+		return lrng_drbg_write_common((const char __user *)p, size,
+					      ent_count_bits, false);
+	case RNDZAPENTCNT:
+	case RNDCLEARPOOL:
+		/* Clear the entropy pool counter. */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		atomic_set(&lrng_pool.irq_info.num_events, 0);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int lrng_fasync(int fd, struct file *filp, int on)
+{
+	return fasync_helper(fd, filp, on, &fasync);
+}
+
+const struct file_operations random_fops = {
+	.read  = lrng_pdrbg_read,
+	.write = lrng_drbg_write,
+	.poll  = lrng_pdrbg_poll,
+	.unlocked_ioctl = lrng_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+const struct file_operations urandom_fops = {
+	.read  = lrng_sdrbg_read,
+	.write = lrng_drbg_write,
+	.unlocked_ioctl = lrng_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+		unsigned int, flags)
+{
+	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
+		return -EINVAL;
+
+	if (count > INT_MAX)
+		count = INT_MAX;
+
+	if (flags & GRND_RANDOM)
+		return lrng_pdrbg_read_common(flags & GRND_NONBLOCK, buf,
+					      count);
+
+	if (unlikely(!lrng_pdrbg.pdrbg_fully_seeded)) {
+		if (flags & GRND_NONBLOCK)
+			return -EAGAIN;
+		wait_event_interruptible(lrng_pdrbg_init_wait,
+					 lrng_pdrbg.pdrbg_fully_seeded);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+	return lrng_sdrbg_read(NULL, buf, count, NULL);
+}
+
+/*************************** LRNG proc interfaces ****************************/
+
+#ifdef CONFIG_SYSCTL
+
+#include <linux/sysctl.h>
+
+static int lrng_min_read_thresh = LRNG_POOL_WORD_BITS;
+static int lrng_min_write_thresh;
+static int lrng_max_read_thresh = LRNG_POOL_SIZE_BITS;
+static int lrng_max_write_thresh = LRNG_DRBG_SECURITY_STRENGTH_BITS;
+static char lrng_sysctl_bootid[16];
+static int lrng_sdrbg_reseed_max_min;
+
+/*
+ * This function is used to return both the bootid UUID, and random
+ * UUID.  The difference is in whether table->data is NULL; if it is,
+ * then a new UUID is generated and returned to the user.
+ *
+ * If the user accesses this via the proc interface, the UUID will be
+ * returned as an ASCII string in the standard UUID format; if via the
+ * sysctl system call, as 16 bytes of binary data.
+ */
+static int lrng_proc_do_uuid(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	unsigned char buf[64], tmp_uuid[16], *uuid;
+
+	uuid = table->data;
+	if (!uuid) {
+		uuid = tmp_uuid;
+		generate_random_uuid(uuid);
+	} else {
+		static DEFINE_SPINLOCK(bootid_spinlock);
+
+		spin_lock(&bootid_spinlock);
+		if (!uuid[8])
+			generate_random_uuid(uuid);
+		spin_unlock(&bootid_spinlock);
+	}
+
+	sprintf(buf, "%pU", uuid);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_do_type(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	unsigned char buf[130];
+
+	snprintf(buf, sizeof(buf), "%s: %s\nDRNG security strength: %u bits\nentropy pool read hash: %s",
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+		 "CTR DRBG",
+#elif defined CONFIG_CRYPTO_DRBG_HMAC
+		 "HMAC DRBG",
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+		 "HASH DRBG",
+#else
+		 "DRNG",
+#endif
+		 LRNG_DRBG_CORE, LRNG_DRBG_SECURITY_STRENGTH_BITS,
+		 LRNG_HASH_NAME);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+/* Return entropy available scaled to integral bits */
+static int lrng_proc_do_entropy(struct ctl_table *table, int write,
+				void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	int entropy_count;
+
+	entropy_count = lrng_avail_entropy();
+
+	fake_table.data = &entropy_count;
+	fake_table.maxlen = sizeof(entropy_count);
+
+	return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_bool(struct ctl_table *table, int write,
+			  void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	int loc_boolean = 0;
+	bool *boolean = (bool *)table->data;
+
+	if (*boolean)
+		loc_boolean = 1;
+
+	fake_table.data = &loc_boolean;
+	fake_table.maxlen = sizeof(loc_boolean);
+
+	return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_sysctl_poolsize = LRNG_POOL_SIZE_BITS;
+static int pdrbg_security_strength = LRNG_DRBG_SECURITY_STRENGTH_BYTES;
+extern struct ctl_table random_table[];
+struct ctl_table random_table[] = {
+	{
+		.procname	= "poolsize",
+		.data		= &lrng_sysctl_poolsize,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "entropy_avail",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_entropy,
+	},
+	{
+		.procname	= "read_wakeup_threshold",
+		.data		= &lrng_read_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_read_thresh,
+		.extra2		= &lrng_max_read_thresh,
+	},
+	{
+		.procname	= "write_wakeup_threshold",
+		.data		= &lrng_write_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_write_thresh,
+		.extra2		= &lrng_max_write_thresh,
+	},
+	{
+		.procname	= "boot_id",
+		.data		= &lrng_sysctl_bootid,
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname	= "uuid",
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname       = "urandom_min_reseed_secs",
+		.data           = &lrng_sdrbg_reseed_max_time,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+		.extra1		= &lrng_sdrbg_reseed_max_min,
+	},
+	{
+		.procname	= "drbg_fully_seeded",
+		.data		= &lrng_pdrbg.pdrbg_fully_seeded,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_bool,
+	},
+	{
+		.procname	= "drbg_minimally_seeded",
+		.data		= &lrng_pdrbg.pdrbg_min_seeded,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_bool,
+	},
+	{
+		.procname	= "lrng_type",
+		.maxlen		= 30,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_type,
+	},
+	{
+		.procname	= "drbg_security_strength",
+		.data		= &pdrbg_security_strength,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "high_resolution_timer",
+		.data		= &lrng_pool.irq_info.irq_highres_timer,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_bool,
+	},
+	{ }
+};
+#endif /* CONFIG_SYSCTL */
+
+/***************************** Initialize DRBG *******************************/
+
+static int __init lrng_init(void)
+{
+	unsigned long flags;
+
+	BUG_ON(lrng_alloc());
+
+	/*
+	 * As we use the IRQ entropic input data processed by the init RNG
+	 * again during lrng_pdrbg_seed_internal, we must not claim that
+	 * the init RNG state has any entropy when injecting its contents as
+	 * an initial seed into the DRBG.
+	 */
+	spin_lock_irqsave(&lrng_init_rng_lock, flags);
+
+	if (random_get_entropy() || random_get_entropy()) {
+		lrng_pool.irq_info.irq_highres_timer = true;
+		lrng_pool.irq_info.irq_entropy_bits = LRNG_IRQ_ENTROPY_BITS;
+	} else {
+		lrng_pool.irq_info.irq_entropy_bits =
+			LRNG_IRQ_ENTROPY_BITS * LRNG_IRQ_OVERSAMPLING_FACTOR;
+		if (fips_enabled) {
+			pr_warn("LRNG not suitable for FIPS 140-2 use cases\n");
+			WARN_ON(1);
+		}
+		pr_warn("operating without high-resolution timer and applying IRQ oversampling factor %u\n",
+			LRNG_IRQ_OVERSAMPLING_FACTOR);
+	}
+	lrng_set_entropy_thresh(LRNG_INIT_ENTROPY_BITS);
+
+	lrng_pdrbg_inject((u8 *)&lrng_init_state,
+			  SHA_WORKSPACE_WORDS * sizeof(lrng_init_state[0]),
+			  0, NULL, 0, false);
+	lrng_sdrbg_seed(lrng_sdrbg[0], lrng_pdrbg_seed);
+	atomic_inc(&lrng_pdrbg_avail);
+	memzero_explicit(&lrng_init_state,
+			 SHA_WORKSPACE_WORDS * sizeof(lrng_init_state[0]));
+	spin_unlock_irqrestore(&lrng_init_rng_lock, flags);
+	pr_info("deactivating initial RNG - %d bytes delivered\n",
+		atomic_read(&lrng_initrng_bytes));
+	return 0;
+}
+
+/* A late init implies that more interrupts are collected for initial seeding */
+late_initcall(lrng_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator");
diff --git a/crypto/lrng_kcapi.c b/crypto/lrng_kcapi.c
new file mode 100644
index 0000000..25c37c5
--- /dev/null
+++ b/crypto/lrng_kcapi.c
@@ -0,0 +1,167 @@
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API.
+ *
+ * Copyright (C) 2016, 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 GPL2
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/drbg.h>
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+int lrng_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+	LIST_HEAD(seedlist);
+	struct drbg_string data;
+	int ret;
+
+	drbg_string_fill(&data, inbuf, inbuflen);
+	list_add_tail(&data.list, &seedlist);
+	ret = drbg->d_ops->update(drbg, &seedlist, drbg->seeded);
+
+	if (ret >= 0)
+		drbg->seeded = true;
+
+	return ret;
+}
+
+int lrng_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	return drbg->d_ops->generate(drbg, outbuf, outbuflen, NULL);
+}
+
+void *lrng_drng_alloc(u8 *drng_name, u32 blocklen_bytes, u32 sec_strength)
+{
+	struct drbg_state *drbg = NULL;
+	int coreref = -1;
+	bool pr = false;
+	int ret;
+
+	drbg_convert_tfm_core(drng_name, &coreref, &pr);
+	if (coreref < 0)
+		return NULL;
+
+	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+	if (!drbg)
+		return NULL;
+
+	drbg->core = &drbg_cores[coreref];
+	drbg->seeded = false;
+	ret = drbg_alloc_state(drbg);
+	if (ret)
+		goto err;
+
+	if (blocklen_bytes != drbg->core->blocklen_bytes)
+		goto dealloc;
+	if (sec_strength > drbg_sec_strength(drbg->core->flags))
+		goto dealloc;
+
+	pr_info("DRBG with %s core allocated\n", drbg->core->backend_cra_name);
+
+	return drbg;
+
+dealloc:
+	if (drbg->d_ops)
+		drbg->d_ops->crypto_fini(drbg);
+	drbg_dealloc_state(drbg);
+err:
+	kfree(drbg);
+	return NULL;
+}
+
+void lrng_drng_dealloc(void *drng)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	drbg_dealloc_state(drbg);
+	kzfree(drbg);
+}
+
+void *lrng_hash_alloc(u8 *hashname, u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size, ret;
+
+	tfm = crypto_alloc_shash(hashname, 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n", hashname);
+		return ERR_PTR(PTR_ERR(tfm));
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+	lrng_hash->shash.flags = 0x0;
+
+	ret = crypto_shash_setkey(tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		crypto_free_shash(tfm);
+		kfree(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	return lrng_hash;
+}
+
+u32 lrng_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digestsize(shash->tfm);
+}
+
+int lrng_hash_buffer(void *hash, u8 *inbuf, u32 inbuflen, u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
-- 
2.7.4

^ permalink raw reply related

* [PATCH v6 4/5] crypto: LRNG - enable compile
From: Stephan Mueller @ 2016-08-11 12:26 UTC (permalink / raw)
  To: herbert
  Cc: Ted Tso, sandyinchina, Jason Cooper, John Denker, H. Peter Anvin,
	Joe Perches, Pavel Machek, George Spelvin, linux-crypto,
	linux-kernel
In-Reply-To: <4723196.TTQvcXsLCG@positron.chronox.de>

Add LRNG compilation support.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/Kconfig  | 11 +++++++++++
 crypto/Makefile |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 84d7148..71df7fc 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1665,6 +1665,17 @@ config CRYPTO_JITTERENTROPY
 	  random numbers. This Jitterentropy RNG registers with
 	  the kernel crypto API and can be used by any caller.
 
+config CRYPTO_LRNG
+	bool "Linux Random Number Generator"
+	select CRYPTO_DRBG_MENU
+	select CRYPTO_CMAC if CRYPTO_DRBG_CTR
+	help
+	  The Linux Random Number Generator (LRNG) is the replacement
+	  of the legacy /dev/random provided with drivers/char/random.c.
+	  It generates entropy from different noise sources and
+	  delivers significant entropy during boot. The LRNG only
+	  works with the presence of a high-resolution timer.
+
 config CRYPTO_USER_API
 	tristate
 
diff --git a/crypto/Makefile b/crypto/Makefile
index 99cc64a..12d4249 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -122,6 +122,8 @@ obj-$(CONFIG_CRYPTO_DRBG) += drbg.o
 obj-$(CONFIG_CRYPTO_JITTERENTROPY) += jitterentropy_rng.o
 CFLAGS_jitterentropy.o = -O0
 jitterentropy_rng-y := jitterentropy.o jitterentropy-kcapi.o
+obj-$(CONFIG_CRYPTO_LRNG) += lrng.o
+lrng-y += lrng_base.o lrng_kcapi.o
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
 obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
 obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
-- 
2.7.4

^ permalink raw reply related

* [PATCH v6 5/5] crypto: LRNG - add ChaCha20 support
From: Stephan Mueller @ 2016-08-11 12:26 UTC (permalink / raw)
  To: herbert
  Cc: Ted Tso, sandyinchina, Jason Cooper, John Denker, H. Peter Anvin,
	Joe Perches, Pavel Machek, George Spelvin, linux-crypto,
	linux-kernel
In-Reply-To: <4723196.TTQvcXsLCG@positron.chronox.de>

In case the kernel crypto API is not compiled, use ChaCha20 stream
cipher as DRNG. The LRNG ChaCha20 support provides the DRNG
implementation with the generate and update functions.

Th DRNG implements enhanced backward secrecy by re-creating the
entire internal state after generating random numbers.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/Kconfig           |   1 -
 crypto/Makefile          |   7 +-
 crypto/lrng_standalone.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 226 insertions(+), 2 deletions(-)
 create mode 100644 crypto/lrng_standalone.c

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 71df7fc..ee5aff4 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1667,7 +1667,6 @@ config CRYPTO_JITTERENTROPY
 
 config CRYPTO_LRNG
 	bool "Linux Random Number Generator"
-	select CRYPTO_DRBG_MENU
 	select CRYPTO_CMAC if CRYPTO_DRBG_CTR
 	help
 	  The Linux Random Number Generator (LRNG) is the replacement
diff --git a/crypto/Makefile b/crypto/Makefile
index 12d4249..99fb0e1 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -123,7 +123,12 @@ obj-$(CONFIG_CRYPTO_JITTERENTROPY) += jitterentropy_rng.o
 CFLAGS_jitterentropy.o = -O0
 jitterentropy_rng-y := jitterentropy.o jitterentropy-kcapi.o
 obj-$(CONFIG_CRYPTO_LRNG) += lrng.o
-lrng-y += lrng_base.o lrng_kcapi.o
+lrng-y += lrng_base.o
+ifeq ($(CONFIG_CRYPTO_DRBG),y)
+lrng-y += lrng_kcapi.o
+else
+lrng-y += lrng_standalone.o
+endif
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
 obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
 obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
diff --git a/crypto/lrng_standalone.c b/crypto/lrng_standalone.c
new file mode 100644
index 0000000..7c5d456
--- /dev/null
+++ b/crypto/lrng_standalone.c
@@ -0,0 +1,220 @@
+/*
+ * Backend for the LRNG providing the cryptographic primitives using
+ * standalone cipher implementations.
+ *
+ * Copyright (C) 2016, 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 GPL2
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cryptohash.h>
+#include <crypto/chacha20.h>
+#include <linux/random.h>
+
+/******************************* ChaCha20 DRNG *******************************/
+
+/* State according to RFC 7539 section 2.3 */
+struct chacha20_state {
+	u32 constants[4];
+	union {
+		u32 u[(CHACHA20_KEY_SIZE / sizeof(u32))];
+		u8  b[CHACHA20_KEY_SIZE];
+	} key;
+	u32 counter;
+	u32 nonce[3];
+};
+
+/**
+ * Update of the ChaCha20 state by generating one ChaCha20 block which is
+ * equal to the state of the ChaCha20. The generated block is XORed into
+ * the key part of the state. This shall ensure backtracking resistance as well
+ * as a proper mix of the ChaCha20 state once the key is injected.
+ */
+static void lrng_chacha20_update(struct chacha20_state *chacha20)
+{
+	u32 tmp[(CHACHA20_BLOCK_SIZE / sizeof(u32))];
+	u32 i;
+
+	BUILD_BUG_ON(sizeof(struct chacha20_state) != CHACHA20_BLOCK_SIZE);
+	BUILD_BUG_ON(CHACHA20_BLOCK_SIZE != 2 * CHACHA20_KEY_SIZE);
+
+	chacha20_block(&chacha20->constants[0], tmp);
+	for (i = 0; i < (CHACHA20_KEY_SIZE / sizeof(uint32_t)); i++)
+		chacha20->key.u[i] ^= tmp[i];
+	for (i = 0; i < (CHACHA20_KEY_SIZE / sizeof(uint32_t)); i++)
+		chacha20->key.u[i] ^=
+			tmp[i + (CHACHA20_KEY_SIZE / sizeof(uint32_t))];
+
+	memzero_explicit(tmp, sizeof(tmp));
+
+	/* Deterministic increment of nonce as required in RFC 7539 chapter 4 */
+	chacha20->nonce[0]++;
+	if (chacha20->nonce[0] == 0)
+		chacha20->nonce[1]++;
+	if (chacha20->nonce[1] == 0)
+		chacha20->nonce[2]++;
+
+	/* Leave counter untouched as it is start value is undefined in RFC */
+}
+
+/**
+ * Seed the ChaCha20 DRNG by injecting the input data into the key part of
+ * the ChaCha20 state. If the input data is longer than the ChaCha20 key size,
+ * perform a ChaCha20 operation after processing of key size input data.
+ * This operation shall spread out the entropy into the ChaCha20 state before
+ * new entropy is injected into the key part.
+ */
+int lrng_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct chacha20_state *chacha20 = (struct chacha20_state *)drng;
+
+	while (inbuflen) {
+		u32 i, todo = min_t(u32, inbuflen, CHACHA20_KEY_SIZE);
+
+		for (i = 0; i < todo; i++)
+			chacha20->key.b[i] ^= inbuf[i];
+
+		/* Break potential dependencies between the inbuf key blocks */
+		lrng_chacha20_update(chacha20);
+		inbuf += todo;
+		inbuflen -= todo;
+	}
+
+	return 0;
+}
+
+/**
+ * Chacha20 DRNG generation of random numbers: the stream output of ChaCha20
+ * is the random number. After the completion of the generation of the
+ * stream, the entire ChaCha20 state is updated.
+ *
+ * Note, as the ChaCha20 implements a 32 bit counter, we must ensure
+ * that this function is only invoked for at most 2^32 - 1 ChaCha20 blocks
+ * before a reseed or an update happens. This is ensured by the variable
+ * outbuflen which is a 32 bit integer defining the number of bytes to be
+ * generated by the ChaCha20 DRNG. At the end of this function, an update
+ * operation is invoked which implies that the 32 bit counter will never be
+ * overflown in this implementation.
+ */
+int lrng_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct chacha20_state *chacha20 = (struct chacha20_state *)drng;
+	u32 ret = outbuflen;
+
+	while (outbuflen >= CHACHA20_BLOCK_SIZE) {
+		chacha20_block(&chacha20->constants[0], outbuf);
+		outbuf += CHACHA20_BLOCK_SIZE;
+		outbuflen -= CHACHA20_BLOCK_SIZE;
+	}
+
+	if (outbuflen) {
+		u8 stream[CHACHA20_BLOCK_SIZE];
+
+		chacha20_block(&chacha20->constants[0], stream);
+		memcpy(outbuf, stream, outbuflen);
+		memzero_explicit(stream, sizeof(stream));
+	}
+
+	lrng_chacha20_update(chacha20);
+
+	return ret;
+}
+
+/**
+ * Allocation of the DRBG state
+ */
+void *lrng_drng_alloc(u8 *drng_name, u32 blocklen_bytes, u32 sec_strength)
+{
+	struct chacha20_state *chacha20;
+	unsigned long v;
+
+	chacha20 = kzalloc(sizeof(struct chacha20_state), GFP_KERNEL);
+	if (!chacha20)
+		return NULL;
+
+	memcpy(&chacha20->constants[0], "expand 32-byte k", 16);
+	if (arch_get_random_long(&v))
+		chacha20->nonce[0] ^= v;
+	if (arch_get_random_long(&v))
+		chacha20->nonce[1] ^= v;
+	if (arch_get_random_long(&v))
+		chacha20->nonce[2] ^= v;
+
+	if (sec_strength > CHACHA20_KEY_SIZE)
+		goto err;
+	if (blocklen_bytes != CHACHA20_BLOCK_SIZE)
+		goto err;
+
+	pr_info("ChaCha20 core allocated\n");
+
+	return chacha20;
+
+err:
+	kfree(chacha20);
+	return NULL;
+}
+
+void lrng_drng_dealloc(void *drng)
+{
+	struct chacha20_state *chacha20 = (struct chacha20_state *)drng;
+
+	kzfree(chacha20);
+}
+
+/******************************* Hash Operation *******************************/
+
+void *lrng_hash_alloc(u8 *hashname, u8 *key, u32 keylen)
+{
+	return NULL;
+}
+
+u32 lrng_hash_digestsize(void *hash)
+{
+	return (SHA_DIGEST_WORDS * sizeof(u32));
+}
+
+int lrng_hash_buffer(void *hash, u8 *inbuf, u32 inbuflen, u8 *digest)
+{
+	u32 i;
+	u32 workspace[SHA_WORKSPACE_WORDS];
+
+	WARN_ON(inbuflen % SHA_WORKSPACE_WORDS);
+
+	for (i = 0; i < inbuflen; i += (SHA_WORKSPACE_WORDS * sizeof(u32)))
+		sha_transform((u32 *)digest, (inbuf + i), workspace);
+	memzero_explicit(workspace, sizeof(workspace));
+
+	return 0;
+}
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH 2/2] ath9k: disable RNG by default
From: Jason Cooper @ 2016-08-11 13:14 UTC (permalink / raw)
  To: miaoqing-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: Pan, Miaoqing, Stephan Mueller, Herbert Xu, Matt Mackall,
	Valo, Kalle, linux-wireless-u79uwXL29TY76Z2rM5mHXA, ath9k-devel,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA, Sepehrdad, Pouyan
In-Reply-To: <14a3879458f3bfc36068c2e8294ca448-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

On Thu, Aug 11, 2016 at 10:54:11AM +0800, miaoqing-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org wrote:
> On 2016-08-10 21:24, Jason Cooper wrote:
> >The fact is, barring userspace expectations of /dev/hwrng, hw_random is
> >the appropriate place for it.  It's not a devicetree blob, mac address,
> >or pci config space.  Which are things we feed in once for the heck of
> >it.  This is a *continuous* source or questionable quality.
> >
> >I'm seriously considering putting this and timeriomem-rng into a
> >subdirectory under hw_random/, maybe environ/.  Anything in there gets
> >quality=0 for default, and *doesn't* contribute to /dev/hwrng.
> >
> >Regardless which path we take, I think we should include 'adc' in the
> >name.  I've heard countless times about "Atheros cards come with an rng
> >on board". :-/
> 
> If I understand correctly, you want to bind the ADC source to
> /dev/hwrng, and then change rng-tools to set the entropy to zero in
> the ioctl call ?  There are two major problems with that approach,

Nope.  I want to leverage the hwrng framework to facilitate feeding the
*kernel* entropy pools like all the other hwrngs do currently.  The
difference for *environmental* sources is that when userspace read()s
from /dev/hwrng, they will *not* contribute.

If the environmental sources are the only sources, then no /dev/hwrng
should appear.

> 1) We already tried once before to bind our solution to /dev/hwrng,
> and got so much complaints. The conclusion was that maybe we know that
> the output of /dev/hwrng does not have perfect entropy, but a normal
> user does not know and will misuse it. You mentioned in
> https://www.kernel.org/doc/Documentation/hw_random.txt we have
> 
> "This data is NOT CHECKED by any
> 	fitness tests, and could potentially be bogus (if the
> 	hardware is faulty or has been tampered with).  Data is only
> 	output if the hardware "has-data" flag is set, but nevertheless
> 	a security-conscious person would run fitness tests on the
> 	data before assuming it is truly random."
> 
> But this is not enough to convince upstream to switch to /dev/hwrng.
> I think the concern of users misusing the solution is a very valid
> concern.

Agreed.

> 2) If we set the entropy to zero in rng-tools, we cannot tolerate the
> load.  Rng-tools is not a timer-based solution. Similar to our
> solution, it is based on
> /proc/sys/kernel/random/write_wakeup_threshold. If we do not increase
> the entropy counter, rng-tools keep writing into the pool, and both
> rng-tools and WiFi chip will be overloaded.

That's why I propose a change to the hwrng framework to permit noise
sources while not wiring them up to feed /dev/hwrng.  timeriomem-rng
should have the same problem ath9k-rng does.

Basically, if it wasn't designed to be an rng, it shouldn't be wired up
to /dev/hwrng.

thx,

Jason.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v6 4/5] crypto: LRNG - enable compile
From: kbuild test robot @ 2016-08-11 13:50 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: kbuild-all, herbert, Ted Tso, sandyinchina, Jason Cooper,
	John Denker, H. Peter Anvin, Joe Perches, Pavel Machek,
	George Spelvin, linux-crypto, linux-kernel
In-Reply-To: <1719085.BFjRV9CsT2@positron.chronox.de>

[-- Attachment #1: Type: text/plain, Size: 3256 bytes --]

Hi Stephan,

[auto build test ERROR on cryptodev/master]
[also build test ERROR on v4.8-rc1]
[cannot apply to next-20160811]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Stephan-Mueller/crypto-DRBG-externalize-DRBG-functions-for-LRNG/20160811-203346
base:   https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
config: tile-allyesconfig (attached as .config)
compiler: tilegx-linux-gcc (GCC) 4.6.2
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=tile 

All error/warnings (new ones prefixed by >>):

   crypto/lrng_base.c: In function 'add_interrupt_randomness':
>> crypto/lrng_base.c:583:10: error: implicit declaration of function 'get_irq_regs'
>> crypto/lrng_base.c:583:26: warning: initialization makes pointer from integer without a cast [enabled by default]
   cc1: some warnings being treated as errors

vim +/get_irq_regs +583 crypto/lrng_base.c

22708393 Stephan Mueller 2016-08-11  567  }
22708393 Stephan Mueller 2016-08-11  568  
22708393 Stephan Mueller 2016-08-11  569  /**
22708393 Stephan Mueller 2016-08-11  570   * Hot code path - Callback for interrupt handler
22708393 Stephan Mueller 2016-08-11  571   */
22708393 Stephan Mueller 2016-08-11  572  void add_interrupt_randomness(int irq, int irq_flags)
22708393 Stephan Mueller 2016-08-11  573  {
22708393 Stephan Mueller 2016-08-11  574  	u32 now_time = random_get_entropy();
22708393 Stephan Mueller 2016-08-11  575  	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
22708393 Stephan Mueller 2016-08-11  576  	u32 irq_num = (u32)atomic_add_return(1, &irq_info->num_events);
22708393 Stephan Mueller 2016-08-11  577  
22708393 Stephan Mueller 2016-08-11  578  	if (lrng_pool.irq_info.irq_highres_timer) {
22708393 Stephan Mueller 2016-08-11  579  		if (lrng_irq_stuck(irq_info, now_time))
22708393 Stephan Mueller 2016-08-11  580  			return;
22708393 Stephan Mueller 2016-08-11  581  		lrng_pool_mixin((u8 *)&now_time, sizeof(now_time), irq_num);
22708393 Stephan Mueller 2016-08-11  582  	} else {
22708393 Stephan Mueller 2016-08-11 @583  		struct pt_regs *regs = get_irq_regs();
22708393 Stephan Mueller 2016-08-11  584  		static atomic_t reg_idx = ATOMIC_INIT(0);
22708393 Stephan Mueller 2016-08-11  585  
22708393 Stephan Mueller 2016-08-11  586  		struct {
22708393 Stephan Mueller 2016-08-11  587  			long jiffies;
22708393 Stephan Mueller 2016-08-11  588  			int irq;
22708393 Stephan Mueller 2016-08-11  589  			int irq_flags;
22708393 Stephan Mueller 2016-08-11  590  			u64 ip;
22708393 Stephan Mueller 2016-08-11  591  			u32 curr_reg;

:::::: The code at line 583 was first introduced by commit
:::::: 227083931f3541c5430b40241419b56057555033 crypto: Linux Random Number Generator

:::::: TO: Stephan Mueller <smueller@chronox.de>
:::::: CC: 0day robot <fengguang.wu@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 45495 bytes --]

^ permalink raw reply

* Re: [PATCH v6 4/5] crypto: LRNG - enable compile
From: Stephan Mueller @ 2016-08-11 14:03 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, herbert, Ted Tso, sandyinchina, Jason Cooper,
	John Denker, H. Peter Anvin, Joe Perches, Pavel Machek,
	George Spelvin, linux-crypto, linux-kernel
In-Reply-To: <201608112159.fFG7Xhcw%fengguang.wu@intel.com>

Am Donnerstag, 11. August 2016, 21:50:15 CEST schrieb kbuild test robot:

Hi,

> Hi Stephan,
> 
> [auto build test ERROR on cryptodev/master]
> [also build test ERROR on v4.8-rc1]
> [cannot apply to next-20160811]
> [if your patch is applied to the wrong git tree, please drop us a note to
> help improve the system]

Thank you for the report. This is due to the missing include of asm/irq_regs.h 
which seem to be included my the tested arches through some other means.

I will add it in an update.

Ciao
Stephan

^ permalink raw reply

* D'oh! (Re: robot build error)
From: Gary R Hook @ 2016-08-11 14:21 UTC (permalink / raw)
  To: linux-crypto@vger.kernel.org; +Cc: Herbert Xu
In-Reply-To: <4d2cb6f0-7e9a-89b7-d5c6-327aade39314@amd.com>

Please ignore this patch.

> [PATCH] crypto: CCP - build error: label 'e_hwrng' undefined
>
> Gary R Hook Wed, 10 Aug 2016 12:27:28 -0700
>
> Fix goto target for when registration fails
>
> Reported-by: kbuild test robot <fengguang...@intel.com>
> Signed-off-by: Gary R Hook <gary.h...@amd.com>
> ---
>  drivers/crypto/ccp/ccp-dev-v5.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
>
> diff --git a/drivers/crypto/ccp/ccp-dev-v5.c
> b/drivers/crypto/ccp/ccp-dev-v5.c
> index 4086714..114675e 100644
> --- a/drivers/crypto/ccp/ccp-dev-v5.c
> +++ b/drivers/crypto/ccp/ccp-dev-v5.c
> @@ -835,7 +835,7 @@ static int ccp5_init(struct ccp_device *ccp)
>         /* Register the DMA engine support */
>         ret = ccp_dmaengine_register(ccp);
>         if (ret)
> -               goto e_hwrng;
> +               goto e_kthread;
>
>         return 0;
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Data type for aio_buf under X32?
From: Jeffrey Walton @ 2016-08-11 17:55 UTC (permalink / raw)
  To: linux-crypto

Hi Everyone,

My apologies for this question and my confusion.

When interfacing with the kernel crypto through AF_ALG, what is the
type of 'aio_buf' under X32?

I know is X32 uses ILP32 data model, so integers/longs/pointers are
32-bits (cf., http://www.unix.org/version2/whatsnew/lp64_wp.html). I
believe Glibc uses a 'void*' for 'aio_buf' (cf.,
http://man7.org/linux/man-pages/man7/aio.7.html). But I believe the
kernel's 'aio_buf' is a u64 under X32.

I'm asking due a failure under X32 because GCC sign extends the
pointer value when upsizing to 64-bits (cf., GCC manual 4.7 Arrays and
Pointers, http://gcc.gnu.org/onlinedocs/gcc/Arrays-and-pointers-implementation.html).

Thanks in advance.

Jeff

^ permalink raw reply

* Re: [PATCH] crypto: XTS - remove test that will fail in FIPS mode
From: Tapas Sarangi @ 2016-08-11 19:42 UTC (permalink / raw)
  To: Stephan Mueller, herbert@gondor.apana.org.au; +Cc: linux-crypto@vger.kernel.org
In-Reply-To: <D3D10E85.2F74%tsarangi@trustwave.com>

Hi Stephan,

Any other ideas about this problem ? Since XTS is not amongst the
self-tests as you observed, is it safe to disable .fips_allowed for
xts(aes) in testmgr.c ?

Thanks
-Tapas


On 8/10/16, 5:08 PM, "Tapas Sarangi" <TSarangi@trustwave.com> wrote:

>Hi Stephan,
>
>Thanks. Sorry for a late reply to this.
>
>I did test your patch for testmgr.h with the vanilla kernel 4.7 source.
>This doesn¹t solve the xts(aes) self-test failure in FIPS mode. I get the
>exact same error as before.
>
>Thanks
>-Tapas
>
>
>
>
>
>
>
>On 8/10/16, 12:49 AM, "Stephan Mueller" <smueller@chronox.de> wrote:
>
>>Hi Tapas, Herbert,
>>
>>Tapas: this patch should fix it. Can you please test?
>>
>>Herbert: The reason why I have to caught this issue in my tests is the
>>following: I compile xts-aes-aesni statically as you can see below. The
>>self test is marked as passed, although there is no XTS test performed.
>>When you boot in FIPS mode, the testmgr prints out all tests. But XTS is
>>not among them. Do you have an idea why that happens?
>>
>>name         : xts(aes)
>>driver       : xts-aes-aesni
>>module       : kernel
>>priority     : 400
>>refcnt       : 1
>>selftest     : passed
>>internal     : no
>>type         : ablkcipher
>>async        : yes
>>blocksize    : 16
>>min keysize  : 32
>>max keysize  : 64
>>ivsize       : 16
>>geniv        : <default>
>>
>>---8<---
>>
>>In FIPS mode, setting XTS keys where the AES key is identical to the
>>tweak key is forbidden. Thus, the self test with such property will fail
>>in FIPS mode.
>>
>>As we have other tests available for XTS, this patch simply removes the
>>offending test vectors.
>>
>>Reported-by: Tapas Sarangi <TSarangi@trustwave.com>
>>Signed-off-by: Stephan Mueller <smueller@chronox.de>
>>---
>> crypto/testmgr.h | 36 ------------------------------------
>> 1 file changed, 36 deletions(-)
>>
>>diff --git a/crypto/testmgr.h b/crypto/testmgr.h
>>index acb6bbf..e4b58f5 100644
>>--- a/crypto/testmgr.h
>>+++ b/crypto/testmgr.h
>>@@ -10179,24 +10179,6 @@ static struct cipher_testvec
>>tf_lrw_dec_tv_template[] = {
>> static struct cipher_testvec tf_xts_enc_tv_template[] = {
>>      /* Generated from AES-XTS test vectors */
>> {
>>-             .key    = "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00",
>>-             .klen   = 32,
>>-             .iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00",
>>-             .input  = "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00",
>>-             .ilen   = 32,
>>-             .result = "\x4b\xc9\x44\x4a\x11\xa3\xef\xac"
>>-                       "\x30\x74\xe4\x44\x52\x77\x97\x43"
>>-                       "\xa7\x60\xb2\x45\x2e\xf9\x00\x90"
>>-                       "\x9f\xaa\xfd\x89\x6e\x9d\x4a\xe0",
>>-             .rlen   = 32,
>>-     }, {
>>              .key    = "\x11\x11\x11\x11\x11\x11\x11\x11"
>>                        "\x11\x11\x11\x11\x11\x11\x11\x11"
>>                        "\x22\x22\x22\x22\x22\x22\x22\x22"
>>@@ -10522,24 +10504,6 @@ static struct cipher_testvec
>>tf_xts_dec_tv_template[] = {
>>      /* Generated from AES-XTS test vectors */
>>      /* same as enc vectors with input and result reversed */
>>      {
>>-             .key    = "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00",
>>-             .klen   = 32,
>>-             .iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00",
>>-             .input  = "\x4b\xc9\x44\x4a\x11\xa3\xef\xac"
>>-                       "\x30\x74\xe4\x44\x52\x77\x97\x43"
>>-                       "\xa7\x60\xb2\x45\x2e\xf9\x00\x90"
>>-                       "\x9f\xaa\xfd\x89\x6e\x9d\x4a\xe0",
>>-             .ilen   = 32,
>>-             .result = "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00"
>>-                       "\x00\x00\x00\x00\x00\x00\x00\x00",
>>-             .rlen   = 32,
>>-     }, {
>>              .key    = "\x11\x11\x11\x11\x11\x11\x11\x11"
>>                        "\x11\x11\x11\x11\x11\x11\x11\x11"
>>                        "\x22\x22\x22\x22\x22\x22\x22\x22"
>>--
>>2.7.4
>>
>>
>


________________________________

This transmission may contain information that is privileged, confidential, and/or exempt from disclosure under applicable law. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution, or use of the information contained herein (including any reliance thereon) is strictly prohibited. If you received this transmission in error, please immediately contact the sender and destroy the material in its entirety, whether in electronic or hard copy format.

^ permalink raw reply

* Re: [PATCH v6 0/5] /dev/random - a new approach
From: Theodore Ts'o @ 2016-08-11 21:36 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: herbert, sandyinchina, Jason Cooper, John Denker, H. Peter Anvin,
	Joe Perches, Pavel Machek, George Spelvin, linux-crypto,
	linux-kernel
In-Reply-To: <4723196.TTQvcXsLCG@positron.chronox.de>

On Thu, Aug 11, 2016 at 02:24:21PM +0200, Stephan Mueller wrote:
> 
> The following patch set provides a different approach to /dev/random which
> I call Linux Random Number Generator (LRNG) to collect entropy within the Linux
> kernel. The main improvements compared to the legacy /dev/random is to provide
> sufficient entropy during boot time as well as in virtual environments and when
> using SSDs. A secondary design goal is to limit the impact of the entropy
> collection on massive parallel systems and also allow the use accelerated
> cryptographic primitives. Also, all steps of the entropic data processing are
> testable. Finally massive performance improvements are visible at /dev/urandom
> and get_random_bytes.
> 
> The design and implementation is driven by a set of goals described in [1]
> that the LRNG completely implements. Furthermore, [1] includes a
> comparison with RNG design suggestions such as SP800-90B, SP800-90C, and
> AIS20/31.

Given the changes that have landed in Linus's tree for 4.8, how many
of the design goals for your LRNG are still left not yet achieved?

Reading the paper, you are still claiming huge performance
improvements over getrandomm and /dev/urandom.  With the use of the
ChaCha20 (and given that you added a ChaCha20 DRBG as well), it's not
clear this is still an advantage over what we currently have.

As far as whether or not you can gather enough entropy at boot time,
what we're really talking about how how much entropy we want to assume
can be gathered from interrupt timings, since what you do in your code
is not all that different from what the current random driver is
doing.  So it's pretty easy to turn a knob and say, "hey presto, we
can get all of the entropy we need before userspace starts!"  But
justifying this is much harder, and using statistical tests isn't
really sufficient as far as I'm concerned.

Cheers,

						- Ted

^ permalink raw reply

* FIPS self test failures (kernel panic) in kernel-4.7
From: Tapas Sarangi @ 2016-08-11 21:55 UTC (permalink / raw)
  To: linux-crypto@vger.kernel.org

Hello,

A few algorithms are failing Œalg self tests' during kernel boot into FIPS
mode (fips=1), causing a kernel panic (see below). I am using vanilla
kernel-4.7 source for these tests.

These messages were from individual boots into FIPS mode, where algorithms
are taken out from ".fips_allowed=1² and compiled.

Following (see below) is a patch to disable tests for some of these
algorithms work and kernel could boot into FIPS mode (fips=1)
successfully. Please Let me know if there is a deeper/lower-level fix to
this.


##
[    1.270663] alg: hash: Failed to load transform for cmac(aes): -2
[    1.271471] Kernel panic - not syncing: cmac(aes): cmac(aes) alg self
test failed in fips mode!

[    1.256148] alg: hash: Failed to load transform for cmac(des3_ede): -2
[    1.257005] Kernel panic - not syncing: cmac(des3_ede): cmac(des3_ede)
alg self test failed in fips mode!
[    1.257005]

[    1.427856] alg: aead: Failed to load transform for
authenc(hmac(sha1),cbc(des3_ede)): -2
[    1.429036] Kernel panic - not syncing:
authenc(hmac(sha1),cbc(des3_ede)): authenc(hmac(sha1),cbc(des3_ede)) alg
self test failed in fips mode!
[    1.429036]


[    1.316830] alg: aead: Failed to load transform for
authenc(hmac(sha224),cbc(des3_ede)): -2
[    1.317914] Kernel panic - not syncing:
authenc(hmac(sha224),cbc(des3_ede)): authenc(hmac(sha224),cbc(des3_ede))
alg self test failed in fips mode!
[    1.317914]


[    1.262950] alg: aead: Failed to load transform for
authenc(hmac(sha256),cbc(des3_ede)): -2
[    1.264094] Kernel panic - not syncing:
authenc(hmac(sha256),cbc(des3_ede)): authenc(hmac(sha256),cbc(des3_ede))
alg self test failed in fips mode!
[    1.264094]


##



#‹‹PATCH‹‹
--- a/crypto/testmgr.c  2016-08-11 14:06:15.925140405 -0500
+++ b/crypto/testmgr.c  2016-08-11 15:42:13.954317991 -0500
@@ -2079,7 +2079,6 @@
        }, {
        .alg = "authenc(hmac(sha1),cbc(des3_ede))",
        .test = alg_test_aead,
-       .fips_allowed = 1,
        .suite = {
                .aead = {
                        .enc = {
@@ -2133,7 +2132,6 @@
        }, {
        .alg = "authenc(hmac(sha224),cbc(des3_ede))",
        .test = alg_test_aead,
-       .fips_allowed = 1,
        .suite = {
                .aead = {
                        .enc = {
@@ -2174,7 +2172,6 @@
        }, {
        .alg = "authenc(hmac(sha256),cbc(des3_ede))",
        .test = alg_test_aead,
-               .fips_allowed = 1,
        .suite = {
                .aead = {
                        .enc = {
@@ -2209,7 +2206,6 @@
        }, {
        .alg = "authenc(hmac(sha384),cbc(des3_ede))",
        .test = alg_test_aead,
-               .fips_allowed = 1,
        .suite = {
                .aead = {
                        .enc = {
@@ -2258,7 +2254,6 @@
        }, {
        .alg = "authenc(hmac(sha512),cbc(des3_ede))",
        .test = alg_test_aead,
-               .fips_allowed = 1,
        .suite = {
                .aead = {
                        .enc = {
@@ -2386,7 +2381,6 @@
        }, {
        .alg = "cbc(des3_ede)",
        .test = alg_test_skcipher,
-               .fips_allowed = 1,
        .suite = {
                .cipher = {
                        .enc = {
@@ -2462,7 +2456,6 @@
                }
        }, {
        .alg = "cmac(aes)",
-               .fips_allowed = 1,
        .test = alg_test_hash,
        .suite = {
                .hash = {
@@ -2472,7 +2465,6 @@
                }
        }, {
        .alg = "cmac(des3_ede)",
-               .fips_allowed = 1,
        .test = alg_test_hash,
        .suite = {
                .hash = {
@@ -3753,7 +3745,6 @@
        }, {
        .alg = "xts(aes)",
        .test = alg_test_skcipher,
-               .fips_allowed = 1,
        .suite = {
                .cipher = {
                        .enc = {



________________________________

This transmission may contain information that is privileged, confidential, and/or exempt from disclosure under applicable law. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution, or use of the information contained herein (including any reliance thereon) is strictly prohibited. If you received this transmission in error, please immediately contact the sender and destroy the material in its entirety, whether in electronic or hard copy format.

^ permalink raw reply

* [PATCH -next] crypto: ccp - Fix non static symbol warning
From: Wei Yongjun @ 2016-08-12  0:00 UTC (permalink / raw)
  To: Tom Lendacky, Gary Hook, Herbert Xu, David S. Miller
  Cc: Wei Yongjun, linux-crypto

Fixes the following sparse warning:

drivers/crypto/ccp/ccp-dev.c:62:14: warning:
 symbol 'ccp_increment_unit_ordinal' was not declared. Should it be static?

Signed-off-by: Wei Yongjun <weiyj.lk@gmail.com>
---
 drivers/crypto/ccp/ccp-dev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
index 38a98d8..5d36eef 100644
--- a/drivers/crypto/ccp/ccp-dev.c
+++ b/drivers/crypto/ccp/ccp-dev.c
@@ -59,7 +59,7 @@ static struct ccp_device *ccp_rr;
 
 /* Ever-increasing value to produce unique unit numbers */
 static atomic_t ccp_unit_ordinal;
-unsigned int ccp_increment_unit_ordinal(void)
+static unsigned int ccp_increment_unit_ordinal(void)
 {
 	return atomic_inc_return(&ccp_unit_ordinal);
 }

^ permalink raw reply related

* Re: [PATCH] crypto: XTS - remove test that will fail in FIPS mode
From: Stephan Mueller @ 2016-08-12  8:43 UTC (permalink / raw)
  To: Tapas Sarangi; +Cc: herbert@gondor.apana.org.au, linux-crypto@vger.kernel.org
In-Reply-To: <D3D23ED9.2F9C%tsarangi@trustwave.com>

Am Donnerstag, 11. August 2016, 19:42:54 CEST schrieb Tapas Sarangi:

Hi Tapas,

> Hi Stephan,
> 
> Any other ideas about this problem ? Since XTS is not amongst the
> self-tests as you observed, is it safe to disable .fips_allowed for
> xts(aes) in testmgr.c ?

If you do that, none of your XTS implementations will be allowed and work in 
FIPS mode. The thing is that I cannot reproduce the issue (yet). I am still 
looking.

Ciao
Stephan

^ permalink raw reply

* Re: [PATCH v6 0/5] /dev/random - a new approach
From: Stephan Mueller @ 2016-08-12  9:34 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: herbert, sandyinchina, Jason Cooper, John Denker, H. Peter Anvin,
	Joe Perches, Pavel Machek, George Spelvin, linux-crypto,
	linux-kernel
In-Reply-To: <20160811213632.GL10626@thunk.org>

Am Donnerstag, 11. August 2016, 17:36:32 CEST schrieb Theodore Ts'o:

Hi Theodore,

> On Thu, Aug 11, 2016 at 02:24:21PM +0200, Stephan Mueller wrote:
> > The following patch set provides a different approach to /dev/random 
which
> > I call Linux Random Number Generator (LRNG) to collect entropy within the
> > Linux kernel. The main improvements compared to the legacy /dev/random is
> > to provide sufficient entropy during boot time as well as in virtual
> > environments and when using SSDs. A secondary design goal is to limit the
> > impact of the entropy collection on massive parallel systems and also
> > allow the use accelerated cryptographic primitives. Also, all steps of
> > the entropic data processing are testable. Finally massive performance
> > improvements are visible at /dev/urandom and get_random_bytes.
> > 
> > The design and implementation is driven by a set of goals described in 
[1]
> > that the LRNG completely implements. Furthermore, [1] includes a
> > comparison with RNG design suggestions such as SP800-90B, SP800-90C, and
> > AIS20/31.
> 
> Given the changes that have landed in Linus's tree for 4.8, how many
> of the design goals for your LRNG are still left not yet achieved?

The core concerns I have at this point are the following:

- correlation: the interrupt noise source is closely correlated to the HID/
block noise sources. I see that the fast_pool somehow "smears" that 
correlation. However, I have not seen a full assessment that the correlation 
is gone away. Given that I do not believe that the HID event values (key 
codes, mouse coordinates) have any entropy -- the user sitting at the console 
exactly knows what he pressed and which mouse coordinates are created, and 
given that for block devices, only the high-resolution time stamp gives any 
entropy, I am suggesting to remove the HID/block device noise sources and 
leave the IRQ noise source. Maybe we could record the HID event values to 
further stir the pool but do not credit it any entropy. Of course, that would 
imply that the assumed entropy in an IRQ event is revalued. I am currently 
finishing up an assessment of how entropy behaves in a VM (where I hope that 
the report is released). Please note that contrary to my initial 
expectations, the IRQ events are the only noise sources which are almost 
unaffected by a VMM operation. Hence, IRQs are much better in a VM 
environment than block or HID noise sources.

- entropy estimate: the current entropy heuristics IMHO have nothing to do 
with the entropy of the data coming in. Currently, the min of first/second/
third derivative of the Jiffies time stamp is used and capped at 11. That 
value is the entropy value credited to the event. Given that the entropy 
rests with the high-res time stamp and not with jiffies or the event value, I 
think that the heuristic is not helpful. I understand that it underestimates 
on average the available entropy, but that is the only relationship I see. In 
my mentioned entropy in VM assessment (plus the BSI report on /dev/random 
which is unfortunately written in German, but available in the Internet) I 
did a min entropy calculation based on different min entropy formulas 
(SP800-90B). That calculation shows that we get from the noise sources is 
about 5 to 6 bits. On average the entropy heuristic credits between 0.5 and 1 
bit for events, so it underestimates the entropy. Yet, the entropy heuristic 
can credit up to 11 bits. Here I think it becomes clear that the current 
entropy heuristic is not helpful. In addition, on systems where no high-res 
timer is available, I assume (I have not measured it yet), the entropy 
heuristic even overestimates the entropy.

- albeit I like the current injection of twice the fast_pool into the 
ChaCha20 (which means that the pathological case where the collection of 128 
bits of entropy would result in an attack resistance of 2 * 128 bits and 
*not* 2^128 bits is now increased to an attack strength of 2^64 * 2 bits), /
dev/urandom has *no* entropy until that injection happens. The injection 
happens early in the boot cycle, but in my test system still after user space 
starts. I tried to inject "atomically" (to not fall into the aforementioned 
pathological case trap) of 32 / 112 / 256 bits of entropy into the /dev/
urandom RNG to have /dev/urandom at least seeded with a few bits before user 
space starts followed by the atomic injection of the subsequent bits.


A minor issue that may not be of too much importance: if there is a user 
space entropy provider waiting with select(2) or poll(2) on /dev/random (like 
rngd or my jitterentropy-rngd), this provider is only woken up when somebody 
pulls on /dev/random. If /dev/urandom is pulled (and the system does not 
receive entropy from the add*randomness noise sources), the user space 
provider is *not* woken up. So, /dev/urandom spins as a DRNG even though it 
could use a topping off of its entropy once in a while. In my jitterentropy-
rngd I have handled the situation that in addition to a select(2), the daemon 
is woken up every 5 seconds to read the entropy_avail file and starts 
injecting data into the kernel if it falls below a threshold. Yet, this is a 
hack. The wakeup function in the kernel should be placed at a different 
location to also have /dev/urandom benefit from the wakeup.
> 
> Reading the paper, you are still claiming huge performance
> improvements over getrandomm and /dev/urandom.  With the use of the
> ChaCha20 (and given that you added a ChaCha20 DRBG as well), it's not
> clear this is still an advantage over what we currently have.

I agree that with your latest changes, the performance of /dev/urandom is 
comparatively to my implementation, considering the tables 6 and 7 in my 
report. Although the speed of my ChaCha20 DRNG is faster for large block 
sizes (470 vs 210 MB/s for 4096 byte blocks), you rightfully state that the 
large block sizes do not really matter and hence I am not really using it for 
comparison. 

The table 6 and 7 reference the old /dev/urandom using still the SHA-1.
> 
> As far as whether or not you can gather enough entropy at boot time,
> what we're really talking about how how much entropy we want to assume
> can be gathered from interrupt timings, since what you do in your code
> is not all that different from what the current random driver is

Correct. I think I am doing exactly what you do regarding the entropy 
collection minus the caveats mentioned above.

> doing.  So it's pretty easy to turn a knob and say, "hey presto, we
> can get all of the entropy we need before userspace starts!"  But
> justifying this is much harder, and using statistical tests isn't
> really sufficient as far as I'm concerned.

I agree that statistics is one hint only. But as of now I have not seen any 
real explanation why an IRQ event measured with a high-res timer should not 
have 1 bit or 0.5 bits of entropy on average. All my statistical measurements 
(see my LRNG paper, see with my hopefully released VM assessment paper) show 
that the statistical measurement indicates that each high-res time stamp of 
an IRQ has more 4 bits of entropy at least when the system is under attack. 
Both one bit or 0.5 bits is more than enough to have a properly working /dev/
random even in virtual environments, embedded systems, headless systems, 
systems with SSDs, systems using a device mapper, etc. All those type of 
systems are currently subject to heavy penalties because of the collision 
problem I mentioned in the first bullet above.

Finally, one remark which I know you could not care less: :-) 

I try to use a known DRNG design that a lot of folks have already assessed -- 
SP800-90A (and please, do not hint to the Dual EC DRBG as this issue was 
pointed out already by researcher shortly after the first SP800-90A came out 
in 2007). This way I do not need to re-invent the wheel and potentially 
forget about things that may be helpful in a DRNG. To allow researchers to 
assess my ChaCha20 DRNG. that used when no kernel crypto API is compiled. 
independently from the kernel, I extracted the ChaCha20 DRNG code into a 
standalone DRNG accessible at [1]. This standalone implementation can be 
debugged and studied in user space. Moreover it is a simple copy of the 
kernel code to allow researchers an easy comparison.

[1] http://www.chronox.de/chacha20_drng.html

Ciao
Stephan

^ permalink raw reply

* [PATCH] crypto: fix ctx pointer and digest copy in sha256-mb
From: Xiaodong Liu @ 2016-08-12 10:24 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, tim.c.chen, megha.dey, linux-kernel, Xiaodong Liu

1. fix ctx pointer
Use req_ctx which is the ctx for the next job that have
been completed in the lanes instead of the first
completed job rctx, whose completion could have been
called and released.
2. fix digest copy
Use XMM register to copy another 16 bytes sha256 digest
instead of a regular register.

Signed-off-by: Xiaodong Liu <xiaodong.liu@intel.com>
---
 arch/x86/crypto/sha256-mb/sha256_mb.c                | 4 ++--
 arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S | 7 ++++---
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/x86/crypto/sha256-mb/sha256_mb.c b/arch/x86/crypto/sha256-mb/sha256_mb.c
index 89fa85e..6f97fb3 100644
--- a/arch/x86/crypto/sha256-mb/sha256_mb.c
+++ b/arch/x86/crypto/sha256-mb/sha256_mb.c
@@ -485,10 +485,10 @@ static int sha_complete_job(struct mcryptd_hash_request_ctx *rctx,
 
 			req = cast_mcryptd_ctx_to_req(req_ctx);
 			if (irqs_disabled())
-				rctx->complete(&req->base, ret);
+				req_ctx->complete(&req->base, ret);
 			else {
 				local_bh_disable();
-				rctx->complete(&req->base, ret);
+				req_ctx->complete(&req->base, ret);
 				local_bh_enable();
 			}
 		}
diff --git a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S b/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S
index b691da9..a78a069 100644
--- a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S
+++ b/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S
@@ -265,13 +265,14 @@ ENTRY(sha256_mb_mgr_get_comp_job_avx2)
 	vpinsrd	$1, _args_digest+1*32(state, idx, 4), %xmm0, %xmm0
 	vpinsrd	$2, _args_digest+2*32(state, idx, 4), %xmm0, %xmm0
 	vpinsrd	$3, _args_digest+3*32(state, idx, 4), %xmm0, %xmm0
-	movl	_args_digest+4*32(state, idx, 4), tmp2_w
+	vmovd   _args_digest(state , idx, 4) , %xmm0
 	vpinsrd	$1, _args_digest+5*32(state, idx, 4), %xmm1, %xmm1
 	vpinsrd	$2, _args_digest+6*32(state, idx, 4), %xmm1, %xmm1
 	vpinsrd	$3, _args_digest+7*32(state, idx, 4), %xmm1, %xmm1
 
-	vmovdqu	%xmm0, _result_digest(job_rax)
-	movl	tmp2_w, _result_digest+1*16(job_rax)
+        vmovdqu %xmm0, _result_digest(job_rax)
+        offset =  (_result_digest + 1*16)
+        vmovdqu %xmm1, offset(job_rax)
 
 	pop	%rbx
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH] crypto: fix ctx pointer in sha512-mb
From: Xiaodong Liu @ 2016-08-12 10:28 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, tim.c.chen, megha.dey, linux-kernel, Xiaodong Liu

Signed-off-by: Xiaodong Liu <xiaodong.liu@intel.com>
---
 arch/x86/crypto/sha512-mb/sha512_mb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/crypto/sha512-mb/sha512_mb.c b/arch/x86/crypto/sha512-mb/sha512_mb.c
index f4cf5b7..d210174 100644
--- a/arch/x86/crypto/sha512-mb/sha512_mb.c
+++ b/arch/x86/crypto/sha512-mb/sha512_mb.c
@@ -497,10 +497,10 @@ static int sha_complete_job(struct mcryptd_hash_request_ctx *rctx,
 
 			req = cast_mcryptd_ctx_to_req(req_ctx);
 			if (irqs_disabled())
-				rctx->complete(&req->base, ret);
+				req_ctx->complete(&req->base, ret);
 			else {
 				local_bh_disable();
-				rctx->complete(&req->base, ret);
+				req_ctx->complete(&req->base, ret);
 				local_bh_enable();
 			}
 		}
-- 
1.9.1

^ permalink raw reply related

* Re: FIPS self test failures (kernel panic) in kernel-4.7
From: Stephan Mueller @ 2016-08-12 13:11 UTC (permalink / raw)
  To: Tapas Sarangi; +Cc: linux-crypto@vger.kernel.org
In-Reply-To: <D3D25E68.3066%tsarangi@trustwave.com>

Am Donnerstag, 11. August 2016, 21:55:05 CEST schrieb Tapas Sarangi:

Hi Tapas,

> Hello,
> 
> A few algorithms are failing Œalg self tests' during kernel boot into FIPS
> mode (fips=1), causing a kernel panic (see below). I am using vanilla
> kernel-4.7 source for these tests.
> 
> These messages were from individual boots into FIPS mode, where algorithms
> are taken out from ".fips_allowed=1² and compiled.
> 
> Following (see below) is a patch to disable tests for some of these
> algorithms work and kernel could boot into FIPS mode (fips=1)
> successfully. Please Let me know if there is a deeper/lower-level fix to
> this.

Can you please send me (not the list) your .config file? I am not really sure 
what is going on as I cannot reproduce it. I use the fips mode during my tests 
and I use cmac or XTS and yet they do not cause an issue.

Thanks.

Ciao
Stephan

^ permalink raw reply

* Re: [PATCH] crypto: fix ctx pointer and digest copy in sha256-mb
From: Tim Chen @ 2016-08-12 16:17 UTC (permalink / raw)
  To: Xiaodong Liu, herbert, Megha Dey; +Cc: linux-crypto, megha.dey, linux-kernel
In-Reply-To: <1470997482-118327-1-git-send-email-xiaodong.liu@intel.com>

On Fri, 2016-08-12 at 06:24 -0400, Xiaodong Liu wrote:
> 1. fix ctx pointer
> Use req_ctx which is the ctx for the next job that have
> been completed in the lanes instead of the first
> completed job rctx, whose completion could have been
> called and released.
> 2. fix digest copy
> Use XMM register to copy another 16 bytes sha256 digest
> instead of a regular register.

The changes look fine to me.  Megha, can you double check?

Tim

> 
> Signed-off-by: Xiaodong Liu <xiaodong.liu@intel.com>
> ---
>  arch/x86/crypto/sha256-mb/sha256_mb.c                | 4 ++--
>  arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S | 7 ++++---
>  2 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/x86/crypto/sha256-mb/sha256_mb.c b/arch/x86/crypto/sha256-mb/sha256_mb.c
> index 89fa85e..6f97fb3 100644
> --- a/arch/x86/crypto/sha256-mb/sha256_mb.c
> +++ b/arch/x86/crypto/sha256-mb/sha256_mb.c
> @@ -485,10 +485,10 @@ static int sha_complete_job(struct mcryptd_hash_request_ctx *rctx,
>  
>  			req = cast_mcryptd_ctx_to_req(req_ctx);
>  			if (irqs_disabled())
> -				rctx->complete(&req->base, ret);
> +				req_ctx->complete(&req->base, ret);
>  			else {
>  				local_bh_disable();
> -				rctx->complete(&req->base, ret);
> +				req_ctx->complete(&req->base, ret);
>  				local_bh_enable();
>  			}
>  		}
> diff --git a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S b/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S
> index b691da9..a78a069 100644
> --- a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S
> +++ b/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S
> @@ -265,13 +265,14 @@ ENTRY(sha256_mb_mgr_get_comp_job_avx2)
>  	vpinsrd	$1, _args_digest+1*32(state, idx, 4), %xmm0, %xmm0
>  	vpinsrd	$2, _args_digest+2*32(state, idx, 4), %xmm0, %xmm0
>  	vpinsrd	$3, _args_digest+3*32(state, idx, 4), %xmm0, %xmm0
> -	movl	_args_digest+4*32(state, idx, 4), tmp2_w
> +	vmovd   _args_digest(state , idx, 4) , %xmm0
>  	vpinsrd	$1, _args_digest+5*32(state, idx, 4), %xmm1, %xmm1
>  	vpinsrd	$2, _args_digest+6*32(state, idx, 4), %xmm1, %xmm1
>  	vpinsrd	$3, _args_digest+7*32(state, idx, 4), %xmm1, %xmm1
>  
> -	vmovdqu	%xmm0, _result_digest(job_rax)
> -	movl	tmp2_w, _result_digest+1*16(job_rax)
> +        vmovdqu %xmm0, _result_digest(job_rax)
> +        offset =  (_result_digest + 1*16)
> +        vmovdqu %xmm1, offset(job_rax)
>  
>  	pop	%rbx
>  

^ permalink raw reply

* Re: [PATCH] crypto: fix ctx pointer in sha512-mb
From: Tim Chen @ 2016-08-12 16:18 UTC (permalink / raw)
  To: Xiaodong Liu, herbert; +Cc: linux-crypto, megha.dey, linux-kernel
In-Reply-To: <1470997711-118507-1-git-send-email-xiaodong.liu@intel.com>

On Fri, 2016-08-12 at 06:28 -0400, Xiaodong Liu wrote:
> Signed-off-by: Xiaodong Liu <xiaodong.liu@intel.com>
> ---
>  arch/x86/crypto/sha512-mb/sha512_mb.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/crypto/sha512-mb/sha512_mb.c b/arch/x86/crypto/sha512-mb/sha512_mb.c
> index f4cf5b7..d210174 100644
> --- a/arch/x86/crypto/sha512-mb/sha512_mb.c
> +++ b/arch/x86/crypto/sha512-mb/sha512_mb.c
> @@ -497,10 +497,10 @@ static int sha_complete_job(struct mcryptd_hash_request_ctx *rctx,
>  
>  			req = cast_mcryptd_ctx_to_req(req_ctx);
>  			if (irqs_disabled())
> -				rctx->complete(&req->base, ret);
> +				req_ctx->complete(&req->base, ret);
>  			else {
>  				local_bh_disable();
> -				rctx->complete(&req->base, ret);
> +				req_ctx->complete(&req->base, ret);
>  				local_bh_enable();
>  			}
>  		}

Changes look fine to me.

Acked.

Tim

^ permalink raw reply

* Re: [PATCH v6 0/5] /dev/random - a new approach
From: Theodore Ts'o @ 2016-08-12 19:22 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: herbert, sandyinchina, Jason Cooper, John Denker, H. Peter Anvin,
	Joe Perches, Pavel Machek, George Spelvin, linux-crypto,
	linux-kernel
In-Reply-To: <6876524.OiXCMsNJHH@tauon.atsec.com>

On Fri, Aug 12, 2016 at 11:34:55AM +0200, Stephan Mueller wrote:
> 
> - correlation: the interrupt noise source is closely correlated to the HID/
> block noise sources. I see that the fast_pool somehow "smears" that 
> correlation. However, I have not seen a full assessment that the correlation 
> is gone away. Given that I do not believe that the HID event values (key 
> codes, mouse coordinates) have any entropy -- the user sitting at the console 
> exactly knows what he pressed and which mouse coordinates are created, and 
> given that for block devices, only the high-resolution time stamp gives any 
> entropy, I am suggesting to remove the HID/block device noise sources and 
> leave the IRQ noise source. Maybe we could record the HID event values to 
> further stir the pool but do not credit it any entropy. Of course, that would 
> imply that the assumed entropy in an IRQ event is revalued. I am currently 
> finishing up an assessment of how entropy behaves in a VM (where I hope that 
> the report is released). Please note that contrary to my initial 
> expectations, the IRQ events are the only noise sources which are almost 
> unaffected by a VMM operation. Hence, IRQs are much better in a VM 
> environment than block or HID noise sources.

The reason why I'm untroubled with leaving them in is because I beieve
the quality of the timing information from the HID and block devices
is better than most of the other interrupt sources.  For example, most
network interfaces these days use NAPI, which means interrupts get
coalesced and sent in batch, which means the time of the interrupt is
latched off of some kind of timer --- and on many embeded devices
there is a single oscillator for the entire mainboard.  We only call
add_disk_randomness for rotational devices (e.g., only HDD's, not
SSD's), after the interrupt has been recorded.  Yes, most of the
entropy is probably going to be found in the high entropy time stamp
rather than the jiffies-based timestamp, especially for the hard drive
completion time.

I also tend to take a much more pragmatic viewpoint towards
measurability.  Sure, the human may know what she is typing, and
something about when she typed it (although probably not accurately
enough on a millisecond basis, so even the jiffies number is going to
be not easily predicted), but the analyst sitting behind the desk at
the NSA or the BND or the MSS is probably not going to have access to
that information.

(Whereas the NSA or the BND probably *can* get low-level information
about the Intel x86 CPU's internal implementation, which is why I'm
extremely amused by the arugment --- "the internals of the Intel CPU
are **so** complex we can't reverse engineer what's going on inside,
so the jitter RNG *must* be good!"  Note BTW that the NSA has only
said they won't do industrial espionage for economic for economic
gain, not that they won't engage in espionage against industrial
entities at all.  This is why the NSA spying on Petrobras is
considered completely fair game, even if it does enrage the
Brazillians.  :-)

> - entropy estimate: the current entropy heuristics IMHO have nothing to do 
> with the entropy of the data coming in. Currently, the min of first/second/
> third derivative of the Jiffies time stamp is used and capped at 11. That 
> value is the entropy value credited to the event. Given that the entropy 
> rests with the high-res time stamp and not with jiffies or the event value, I 
> think that the heuristic is not helpful. I understand that it underestimates 
> on average the available entropy, but that is the only relationship I see. In 
> my mentioned entropy in VM assessment (plus the BSI report on /dev/random 
> which is unfortunately written in German, but available in the Internet) I 
> did a min entropy calculation based on different min entropy formulas 
> (SP800-90B). That calculation shows that we get from the noise sources is 
> about 5 to 6 bits. On average the entropy heuristic credits between 0.5 and 1 
> bit for events, so it underestimates the entropy. Yet, the entropy heuristic 
> can credit up to 11 bits. Here I think it becomes clear that the current 
> entropy heuristic is not helpful. In addition, on systems where no high-res 
> timer is available, I assume (I have not measured it yet), the entropy 
> heuristic even overestimates the entropy.

The disks on a VM are not rotational disks, so we wouldn't be using
the add-disk-randomness entropy calculation.  And you generally don't
have a keyboard on a mouse attached to the VM, so we would be using
the entropy estimate from the interrupt timing.

As far as whether you can get 5-6 bits of entropy from interrupt
timings --- that just doesn't pass the laugh test.  The min-entropy
formulas are estimates assuming IID data sources, and it's not at all
clear (in fact, i'd argue pretty clearly _not_) that they are IID.  As
I said, take for example the network interfaces, and how NAPI gets
implemented.  And in a VM environment, where everything is synthetic,
the interrupt timings are definitely not IID, and there may be
patterns that will not detectable by statistical mechanisms.

> - albeit I like the current injection of twice the fast_pool into the 
> ChaCha20 (which means that the pathological case where the collection of 128 
> bits of entropy would result in an attack resistance of 2 * 128 bits and 
> *not* 2^128 bits is now increased to an attack strength of 2^64 * 2 bits), /
> dev/urandom has *no* entropy until that injection happens. The injection 
> happens early in the boot cycle, but in my test system still after user space 
> starts. I tried to inject "atomically" (to not fall into the aforementioned 
> pathological case trap) of 32 / 112 / 256 bits of entropy into the /dev/
> urandom RNG to have /dev/urandom at least seeded with a few bits before user 
> space starts followed by the atomic injection of the subsequent bits.

The early boot problem is a hard one.  We can inject some noise in,
but I don't think a few bits actually does much good.  So the question
is whether it's faster to get to fully seeded, or to inject in 32 bits
of entropy in the hopes that this will do some good.  Personally, I'm
not convinced.  So the tack I've taken is to have warning messages
printed when someone *does* draw from /dev/urandom before it's fully
seeded.  In many cases, it's for entirely bogus, non-cryptographic
reasons.  (For example, Python wanting to use a random salt to protect
against certain DOS attacks when Python is being used in a web server
--- a use case which is completely irrelevant when it's being used by
systemd generator scripts at boot time.)

Ultimately, I think the right answer here is we need help from the
bootloader, and ultimately some hardware help or some initialization
at factory time which isn't too easily hacked by a Tailored Access
Organization team who can intercept hardware shipments.  :-)

> A minor issue that may not be of too much importance: if there is a user 
> space entropy provider waiting with select(2) or poll(2) on /dev/random (like 
> rngd or my jitterentropy-rngd), this provider is only woken up when somebody 
> pulls on /dev/random. If /dev/urandom is pulled (and the system does not 
> receive entropy from the add*randomness noise sources), the user space 
> provider is *not* woken up. So, /dev/urandom spins as a DRNG even though it 
> could use a topping off of its entropy once in a while. In my jitterentropy-
> rngd I have handled the situation that in addition to a select(2), the daemon 
> is woken up every 5 seconds to read the entropy_avail file and starts 
> injecting data into the kernel if it falls below a threshold. Yet, this is a 
> hack. The wakeup function in the kernel should be placed at a different 
> location to also have /dev/urandom benefit from the wakeup.

Either /dev/urandom is a DRBG or is it isn't.  If it's a DRBG then you
don't need to track the entropy of the DRBG at all.  In fact, the
concept doesn't even really make sense for DRBG's.  Since we will be
reseeding the DRBG every five minutes if it is in constant use, there
will be plenty of opportunity to pull from a rngd or some other
hw_random device.

> Finally, one remark which I know you could not care less: :-) 
> 
> I try to use a known DRNG design that a lot of folks have already assessed -- 
> SP800-90A (and please, do not hint to the Dual EC DRBG as this issue was 
> pointed out already by researcher shortly after the first SP800-90A came out 
> in 2007). This way I do not need to re-invent the wheel and potentially 
> forget about things that may be helpful in a DRNG. To allow researchers to 
> assess my ChaCha20 DRNG. that used when no kernel crypto API is compiled. 
> independently from the kernel, I extracted the ChaCha20 DRNG code into a 
> standalone DRNG accessible at [1]. This standalone implementation can be 
> debugged and studied in user space. Moreover it is a simple copy of the 
> kernel code to allow researchers an easy comparison.

SP800-90A consists of a high level architecture of a DRBG, plus some
lower-level examples of how to use that high level architecture
assuming you have a hash function, or a block cipher, etc.  But it
doesn't have an example on using a stream cipher like ChaCha20.  So
all you can really do is follow the high-level architecture.  Mapping
the high-level architecture to the current /dev/random generator isn't
hard.  And no, I don't see the point of renaming things or moving
things around just to make the mapping to the SP800-90A easier.

       	      	      	       	       	  - Ted

^ permalink raw reply

* JZ4780 RNG and entropy depletion
From: Jeffrey Walton @ 2016-08-14  5:33 UTC (permalink / raw)
  To: linux-crypto

Hi Everyone,

I have a MIPSEL ci20 dev board for testing. The board has a hardware
based rng, but its suffering entropy depletion. I have Debian's
rng-tools package installed.

The board lacks /dev/hwrng. /dev/random blocks indefinitely after
draining the device. "Indefinitely" may not be accurate, but I killed
a program that waited over 4 hours for 16 bytes after draining
/dev/random.

The ci20's documentation is a bit scant, but it can be found at
http://mipscreator.imgtec.com/CI20/hardware/soc/JZ4780_PM.pdf. I'm not
sure what the output rate is, but it seems to be capable of one
machine word (4 bytes) every few milliseconds. Without a delay, I can
see values being shifted into the register mapped at 0x100000DC.

I have a few questions:

  * Is there a driver for JZ4780 rng?
  * Is there a particular package for the driver that needs to be installed?
  * What causes/triggers /dev/hwrng to replenish /dev/random?

Thanks in advance.

Jeff

^ permalink raw reply

* Re: [PATCH v2] RANDOM: ATH9K RNG delivers zero bits of entropy
From: Jason Cooper @ 2016-08-14 18:11 UTC (permalink / raw)
  To: Theodore Ts'o, Pan, Miaoqing, Stephan Mueller,
	Sepehrdad, Pouyan, herbert@gondor.apana.org.au,
	linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org,
	ath9k-devel, linux-wireless@vger.kernel.org,
	ath9k-devel@lists.ath9k.org, Kalle Valo
In-Reply-To: <20160810234425.GG10523@thunk.org>

Hey Ted,

On Wed, Aug 10, 2016 at 07:44:25PM -0400, Theodore Ts'o wrote:
> On Tue, Aug 09, 2016 at 02:04:44PM +0000, Jason Cooper wrote:
> > iiuc, Ted, you're saying using the hw_random framework would be
> > disasterous because despite most drivers having a default quality of 0,
> > rngd assumes 1 bit of entropy for every bit read?
> 
> Sorry, what I was trying to say (but failed) was that bypassing the
> hwrng framework and injecting entropy directly the entropy pool was
> disatrous.

Ok, whew. :)

> > Thankfully, most hw_random drivers don't set the quality.  So unless the
> > user sets the default_quality param, it's zero.
> 
> The fact that this is "most" and not "all" does scare me a little.

My recent grep showed that only virtio-rng set it to a non-zero value.

> As far as I'm concerned *all* hw_random drivers should set quality to
> zero, since it should be up to the system administrator.

Agreed.

Gathering conversation about this from a few related threads, I have one
concern.  Apparently there is some confusion in userspace consumers of
/dev/hwrng data as to the quality of it.  Specifically, rngd (spotted by
Stephan Mueller) appears to assume 1bit of entropy per 1 bit read. :-/

So, while moving ath9k-rng to the hwrng framework makes complete sense
internally, it's not so good for existing userspace assumptions.  I'd
think that timeriomem-rng falls in this same category.

In light of this, do you think it's worth the effort (I'm volunteering)
to create a subcategory of hwrng drivers that are 'environemntal' rngs?
They can contribute to the kernel entropy pools, but not to /dev/hwrng.

thx,

Jason.

^ permalink raw reply

* Re: JZ4780 RNG and entropy depletion
From: Stephan Mueller @ 2016-08-15  4:58 UTC (permalink / raw)
  To: noloader; +Cc: linux-crypto
In-Reply-To: <CAH8yC8=S7ZaK9o+VCjRrpF0gNwTEL9a-SfQmFkjt97j6h34kBw@mail.gmail.com>

Am Sonntag, 14. August 2016, 01:33:32 CEST schrieb Jeffrey Walton:

Hi Jeffrey,

> Hi Everyone,
> 
> I have a MIPSEL ci20 dev board for testing. The board has a hardware
> based rng, but its suffering entropy depletion. I have Debian's
> rng-tools package installed.
> 
> The board lacks /dev/hwrng. /dev/random blocks indefinitely after
> draining the device. "Indefinitely" may not be accurate, but I killed
> a program that waited over 4 hours for 16 bytes after draining
> /dev/random.
> 
> The ci20's documentation is a bit scant, but it can be found at
> http://mipscreator.imgtec.com/CI20/hardware/soc/JZ4780_PM.pdf. I'm not
> sure what the output rate is, but it seems to be capable of one
> machine word (4 bytes) every few milliseconds. Without a delay, I can
> see values being shifted into the register mapped at 0x100000DC.
> 
> I have a few questions:
> 
>   * Is there a driver for JZ4780 rng?

What is the PCI ID?

>   * Is there a particular package for the driver that needs to be installed?
> * What causes/triggers /dev/hwrng to replenish /dev/random?

Using rngd which is triggered by /dev/random automatically when its entropy 
level falls below a threshold.

Ciao
Stephan

^ permalink raw reply

* Re: [PATCH v6 0/5] /dev/random - a new approach
From: Stephan Mueller @ 2016-08-15  6:13 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: herbert, sandyinchina, Jason Cooper, John Denker, H. Peter Anvin,
	Joe Perches, Pavel Machek, George Spelvin, linux-crypto,
	linux-kernel
In-Reply-To: <20160812192208.GA30280@thunk.org>

Am Freitag, 12. August 2016, 15:22:08 CEST schrieb Theodore Ts'o:

Hi Theodore,

> On Fri, Aug 12, 2016 at 11:34:55AM +0200, Stephan Mueller wrote:
> > - correlation: the interrupt noise source is closely correlated to the
> > HID/
> > block noise sources. I see that the fast_pool somehow "smears" that
> > correlation. However, I have not seen a full assessment that the
> > correlation is gone away. Given that I do not believe that the HID event
> > values (key codes, mouse coordinates) have any entropy -- the user
> > sitting at the console exactly knows what he pressed and which mouse
> > coordinates are created, and given that for block devices, only the
> > high-resolution time stamp gives any entropy, I am suggesting to remove
> > the HID/block device noise sources and leave the IRQ noise source. Maybe
> > we could record the HID event values to further stir the pool but do not
> > credit it any entropy. Of course, that would imply that the assumed
> > entropy in an IRQ event is revalued. I am currently finishing up an
> > assessment of how entropy behaves in a VM (where I hope that the report
> > is released). Please note that contrary to my initial
> > expectations, the IRQ events are the only noise sources which are almost
> > unaffected by a VMM operation. Hence, IRQs are much better in a VM
> > environment than block or HID noise sources.
> 
> The reason why I'm untroubled with leaving them in is because I beieve
> the quality of the timing information from the HID and block devices
> is better than most of the other interrupt sources.  For example, most
> network interfaces these days use NAPI, which means interrupts get
> coalesced and sent in batch, which means the time of the interrupt is
> latched off of some kind of timer --- and on many embeded devices

According to my understanding of NAPI, the network card sends one interrupt 
when receiving the first packet of a packet stream and then the driver goes 
into polling mode, disabling the interrupt. So, I cannot see any batching 
based on some on-board timer where add_interrupt_randomness is affected.
 
Can you please elaborate?

> there is a single oscillator for the entire mainboard.  We only call
> add_disk_randomness for rotational devices (e.g., only HDD's, not
> SSD's), after the interrupt has been recorded.  Yes, most of the
> entropy is probably going to be found in the high entropy time stamp
> rather than the jiffies-based timestamp, especially for the hard drive
> completion time.
> 
> I also tend to take a much more pragmatic viewpoint towards
> measurability.  Sure, the human may know what she is typing, and
> something about when she typed it (although probably not accurately
> enough on a millisecond basis, so even the jiffies number is going to
> be not easily predicted), but the analyst sitting behind the desk at
> the NSA or the BND or the MSS is probably not going to have access to
> that information.

Well, injecting a trojan to a system in user space as unprivileged user that 
starts some X11 session and that can perform the following command is all you 
need to get to the key commands of the console.

xinput list |   grep -Po 'id=\K\d+(?=.*slave\s*keyboard)' |   xargs -P0 -n1 
xinput test

That is fully within reach of not only some agencies but also other folks. It 
is similar for mice.

> 
> (Whereas the NSA or the BND probably *can* get low-level information
> about the Intel x86 CPU's internal implementation, which is why I'm
> extremely amused by the arugment --- "the internals of the Intel CPU
> are **so** complex we can't reverse engineer what's going on inside,
> so the jitter RNG *must* be good!"  Note BTW that the NSA has only

Sure, agencies may know the full internals of a CPU like they know the full 
internals of the Linux kernel with the /dev/random implementation or just like 
they know the full internals of AES. But they do not know the current state of 
the system. And the cryptographic strength comes from that state.

When you refer to my Jitter RNG, I think I have shown that its strength comes 
from the internal state of the CPU (states of the internal building blocks 
relative to each other which may cause internal wait states, state of branch 
prediction or pipelines, etc.) and not of the layout of the CPU.

> said they won't do industrial espionage for economic for economic
> gain, not that they won't engage in espionage against industrial
> entities at all.  This is why the NSA spying on Petrobras is
> considered completely fair game, even if it does enrage the
> Brazillians.  :-)
> 
> > - entropy estimate: the current entropy heuristics IMHO have nothing to do
> > with the entropy of the data coming in. Currently, the min of
> > first/second/
> > third derivative of the Jiffies time stamp is used and capped at 11. That
> > value is the entropy value credited to the event. Given that the entropy
> > rests with the high-res time stamp and not with jiffies or the event
> > value, I think that the heuristic is not helpful. I understand that it
> > underestimates on average the available entropy, but that is the only
> > relationship I see. In my mentioned entropy in VM assessment (plus the
> > BSI report on /dev/random which is unfortunately written in German, but
> > available in the Internet) I did a min entropy calculation based on
> > different min entropy formulas (SP800-90B). That calculation shows that
> > we get from the noise sources is about 5 to 6 bits. On average the
> > entropy heuristic credits between 0.5 and 1 bit for events, so it
> > underestimates the entropy. Yet, the entropy heuristic can credit up to
> > 11 bits. Here I think it becomes clear that the current entropy heuristic
> > is not helpful. In addition, on systems where no high-res timer is
> > available, I assume (I have not measured it yet), the entropy heuristic
> > even overestimates the entropy.
> 
> The disks on a VM are not rotational disks, so we wouldn't be using
> the add-disk-randomness entropy calculation.  And you generally don't
> have a keyboard on a mouse attached to the VM, so we would be using
> the entropy estimate from the interrupt timing.

On VMs, the add_disk_randomness is always used with the exception of KVM when 
using a virtio disk. All other VMs do not use virtio and offer the disk as a 
SCSI or IDE device. In fact, add_disk_randomness is only disabled when the 
kernel detects:

- SDDs

- virtio

- use of device mapper

(Btw we should be thankful that this is done on Hyper-V as we would have a 
fatal state in a very common use case where /dev/random would have collected 
no entropy and /dev/urandom would have provided bogus data before the patch 
for using the VMBus interrupts was added.)
> 
> As far as whether you can get 5-6 bits of entropy from interrupt
> timings --- that just doesn't pass the laugh test.  The min-entropy

May I ask what you find amusing? When you have a noise source for which you 
have no theoretical model, all you can do is to revert to statistical 
measurements.

> formulas are estimates assuming IID data sources, and it's not at all
> clear (in fact, i'd argue pretty clearly _not_) that they are IID.  As

Sure, they are not IID based on the SP800-90B IID verification tests. For 
that, SP800-90B has non-IID versions of the min entropy calculations. See 
section 9.1 together with 9.3 of SP800-90B where I used those non-IID 
formulas.

Sure, it is "just" some statistical test. But it is better IMHO than to brush 
away available entropy entirely just because "my stomach tells me it is not 
good".

Just see the guy that sent an email to linux-crypto today. His MIPS /dev/
random cannot produce 16 bytes of data within 4 hours (which is similar to 
what I see on POWER systems). This raises a very interesting security issue: /
dev/urandom is not seeded properly. And we all know what folks do in the wild: 
when /dev/random does not produce data, /dev/urandom is used -- all general 
user space libs (OpenSSL, libgcrypt, nettle, ...) seed from /dev/urandom per 
default.

And I call that a very insecure state of affairs.

> I said, take for example the network interfaces, and how NAPI gets

As mentioned above, I do not see NAPI as an issue for interrupt entropy.

> implemented.  And in a VM environment, where everything is synthetic,
> the interrupt timings are definitely not IID, and there may be
> patterns that will not detectable by statistical mechanisms.

As mentioned, to my very surprise, I found that interrupts are the only thing 
in a VM that works extremely well even under attack scenarios. VMMs that I 
quantiatively tested include QEMU/KVM, VirtualBox, VMWare ESXi and Hyper-V. 
After more research, I came to the conclusion that even on the theoretical 
side, it must be one of the better noise sources in a VM.

Note, this was the key motivation for me to start my own implementation of /
dev/random.
> 
> > - albeit I like the current injection of twice the fast_pool into the
> > ChaCha20 (which means that the pathological case where the collection of
> > 128 bits of entropy would result in an attack resistance of 2 * 128 bits
> > and *not* 2^128 bits is now increased to an attack strength of 2^64 * 2
> > bits), / dev/urandom has *no* entropy until that injection happens. The
> > injection happens early in the boot cycle, but in my test system still
> > after user space starts. I tried to inject "atomically" (to not fall into
> > the aforementioned pathological case trap) of 32 / 112 / 256 bits of
> > entropy into the /dev/ urandom RNG to have /dev/urandom at least seeded
> > with a few bits before user space starts followed by the atomic injection
> > of the subsequent bits.
> The early boot problem is a hard one.  We can inject some noise in,
> but I don't think a few bits actually does much good.  So the question
> is whether it's faster to get to fully seeded, or to inject in 32 bits

I am not talking about the 32 bits. We can leave the current 64 bits for the 
first seed.

I am concerned about the *two* separate injections of 64 bits. It should 
rather be *one* injection of at least 112 bit (or 128 bits). This is what I 
mean with "atomic" operation here.

> of entropy in the hopes that this will do some good.  Personally, I'm
> not convinced.  So the tack I've taken is to have warning messages
> printed when someone *does* draw from /dev/urandom before it's fully
> seeded.  In many cases, it's for entirely bogus, non-cryptographic
> reasons.  (For example, Python wanting to use a random salt to protect
> against certain DOS attacks when Python is being used in a web server
> --- a use case which is completely irrelevant when it's being used by
> systemd generator scripts at boot time.)
> 
> Ultimately, I think the right answer here is we need help from the
> bootloader, and ultimately some hardware help or some initialization
> at factory time which isn't too easily hacked by a Tailored Access
> Organization team who can intercept hardware shipments.  :-)

I agree. But we can still try to make the Linux side good as possible to cover 
people who do not have the luxury to control the hardware.
> 
[...]
> 
> > Finally, one remark which I know you could not care less: :-)
> > 
> > I try to use a known DRNG design that a lot of folks have already assessed
> > -- SP800-90A (and please, do not hint to the Dual EC DRBG as this issue
> > was pointed out already by researcher shortly after the first SP800-90A
> > came out in 2007). This way I do not need to re-invent the wheel and
> > potentially forget about things that may be helpful in a DRNG. To allow
> > researchers to assess my ChaCha20 DRNG. that used when no kernel crypto
> > API is compiled. independently from the kernel, I extracted the ChaCha20
> > DRNG code into a standalone DRNG accessible at [1]. This standalone
> > implementation can be debugged and studied in user space. Moreover it is
> > a simple copy of the kernel code to allow researchers an easy comparison.
> 
> SP800-90A consists of a high level architecture of a DRBG, plus some
> lower-level examples of how to use that high level architecture
> assuming you have a hash function, or a block cipher, etc.  But it
> doesn't have an example on using a stream cipher like ChaCha20.  So
> all you can really do is follow the high-level architecture.  Mapping
> the high-level architecture to the current /dev/random generator isn't
> hard.  And no, I don't see the point of renaming things or moving
> things around just to make the mapping to the SP800-90A easier.

Unfortunately I have seen subtle problems with DRNG implementations -- and a 
new one will emerge in the not too far future... There are examples of that 
and I like tests against reference implementations.

For example, the one key problem I have with the ChaCha20 DRNG is the 
following: when final update of the internal state is made for enhanced 
prediction resistance, ChaCha20 is used to generate one more block. That new 
block has 512 bits in size. In your implementation, you use the first 256 bits 
to inject it back into ChaCha20 as key. I use the entire 512 bits. I do not 
know whether one is better than the other (in the sense that it does not loose 
entropy). But barring any real research from other cryptographers, I guess we 
both do not know. And I have seen that such subtle issues may lead to 
catastrophic problems.

Thus, knowing valid DRNG designs may cover 99% of a new DRNG design. But the 
remaining 1% usually gives you the creeps.

Ciao
Stephan

^ permalink raw reply

* Re: [PATCH v2] RANDOM: ATH9K RNG delivers zero bits of entropy
From: Kalle Valo @ 2016-08-15 11:01 UTC (permalink / raw)
  To: Pan, Miaoqing
  Cc: Stephan Mueller, Ted Tso, Sepehrdad, Pouyan,
	herbert@gondor.apana.org.au, linux-kernel@vger.kernel.org,
	linux-crypto@vger.kernel.org, ath9k-devel,
	linux-wireless@vger.kernel.org, ath9k-devel@lists.ath9k.org,
	Jason Cooper
In-Reply-To: <657897b90b8344eeab10d7a0f604988d@aptaiexm02f.ap.qualcomm.com>

"Pan, Miaoqing" <miaoqing@qti.qualcomm.com> writes:

> The entropy was evaluated by crypto expert, the analysis report show
> the ADC with at least 10bits and up to 22 bits of min-entropy for a 32
> bits value, we conservatively assume the min-entropy is 10 bits out of
> 32 bits, so that's why set entropy quality to 320/1024 = 10/32. Also
> we have explained in the commit message why can't use the HW RNG
> framework.
>
> Otherwise, your patch will cause high CPU load, as continuously read
> ADC data if entropy bits under write_wakeup_threshold.

Please don't top post, it breaks patchwork which is extremely annoying
for me:

https://patchwork.kernel.org/patch/9266265/

https://patchwork.kernel.org/patch/9266617/

-- 
Kalle Valo

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox