WIP: update tizen_qemu_defconfig
[platform/kernel/linux-starfive.git] / crypto / jitterentropy.c
index 4dc2261..227cedf 100644 (file)
@@ -85,10 +85,14 @@ struct rand_data {
                                      * bit generation */
 
        /* Repetition Count Test */
-       int rct_count;                  /* Number of stuck values */
+       unsigned int rct_count;                 /* Number of stuck values */
 
-       /* Adaptive Proportion Test for a significance level of 2^-30 */
+       /* 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
@@ -97,8 +101,6 @@ struct rand_data {
        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 health_failure:1;  /* Permanent health failure */
 };
 
 /* Flags that can be used to initialize the RNG */
@@ -115,8 +117,23 @@ struct rand_data {
                                   * zero). */
 #define JENT_ESTUCK            8 /* Too many stuck results during init. */
 #define JENT_EHEALTH           9 /* Health test failed during initialization */
-#define JENT_ERCT              10 /* RCT 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 "jitterentropy.h"
 
 /***************************************************************************
@@ -153,19 +170,26 @@ static void jent_apt_insert(struct rand_data *ec, unsigned int delta_masked)
                return;
        }
 
-       if (delta_masked == ec->apt_base) {
+       if (delta_masked == ec->apt_base)
                ec->apt_count++;
 
-               if (ec->apt_count >= JENT_APT_CUTOFF)
-                       ec->health_failure = 1;
-       }
-
        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;
+}
+
 /***************************************************************************
  * Stuck Test and its use as Repetition Count Test
  *
@@ -190,55 +214,14 @@ static void jent_apt_insert(struct rand_data *ec, unsigned int delta_masked)
  */
 static void jent_rct_insert(struct rand_data *ec, int stuck)
 {
-       /*
-        * If we have a count less than zero, a previous RCT round identified
-        * a failure. We will not overwrite it.
-        */
-       if (ec->rct_count < 0)
-               return;
-
        if (stuck) {
                ec->rct_count++;
-
-               /*
-                * The cutoff value is based on the following consideration:
-                * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
-                * In addition, we require an entropy value H of 1/OSR as this
-                * is the minimum entropy required to provide full entropy.
-                * Note, we collect 64 * OSR deltas for inserting them into
-                * the entropy pool which should then have (close to) 64 bits
-                * of entropy.
-                *
-                * Note, ec->rct_count (which equals to value B in the pseudo
-                * code of SP800-90B section 4.4.1) starts with zero. Hence
-                * we need to subtract one from the cutoff value as calculated
-                * following SP800-90B.
-                */
-               if ((unsigned int)ec->rct_count >= (31 * ec->osr)) {
-                       ec->rct_count = -1;
-                       ec->health_failure = 1;
-               }
        } else {
+               /* Reset RCT */
                ec->rct_count = 0;
        }
 }
 
-/*
- * Is there an RCT health test failure?
- *
- * @ec [in] Reference to entropy collector
- *
- * @return
- *     0 No health test failure
- *     1 Permanent health test failure
- */
-static int jent_rct_failure(struct rand_data *ec)
-{
-       if (ec->rct_count < 0)
-               return 1;
-       return 0;
-}
-
 static inline __u64 jent_delta(__u64 prev, __u64 next)
 {
 #define JENT_UINT64_MAX                (__u64)(~((__u64) 0))
@@ -265,7 +248,6 @@ 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);
-       unsigned int delta_masked = current_delta & JENT_APT_WORD_MASK;
 
        ec->last_delta = current_delta;
        ec->last_delta2 = delta2;
@@ -274,7 +256,7 @@ static int jent_stuck(struct rand_data *ec, __u64 current_delta)
         * Insert the result of the comparison of two back-to-back time
         * deltas.
         */
-       jent_apt_insert(ec, delta_masked);
+       jent_apt_insert(ec, current_delta);
 
        if (!current_delta || !delta2 || !delta3) {
                /* RCT with a stuck bit */
@@ -288,22 +270,26 @@ static int jent_stuck(struct rand_data *ec, __u64 current_delta)
        return 0;
 }
 
-/*
- * Report any health test failures
- *
- * @ec [in] Reference to entropy collector
- *
- * @return
- *     0 No health test failure
- *     1 Permanent health test failure
- */
+/* 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)
 {
-       /* Test is only enabled in FIPS mode */
-       if (!jent_fips_enabled())
-               return 0;
+       return jent_rct_failure(ec) | jent_apt_failure(ec);
+}
 
-       return ec->health_failure;
+static int jent_permanent_health_failure(struct rand_data *ec)
+{
+       return jent_rct_permanent_failure(ec) | jent_apt_permanent_failure(ec);
 }
 
 /***************************************************************************
@@ -547,12 +533,15 @@ static int jent_measure_jitter(struct rand_data *ec)
  */
 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;
@@ -561,7 +550,7 @@ 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;
        }
 }
@@ -586,8 +575,8 @@ static void jent_gen_entropy(struct rand_data *ec)
  *
  * The following error codes can occur:
  *     -1      entropy_collector is NULL
- *     -2      RCT failed
- *     -3      APT test failed
+ *     -2      Intermittent health failure
+ *     -3      Permanent health failure
  */
 int jent_read_entropy(struct rand_data *ec, unsigned char *data,
                      unsigned int len)
@@ -602,39 +591,23 @@ int jent_read_entropy(struct rand_data *ec, unsigned char *data,
 
                jent_gen_entropy(ec);
 
-               if (jent_health_failure(ec)) {
-                       int ret;
-
-                       if (jent_rct_failure(ec))
-                               ret = -2;
-                       else
-                               ret = -3;
-
+               if (jent_permanent_health_failure(ec)) {
                        /*
-                        * Re-initialize the noise source
-                        *
-                        * If the health test fails, the Jitter RNG remains
-                        * in failure state and will return a health failure
-                        * during next invocation.
+                        * 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.
                         */
-                       if (jent_entropy_init())
-                               return ret;
-
-                       /* Set APT to initial state */
-                       jent_apt_reset(ec, 0);
-                       ec->apt_base_set = 0;
-
-                       /* Set RCT to initial state */
-                       ec->rct_count = 0;
-
-                       /* Re-enable Jitter RNG */
-                       ec->health_failure = 0;
-
+                       return -3;
+               } else if (jent_health_failure(ec)) {
                        /*
-                        * Return the health test failure status to the
-                        * caller as the generated value is not appropriate.
+                        * Perform startup health tests and return permanent
+                        * error if it fails.
                         */
-                       return ret;
+                       if (jent_entropy_init())
+                               return -3;
+
+                       return -2;
                }
 
                if ((DATA_SIZE_BITS / 8) < len)
@@ -788,14 +761,12 @@ int jent_entropy_init(void)
                        if ((nonstuck % JENT_APT_WINDOW_SIZE) == 0) {
                                jent_apt_reset(&ec,
                                               delta & JENT_APT_WORD_MASK);
-                               if (jent_health_failure(&ec))
-                                       return JENT_EHEALTH;
                        }
                }
 
-               /* Validate RCT */
-               if (jent_rct_failure(&ec))
-                       return JENT_ERCT;
+               /* Validate health test result */
+               if (jent_health_failure(&ec))
+                       return JENT_EHEALTH;
 
                /* test whether we have an increasing timer */
                if (!(time2 > time))