[kernel][entropy] Add cmdlines for jitterentropy

Add a few cmdline-tweakable parameters for the jitterentropy entropy
collector. The cmdlines are used to support MG-1022 (optimizing
jitterentropy's parameter values).

Change-Id: I1d78c49738edf498819097b8f0bc85b1803cf445
diff --git a/docs/kernel_cmdline.md b/docs/kernel_cmdline.md
index cc229c2..14049ab 100644
--- a/docs/kernel_cmdline.md
+++ b/docs/kernel_cmdline.md
@@ -72,7 +72,42 @@
 
 Provides entropy to be mixed into the kernel's CPRNG.
 
-## kernel.entropy_test.len=\<len>
+## kernel.entropy.jitterentropy.bs=\<num>
+
+Sets the "memory block size" parameter for jitterentropy (the default is 64).
+When jitterentropy is performing memory operations (to increase variation in CPU
+timing), the memory will be accessed in blocks of this size.
+
+## kernel.entropy.jitterentropy.bc=\<num>
+
+Sets the "memory block count" parameter for jitterentropy (the default is 1024).
+When jitterentropy is performing memory operations (to increase variation in CPU
+timing), this controls how many blocks (of size
+`kernel.entropy.jitterentropy.bs`) are accessed.
+
+## kernel.entropy.jitterentropy.ml=\<num>
+
+Sets the "memory loops" parameter for jitterentropy (the default is 128). When
+jitterentropy is performing memory operations (to increase variation in CPU
+timing), this controls how many times the memory access routine is repeated.
+This parameter is only used when `kernel.entropy.jitterentropy.raw` is true
+(otherwise, jitterentropy chooses the number of loops is a random-ish way).
+
+## kernel.entropy.jitterentropy.ll=\<num>
+
+Sets the "LFSR loops" parameter for jitterentropy (the default is 16). When
+jitterentropy is performing CPU-intensive LFSR operations (to increase variation
+in CPU timing), this controls how many times the LFSR routine is repeated.  This
+parameter is only used when `kernel.entropy.jitterentropy.raw` is true
+(otherwise, jitterentropy chooses the number of loops is a random-ish way).
+
+## kernel.entropy.jitterentropy.raw=\<bool>
+
+When true, the jitterentropy entropy collector will return raw, unprocessed
+samples. When false (the default), the raw samples will be processed by
+jitterentropy, producing output data that looks closer to uniformly random.
+
+## kernel.entropy\_test.len=\<len>
 
 When running an entropy collector quality test, collect the provided number of
 bytes. Defaults to the maximum value `ENTROPY_COLLECTOR_TEST_MAXLEN`.
@@ -80,10 +115,10 @@
 The default value for the compile-time constant `ENTROPY_COLLECTOR_TEST_MAXLEN`
 is 128 KiB.
 
-## kernel.entropy_test.src=\<source>
+## kernel.entropy\_test.src=\<source>
 
 When running an entropy collector quality test, use the provided entropy source.
-Currently recognized sources: `hw_rng`.
+Currently recognized sources: `hw_rng`, `jitterentropy`.
 
 ## kernel.halt_on_panic=\<bool>
 If this option is set (disabled by default), the system will halt on
diff --git a/kernel/lib/crypto/entropy/jitterentropy_collector.cpp b/kernel/lib/crypto/entropy/jitterentropy_collector.cpp
index 87dd522..333dd0b 100644
--- a/kernel/lib/crypto/entropy/jitterentropy_collector.cpp
+++ b/kernel/lib/crypto/entropy/jitterentropy_collector.cpp
@@ -63,14 +63,18 @@
 }
 
 JitterentropyCollector::JitterentropyCollector(uint8_t* mem, size_t len)
-    : Collector("jitterentropy", /* entropy_per_1000_bytes */ 8000), lock_() {
-    // TODO(MG-1022): optimize default jitterentropy parameters
-    uint32_t block_size = cmdline_get_uint32("kernel.entropy.jitter.bs", 64);
-    uint32_t block_count = cmdline_get_uint32("kernel.entropy.jitter.bc", 1024);
-    uint32_t mem_loops = cmdline_get_uint32("kernel.entropy.jitter.ml", 128);
+    : Collector("jitterentropy", /* entropy_per_1000_bytes */ 8000) {
+    // TODO(MG-1022): optimize default jitterentropy parameters, then update
+    // values here and in docs/kernel_cmdline.md.
+    uint32_t bs = cmdline_get_uint32("kernel.entropy.jitterentropy.bs", 64);
+    uint32_t bc = cmdline_get_uint32("kernel.entropy.jitterentropy.bc", 1024);
+    mem_loops_ = cmdline_get_uint32("kernel.entropy.jitterentropy.ml", 128);
+    lfsr_loops_ = cmdline_get_uint32("kernel.entropy.jitterentropy.ll", 16);
+    use_raw_samples_ = cmdline_get_bool("kernel.entropy.jitterentropy.raw",
+                                        false);
 
-    jent_entropy_collector_init(&ec_, mem, len, block_size, block_count,
-                                mem_loops, /* stir */ true);
+    jent_entropy_collector_init(&ec_, mem, len, bs, bc, mem_loops_,
+                                /* stir */ true);
 }
 
 size_t JitterentropyCollector::DrawEntropy(uint8_t* buf, size_t len) {
@@ -79,8 +83,17 @@
     // multi-threaded systems.
     mxtl::AutoLock guard(&lock_);
 
-    ssize_t result = jent_read_entropy(&ec_, reinterpret_cast<char*>(buf), len);
-    return (result < 0) ? 0 : static_cast<size_t>(result);
+    if (use_raw_samples_) {
+        for (size_t i = 0; i < len; i++) {
+            buf[i] = static_cast<uint8_t>(jent_lfsr_var_stat(&ec_, lfsr_loops_,
+                                                             mem_loops_));
+        }
+        return len;
+    } else {
+        ssize_t err =jent_read_entropy(&ec_, reinterpret_cast<char*>(buf),
+                                       len);
+        return (err < 0) ? 0 : static_cast<size_t>(err);
+    }
 }
 
 } // namespace entropy
diff --git a/kernel/lib/crypto/include/lib/crypto/entropy/jitterentropy_collector.h b/kernel/lib/crypto/include/lib/crypto/entropy/jitterentropy_collector.h
index 2037693..74b6824 100644
--- a/kernel/lib/crypto/include/lib/crypto/entropy/jitterentropy_collector.h
+++ b/kernel/lib/crypto/include/lib/crypto/entropy/jitterentropy_collector.h
@@ -53,6 +53,8 @@
 
     struct rand_data ec_;
     mxtl::Mutex lock_;
+    uint32_t mem_loops_, lfsr_loops_;
+    bool use_raw_samples_;
 };
 
 } // namespace entropy
diff --git a/third_party/lib/jitterentropy/include/lib/jitterentropy/jitterentropy.h b/third_party/lib/jitterentropy/include/lib/jitterentropy/jitterentropy.h
index f3415b0..d4795d3 100644
--- a/third_party/lib/jitterentropy/include/lib/jitterentropy/jitterentropy.h
+++ b/third_party/lib/jitterentropy/include/lib/jitterentropy/jitterentropy.h
@@ -46,6 +46,7 @@
  * - Add #include lines for required system libraries.
  * - Remove CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT flag.
  * - Add jent_entropy_collector_init declaration.
+ * - Moved comment for jent_lfsr_var_stat from jitterentropy-base.c to here.
  */
 
 #ifndef _JITTERENTROPY_H
@@ -148,8 +149,16 @@
 
 /* -- BEGIN statistical test functions only complied with CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT -- */
 
+/*
+ * Statistical test: return the time duration for the folding operation. If
+ * lfsr_loops_override/mem_loops_override is non-zero, perform the given number
+ * of LFSR/memaccess ops. Otherwise, allow the loop count shuffling to define
+ * the number of LFSR/memaccess ops.
+ */
 JENT_PRIVATE_STATIC
-uint64_t jent_lfsr_var_stat(struct rand_data *ec, unsigned int min);
+uint64_t jent_lfsr_var_stat(struct rand_data *ec,
+                            unsigned int lfsr_loops_override,
+                            unsigned int mem_loops_override);
 
 /* -- END of statistical test function -- */
 
diff --git a/third_party/lib/jitterentropy/jitterentropy-base.c b/third_party/lib/jitterentropy/jitterentropy-base.c
index 6aaaff2..2aa89e5 100644
--- a/third_party/lib/jitterentropy/jitterentropy-base.c
+++ b/third_party/lib/jitterentropy/jitterentropy-base.c
@@ -57,6 +57,9 @@
  * - Remove CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT flag.
  * - Add jent_entropy_collector_init definition.
  * - Remove '#pragma GCC optimize ("O0")' (not recognized by clang)
+ * - Replace 'min' parameter by 'lfsr_loops_override' and 'mem_loops_override'
+ *   in jent_lfsr_var_stat, and moved comment for jent_lfsr_var_stat to
+ *   jitterentropy.h.
  */
 
 #undef _FORTIFY_SOURCE
@@ -779,20 +782,17 @@
  * Statistical test logic not compiled for regular operation
  ***************************************************************************/
 
-/*
- * Statistical test: return the time duration for the folding operation. If min
- * is set, perform the given number of LFSR ops. Otherwise, allow the
- * loop count shuffling to define the number of LFSR ops.
- */
 JENT_PRIVATE_STATIC
-uint64_t jent_lfsr_var_stat(struct rand_data *ec, unsigned int min)
+uint64_t jent_lfsr_var_stat(struct rand_data *ec,
+                            unsigned int lfsr_loops_override,
+                            unsigned int mem_loops_override)
 {
 	uint64_t time = 0;
 	uint64_t time2 = 0;
 
 	jent_get_nstime(&time);
-	jent_memaccess(ec, min);
-	jent_lfsr_time(ec, time, min);
+	jent_memaccess(ec, mem_loops_override);
+	jent_lfsr_time(ec, time, lfsr_loops_override);
 	jent_get_nstime(&time2);
 	return ((time2 - time));
 }