2
* rngd.c -- Random Number Generator daemon
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.
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
12
* Copyright (C) 2001 Philipp Rumpf
13
* Copyright (C) 2004 Henrique de Moraes Holschuh <hmh@debian.org>
15
* This program is free software; you can redistribute it and/or modify
16
* it under the terms of the GNU General Public License as published by
17
* the Free Software Foundation; either version 2 of the License, or
18
* (at your option) any later version.
20
* This program is distributed in the hope that it will be useful,
21
* but WITHOUT ANY WARRANTY; without even the implied warranty of
22
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
* GNU General Public License for more details.
25
* You should have received a copy of the GNU General Public License
26
* along with this program; if not, write to the Free Software
27
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33
#error Invalid or missing autoconf build environment
36
#include "rng-tools-config.h"
42
#include <sys/types.h>
56
#include "rngd_threads.h"
57
#include "rngd_entsource.h"
58
#include "rngd_linux.h"
61
# include <sys/file.h>
65
#define PROGNAME "rngd"
72
struct rng_stats rng_stats;
74
/* Background/daemon mode */
75
pid_t masterprocess; /* PID of the master process */
76
int am_daemon; /* Nonzero if we went daemon */
77
int exitstatus = EXIT_SUCCESS; /* Exit status on SIGTERM */
78
static FILE *daemon_lockfp = NULL; /* Lockfile file pointer */
79
static int daemon_lockfd; /* Lockfile file descriptior */
82
volatile int gotsigterm = 0; /* Received a TERM signal */
83
static volatile int gotsigusr1 = 0; /* Received a USR1 signal */
85
/* Command line arguments and processing */
86
const char *argp_program_version =
87
PROGNAME " " VERSION "\n"
88
"Copyright (c) 2001 by Philipp Rumpf\n"
89
"This is free software; see the source for copying conditions. There is NO "
90
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.";
91
const char *argp_program_bug_address = PACKAGE_BUGREPORT;
92
error_t argp_err_exit_status = EXIT_USAGE;
95
"Check and feed random data from hardware device to kernel entropy pool.\n";
97
#define ARGP_RNGD_CMDLINE_TRNG 0x81
99
static struct argp_option options[] = {
100
{ "foreground", 'f', 0, 0, "Do not fork and become a daemon" },
102
{ "background", 'b', 0, 0, "Become a daemon (default)" },
104
{ "random-device", 'o', "file", 0,
105
"Kernel device used for entropy output (default: " DEVRANDOM ")" },
107
{ "rng-device", 'r', "file", 0,
108
"Entropy source (default: " DEVHWRANDOM ")" },
110
{ "random-step", 's', "n", 0,
111
"Number of bytes written to random-device at a time (default: 64), 8 <= n <= " STR(FIPS_RNG_BUFFER_SIZE) ", n must be even" },
113
{ "fill-watermark", 'W', "n", 0,
114
"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" },
116
{ "timeout", 't', "n", 0,
117
"Interval written to random-device when the entropy pool is full, in seconds (default: 60)" },
119
{ "pidfile", 'p', "file", 0,
120
"Path to file to write PID to in daemon mode (default: " PIDFILE ")" },
122
{ "rng-entropy", 'H', "n", 0,
123
"Entropy per bit of the hardware RNG (default: 1.0), 0 < n <= 1.0" },
125
{ "rng-buffers", 'B', "n", 0,
126
"Number of buffers (default: 3), 0 < n <= " STR(MAX_RNG_BUFFERS) },
128
{ "trng", ARGP_RNGD_CMDLINE_TRNG, "name", 0,
129
"Load known-good defaults for a given TRNG. Use --trng=help to get a list of known TRNGs" },
133
static struct arguments default_arguments = {
134
.rng_name = DEVHWRANDOM,
135
.random_name = DEVRANDOM,
136
.pidfile_name = PIDFILE,
139
.fill_watermark = 2048,
144
struct arguments *arguments = &default_arguments;
146
/* Predefined known-good values for TRNGs */
148
char *tag; /* Short name of TRNG */
149
char *name; /* Full Name of TRNG */
150
int width; /* Best width for continuous run test */
151
int buffers; /* Recommended value for rng-buffers */
152
double entropy; /* Recommended value for rng-entropy */
154
static struct trng_params trng_parameters[] = {
155
/* Device: Intel FWH TRNG (82802AB/82802AC)
156
* Kernel driver: hw_random or i810_rng
157
* Device width: 8 bits
160
* Slow, about 20Kibits/s (variable bitrate) with current
161
* kernel drivers, but the hardware should be capable of
162
* about 75kbit/s. The kernel driver uses a lot of CPU
163
* time. It is often misdetected (false positive).
165
* Whitepaper: Cryptographic Research
166
* http://www.cryptography.com/resources/whitepapers/IntelRNG.pdf
168
{ .name = "Intel FWH (82802AB/AC) TRNG",
175
/* Device: VIA Padlock (Nehemiah CPU core) TRNG
176
* Kernel driver: hw_random
177
* Device width: 8 bits (internal), 64 bits (external)
178
* Entropy: H > 0.75 (whitener disabled)
179
* H > 0.99 (whitener enabled)
181
* Very fast, about 30-50 Mibits/s with the whitener disabled,
182
* and 4-9 Mibits/s with whitener enabled. The kernel drivers
183
* need patching to archieve better performance (patches and
184
* data from http://peertech.org/hardware/viarng/).
186
* The hardware has 4 64bit FIFOs to store TRNG data.
188
* Whitepaper: Cryptographic Research
189
* http://www.cryptography.com/resources/whitepapers/VIA_rng.pdf
191
{ .name = "VIA Padlock (Nehemiah) TRNG",
201
* command line processing
203
#define SEEN_OPT_RNGBUFFERS 0x01
204
#define SEEN_OPT_RNGENTROPY 0x02
206
static error_t parse_opt (int key, char *arg, struct argp_state *state)
208
struct arguments *arguments = state->input;
209
static unsigned int seen_opt = 0;
213
arguments->random_name = arg;
216
arguments->rng_name = arg;
219
arguments->pidfile_name = arg;
223
if (sscanf(arg, "%f", &f) == 0)
226
arguments->poll_timeout = f;
231
arguments->daemon = 0;
234
arguments->daemon = 1;
238
if ((sscanf(arg, "%i", &n) == 0) || (n < 8) ||
239
(n > FIPS_RNG_BUFFER_SIZE) || (n & 1))
242
arguments->random_step = n;
247
if ((sscanf(arg, "%i", &n) == 0) || (n < 0) || (n > 4096))
250
arguments->fill_watermark = n;
256
if ((sscanf(arg, "%f", &H) == 0) || (H <= 0) || (H > 1))
259
arguments->rng_entropy = H;
260
seen_opt |= SEEN_OPT_RNGENTROPY;
266
if ((sscanf(arg, "%i", &n) == 0) || (n < 1) || (n > MAX_RNG_BUFFERS ))
269
arguments->rng_buffers = n;
270
seen_opt |= SEEN_OPT_RNGBUFFERS;
274
case ARGP_RNGD_CMDLINE_TRNG: { /* --trng */
276
if (strcasecmp(arg, "help") == 0) {
277
fprintf(state->out_stream,
278
"TRNG Description\n");
279
while (trng_parameters[i].tag) {
280
fprintf(state->out_stream, "%-8s \"%s\"\n",
281
trng_parameters[i].tag,
282
trng_parameters[i].name);
283
fprintf(state->out_stream,
285
"rng-entropy=%0.3f, "
287
" ", trng_parameters[i].entropy,
288
trng_parameters[i].buffers);
293
while (trng_parameters[i].tag) {
294
if (strcasecmp(arg, trng_parameters[i].tag) == 0) {
295
if (! (seen_opt & SEEN_OPT_RNGENTROPY))
296
arguments->rng_entropy =
297
trng_parameters[i].entropy;
298
if (! (seen_opt & SEEN_OPT_RNGBUFFERS))
299
arguments->rng_buffers =
300
trng_parameters[i].buffers;
305
if (!trng_parameters[i].tag)
306
argp_failure(state, argp_err_exit_status, 0,
307
"Unknown TRNG, try --trng=help");
312
return ARGP_ERR_UNKNOWN;
317
static struct argp argp = { options, parse_opt, NULL, doc };
324
if (am_daemon) syslog(LOG_ERR, "Exiting with status %d...", status);
329
* Write our pid to our pidfile, and lock it
331
static void get_lock(const char* pidfile_name)
335
if (!daemon_lockfp) {
336
if (((daemon_lockfd = open(pidfile_name, O_RDWR|O_CREAT, 0644)) == -1)
337
|| ((daemon_lockfp = fdopen(daemon_lockfd, "r+"))) == NULL) {
338
message(LOG_ERR, "can't open or create %s", pidfile_name);
344
if ( flock(daemon_lockfd, LOCK_EX|LOCK_NB) != 0 ) {
346
if ( lockf(fileno(daemon_lockfp), F_TLOCK, 0) != 0 ) {
348
rewind(daemon_lockfp);
349
fscanf(daemon_lockfp, "%d", &otherpid);
350
message(LOG_ERR, "can't lock %s, running daemon's pid may be %d",
351
pidfile_name, otherpid);
355
fcntl(daemon_lockfd, F_SETFD, 1);
357
rewind(daemon_lockfp);
358
fprintf(daemon_lockfp, "%d\n", (int) getpid());
359
fflush(daemon_lockfp);
360
ftruncate(fileno(daemon_lockfp), ftell(daemon_lockfp));
366
static void sigterm_handler(int sig)
368
gotsigterm = 128 | sig;
371
static void sigusr1_handler(int sig)
376
static void init_sighandlers(void)
378
struct sigaction action;
380
sigemptyset(&action.sa_mask);
382
action.sa_handler = sigterm_handler;
384
/* Handle SIGTERM and SIGINT the same way */
385
if (sigaction(SIGTERM, &action, NULL) < 0) {
387
"unable to install signal handler for SIGTERM: %s",
391
if (sigaction(SIGINT, &action, NULL) < 0) {
393
"unable to install signal handler for SIGINT: %s",
398
/* Handle SIGUSR1 in a more friendly way */
399
action.sa_flags = SA_RESTART;
400
action.sa_handler = sigusr1_handler;
401
if (sigaction(SIGUSR1, &action, NULL) < 0) {
403
"unable to install signal handler for SIGUSR1: %s",
410
* Statistics, n is the number of rng buffers
412
static void init_rng_stats(int n)
414
set_stat_prefix("stats: ");
416
memset(&rng_stats, 0, sizeof(rng_stats));
417
rng_stats.buffer_lowmark = n - 1; /* one is always in use */
419
pthread_mutex_init(&rng_stats.group1_mutex, NULL);
420
pthread_mutex_init(&rng_stats.group2_mutex, NULL);
421
pthread_mutex_init(&rng_stats.group3_mutex, NULL);
424
static void dump_rng_stats(void)
429
pthread_mutex_lock(&rng_stats.group1_mutex);
430
message(LOG_INFO, dump_stat_counter(buf, sizeof(buf),
431
"bits received from TRNG source",
432
rng_stats.bytes_received * 8));
433
pthread_mutex_unlock(&rng_stats.group1_mutex);
434
pthread_mutex_lock(&rng_stats.group3_mutex);
435
message(LOG_INFO, dump_stat_counter(buf, sizeof(buf),
436
"bits sent to kernel pool",
437
rng_stats.bytes_sent * 8));
438
message(LOG_INFO, dump_stat_counter(buf, sizeof(buf),
439
"entropy added to kernel pool",
440
rng_stats.entropy_sent));
441
pthread_mutex_unlock(&rng_stats.group3_mutex);
442
pthread_mutex_lock(&rng_stats.group2_mutex);
443
message(LOG_INFO, dump_stat_counter(buf, sizeof(buf),
444
"FIPS 140-2 successes",
445
rng_stats.good_fips_blocks));
446
message(LOG_INFO, dump_stat_counter(buf, sizeof(buf),
447
"FIPS 140-2 failures",
448
rng_stats.bad_fips_blocks));
449
for (j = 0; j < N_FIPS_TESTS; j++)
450
message(LOG_INFO, dump_stat_counter(buf, sizeof(buf), fips_test_names[j],
451
rng_stats.fips_failures[j]));
452
pthread_mutex_unlock(&rng_stats.group2_mutex);
453
pthread_mutex_lock(&rng_stats.group1_mutex);
454
message(LOG_INFO, dump_stat_bw(buf, sizeof(buf),
455
"TRNG source speed", "bits",
456
&rng_stats.source_blockfill, FIPS_RNG_BUFFER_SIZE*8));
457
pthread_mutex_unlock(&rng_stats.group1_mutex);
458
pthread_mutex_lock(&rng_stats.group2_mutex);
459
message(LOG_INFO, dump_stat_bw(buf, sizeof(buf),
460
"FIPS tests speed", "bits",
461
&rng_stats.fips_blockfill, FIPS_RNG_BUFFER_SIZE*8));
462
pthread_mutex_unlock(&rng_stats.group2_mutex);
463
pthread_mutex_lock(&rng_stats.group3_mutex);
464
message(LOG_INFO, dump_stat_counter(buf, sizeof(buf),
465
"Lowest ready-buffers level",
466
rng_stats.buffer_lowmark));
467
message(LOG_INFO, dump_stat_counter(buf, sizeof(buf),
468
"Entropy starvations",
469
rng_stats.sink_starved));
470
message(LOG_INFO, dump_stat_stat(buf, sizeof(buf),
471
"Time spent starving for entropy",
473
&rng_stats.sink_wait));
474
pthread_mutex_unlock(&rng_stats.group3_mutex);
477
int main(int argc, char **argv)
483
argp_parse(&argp, argc, argv, 0, 0, arguments);
485
/* close useless FDs we might have gotten somehow */
486
for(fd = 3; fd < 250; fd++) (void) close(fd);
488
/* Init statistics */
489
init_rng_stats(arguments->rng_buffers);
491
/* Init entropy source, and open TRNG device */
492
init_entropy_source(arguments->rng_name);
494
/* Init entropy sink and open random device */
495
init_kernel_rng(arguments->random_name);
497
if (arguments->daemon) {
498
/* check if another rngd is running,
499
* create pidfile and lock it */
500
get_lock(arguments->pidfile_name);
502
if (daemon(0, 0) < 0) {
503
message(LOG_ERR, "can't daemonize: %s",
508
openlog(PROGNAME, 0, SYSLOG_FACILITY);
512
get_lock(arguments->pidfile_name);
515
masterprocess = getpid();
516
message(LOG_INFO, PROGNAME " " VERSION " starting up...");
518
/* post-fork initialization */
519
init_rng_buffers(arguments->rng_buffers);
522
/* Fire up worker threads */
523
if (pthread_create(&t1, NULL, &do_rng_data_source_loop, NULL) |
524
pthread_create(&t2, NULL, &do_rng_fips_test_loop, NULL ) |
525
pthread_create(&t3, NULL, &do_rng_data_sink_loop, NULL )) {
526
message(LOG_ERR, "Insufficient resources to start threads");
531
* All we can do now is spin around waiting for a hit to the head.
532
* Dump stats every hour, and at exit...
535
while (!gotsigterm) {
536
sleeptime = sleep(sleeptime);
537
if ((sleeptime == 0) || gotsigusr1 || gotsigterm) {
544
if (exitstatus == EXIT_SUCCESS)
545
message(LOG_INFO, "Exiting...");
548
"Exiting with status %d", exitstatus);