diff options
| author | Nick Kralevich <nnk@google.com> | 2009-06-17 16:03:22 -0700 |
|---|---|---|
| committer | Nick Kralevich <nnk@google.com> | 2009-06-18 11:00:19 -0700 |
| commit | 4fb256117ca271e3e37284a19b663d116f6ec20c (patch) | |
| tree | 1882f2a0a7e69dfeeb1238c9690a560c8d2ec77e /services | |
| parent | 3f4263fac6bcc68b3c7fff8e6ac9ad2d97b2ad4c (diff) | |
| download | frameworks_base-4fb256117ca271e3e37284a19b663d116f6ec20c.zip frameworks_base-4fb256117ca271e3e37284a19b663d116f6ec20c.tar.gz frameworks_base-4fb256117ca271e3e37284a19b663d116f6ec20c.tar.bz2 | |
load entropy data at boot. Periodically write entropy data to disk.
Diffstat (limited to 'services')
| -rw-r--r-- | services/java/com/android/server/EntropyService.java | 101 | ||||
| -rw-r--r-- | services/java/com/android/server/RandomBlock.java | 90 | ||||
| -rw-r--r-- | services/java/com/android/server/SystemServer.java | 3 |
3 files changed, 194 insertions, 0 deletions
diff --git a/services/java/com/android/server/EntropyService.java b/services/java/com/android/server/EntropyService.java new file mode 100644 index 0000000..e51a0af --- /dev/null +++ b/services/java/com/android/server/EntropyService.java @@ -0,0 +1,101 @@ +/* + * 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(); + } +} diff --git a/services/java/com/android/server/RandomBlock.java b/services/java/com/android/server/RandomBlock.java new file mode 100644 index 0000000..c08761e --- /dev/null +++ b/services/java/com/android/server/RandomBlock.java @@ -0,0 +1,90 @@ +/* + * 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); + } + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index f6c1525..3e4d5f9 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -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); |
