Merge "Make EntropyMixer mix in output of Hardware RNG into Linux RNG."
This commit is contained in:
@@ -36,7 +36,8 @@ import android.util.Slog;
|
||||
|
||||
/**
|
||||
* 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 @@ import android.util.Slog;
|
||||
* 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 "randomness" 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 @@ public class EntropyMixer extends Binder {
|
||||
private static final long START_NANOTIME = System.nanoTime();
|
||||
|
||||
private final String randomDevice;
|
||||
private final String hwRandomDevice;
|
||||
private final String entropyFile;
|
||||
|
||||
/**
|
||||
@@ -69,6 +78,7 @@ public class EntropyMixer extends Binder {
|
||||
Slog.e(TAG, "Will not process invalid message");
|
||||
return;
|
||||
}
|
||||
addHwRandomEntropy();
|
||||
writeEntropy();
|
||||
scheduleEntropyWriter();
|
||||
}
|
||||
@@ -82,18 +92,25 @@ public class EntropyMixer extends Binder {
|
||||
};
|
||||
|
||||
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 @@ 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() {
|
||||
File dataDir = Environment.getDataDirectory();
|
||||
File systemDir = new File(dataDir, "system");
|
||||
|
||||
@@ -34,7 +34,7 @@ public class EntropyMixerTest extends AndroidTestCase {
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user