1657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/*
2657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * Copyright (c) 2011, The Linux Foundation. All rights reserved.
3657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *
4657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * Redistribution and use in source and binary forms, with or without
5657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * modification, are permitted provided that the following conditions are
6657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * met:
7657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *     * Redistributions of source code must retain the above copyright
8657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *       notice, this list of conditions and the following disclaimer.
9657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *     * Redistributions in binary form must reproduce the above
10657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *       copyright notice, this list of conditions and the following
11657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *       disclaimer in the documentation and/or other materials provided
12657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *       with the distribution.
13657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *     * Neither the name of The Linux Foundation nor the names of its
14657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *       contributors may be used to endorse or promote products derived
15657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *       from this software without specific prior written permission.
16657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani *
17657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani */
29657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <stdint.h>
30657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <stdio.h>
31657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <stdlib.h>
32657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <string.h>
33657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <errno.h>
34657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <fcntl.h>
35657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <signal.h>
36657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <syslog.h>
37657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <unistd.h>
38657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <linux/random.h>
39657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <linux/types.h>
40657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <sys/ioctl.h>
41657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <sys/stat.h>
42657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <sys/time.h>
43657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <sys/types.h>
44657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <sys/poll.h>
45657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <linux/capability.h>
46657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <sys/prctl.h>
47657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <private/android_filesystem_config.h>
48657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
49657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#ifdef ANDROID_CHANGES
50657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#include <android/log.h>
51657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#endif
52657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
53657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#ifndef min
54657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	#define min(a,b) (((a)>(b))?(b):(a))
55657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#endif
56657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
57657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanitypedef unsigned char bool;
58657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
59657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define TRUE 1
60657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define FALSE 0
61657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
62657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define RANDOM_DEVICE       "/dev/random"
63657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define RANDOM_DEVICE_HW    "/dev/hw_random"
64657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
65657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* The device (/dev/random) internal limits 4096 bits of entropy, 512 bytes */
66657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define MAX_ENT_POOL_BITS  4096
67657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define MAX_ENT_POOL_BYTES (MAX_ENT_POOL_BITS / 8)
68657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
69657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define MAX_ENT_POOL_WRITES 128  		/* write pool with smaller chunks */
70657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
71657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani///* Burst-mode timeout in us (micro-seconds) */
72657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani//#define BURST_MODE_TIMEOUT 100000		/* 100ms */
73657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani///* Idle-mode wait in us (micro-seconds) */
74657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani//#define IDLE_MODE_WAIT 10000			/* 10ms */
75657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
76657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* Buffer to hold hardware entropy bytes (this must be 2KB for FIPS testing       */
77657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define MAX_BUFFER 2048				/* do not change this value       */
78657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistatic unsigned char databuf[MAX_BUFFER];	/* create buffer for FIPS testing */
79657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistatic unsigned long buffsize;			/* size of data in buffer         */
80657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistatic unsigned long curridx;			/* position of current index      */
81657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
82657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* Globals */
83657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani//static bool read_blocked = FALSE;
84657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani//static pid_t qrngd_pid;
85657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
86657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* User parameters */
87657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistruct user_options {
88657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	char            input_device_name[128];
89657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	char            output_device_name[128];
90657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	bool            run_as_daemon;
91657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani};
92657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
93657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* Version number of this source */
94657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define APP_VERSION "1.01"
95657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#define APP_NAME    "qrngd"
96657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
97657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudaniconst char *program_version =
98657f34d56b357db271fbe3bd28bc8f4367412676Ajay DudaniAPP_NAME " " APP_VERSION "\n"
99657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani"Copyright (c) 2011, The Linux Foundation. All rights reserved.\n"
100657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani"This is free software; see the source for copying conditions.  There is NO\n"
101657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n";
102657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
103657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudaniconst char *program_usage =
104657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani"Usage: " APP_NAME " [OPTION...]\n"
105657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani"  -b                 background - become a daemon (default)\n"
106657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani"  -f                 foreground - do not fork and become a daemon\n"
107657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani"  -r <device name>   hardware random input device (default: /dev/hw_random)\n"
108657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani"  -o <device name>   system random output device (default: /dev/random)\n"
109657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani"  -h                 help (this page)\n";
110657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
111657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* Logging information */
112657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanienum log_level {
113657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	DEBUG = 0,
114657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	INFO = 1,
115657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	WARNING = 2,
116657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	ERROR = 3,
117657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	FATAL = 4,
118657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	LOG_MAX = 4,
119657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani};
120657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
121657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* Logging function for outputing to stderr or log */
122657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanivoid log_print(int level, char *format, ...)
123657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani{
124657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (level >= 0 && level <= LOG_MAX) {
125657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#ifdef ANDROID_CHANGES
126657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		static int levels[5] = {
127657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
128657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
129657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		};
130657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		va_list ap;
131657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		va_start(ap, format);
132657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		__android_log_vprint(levels[level], APP_NAME, format, ap);
133657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		va_end(ap);
134657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#else
135657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		static char *levels = "DIWEF";
136657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		va_list ap;
137657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		fprintf(stderr, "%c: ", levels[level]);
138657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		va_start(ap, format);
139657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		vfprintf(stderr, format, ap);
140657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		va_end(ap);
141657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		fputc('\n', stderr);
142657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#endif
143657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
144657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani}
145657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
146657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistatic void title(void)
147657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani{
148657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	printf("%s", program_version);
149657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani}
150657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
151657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistatic void usage(void)
152657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani{
153657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	printf("%s", program_usage);
154657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani}
155657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
156657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* Parse command line parameters */
157657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistatic int get_user_options(struct user_options *user_ops, int argc, char **argv)
158657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani{
159657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int max_params = argc;
160657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int itr = 1;			/* skip program name */
161657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	while (itr < max_params) {
162657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (argv[itr][0] != '-')
163657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			return -1;
164657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
165657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		switch (argv[itr++][1]) {
166657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			case 'b':
167657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				user_ops->run_as_daemon = TRUE;
168657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				break;
169657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
170657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			case 'f':
171657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				user_ops->run_as_daemon = FALSE;
172657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				break;
173657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
174657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			case 'r':
175657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				if (itr < max_params) {
176657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani					if (strlen(argv[itr]) < sizeof(user_ops->input_device_name))
177657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani						strcpy(user_ops->input_device_name, argv[itr++]);
178657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani					else
179657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani						return -1;
180657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani					break;
181657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				}
182657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				else
183657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani					return -1;
184657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
185657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			case 'o':
186657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				if (itr < max_params) {
187657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani					if (strlen(argv[itr]) < sizeof(user_ops->output_device_name))
188657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani						strcpy(user_ops->output_device_name, argv[itr++]);
189657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani					else
190657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani						return -1;
191657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani					break;
192657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				}
193657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				else
194657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani					return -1;
195657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
196657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			case 'h':
197657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				return -1;
198657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
199657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
200657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			default:
201657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				fprintf(stderr, "ERROR: Bad option: '%s'\n", argv[itr-1]);
202657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				return -1;
203657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		}
204657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
205657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	return 0;
206657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani}
207657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
208657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* Only check FIPS 140-2 (Continuous Random Number Generator Test) */
209657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistatic int fips_test(const unsigned char *buf, size_t size)
210657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani{
211657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	unsigned long *buff_ul = (unsigned long *) buf;
212657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	size_t size_ul = size >> 2;	/* convert byte to word size */
213657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	unsigned long last_value;
214657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	unsigned int rnd_ctr[256];
215657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int i;
216657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
217657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
218657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* Continuous Random Number Generator Test */
219657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	last_value = *(buff_ul++);
220657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	size_ul--;
221657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
222657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	while (size_ul > 0) {
223657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (*buff_ul == last_value) {
224657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			log_print(ERROR, "ERROR: Bad word value from hardware.");
225657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			return -1;
226657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		} else
227657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			last_value = *buff_ul;
228657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		buff_ul++;
229657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		size_ul--;
230657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
231657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
232657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* count each random number */
233657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	for (i = 0; i < size; ++i) {
234657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		rnd_ctr[buf[i]]++;
235657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
236657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
237657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* check random numbers to make sure they are not bogus */
238657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	for (i = 0; i < 256; ++i) {
239657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (rnd_ctr[i] == 0) {
240657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			log_print(ERROR, "ERROR: Bad spectral random number sample.");
241657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			return -1;
242657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		}
243657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
244657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
245657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	return 0;
246657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani}
247657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
248657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* Read data from the hardware RNG source */
249657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistatic int read_src(int fd, void *buf, size_t size)
250657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani{
251657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	size_t offset = 0;
252657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	char *chr = (char *) buf;
253657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	ssize_t ret;
254657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
255657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (!size)
256657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		return -1;
257657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	do {
258657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		ret = read(fd, chr + offset, size);
259657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		/* any read failure is bad */
260657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (ret == -1)
261657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			return -1;
262657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		size -= ret;
263657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		offset += ret;
264657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	} while (size > 0);
265657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
266657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* should have read in all of requested data */
267657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (size > 0)
268657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		return -1;
269657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	return 0;
270657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani}
271657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
272657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/*Hold minimal permissions, so as to get IOCTL working*/
273657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudanistatic int qrng_update_cap()
274657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani{
275657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int retvalue = 0;
276657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	struct __user_cap_header_struct header;
277657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	struct __user_cap_data_struct cap;
278657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
279657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	memset(&header, 0, sizeof(header));
280657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	memset(&cap, 0, sizeof(cap));
281657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
282657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if( 0 != setgid(AID_SYSTEM)){
283657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		fprintf(stderr, "setgid error\n");
284657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		return -1;
285657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
286657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if( 0 != setuid(AID_SYSTEM)){
287657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		fprintf(stderr, "setuid error\n");
288657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		return -1;
289657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
290657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	header.version = _LINUX_CAPABILITY_VERSION;
291657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	header.pid = 0;
292657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	cap.effective = (1 << CAP_SYS_ADMIN) | (1 << CAP_NET_RAW);
293657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	cap.permitted = cap.effective;
294657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	cap.inheritable = 0;
295657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	retvalue = capset(&header, &cap);
296657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if(retvalue != 0){
297657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		fprintf(stderr, "capset error\n");
298657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		return -1;
299657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
300657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	return 0;
301657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani}
302657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
303657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani/* The beginning of everything */
304657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudaniint main(int argc, char **argv)
305657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani{
306657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	struct user_options user_ops;		/* holds user configuration data     */
307657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	struct rand_pool_info *rand = NULL;	/* structure to pass entropy (IOCTL) */
308657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int random_fd = 0;			/* output file descriptor            */
309657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int random_hw_fd = 0;			/* input file descriptor             */
310657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int ent_count;				/* current system entropy            */
311657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int write_size;				/* max entropy data to pass          */
312657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	struct pollfd fds[1];			/* used for polling file descriptor  */
313657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int ret;
314657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	int exitval = 0;
315657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
316657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* set default parameters */
317657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	user_ops.run_as_daemon = TRUE;
318657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	strcpy(user_ops.input_device_name, RANDOM_DEVICE_HW);
319657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	strcpy(user_ops.output_device_name, RANDOM_DEVICE);
320657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
321657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* display application header */
322657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	title();
323657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
324657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* get user preferences */
325657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	ret = get_user_options(&user_ops, argc, argv);
326657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (ret < 0) {
327657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		usage();
328657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		exitval = 1;
329657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		goto exit;
330657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
331657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
332657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* open hardware random device */
333657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	random_hw_fd = open(user_ops.input_device_name, O_RDONLY);
334657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (random_hw_fd < 0) {
335657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		fprintf(stderr, "Can't open hardware random device file %s\n", user_ops.input_device_name);
336657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		exitval = 1;
337657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		goto exit;
338657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
339657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
340657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/*Hold minimal permissions, just enough to get IOCTL working*/
341657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if(0 != qrng_update_cap()){
342657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		log_print(ERROR, "qrngd permission reset failed, exiting\n");
343657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		exitval = 1;
344657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		goto exit;
345657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
346657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
347657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* open random device */
348657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	random_fd = open(user_ops.output_device_name, O_RDWR);
349657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (random_fd < 0) {
350657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		fprintf(stderr, "Can't open random device file %s\n", user_ops.output_device_name);
351657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		exitval = 1;
352657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		goto exit;
353657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
354657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
355657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* allocate memory for ioctl data struct and buffer */
356657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	rand = malloc(sizeof(struct rand_pool_info) + MAX_ENT_POOL_WRITES);
357657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (!rand) {
358657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		fprintf(stderr, "Can't allocate memory\n");
359657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		exitval = 1;
360657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		goto exit;
361657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
362657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
363657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* setup poll() data */
364657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	memset(fds, 0 , sizeof(fds));
365657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	fds[0].fd = random_fd;
366657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	fds[0].events = POLLOUT;
367657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
368657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* run as daemon if requested to do so */
369657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (user_ops.run_as_daemon) {
370657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		fprintf(stderr, "Starting daemon.\n");
371657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (daemon(0, 0) < 0) {
372657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			fprintf(stderr, "can't daemonize: %s\n", strerror(errno));
373657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			exitval = 1;
374657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			goto exit;
375657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		}
376657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#ifndef ANDROID_CHANGES
377657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		openlog(APP_NAME, 0, LOG_DAEMON);
378657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani#endif
379657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
380657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
381657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* log message */
382657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	log_print(INFO, APP_NAME " has started:\n" "Reading device:'%s' updating entropy for device:'%s'",
383657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		  user_ops.input_device_name,
384657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		  user_ops.output_device_name);
385657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
386657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* main loop to get data from hardware and feed RNG entropy pool */
387657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	while (1) {
388657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
389657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		/* Check for empty buffer and fill with hardware random generated numbers */
390657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (buffsize == 0) {
391657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			/* fill buffer with random data from hardware */
392657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			ret = read_src(random_hw_fd, databuf, MAX_BUFFER);
393657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			if (ret < 0) {
394657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				log_print(ERROR, "ERROR: Can't read from hardware source.");
395657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				exitval = 1;
396657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				goto exit;
397657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			}
398657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			/* run FIPS test on buffer, if buffer fails then ditch it and get new data */
399657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			ret = fips_test(databuf, MAX_BUFFER);
400657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			if (ret < 0) {
401657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				buffsize = 0;
402657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				log_print(INFO, "ERROR: Failed FIPS test.");
403657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			}
404657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			/* everything good, reset buffer variables to indicate full buffer */
405657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			else {
406657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				buffsize = MAX_BUFFER;
407657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani				curridx  = 0;
408657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			}
409657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		}
410657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		/* We should have data here, if not then something bad happened above and we should wait and try again */
411657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (buffsize == 0) {
412657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			log_print(ERROR, "ERROR: Timeout getting valid random data from hardware.");
413657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			usleep(100000);	/* 100ms */
414657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			continue;
415657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		}
416657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
417657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		/* Get current entropy pool size in bits and convert to bytes */
418657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (ioctl(random_fd, RNDGETENTCNT, &ent_count) != 0) {
419657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			log_print(ERROR, "ERROR: Can't read entropy count.");
420657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			exitval = 1;
421657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			goto exit;
422657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		}
423657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		/* convert entropy bits to bytes */
424657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		ent_count >>= 3;
425657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
426657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		/* fill entropy pool */
427657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		write_size = min(buffsize, MAX_ENT_POOL_WRITES);
428657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
429657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		/* Write some data to the device */
430657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		rand->entropy_count = write_size * 8;
431657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		rand->buf_size      = write_size;
432657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		memcpy(rand->buf, &databuf[curridx], write_size);
433657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		curridx  += write_size;
434657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		buffsize -= write_size;
435657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
436657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		/* Issue the ioctl to increase the entropy count */
437657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (ioctl(random_fd, RNDADDENTROPY, rand) < 0) {
438657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			log_print(ERROR,"ERROR: RNDADDENTROPY ioctl() failed.");
439657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			exitval = 1;
440657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			goto exit;
441657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		}
442657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
443657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		/* Wait if entropy pool is full */
444657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		ret = poll(fds, 1, -1);
445657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		if (ret < 0) {
446657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			log_print(ERROR,"ERROR: poll call failed.");
447657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			/* wait if error */
448657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani			usleep(100000);
449657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		}
450657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	}
451657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
452657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudaniexit:
453657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	/* free other resources */
454657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (rand)
455657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		free(rand);
456657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (random_fd)
457657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		close(random_fd);
458657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	if (random_hw_fd)
459657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani		close(random_hw_fd);
460657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani	return exitval;
461657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani}
462657f34d56b357db271fbe3bd28bc8f4367412676Ajay Dudani
463