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

Commit 5ad76ef5 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 4521 into donut

* changes:
  load entropy data at boot.  Periodically write entropy data to disk.
parents df1ff2cb 4fb25611
Loading
Loading
Loading
Loading
+101 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import java.io.File;
import java.io.IOException;

import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * A service designed to load and periodically save "randomness"
 * for the Linux kernel.
 *
 * <p>When a Linux system starts up, the entropy pool associated with
 * {@code /dev/random} may be in a fairly predictable state.  Applications which
 * depend strongly on randomness may find {@code /dev/random} or
 * {@code /dev/urandom} returning predictable data.  In order to counteract
 * this effect, it's helpful to carry the entropy pool information across
 * shutdowns and startups.
 *
 * <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>.
 *
 * <p>TODO: Investigate attempting to write entropy data at shutdown time
 * instead of periodically.
 */
public class EntropyService extends Binder {
    private static final String ENTROPY_FILENAME = getSystemDir() + "/entropy.dat";
    private static final String TAG = "EntropyService";
    private static final int ENTROPY_WHAT = 1;
    private static final int ENTROPY_WRITE_PERIOD = 3 * 60 * 60 * 1000;  // 3 hrs
    private static final String RANDOM_DEV = "/dev/urandom";

    /**
     * Handler that periodically updates the entropy on disk.
     */
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what != ENTROPY_WHAT) {
                Log.e(TAG, "Will not process invalid message");
                return;
            }
            writeEntropy();
            scheduleEntropyWriter();
        }
    };

    public EntropyService() {
        loadInitialEntropy();
        writeEntropy();
        scheduleEntropyWriter();
    }

    private void scheduleEntropyWriter() {
        mHandler.removeMessages(ENTROPY_WHAT);
        mHandler.sendEmptyMessageDelayed(ENTROPY_WHAT, ENTROPY_WRITE_PERIOD);
    }

    private void loadInitialEntropy() {
        try {
            RandomBlock.fromFile(ENTROPY_FILENAME).toFile(RANDOM_DEV);
        } catch (IOException e) {
            Log.w(TAG, "unable to load initial entropy (first boot?)", e);
        }
    }

    private void writeEntropy() {
        try {
            RandomBlock.fromFile(RANDOM_DEV).toFile(ENTROPY_FILENAME);
        } catch (IOException e) {
            Log.e(TAG, "unable to write entropy", e);
        }
    }

    private static String getSystemDir() {
        File dataDir = Environment.getDataDirectory();
        File systemDir = new File(dataDir, "system");
        systemDir.mkdirs();
        return systemDir.toString();
    }
}
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import android.util.Log;

import java.io.Closeable;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * A 4k block of random {@code byte}s.
 */
class RandomBlock {

    private static final String TAG = "RandomBlock";
    private static final int BLOCK_SIZE = 4096;
    private byte[] block = new byte[BLOCK_SIZE];

    private RandomBlock() { }

    static RandomBlock fromFile(String filename) throws IOException {
        Log.v(TAG, "reading from file " + filename);
        InputStream stream = null;
        try {
            stream = new FileInputStream(filename);
            return fromStream(stream);
        } finally {
            close(stream);
        }
    }

    private static RandomBlock fromStream(InputStream in) throws IOException {
        RandomBlock retval = new RandomBlock();
        int total = 0;
        while(total < BLOCK_SIZE) {
            int result = in.read(retval.block, total, BLOCK_SIZE - total);
            if (result == -1) {
                throw new EOFException();
            }
            total += result;
        }
        return retval;
    }

    void toFile(String filename) throws IOException {
        Log.v(TAG, "writing to file " + filename);
        OutputStream out = null;
        try {
            // TODO: Investigate using RandomAccessFile
            out = new FileOutputStream(filename);
            toStream(out);
        } finally {
            close(out);
        }
    }

    private void toStream(OutputStream out) throws IOException {
        out.write(block);
    }

    private static void close(Closeable c) {
        try {
            if (c == null) {
                return;
            }
            c.close();
        } catch (IOException e) {
            Log.w(TAG, "IOException thrown while closing Closeable", e);
        }
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -97,6 +97,9 @@ class ServerThread extends Thread {

        // Critical services...
        try {
            Log.i(TAG, "Starting Entropy Service.");
            ServiceManager.addService("entropy", new EntropyService());

            Log.i(TAG, "Starting Power Manager.");
            power = new PowerManagerService();
            ServiceManager.addService(Context.POWER_SERVICE, power);