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

Commit 87e385ef authored by Alex Klyubin's avatar Alex Klyubin Committed by Android Git Automerger
Browse files

am aa947f15: am a9bce468: am 84742149: Merge "Make EntropyMixer mix in output...

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

* commit 'aa947f15':
  Make EntropyMixer mix in output of Hardware RNG into Linux RNG.
parents 6981a924 aa947f15
Loading
Loading
Loading
Loading
+34 −3
Original line number Original line Diff line number Diff line
@@ -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
@@ -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 &quot;randomness&quot; 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>.
@@ -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;


    /**
    /**
@@ -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();
        }
        }
@@ -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);
@@ -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");
+1 −1
Original line number Original line Diff line number Diff line
@@ -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);
    }
    }