Loading services/java/com/android/server/EntropyMixer.java +34 −3 Original line number Original line Diff line number Diff line Loading @@ -36,7 +36,8 @@ import android.util.Slog; /** /** * A service designed to load and periodically save "randomness" * 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 * <p>When a Linux system starts up, the entropy pool associated with * {@code /dev/random} may be in a fairly predictable state. Applications which * {@code /dev/random} may be in a fairly predictable state. Applications which Loading @@ -45,6 +46,13 @@ import android.util.Slog; * this effect, it's helpful to carry the entropy pool information across * this effect, it's helpful to carry the entropy pool information across * shutdowns and startups. * 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 "randomness" of the HW RNG. * * <p>This class was modeled after the script in * <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 * <a href="http://www.kernel.org/doc/man-pages/online/pages/man4/random.4.html">man * 4 random</a>. * 4 random</a>. Loading @@ -57,6 +65,7 @@ public class EntropyMixer extends Binder { private static final long START_NANOTIME = System.nanoTime(); private static final long START_NANOTIME = System.nanoTime(); private final String randomDevice; private final String randomDevice; private final String hwRandomDevice; private final String entropyFile; private final String entropyFile; /** /** Loading @@ -69,6 +78,7 @@ public class EntropyMixer extends Binder { Slog.e(TAG, "Will not process invalid message"); Slog.e(TAG, "Will not process invalid message"); return; return; } } addHwRandomEntropy(); writeEntropy(); writeEntropy(); scheduleEntropyWriter(); scheduleEntropyWriter(); } } Loading @@ -82,18 +92,25 @@ public class EntropyMixer extends Binder { }; }; public EntropyMixer(Context context) { 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 */ /** 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 (randomDevice == null) { throw new NullPointerException("randomDevice"); } if (hwRandomDevice == null) { throw new NullPointerException("hwRandomDevice"); } if (entropyFile == null) { throw new NullPointerException("entropyFile"); } if (entropyFile == null) { throw new NullPointerException("entropyFile"); } this.randomDevice = randomDevice; this.randomDevice = randomDevice; this.hwRandomDevice = hwRandomDevice; this.entropyFile = entropyFile; this.entropyFile = entropyFile; loadInitialEntropy(); loadInitialEntropy(); addDeviceSpecificEntropy(); addDeviceSpecificEntropy(); addHwRandomEntropy(); writeEntropy(); writeEntropy(); scheduleEntropyWriter(); scheduleEntropyWriter(); IntentFilter broadcastFilter = new IntentFilter(Intent.ACTION_SHUTDOWN); IntentFilter broadcastFilter = new IntentFilter(Intent.ACTION_SHUTDOWN); Loading Loading @@ -168,6 +185,20 @@ public class EntropyMixer extends Binder { } } } } /** * 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() { private static String getSystemDir() { File dataDir = Environment.getDataDirectory(); File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); File systemDir = new File(dataDir, "system"); Loading services/tests/servicestests/src/com/android/server/EntropyMixerTest.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -34,7 +34,7 @@ public class EntropyMixerTest extends AndroidTestCase { assertEquals(0, FileUtils.readTextFile(file, 0, null).length()); assertEquals(0, FileUtils.readTextFile(file, 0, null).length()); // The constructor has the side effect of writing to file // 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); assertTrue(FileUtils.readTextFile(file, 0, null).length() > 0); } } Loading Loading
services/java/com/android/server/EntropyMixer.java +34 −3 Original line number Original line Diff line number Diff line Loading @@ -36,7 +36,8 @@ import android.util.Slog; /** /** * A service designed to load and periodically save "randomness" * 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 * <p>When a Linux system starts up, the entropy pool associated with * {@code /dev/random} may be in a fairly predictable state. Applications which * {@code /dev/random} may be in a fairly predictable state. Applications which Loading @@ -45,6 +46,13 @@ import android.util.Slog; * this effect, it's helpful to carry the entropy pool information across * this effect, it's helpful to carry the entropy pool information across * shutdowns and startups. * 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 "randomness" of the HW RNG. * * <p>This class was modeled after the script in * <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 * <a href="http://www.kernel.org/doc/man-pages/online/pages/man4/random.4.html">man * 4 random</a>. * 4 random</a>. Loading @@ -57,6 +65,7 @@ public class EntropyMixer extends Binder { private static final long START_NANOTIME = System.nanoTime(); private static final long START_NANOTIME = System.nanoTime(); private final String randomDevice; private final String randomDevice; private final String hwRandomDevice; private final String entropyFile; private final String entropyFile; /** /** Loading @@ -69,6 +78,7 @@ public class EntropyMixer extends Binder { Slog.e(TAG, "Will not process invalid message"); Slog.e(TAG, "Will not process invalid message"); return; return; } } addHwRandomEntropy(); writeEntropy(); writeEntropy(); scheduleEntropyWriter(); scheduleEntropyWriter(); } } Loading @@ -82,18 +92,25 @@ public class EntropyMixer extends Binder { }; }; public EntropyMixer(Context context) { 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 */ /** 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 (randomDevice == null) { throw new NullPointerException("randomDevice"); } if (hwRandomDevice == null) { throw new NullPointerException("hwRandomDevice"); } if (entropyFile == null) { throw new NullPointerException("entropyFile"); } if (entropyFile == null) { throw new NullPointerException("entropyFile"); } this.randomDevice = randomDevice; this.randomDevice = randomDevice; this.hwRandomDevice = hwRandomDevice; this.entropyFile = entropyFile; this.entropyFile = entropyFile; loadInitialEntropy(); loadInitialEntropy(); addDeviceSpecificEntropy(); addDeviceSpecificEntropy(); addHwRandomEntropy(); writeEntropy(); writeEntropy(); scheduleEntropyWriter(); scheduleEntropyWriter(); IntentFilter broadcastFilter = new IntentFilter(Intent.ACTION_SHUTDOWN); IntentFilter broadcastFilter = new IntentFilter(Intent.ACTION_SHUTDOWN); Loading Loading @@ -168,6 +185,20 @@ public class EntropyMixer extends Binder { } } } } /** * 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() { private static String getSystemDir() { File dataDir = Environment.getDataDirectory(); File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); File systemDir = new File(dataDir, "system"); Loading
services/tests/servicestests/src/com/android/server/EntropyMixerTest.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -34,7 +34,7 @@ public class EntropyMixerTest extends AndroidTestCase { assertEquals(0, FileUtils.readTextFile(file, 0, null).length()); assertEquals(0, FileUtils.readTextFile(file, 0, null).length()); // The constructor has the side effect of writing to file // 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); assertTrue(FileUtils.readTextFile(file, 0, null).length() > 0); } } Loading