]>
Commit | Line | Data |
---|---|---|
61af3de3 JG |
1 | /* |
2 | * rngd.c -- Random Number Generator daemon | |
3 | * | |
4 | * rngd reads data from a hardware random number generator, verifies it | |
5 | * looks like random data, and adds it to /dev/random's entropy store. | |
6 | * | |
7 | * In theory, this should allow you to read very quickly from | |
8 | * /dev/random; rngd also adds bytes to the entropy store periodically | |
9 | * when it's full, which makes predicting the entropy store's contents | |
10 | * harder. | |
11 | * | |
12 | * Copyright (C) 2001 Philipp Rumpf | |
13 | * | |
14 | * This program is free software; you can redistribute it and/or modify | |
15 | * it under the terms of the GNU General Public License as published by | |
16 | * the Free Software Foundation; either version 2 of the License, or | |
17 | * (at your option) any later version. | |
18 | * | |
19 | * This program is distributed in the hope that it will be useful, | |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
22 | * GNU General Public License for more details. | |
23 | * | |
24 | * You should have received a copy of the GNU General Public License | |
25 | * along with this program; if not, write to the Free Software | |
26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
27 | */ | |
28 | ||
29 | #define _GNU_SOURCE | |
30 | ||
31 | #ifndef HAVE_CONFIG_H | |
32 | #error Invalid or missing autoconf build environment | |
33 | #endif | |
34 | ||
35 | #include "rng-tools-config.h" | |
36 | ||
37 | #include <unistd.h> | |
38 | #include <stdint.h> | |
39 | #include <stdio.h> | |
40 | #include <stdlib.h> | |
41 | #include <sys/types.h> | |
42 | #include <sys/stat.h> | |
43 | #include <fcntl.h> | |
44 | #include <errno.h> | |
45 | #include <string.h> | |
46 | #include <argp.h> | |
47 | #include <syslog.h> | |
48 | ||
49 | #include "rngd.h" | |
50 | #include "fips.h" | |
51 | #include "exits.h" | |
52 | #include "rngd_entsource.h" | |
53 | #include "rngd_linux.h" | |
54 | ||
55 | /* | |
56 | * Globals | |
57 | */ | |
58 | ||
59 | /* Background/daemon mode */ | |
60 | int am_daemon; /* Nonzero if we went daemon */ | |
61 | ||
62 | /* Command line arguments and processing */ | |
63 | const char *argp_program_version = | |
64 | "rngd " VERSION "\n" | |
65 | "Copyright 2001-2004 Jeff Garzik\n" | |
66 | "Copyright (c) 2001 by Philipp Rumpf\n" | |
67 | "This is free software; see the source for copying conditions. There is NO " | |
68 | "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."; | |
69 | ||
70 | const char *argp_program_bug_address = PACKAGE_BUGREPORT; | |
71 | ||
72 | static char doc[] = | |
73 | "Check and feed random data from hardware device to kernel entropy pool.\n"; | |
74 | ||
75 | static struct argp_option options[] = { | |
76 | { "foreground", 'f', 0, 0, "Do not fork and become a daemon" }, | |
77 | ||
78 | { "background", 'b', 0, 0, "Become a daemon (default)" }, | |
79 | ||
80 | { "random-device", 'o', "file", 0, | |
81 | "Kernel device used for random number output (default: /dev/random)" }, | |
82 | ||
83 | { "rng-device", 'r', "file", 0, | |
84 | "Kernel device used for random number input (default: /dev/hwrandom)" }, | |
85 | ||
86 | { "random-step", 's', "nnn", 0, | |
87 | "Number of bytes written to random-device at a time (default: 64)" }, | |
88 | ||
89 | { "fill-watermark", 'W', "n", 0, | |
90 | "Do not stop feeding entropy to random-device until at least n bits of entropy are available in the pool (default: 2048), 0 <= n <= 4096" }, | |
91 | ||
92 | { "timeout", 't', "nnn", 0, | |
93 | "Interval written to random-device when the entropy pool is full, in seconds (default: 60)" }, | |
94 | ||
95 | { 0 }, | |
96 | }; | |
97 | ||
98 | static struct arguments default_arguments = { | |
99 | .rng_name = "/dev/hwrandom", | |
100 | .random_name = "/dev/random", | |
101 | .poll_timeout = 60, | |
102 | .random_step = 64, | |
103 | .fill_watermark = 2048, | |
104 | .daemon = 1, | |
105 | }; | |
106 | struct arguments *arguments = &default_arguments; | |
107 | ||
108 | ||
109 | /* | |
110 | * command line processing | |
111 | */ | |
112 | static error_t parse_opt (int key, char *arg, struct argp_state *state) | |
113 | { | |
114 | struct arguments *arguments = state->input; | |
115 | ||
116 | switch(key) { | |
117 | case 'o': | |
118 | arguments->random_name = arg; | |
119 | break; | |
120 | case 'r': | |
121 | arguments->rng_name = arg; | |
122 | break; | |
123 | case 't': { | |
124 | float f; | |
125 | if (sscanf(arg, "%f", &f) == 0) | |
126 | argp_usage(state); | |
127 | else | |
128 | arguments->poll_timeout = f; | |
129 | break; | |
130 | } | |
131 | ||
132 | case 'f': | |
133 | arguments->daemon = 0; | |
134 | break; | |
135 | case 'b': | |
136 | arguments->daemon = 1; | |
137 | break; | |
138 | case 's': | |
139 | if (sscanf(arg, "%i", &arguments->random_step) == 0) | |
140 | argp_usage(state); | |
141 | break; | |
142 | case 'W': { | |
143 | int n; | |
144 | if ((sscanf(arg, "%i", &n) == 0) || (n < 0) || (n > 4096)) | |
145 | argp_usage(state); | |
146 | else | |
147 | arguments->fill_watermark = n; | |
148 | break; | |
149 | } | |
150 | ||
151 | default: | |
152 | return ARGP_ERR_UNKNOWN; | |
153 | } | |
154 | ||
155 | return 0; | |
156 | } | |
157 | ||
158 | static struct argp argp = { options, parse_opt, NULL, doc }; | |
159 | ||
160 | ||
161 | static void do_loop(int random_step, | |
162 | double poll_timeout) | |
163 | { | |
164 | unsigned char buf[FIPS_RNG_BUFFER_SIZE]; | |
165 | unsigned char *p; | |
166 | int fips; | |
167 | ||
168 | for (;;) { | |
169 | xread(buf, sizeof buf); | |
170 | ||
171 | fips = fips_run_rng_test(&fipsctx, buf); | |
172 | ||
173 | if (fips) { | |
174 | message(LOG_DAEMON|LOG_ERR, "failed fips test\n"); | |
175 | sleep(1); | |
176 | continue; | |
177 | } | |
178 | ||
179 | for (p = buf; p + random_step <= &buf[sizeof buf]; | |
180 | p += random_step) { | |
181 | random_add_entropy(p, random_step); | |
182 | random_sleep(poll_timeout); | |
183 | } | |
184 | } | |
185 | } | |
186 | ||
187 | ||
188 | int main(int argc, char **argv) | |
189 | { | |
190 | argp_parse(&argp, argc, argv, 0, 0, arguments); | |
191 | ||
192 | /* Init entropy source, and open TRNG device */ | |
193 | init_entropy_source(arguments->rng_name); | |
194 | ||
195 | /* Init entropy sink and open random device */ | |
196 | init_kernel_rng(arguments->random_name); | |
197 | ||
198 | if (arguments->daemon) { | |
199 | am_daemon = 1; | |
200 | ||
201 | if (daemon(0, 0) < 0) { | |
202 | fprintf(stderr, "can't daemonize: %s\n", | |
203 | strerror(errno)); | |
204 | return 1; | |
205 | } | |
206 | ||
207 | openlog("rngd", 0, LOG_DAEMON); | |
208 | } | |
209 | ||
210 | do_loop(arguments->random_step, | |
211 | arguments->poll_timeout ? : -1.0); | |
212 | ||
213 | return 0; | |
214 | } |