am a9bce468: am 84742149: Merge "Make EntropyMixer mix in output of Hardware RNG into Linux RNG."

* commit 'a9bce46876d6f1f82727ab6922748fcc6b43c767':
  Make EntropyMixer mix in output of Hardware RNG into Linux RNG.
diff --git a/services/java/com/android/server/EntropyMixer.java b/services/java/com/android/server/EntropyMixer.java
index fbb66f9..cfdbf7d 100644
--- a/services/java/com/android/server/EntropyMixer.java
+++ b/services/java/com/android/server/EntropyMixer.java
@@ -36,7 +36,8 @@
 
 /**
  * A service designed to load and periodically save "randomness"
- * for the Linux kernel.
+ * for the Linux kernel RNG and to mix in data from Hardware RNG (if present)
+ * into the Linux RNG.
  *
  * <p>When a Linux system starts up, the entropy pool associated with
  * {@code /dev/random} may be in a fairly predictable state.  Applications which
@@ -45,6 +46,13 @@
  * this effect, it's helpful to carry the entropy pool information across
  * shutdowns and startups.
  *
+ * <p>On systems with Hardware RNG (/dev/hw_random), a block of output from HW
+ * RNG is mixed into the Linux RNG on EntropyMixer's startup and whenever
+ * EntropyMixer periodically runs to save a block of output from Linux RNG on
+ * disk. This mixing is done in a way that does not increase the Linux RNG's
+ * entropy estimate is not increased. This is to avoid having to trust/verify
+ * the quality and authenticity of the &quot;randomness&quot; of the HW RNG.
+ *
  * <p>This class was modeled after the script in
  * <a href="http://www.kernel.org/doc/man-pages/online/pages/man4/random.4.html">man
  * 4 random</a>.
@@ -57,6 +65,7 @@
     private static final long START_NANOTIME = System.nanoTime();
 
     private final String randomDevice;
+    private final String hwRandomDevice;
     private final String entropyFile;
 
     /**
@@ -69,6 +78,7 @@
                 Slog.e(TAG, "Will not process invalid message");
                 return;
             }
+            addHwRandomEntropy();
             writeEntropy();
             scheduleEntropyWriter();
         }
@@ -82,18 +92,25 @@
     };
 
     public EntropyMixer(Context context) {
-        this(context, getSystemDir() + "/entropy.dat", "/dev/urandom");
+        this(context, getSystemDir() + "/entropy.dat", "/dev/urandom", "/dev/hw_random");
     }
 
     /** Test only interface, not for public use */
-    public EntropyMixer(Context context, String entropyFile, String randomDevice) {
+    public EntropyMixer(
+            Context context,
+            String entropyFile,
+            String randomDevice,
+            String hwRandomDevice) {
         if (randomDevice == null) { throw new NullPointerException("randomDevice"); }
+        if (hwRandomDevice == null) { throw new NullPointerException("hwRandomDevice"); }
         if (entropyFile == null) { throw new NullPointerException("entropyFile"); }
 
         this.randomDevice = randomDevice;
+        this.hwRandomDevice = hwRandomDevice;
         this.entropyFile = entropyFile;
         loadInitialEntropy();
         addDeviceSpecificEntropy();
+        addHwRandomEntropy();
         writeEntropy();
         scheduleEntropyWriter();
         IntentFilter broadcastFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
@@ -168,6 +185,20 @@
         }
     }
 
+    /**
+     * Mixes in the output from HW RNG (if present) into the Linux RNG.
+     */
+    private void addHwRandomEntropy() {
+        try {
+            RandomBlock.fromFile(hwRandomDevice).toFile(randomDevice, false);
+            Slog.i(TAG, "Added HW RNG output to entropy pool");
+        } catch (FileNotFoundException ignored) {
+            // HW RNG not present/exposed -- ignore
+        } catch (IOException e) {
+            Slog.w(TAG, "Failed to add HW RNG output to entropy pool", e);
+        }
+    }
+
     private static String getSystemDir() {
         File dataDir = Environment.getDataDirectory();
         File systemDir = new File(dataDir, "system");
diff --git a/services/tests/servicestests/src/com/android/server/EntropyMixerTest.java b/services/tests/servicestests/src/com/android/server/EntropyMixerTest.java
index 58d6dae..50e7a03 100644
--- a/services/tests/servicestests/src/com/android/server/EntropyMixerTest.java
+++ b/services/tests/servicestests/src/com/android/server/EntropyMixerTest.java
@@ -34,7 +34,7 @@
         assertEquals(0, FileUtils.readTextFile(file, 0, null).length());
 
         // The constructor has the side effect of writing to file
-        new EntropyMixer(getContext(), "/dev/null", file.getCanonicalPath());
+        new EntropyMixer(getContext(), "/dev/null", file.getCanonicalPath(), "/dev/null");
 
         assertTrue(FileUtils.readTextFile(file, 0, null).length() > 0);
     }