Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84742149 authored by Alex Klyubin's avatar Alex Klyubin Committed by Gerrit Code Review
Browse files

Merge "Make EntropyMixer mix in output of Hardware RNG into Linux RNG."

parents 1a07229b 6ab3d20d
Loading
Loading
Loading
Loading
+34 −3
Original line number Diff line number Diff line
@@ -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 &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 @@ 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");
+1 −1
Original line number Diff line number Diff line
@@ -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);
    }