[][kernel][common][Backport jitterrng to 2.2.0]
[Description]
Add the patch, 999-1050-v6.4-backport-jitterrng-2.2.0.patch,
to backport jitter2.2.0. The purpose is to pass FIPS 140-3 compliance.
This patch fix commit 8248290 bug, caused kernel panic.
[Release-log]
Change-Id: Ia3e1e5e3ba18eb1195cf14d5fea41db8a5b07e13
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/8445320
diff --git a/target/linux/mediatek/patches-5.4/999-1050-v6.4-backport-jitterrng-2.2.0.patch b/target/linux/mediatek/patches-5.4/999-1050-v6.4-backport-jitterrng-2.2.0.patch
new file mode 100644
index 0000000..7161543
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/999-1050-v6.4-backport-jitterrng-2.2.0.patch
@@ -0,0 +1,1155 @@
+diff --git a/crypto/Makefile b/crypto/Makefile
+index 4e7a0a8f7..2b5a2a9c8 100644
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -156,6 +156,7 @@ CFLAGS_jitterentropy.o = -O0
+ KASAN_SANITIZE_jitterentropy.o = n
+ UBSAN_SANITIZE_jitterentropy.o = n
+ jitterentropy_rng-y := jitterentropy.o jitterentropy-kcapi.o
++jitterentropy_rng-$(CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG) += jitterentropy-dbg.o
+ 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/jitterentropy-dbg.c b/crypto/jitterentropy-dbg.c
+new file mode 100644
+index 000000000..2e7e98b9a
+--- /dev/null
++++ b/crypto/jitterentropy-dbg.c
+@@ -0,0 +1,242 @@
++/*
++ * Non-physical true random number generator based on timing jitter - DebugFS
++ *
++ * Copyright Stephan Mueller <smueller@chronox.de>, 2013
++ *
++ * License
++ * =======
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, and the entire permission notice in its entirety,
++ * including the disclaimer of warranties.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * ALTERNATIVELY, this product may be distributed under the terms of
++ * the GNU General Public License, in which case the provisions of the GPL are
++ * required INSTEAD OF the above restrictions. (This clause is
++ * necessary due to a potential bad interaction between the GPL and
++ * the restrictions contained in a BSD-style copyright.)
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
++ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <asm/uaccess.h>
++#include <linux/string.h>
++#include <linux/compat.h>
++#include <linux/export.h>
++#include <linux/file.h>
++#include <linux/debugfs.h>
++
++#include "jitterentropy.h"
++#include "jitterentropy-dbg.h"
++
++struct jent_debugfs {
++ struct dentry *jent_debugfs_root;
++ struct dentry *jent_debugfs_entropy;
++ struct dentry *jent_debugfs_noise;
++};
++
++struct jent_raw
++{
++ spinlock_t raw_lock;
++ struct rand_data *entropy_collector;
++};
++
++static struct jent_debugfs jent_debugfs;
++static struct jent_raw raw_entropy;
++
++void jent_drng_cleanup_raw(struct jent_raw *raw)
++{
++ spin_lock_bh(&raw->raw_lock);
++ if (NULL != raw->entropy_collector)
++ jent_entropy_collector_free(raw->entropy_collector);
++ raw->entropy_collector = NULL;
++ spin_unlock_bh(&raw->raw_lock);
++}
++
++int jent_drng_get_bytes_raw(struct jent_raw *raw, char *data, size_t len)
++{
++ int ret = 0;
++
++ spin_lock_bh(&raw->raw_lock);
++ ret = jent_read_entropy(raw->entropy_collector, data, len);
++ if (0 > ret) {
++ printk(DRIVER_NAME": Unable to obtain %zu bytes of entropy\n", len);
++ ret = -EAGAIN;
++ }
++
++ spin_unlock_bh(&raw->raw_lock);
++ return ret;
++}
++
++
++static inline int jent_dbg_raw_bytes(char *data, size_t len)
++{
++ return jent_drng_get_bytes_raw(&raw_entropy, data, len);
++}
++
++static ssize_t jent_debugfs_read_func(struct file *file,
++ char __user *buf, size_t nbytes,
++ loff_t *ppos, size_t chunk,
++ int (*source)(char *out, size_t len))
++{
++ ssize_t total = 0;
++ int ret = 0;
++ loff_t pos = *ppos;
++ char *out;
++
++ if (!nbytes)
++ return -EINVAL;
++
++ out = kzalloc(chunk, GFP_KERNEL);
++ if (!out)
++ return -ENOMEM;
++
++ while (nbytes > 0) {
++ int copy = min_t(int, chunk, nbytes);
++ ret = source(out, copy);
++ if (0 > ret) {
++ printk(DRIVER_NAME": could not obtain random data: %d\n", ret);
++ ret = -EAGAIN;
++ break;
++ }
++ if (copy_to_user(buf+pos+total, out, copy)) {
++ ret = -EFAULT;
++ break;
++ }
++ nbytes -= copy;
++ total += copy;
++ }
++ kzfree(out);
++
++ return ((0 > ret) ? ret : total);
++}
++
++static ssize_t jent_debugfs_noise_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
++{
++ struct rand_data *ec = raw_entropy.entropy_collector;
++ int total = 0;
++ loff_t pos = *ppos;
++ char *out;
++
++ out = kzalloc(8, GFP_KERNEL);
++
++ while (nbytes > 0) {
++ int len = min_t(int, 8, nbytes);
++ jent_lfsr_time(ec, 0, 0, 0);
++ memcpy(out, &ec->data, len);
++ if (copy_to_user(buf+pos+total, out, len)) {
++ break;
++ }
++ nbytes -= len;
++ total += len;
++ }
++ kzfree(out);
++ return total;
++
++}
++static ssize_t jent_debugfs_seed_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
++{
++ int ret = jent_debugfs_read_func(file, buf, nbytes, ppos, 8,
++ jent_dbg_raw_bytes);
++ return ret;
++}
++
++int jent_drng_init_raw(struct jent_raw *raw, unsigned int flags)
++{
++ int ret = 0;
++
++ raw->entropy_collector = jent_entropy_collector_alloc(1, flags);
++ if (!raw->entropy_collector)
++ ret = -ENOMEM;
++
++ spin_lock_init(&raw->raw_lock);
++ return ret;
++}
++
++static struct file_operations jent_seed_fops = {
++ .owner = THIS_MODULE,
++ .read = jent_debugfs_seed_read,
++};
++
++static struct file_operations jent_noise_fops = {
++ .owner = THIS_MODULE,
++ .read = jent_debugfs_noise_read,
++};
++
++
++int __init jent_dbg_init(void)
++{
++ int ret = -EINVAL;
++ jent_debugfs.jent_debugfs_root = NULL;
++ jent_debugfs.jent_debugfs_noise = NULL;
++ jent_debugfs.jent_debugfs_entropy = NULL;
++
++ ret = jent_drng_init_raw(&raw_entropy, JENT_DISABLE_STIR);
++ if (ret) {
++ printk(DRIVER_NAME": Raw entropy collector instantiation failed\n");
++ return ret;
++ }
++ jent_debugfs.jent_debugfs_root =
++ debugfs_create_dir(DRIVER_NAME, NULL);
++ if (IS_ERR(jent_debugfs.jent_debugfs_root)) {
++ printk(DRIVER_NAME": initialization of debugfs directory failed\n");
++ goto cleandir;
++ }
++
++ jent_debugfs.jent_debugfs_entropy =
++ debugfs_create_file("entropy", S_IRUGO,
++ jent_debugfs.jent_debugfs_root,
++ NULL, &jent_seed_fops);
++ if (IS_ERR(jent_debugfs.jent_debugfs_entropy)) {
++ printk(DRIVER_NAME": initialization of entropy file failed\n");
++ goto cleandir;
++ }
++
++ jent_debugfs.jent_debugfs_noise =
++ debugfs_create_file("noise", S_IRUGO,
++ jent_debugfs.jent_debugfs_root,
++ NULL, &jent_noise_fops);
++ if (IS_ERR(jent_debugfs.jent_debugfs_noise)) {
++ printk(DRIVER_NAME": initialization of noise file failed\n");
++ goto cleandir;
++ }
++ return 0;
++
++cleandir:
++ debugfs_remove_recursive(jent_debugfs.jent_debugfs_root);
++ jent_drng_cleanup_raw(&raw_entropy);
++
++ return ret;
++}
++
++void jent_dbg_exit(void)
++{
++ debugfs_remove_recursive(jent_debugfs.jent_debugfs_root);
++ jent_drng_cleanup_raw(&raw_entropy);
++}
+diff --git a/crypto/jitterentropy-dbg.h b/crypto/jitterentropy-dbg.h
+new file mode 100644
+index 000000000..921bd65dc
+--- /dev/null
++++ b/crypto/jitterentropy-dbg.h
+@@ -0,0 +1,49 @@
++/*
++ * Non-physical true random number generator based on timing jitter.
++ *
++ * Copyright Stephan Mueller <smueller@chronox.de>, 2013
++ *
++ * License
++ * =======
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, and the entire permission notice in its entirety,
++ * including the disclaimer of warranties.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * ALTERNATIVELY, this product may be distributed under the terms of
++ * the GNU General Public License, in which case the provisions of the GPL are
++ * required INSTEAD OF the above restrictions. (This clause is
++ * necessary due to a potential bad interaction between the GPL and
++ * the restrictions contained in a BSD-style copyright.)
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
++ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ */
++
++#ifndef _JITTERENTROPY_DBG_KERNEL_H
++#define _JITTERENTROPY_DBG_KERNEL_H
++
++int __init jent_dbg_init(void);
++void jent_dbg_exit(void);
++
++
++#endif /* _JITTERENTROPY_DBG_KERNEL_H */
+diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c
+index 701b8d86a..7a3691fab 100644
+--- a/crypto/jitterentropy-kcapi.c
++++ b/crypto/jitterentropy-kcapi.c
+@@ -44,13 +44,11 @@
+ #include <linux/crypto.h>
+ #include <crypto/internal/rng.h>
+
+-struct rand_data;
+-int jent_read_entropy(struct rand_data *ec, unsigned char *data,
+- unsigned int len);
+-int jent_entropy_init(void);
+-struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
+- unsigned int flags);
+-void jent_entropy_collector_free(struct rand_data *entropy_collector);
++#include "jitterentropy.h"
++
++#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG
++#include "jitterentropy-dbg.h"
++#endif
+
+ /***************************************************************************
+ * Helper function
+@@ -148,7 +146,31 @@ static int jent_kcapi_random(struct crypto_rng *tfm,
+ int ret = 0;
+
+ spin_lock(&rng->jent_lock);
++
+ ret = jent_read_entropy(rng->entropy_collector, rdata, dlen);
++
++ if (ret == -3) {
++ /* Handle permanent health test error */
++ /*
++ * If the kernel was booted with fips=1, it implies that
++ * the entire kernel acts as a FIPS 140 module. In this case
++ * an SP800-90B permanent health test error is treated as
++ * a FIPS module error.
++ */
++ if (fips_enabled)
++ panic("Jitter RNG permanent health test failure\n");
++
++ pr_err("Jitter RNG permanent health test failure\n");
++ ret = -EFAULT;
++ } else if (ret == -2) {
++ /* Handle intermittent health test error */
++ pr_warn_ratelimited("Reset Jitter RNG due to intermittent health test failure\n");
++ ret = -EAGAIN;
++ } else if (ret == -1) {
++ /* Handle other errors */
++ ret = -EINVAL;
++ }
++
+ spin_unlock(&rng->jent_lock);
+
+ return ret;
+@@ -182,15 +204,31 @@ static int __init jent_mod_init(void)
+
+ ret = jent_entropy_init();
+ if (ret) {
++ /* Handle permanent health test error */
++ if (fips_enabled)
++ panic("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret);
++
+ pr_info("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret);
+ return -EFAULT;
+ }
++
++#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG
++ ret = jent_dbg_init();
++#endif
++ if(ret)
++ return ret;
++ printk("Debug interface error\n");
+ return crypto_register_rng(&jent_alg);
++
+ }
+
+ static void __exit jent_mod_exit(void)
+ {
+ crypto_unregister_rng(&jent_alg);
++
++#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG
++ jent_dbg_exit();
++#endif
+ }
+
+ module_init(jent_mod_init);
+diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
+index 77fa2120f..fea7a6d42 100644
+--- a/crypto/jitterentropy.c
++++ b/crypto/jitterentropy.c
+@@ -2,12 +2,12 @@
+ * Non-physical true random number generator based on timing jitter --
+ * Jitter RNG standalone code.
+ *
+- * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2019
++ * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2020
+ *
+ * Design
+ * ======
+ *
+- * See http://www.chronox.de/jent.html
++ * See https://www.chronox.de/jent.html
+ *
+ * License
+ * =======
+@@ -47,7 +47,7 @@
+
+ /*
+ * This Jitterentropy RNG is based on the jitterentropy library
+- * version 2.1.2 provided at http://www.chronox.de/jent.html
++ * version 2.2.0 provided at https://www.chronox.de/jent.html
+ */
+
+ #ifdef __OPTIMIZE__
+@@ -58,32 +58,8 @@ typedef unsigned long long __u64;
+ typedef long long __s64;
+ typedef unsigned int __u32;
+ #define NULL ((void *) 0)
++#include "jitterentropy.h"
+
+-/* The entropy pool */
+-struct rand_data {
+- /* all data values that are vital to maintain the security
+- * of the RNG are marked as SENSITIVE. A user must not
+- * access that information while the RNG executes its loops to
+- * calculate the next random value. */
+- __u64 data; /* SENSITIVE Actual random number */
+- __u64 old_data; /* SENSITIVE Previous random number */
+- __u64 prev_time; /* SENSITIVE Previous time stamp */
+-#define DATA_SIZE_BITS ((sizeof(__u64)) * 8)
+- __u64 last_delta; /* SENSITIVE stuck test */
+- __s64 last_delta2; /* SENSITIVE stuck test */
+- unsigned int osr; /* Oversample rate */
+-#define JENT_MEMORY_BLOCKS 64
+-#define JENT_MEMORY_BLOCKSIZE 32
+-#define JENT_MEMORY_ACCESSLOOPS 128
+-#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
+- unsigned char *mem; /* Memory access location with size of
+- * memblocks * memblocksize */
+- unsigned int memlocation; /* Pointer to byte in *mem */
+- unsigned int memblocks; /* Number of memory blocks in *mem */
+- unsigned int memblocksize; /* Size of one memory block in bytes */
+- unsigned int memaccessloops; /* Number of memory accesses per random
+- * bit generation */
+-};
+
+ /* Flags that can be used to initialize the RNG */
+ #define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more
+@@ -98,19 +74,187 @@ struct rand_data {
+ * variations (2nd derivation of time is
+ * zero). */
+ #define JENT_ESTUCK 8 /* Too many stuck results during init. */
++#define JENT_EHEALTH 9 /* Health test failed during initialization */
++
++/*
++ * The output n bits can receive more than n bits of min entropy, of course,
++ * but the fixed output of the conditioning function can only asymptotically
++ * approach the output size bits of min entropy, not attain that bound. Random
++ * maps will tend to have output collisions, which reduces the creditable
++ * output entropy (that is what SP 800-90B Section 3.1.5.1.2 attempts to bound).
++ *
++ * The value "64" is justified in Appendix A.4 of the current 90C draft,
++ * and aligns with NIST's in "epsilon" definition in this document, which is
++ * that a string can be considered "full entropy" if you can bound the min
++ * entropy in each bit of output to at least 1-epsilon, where epsilon is
++ * required to be <= 2^(-32).
++ */
++#define JENT_ENTROPY_SAFETY_FACTOR 64
++
++#include <linux/fips.h>
++#include <linux/printk.h>
++
++/***************************************************************************
++ * Adaptive Proportion Test
++ *
++ * This test complies with SP800-90B section 4.4.2.
++ ***************************************************************************/
++
++/*
++ * Reset the APT counter
++ *
++ * @ec [in] Reference to entropy collector
++ */
++static void jent_apt_reset(struct rand_data *ec, unsigned int delta_masked)
++{
++ /* Reset APT counter */
++ ec->apt_count = 0;
++ ec->apt_base = delta_masked;
++ ec->apt_observations = 0;
++}
++
++/*
++ * Insert a new entropy event into APT
++ *
++ * @ec [in] Reference to entropy collector
++ * @delta_masked [in] Masked time delta to process
++ */
++static void jent_apt_insert(struct rand_data *ec, unsigned int delta_masked)
++{
++ /* Initialize the base reference */
++ if (!ec->apt_base_set) {
++ ec->apt_base = delta_masked;
++ ec->apt_base_set = 1;
++ return;
++ }
++
++ if (delta_masked == ec->apt_base)
++ ec->apt_count++;
++
++ ec->apt_observations++;
++
++ if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
++ jent_apt_reset(ec, delta_masked);
++}
++
++/* APT health test failure detection */
++static int jent_apt_permanent_failure(struct rand_data *ec)
++{
++ return (ec->apt_count >= JENT_APT_CUTOFF_PERMANENT) ? 1 : 0;
++}
++
++static int jent_apt_failure(struct rand_data *ec)
++{
++ return (ec->apt_count >= JENT_APT_CUTOFF) ? 1 : 0;
++}
+
+ /***************************************************************************
+- * Helper functions
++ * Stuck Test and its use as Repetition Count Test
++ *
++ * The Jitter RNG uses an enhanced version of the Repetition Count Test
++ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
++ * back-to-back values, the input to the RCT is the counting of the stuck
++ * values during the generation of one Jitter RNG output block.
++ *
++ * The RCT is applied with an alpha of 2^{-30} compliant to FIPS 140-2 IG 9.8.
++ *
++ * During the counting operation, the Jitter RNG always calculates the RCT
++ * cut-off value of C. If that value exceeds the allowed cut-off value,
++ * the Jitter RNG output block will be calculated completely but discarded at
++ * the end. The caller of the Jitter RNG is informed with an error code.
+ ***************************************************************************/
+
+-void jent_get_nstime(__u64 *out);
+-void *jent_zalloc(unsigned int len);
+-void jent_zfree(void *ptr);
+-int jent_fips_enabled(void);
+-void jent_panic(char *s);
+-void jent_memcpy(void *dest, const void *src, unsigned int n);
++/*
++ * Repetition Count Test as defined in SP800-90B section 4.4.1
++ *
++ * @ec [in] Reference to entropy collector
++ * @stuck [in] Indicator whether the value is stuck
++ */
++static void jent_rct_insert(struct rand_data *ec, int stuck)
++{
++ if (stuck) {
++ ec->rct_count++;
++ } else {
++ /* Reset RCT */
++ ec->rct_count = 0;
++ }
++}
++
++static inline __u64 jent_delta(__u64 prev, __u64 next)
++{
++#define JENT_UINT64_MAX (__u64)(~((__u64) 0))
++ return (prev < next) ? (next - prev) :
++ (JENT_UINT64_MAX - prev + 1 + next);
++}
++
++/*
++ * Stuck test by checking the:
++ * 1st derivative of the jitter measurement (time delta)
++ * 2nd derivative of the jitter measurement (delta of time deltas)
++ * 3rd derivative of the jitter measurement (delta of delta of time deltas)
++ *
++ * All values must always be non-zero.
++ *
++ * @ec [in] Reference to entropy collector
++ * @current_delta [in] Jitter time delta
++ *
++ * @return
++ * 0 jitter measurement not stuck (good bit)
++ * 1 jitter measurement stuck (reject bit)
++ */
++static int jent_stuck(struct rand_data *ec, __u64 current_delta)
++{
++ __u64 delta2 = jent_delta(ec->last_delta, current_delta);
++ __u64 delta3 = jent_delta(ec->last_delta2, delta2);
++
++ ec->last_delta = current_delta;
++ ec->last_delta2 = delta2;
++
++ /*
++ * Insert the result of the comparison of two back-to-back time
++ * deltas.
++ */
++ jent_apt_insert(ec, current_delta);
++
++ if (!current_delta || !delta2 || !delta3) {
++ /* RCT with a stuck bit */
++ jent_rct_insert(ec, 1);
++ return 1;
++ }
++
++ /* RCT with a non-stuck bit */
++ jent_rct_insert(ec, 0);
++
++ return 0;
++}
++
++/* RCT health test failure detection */
++static int jent_rct_permanent_failure(struct rand_data *ec)
++{
++ return (ec->rct_count >= JENT_RCT_CUTOFF_PERMANENT) ? 1 : 0;
++}
++
++static int jent_rct_failure(struct rand_data *ec)
++{
++ return (ec->rct_count >= JENT_RCT_CUTOFF) ? 1 : 0;
++}
++
++/* Report of health test failures */
++static int jent_health_failure(struct rand_data *ec)
++{
++ return jent_rct_failure(ec) | jent_apt_failure(ec);
++}
++
++static int jent_permanent_health_failure(struct rand_data *ec)
++{
++ return jent_rct_permanent_failure(ec) | jent_apt_permanent_failure(ec);
++}
++
++/***************************************************************************
++ * Noise sources
++ ***************************************************************************/
+
+-/**
++/*
+ * Update of the loop count used for the next round of
+ * an entropy collection.
+ *
+@@ -153,11 +297,7 @@ static __u64 jent_loop_shuffle(struct rand_data *ec,
+ return (shuffle + (1<<min));
+ }
+
+-/***************************************************************************
+- * Noise sources
+- ***************************************************************************/
+-
+-/**
++/*
+ * CPU Jitter noise source -- this is the noise source based on the CPU
+ * execution time jitter
+ *
+@@ -171,18 +311,19 @@ static __u64 jent_loop_shuffle(struct rand_data *ec,
+ * the CPU execution time jitter. Any change to the loop in this function
+ * implies that careful retesting must be done.
+ *
+- * Input:
+- * @ec entropy collector struct -- may be NULL
+- * @time time stamp to be injected
+- * @loop_cnt if a value not equal to 0 is set, use the given value as number of
+- * loops to perform the folding
++ * @ec [in] entropy collector struct
++ * @time [in] time stamp to be injected
++ * @loop_cnt [in] if a value not equal to 0 is set, use the given value as
++ * number of loops to perform the folding
++ * @stuck [in] Is the time stamp identified as stuck?
+ *
+ * Output:
+ * updated ec->data
+ *
+ * @return Number of loops the folding operation is performed
+ */
+-static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
++void jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt,
++ int stuck)
+ {
+ unsigned int i;
+ __u64 j = 0;
+@@ -225,12 +366,20 @@ static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
+ new ^= tmp;
+ }
+ }
+- ec->data = new;
+
+- return fold_loop_cnt;
++ /*
++ * If the time stamp is stuck, do not finally insert the value into
++ * the entropy pool. Although this operation should not do any harm
++ * even when the time stamp has no entropy, SP800-90B requires that
++ * any conditioning operation (SP800-90B considers the LFSR to be a
++ * conditioning operation) to have an identical amount of input
++ * data according to section 3.1.5.
++ */
++ if (!stuck)
++ ec->data = new;
+ }
+
+-/**
++/*
+ * Memory Access noise source -- this is a noise source based on variations in
+ * memory access times
+ *
+@@ -248,16 +397,13 @@ static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
+ * to reliably access either L3 or memory, the ec->mem memory must be quite
+ * large which is usually not desirable.
+ *
+- * Input:
+- * @ec Reference to the entropy collector with the memory access data -- if
+- * the reference to the memory block to be accessed is NULL, this noise
+- * source is disabled
+- * @loop_cnt if a value not equal to 0 is set, use the given value as number of
+- * loops to perform the folding
+- *
+- * @return Number of memory access operations
++ * @ec [in] Reference to the entropy collector with the memory access data -- if
++ * the reference to the memory block to be accessed is NULL, this noise
++ * source is disabled
++ * @loop_cnt [in] if a value not equal to 0 is set, use the given value
++ * number of loops to perform the LFSR
+ */
+-static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
++static void jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
+ {
+ unsigned int wrap = 0;
+ __u64 i = 0;
+@@ -267,7 +413,7 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
+ jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
+
+ if (NULL == ec || NULL == ec->mem)
+- return 0;
++ return;
+ wrap = ec->memblocksize * ec->memblocks;
+
+ /*
+@@ -293,44 +439,12 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
+ ec->memlocation = ec->memlocation + ec->memblocksize - 1;
+ ec->memlocation = ec->memlocation % wrap;
+ }
+- return i;
+ }
+
+ /***************************************************************************
+ * Start of entropy processing logic
+ ***************************************************************************/
+-
+-/**
+- * Stuck test by checking the:
+- * 1st derivation of the jitter measurement (time delta)
+- * 2nd derivation of the jitter measurement (delta of time deltas)
+- * 3rd derivation of the jitter measurement (delta of delta of time deltas)
+- *
+- * All values must always be non-zero.
+- *
+- * Input:
+- * @ec Reference to entropy collector
+- * @current_delta Jitter time delta
+- *
+- * @return
+- * 0 jitter measurement not stuck (good bit)
+- * 1 jitter measurement stuck (reject bit)
+- */
+-static int jent_stuck(struct rand_data *ec, __u64 current_delta)
+-{
+- __s64 delta2 = ec->last_delta - current_delta;
+- __s64 delta3 = delta2 - ec->last_delta2;
+-
+- ec->last_delta = current_delta;
+- ec->last_delta2 = delta2;
+-
+- if (!current_delta || !delta2 || !delta3)
+- return 1;
+-
+- return 0;
+-}
+-
+-/**
++/*
+ * This is the heart of the entropy generation: calculate time deltas and
+ * use the CPU jitter in the time deltas. The jitter is injected into the
+ * entropy pool.
+@@ -339,15 +453,15 @@ static int jent_stuck(struct rand_data *ec, __u64 current_delta)
+ * of this function! This can be done by calling this function
+ * and not using its result.
+ *
+- * Input:
+- * @entropy_collector Reference to entropy collector
++ * @ec [in] Reference to entropy collector
+ *
+ * @return result of stuck test
+ */
+-static int jent_measure_jitter(struct rand_data *ec)
++int jent_measure_jitter(struct rand_data *ec)
+ {
+ __u64 time = 0;
+ __u64 current_delta = 0;
++ int stuck;
+
+ /* Invoke one noise source before time measurement to add variations */
+ jent_memaccess(ec, 0);
+@@ -357,31 +471,33 @@ static int jent_measure_jitter(struct rand_data *ec)
+ * invocation to measure the timing variations
+ */
+ jent_get_nstime(&time);
+- current_delta = time - ec->prev_time;
++ current_delta = jent_delta(ec->prev_time, time);
+ ec->prev_time = time;
++ /* Check whether we have a stuck measurement. */
++ stuck = jent_stuck(ec, current_delta);
+
+ /* Now call the next noise sources which also injects the data */
+- jent_lfsr_time(ec, current_delta, 0);
+-
+- /* Check whether we have a stuck measurement. */
+- return jent_stuck(ec, current_delta);
++ jent_lfsr_time(ec, current_delta, 0, stuck);
++ return stuck;
+ }
+
+-/**
++/*
+ * Generator of one 64 bit random number
+ * Function fills rand_data->data
+ *
+- * Input:
+- * @ec Reference to entropy collector
++ * @ec [in] Reference to entropy collector
+ */
+ static void jent_gen_entropy(struct rand_data *ec)
+ {
+- unsigned int k = 0;
++ unsigned int k = 0, safety_factor = 0;
++
++ if (fips_enabled)
++ safety_factor = JENT_ENTROPY_SAFETY_FACTOR;
+
+ /* priming of the ->prev_time value */
+ jent_measure_jitter(ec);
+
+- while (1) {
++ while (!jent_health_failure(ec)) {
+ /* If a stuck measurement is received, repeat measurement */
+ if (jent_measure_jitter(ec))
+ continue;
+@@ -390,37 +506,12 @@ static void jent_gen_entropy(struct rand_data *ec)
+ * We multiply the loop value with ->osr to obtain the
+ * oversampling rate requested by the caller
+ */
+- if (++k >= (DATA_SIZE_BITS * ec->osr))
++ if (++k >= ((DATA_SIZE_BITS + safety_factor) * ec->osr))
+ break;
+ }
+ }
+
+-/**
+- * The continuous test required by FIPS 140-2 -- the function automatically
+- * primes the test if needed.
+- *
+- * Return:
+- * 0 if FIPS test passed
+- * < 0 if FIPS test failed
+- */
+-static void jent_fips_test(struct rand_data *ec)
+-{
+- if (!jent_fips_enabled())
+- return;
+-
+- /* prime the FIPS test */
+- if (!ec->old_data) {
+- ec->old_data = ec->data;
+- jent_gen_entropy(ec);
+- }
+-
+- if (ec->data == ec->old_data)
+- jent_panic("jitterentropy: Duplicate output detected\n");
+-
+- ec->old_data = ec->data;
+-}
+-
+-/**
++/*
+ * Entry function: Obtain entropy for the caller.
+ *
+ * This function invokes the entropy gathering logic as often to generate
+@@ -430,42 +521,62 @@ static void jent_fips_test(struct rand_data *ec)
+ * This function truncates the last 64 bit entropy value output to the exact
+ * size specified by the caller.
+ *
+- * Input:
+- * @ec Reference to entropy collector
+- * @data pointer to buffer for storing random data -- buffer must already
+- * exist
+- * @len size of the buffer, specifying also the requested number of random
+- * in bytes
++ * @ec [in] Reference to entropy collector
++ * @data [in] pointer to buffer for storing random data -- buffer must already
++ * exist
++ * @len [in] size of the buffer, specifying also the requested number of random
++ * in bytes
+ *
+ * @return 0 when request is fulfilled or an error
+ *
+ * The following error codes can occur:
+ * -1 entropy_collector is NULL
++ * -2 Intermittent health failure
++ * -3 Permanent health failure
+ */
+ int jent_read_entropy(struct rand_data *ec, unsigned char *data,
+ unsigned int len)
+ {
+ unsigned char *p = data;
+
+ if (!ec)
+ return -1;
+
+- while (0 < len) {
++ while (len > 0) {
+ unsigned int tocopy;
+
+ jent_gen_entropy(ec);
+- jent_fips_test(ec);
++
++ if (jent_permanent_health_failure(ec)) {
++ /*
++ * At this point, the Jitter RNG instance is considered
++ * as a failed instance. There is no rerun of the
++ * startup test any more, because the caller
++ * is assumed to not further use this instance.
++ */
++ return -3;
++ } else if (jent_health_failure(ec)) {
++ /*
++ * Perform startup health tests and return permanent
++ * error if it fails.
++ */
++ if (jent_entropy_init())
++ return -3;
++
++ return -2;
++ }
++
+ if ((DATA_SIZE_BITS / 8) < len)
+ tocopy = (DATA_SIZE_BITS / 8);
+ else
+ tocopy = len;
+ jent_memcpy(p, &ec->data, tocopy);
+
+ len -= tocopy;
+ p += tocopy;
+ }
+
+ return 0;
+ }
+
+ /***************************************************************************
+@@ -496,7 +609,7 @@ struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
+ }
+
+ /* verify and set the oversampling rate */
+- if (0 == osr)
++ if (osr == 0)
+ osr = 1; /* minimum sampling rate is 1 */
+ entropy_collector->osr = osr;
+
+@@ -518,11 +631,15 @@ int jent_entropy_init(void)
+ int i;
+ __u64 delta_sum = 0;
+ __u64 old_delta = 0;
++ unsigned int nonstuck = 0;
+ int time_backwards = 0;
+ int count_mod = 0;
+ int count_stuck = 0;
+ struct rand_data ec = { 0 };
+
++ /* Required for RCT */
++ ec.osr = 1;
++
+ /* We could perform statistical tests here, but the problem is
+ * that we only have a few loop counts to do testing. These
+ * loop counts may show some slight skew and we produce
+@@ -544,8 +661,10 @@ int jent_entropy_init(void)
+ /*
+ * TESTLOOPCOUNT needs some loops to identify edge systems. 100 is
+ * definitely too little.
++ *
++ * SP800-90B requires at least 1024 initial test cycles.
+ */
+-#define TESTLOOPCOUNT 300
++#define TESTLOOPCOUNT 1024
+ #define CLEARCACHE 100
+ for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
+ __u64 time = 0;
+@@ -557,13 +676,13 @@ int jent_entropy_init(void)
+ /* Invoke core entropy collection logic */
+ jent_get_nstime(&time);
+ ec.prev_time = time;
+- jent_lfsr_time(&ec, time, 0);
++ jent_lfsr_time(&ec, time, 0, 0);
+ jent_get_nstime(&time2);
+
+ /* test whether timer works */
+ if (!time || !time2)
+ return JENT_ENOTIME;
+- delta = time2 - time;
++ delta = jent_delta(time, time2);
+ /*
+ * test whether timer is fine grained enough to provide
+ * delta even when called shortly after each other -- this
+@@ -581,11 +700,31 @@ int jent_entropy_init(void)
+ * etc. with the goal to clear it to get the worst case
+ * measurements.
+ */
+- if (CLEARCACHE > i)
++ if (i < CLEARCACHE)
+ continue;
+
+ if (stuck)
+ count_stuck++;
++ else {
++ nonstuck++;
++
++ /*
++ * Ensure that the APT succeeded.
++ *
++ * With the check below that count_stuck must be less
++ * than 10% of the overall generated raw entropy values
++ * it is guaranteed that the APT is invoked at
++ * floor((TESTLOOPCOUNT * 0.9) / 64) == 14 times.
++ */
++ if ((nonstuck % JENT_APT_WINDOW_SIZE) == 0) {
++ jent_apt_reset(&ec,
++ delta & JENT_APT_WORD_MASK);
++ }
++ }
++
++ /* Validate health test result */
++ if (jent_health_failure(&ec))
++ return JENT_EHEALTH;
+
+ /* test whether we have an increasing timer */
+ if (!(time2 > time))
+@@ -616,7 +755,7 @@ int jent_entropy_init(void)
+ * should not fail. The value of 3 should cover the NTP case being
+ * performed during our test run.
+ */
+- if (3 < time_backwards)
++ if (time_backwards > 3)
+ return JENT_ENOMONOTONIC;
+
+ /*
+diff --git a/crypto/jitterentropy.h b/crypto/jitterentropy.h
+new file mode 100644
+index 000000000..ee555f642
+--- /dev/null
++++ b/crypto/jitterentropy.h
+@@ -0,0 +1,79 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++#ifndef _JITTERENTROPY_H
++#define _JITTERENTROPY_H
++#include <linux/types.h>
++
++/* Flags that can be used to initialize the RNG */
++#define JENT_DISABLE_STIR (1<<0) /* Disable stirring the entropy pool */
++#define JENT_DISABLE_UNBIAS (1<<1) /* Disable the Von-Neuman Unbiaser */
++#define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more
++ entropy, saves MEMORY_SIZE RAM for
++ entropy collector */
++#define DRIVER_NAME "jitterentropy"
++
++struct rand_data {
++ /* all data values that are vital to maintain the security
++ * of the RNG are marked as SENSITIVE. A user must not
++ * access that information while the RNG executes its loops to
++ * calculate the next random value. */
++ __u64 data; /* SENSITIVE Actual random number */
++ __u64 old_data; /* SENSITIVE Previous random number */
++ __u64 prev_time; /* SENSITIVE Previous time stamp */
++#define DATA_SIZE_BITS ((sizeof(__u64)) * 8)
++ __u64 last_delta; /* SENSITIVE stuck test */
++ __s64 last_delta2; /* SENSITIVE stuck test */
++ unsigned int osr; /* Oversample rate */
++#define JENT_MEMORY_BLOCKS 64
++#define JENT_MEMORY_BLOCKSIZE 32
++#define JENT_MEMORY_ACCESSLOOPS 128
++#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
++ unsigned char *mem; /* Memory access location with size of
++ * memblocks * memblocksize */
++ unsigned int memlocation; /* Pointer to byte in *mem */
++ unsigned int memblocks; /* Number of memory blocks in *mem */
++ unsigned int memblocksize; /* Size of one memory block in bytes */
++ unsigned int memaccessloops; /* Number of memory accesses per random
++ * bit generation */
++
++ /* Repetition Count Test */
++ unsigned int rct_count; /* Number of stuck values */
++
++ /* Intermittent health test failure threshold of 2^-30 */
++#define JENT_RCT_CUTOFF 30 /* Taken from SP800-90B sec 4.4.1 */
++#define JENT_APT_CUTOFF 325 /* Taken from SP800-90B sec 4.4.2 */
++ /* Permanent health test failure threshold of 2^-60 */
++#define JENT_RCT_CUTOFF_PERMANENT 60
++#define JENT_APT_CUTOFF_PERMANENT 355
++#define JENT_APT_WINDOW_SIZE 512 /* Data window size */
++ /* LSB of time stamp to process */
++#define JENT_APT_LSB 16
++#define JENT_APT_WORD_MASK (JENT_APT_LSB - 1)
++ unsigned int apt_observations; /* Number of collected observations */
++ unsigned int apt_count; /* APT counter */
++ unsigned int apt_base; /* APT base reference */
++ unsigned int apt_base_set:1; /* APT base reference set? */
++ unsigned int stir:1; /* Post-processing stirring */
++ unsigned int disable_unbias:1; /* Deactivate Von-Neuman unbias */
++};
++extern void *jent_zalloc(unsigned int len);
++extern void jent_zfree(void *ptr);
++extern void jent_memcpy(void *dest, const void *src, unsigned int n);
++extern void jent_get_nstime(__u64 *out);
++
++struct rand_data;
++extern int jent_entropy_init(void);
++extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
++ unsigned int len);
++
++extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
++ unsigned int flags);
++extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
++
++unsigned int jent_version(void);
++
++void jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt, int stuck);
++
++int jent_measure_jitter(struct rand_data *ec);
++
++#endif /* _JITTERENTROPY_H */