blob: e51a0afb4ef200aace49e1a532a99215c9b41459 [file] [log] [blame]
Nick Kralevich4fb25612009-06-17 16:03:22 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import java.io.File;
20import java.io.IOException;
21
22import android.os.Binder;
23import android.os.Environment;
24import android.os.Handler;
25import android.os.Message;
26import android.util.Log;
27
28/**
29 * A service designed to load and periodically save "randomness"
30 * for the Linux kernel.
31 *
32 * <p>When a Linux system starts up, the entropy pool associated with
33 * {@code /dev/random} may be in a fairly predictable state. Applications which
34 * depend strongly on randomness may find {@code /dev/random} or
35 * {@code /dev/urandom} returning predictable data. In order to counteract
36 * this effect, it's helpful to carry the entropy pool information across
37 * shutdowns and startups.
38 *
39 * <p>This class was modeled after the script in
40 * <a href="http://www.kernel.org/doc/man-pages/online/pages/man4/random.4.html">man
41 * 4 random</a>.
42 *
43 * <p>TODO: Investigate attempting to write entropy data at shutdown time
44 * instead of periodically.
45 */
46public class EntropyService extends Binder {
47 private static final String ENTROPY_FILENAME = getSystemDir() + "/entropy.dat";
48 private static final String TAG = "EntropyService";
49 private static final int ENTROPY_WHAT = 1;
50 private static final int ENTROPY_WRITE_PERIOD = 3 * 60 * 60 * 1000; // 3 hrs
51 private static final String RANDOM_DEV = "/dev/urandom";
52
53 /**
54 * Handler that periodically updates the entropy on disk.
55 */
56 private final Handler mHandler = new Handler() {
57 @Override
58 public void handleMessage(Message msg) {
59 if (msg.what != ENTROPY_WHAT) {
60 Log.e(TAG, "Will not process invalid message");
61 return;
62 }
63 writeEntropy();
64 scheduleEntropyWriter();
65 }
66 };
67
68 public EntropyService() {
69 loadInitialEntropy();
70 writeEntropy();
71 scheduleEntropyWriter();
72 }
73
74 private void scheduleEntropyWriter() {
75 mHandler.removeMessages(ENTROPY_WHAT);
76 mHandler.sendEmptyMessageDelayed(ENTROPY_WHAT, ENTROPY_WRITE_PERIOD);
77 }
78
79 private void loadInitialEntropy() {
80 try {
81 RandomBlock.fromFile(ENTROPY_FILENAME).toFile(RANDOM_DEV);
82 } catch (IOException e) {
83 Log.w(TAG, "unable to load initial entropy (first boot?)", e);
84 }
85 }
86
87 private void writeEntropy() {
88 try {
89 RandomBlock.fromFile(RANDOM_DEV).toFile(ENTROPY_FILENAME);
90 } catch (IOException e) {
91 Log.e(TAG, "unable to write entropy", e);
92 }
93 }
94
95 private static String getSystemDir() {
96 File dataDir = Environment.getDataDirectory();
97 File systemDir = new File(dataDir, "system");
98 systemDir.mkdirs();
99 return systemDir.toString();
100 }
101}