[PATCH 3/4] random: get_source_long() function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This function gets random data from the best available source

The current code has a sequence in several places that calls one or
more of arch_get_random_long() or related functions, checks the
return value(s) and on failure falls back to random_get_entropy().
get_source long() is intended to replace all such sequences.

This is better in several ways. In the fallback case it gives
much more random output than random_get_entropy(). It never
wastes effort by calling arch_get_random_long() et al. when
the relevant config variables are not set. When it does use
arch_get_random_long(), it does not deliver raw output from
that function but masks it by mixing with stored random data.

Signed-off-by: Sandy Harris <sandyinchina@xxxxxxxxx>
---
 drivers/char/random.c | 74 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 9edf65ad4259..6c77fd056f66 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1031,6 +1031,80 @@ static void xtea_rekey(void)
     xtea_iterations = 0 ;
 }

+/**************************************************************************
+ * Load a 64-bit word with data from whatever source we have
+ *
+ *       arch_get_random_long()
+ *       hardware RNG
+ *       emulated HWRNG in a VM
+ *
+ * When there are two sources, alternate.
+ * If you have no better source, or if one fails,
+ * fall back to get_xtea_long()
+ *
+ * This function always succeeds, which allows some
+ * simplifications elsewhere in the code.
+ *
+ * This is intended only for use inside the kernel.
+ * Any data sent to user space should come from the
+ * chacha-based crng construction.
+ ***************************************************************************/
+
+static int load_count = 0;
+#define COUNT_RESTART 128
+
+/*
+ * Add a mask variable so we can avoid using data
+ * from any source directly as output.
+ */
+static unsigned long source_mask ;
+
+/*
+ * Use xtea sometimes even if we have a good source
+ * Avoids trusting the source completely
+ */
+#define MIX_MASK 15
+
+static void get_source_long(unsigned long *x)
+{
+    int a, b ;
+    int ret = 0 ;
+
+    if (load_count >= COUNT_RESTART)
+        load_count = 0 ;
+    if (load_count == 0)
+        get_xtea_long(&source_mask) ;
+
+    a = IS_ENABLED(CONFIG_ARCH_RANDOM) ;
+    b = IS_ENABLED(CONFIG_HW_RANDOM) ;
+
+    if (a && b)    {
+        if (load_count & 1)
+            ret = arch_get_random_long(x) ;
+        else    ret = get_hw_long(x) ;
+    }
+    if (a && !b)    {
+        if (load_count&MIX_MASK)
+            ret = arch_get_random_long(x) ;
+    }
+    if (!a && b)    {
+        if (load_count&MIX_MASK)
+            ret = get_hw_long(x) ;
+    }
+    /*
+    * no source configured
+    * or configured one failed
+    *
+    * or it is just time for tea,
+    * (load_count&MIX_MASK) == 0
+    */
+    if (!ret)
+        get_xtea_long(x) ;
+
+    *x += source_mask ;
+        load_count++ ;
+}
+
 /*********************************************************************
  *
  * CRNG using CHACHA20
-- 
2.25.1



[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux