1 /*
2  * Copyright (c) 2011, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above
10  *       copyright notice, this list of conditions and the following
11  *       disclaimer in the documentation and/or other materials provided
12  *       with the distribution.
13  *     * Neither the name of The Linux Foundation nor the names of its
14  *       contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <signal.h>
36 #include <syslog.h>
37 #include <unistd.h>
38 #include <linux/random.h>
39 #include <linux/types.h>
40 #include <sys/ioctl.h>
41 #include <sys/stat.h>
42 #include <sys/time.h>
43 #include <sys/types.h>
44 #include <sys/poll.h>
45 #include <linux/capability.h>
46 #include <sys/prctl.h>
47 #include <private/android_filesystem_config.h>
48 
49 #ifdef ANDROID_CHANGES
50 #include <android/log.h>
51 #endif
52 
53 #ifndef min
54 	#define min(a,b) (((a)>(b))?(b):(a))
55 #endif
56 
57 typedef unsigned char bool;
58 
59 #define TRUE 1
60 #define FALSE 0
61 
62 #define RANDOM_DEVICE       "/dev/random"
63 #define RANDOM_DEVICE_HW    "/dev/hw_random"
64 
65 /* The device (/dev/random) internal limits 4096 bits of entropy, 512 bytes */
66 #define MAX_ENT_POOL_BITS  4096
67 #define MAX_ENT_POOL_BYTES (MAX_ENT_POOL_BITS / 8)
68 
69 #define MAX_ENT_POOL_WRITES 128  		/* write pool with smaller chunks */
70 
71 ///* Burst-mode timeout in us (micro-seconds) */
72 //#define BURST_MODE_TIMEOUT 100000		/* 100ms */
73 ///* Idle-mode wait in us (micro-seconds) */
74 //#define IDLE_MODE_WAIT 10000			/* 10ms */
75 
76 /* Buffer to hold hardware entropy bytes (this must be 2KB for FIPS testing       */
77 #define MAX_BUFFER 2048				/* do not change this value       */
78 static unsigned char databuf[MAX_BUFFER];	/* create buffer for FIPS testing */
79 static unsigned long buffsize;			/* size of data in buffer         */
80 static unsigned long curridx;			/* position of current index      */
81 
82 /* Globals */
83 //static bool read_blocked = FALSE;
84 //static pid_t qrngd_pid;
85 
86 /* User parameters */
87 struct user_options {
88 	char            input_device_name[128];
89 	char            output_device_name[128];
90 	bool            run_as_daemon;
91 };
92 
93 /* Version number of this source */
94 #define APP_VERSION "1.01"
95 #define APP_NAME    "qrngd"
96 
97 const char *program_version =
98 APP_NAME " " APP_VERSION "\n"
99 "Copyright (c) 2011, The Linux Foundation. All rights reserved.\n"
100 "This is free software; see the source for copying conditions.  There is NO\n"
101 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n";
102 
103 const char *program_usage =
104 "Usage: " APP_NAME " [OPTION...]\n"
105 "  -b                 background - become a daemon (default)\n"
106 "  -f                 foreground - do not fork and become a daemon\n"
107 "  -r <device name>   hardware random input device (default: /dev/hw_random)\n"
108 "  -o <device name>   system random output device (default: /dev/random)\n"
109 "  -h                 help (this page)\n";
110 
111 /* Logging information */
112 enum log_level {
113 	DEBUG = 0,
114 	INFO = 1,
115 	WARNING = 2,
116 	ERROR = 3,
117 	FATAL = 4,
118 	LOG_MAX = 4,
119 };
120 
121 /* Logging function for outputing to stderr or log */
log_print(int level,char * format,...)122 void log_print(int level, char *format, ...)
123 {
124 	if (level >= 0 && level <= LOG_MAX) {
125 #ifdef ANDROID_CHANGES
126 		static int levels[5] = {
127 			ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
128 			ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
129 		};
130 		va_list ap;
131 		va_start(ap, format);
132 		__android_log_vprint(levels[level], APP_NAME, format, ap);
133 		va_end(ap);
134 #else
135 		static char *levels = "DIWEF";
136 		va_list ap;
137 		fprintf(stderr, "%c: ", levels[level]);
138 		va_start(ap, format);
139 		vfprintf(stderr, format, ap);
140 		va_end(ap);
141 		fputc('\n', stderr);
142 #endif
143 	}
144 }
145 
title(void)146 static void title(void)
147 {
148 	printf("%s", program_version);
149 }
150 
usage(void)151 static void usage(void)
152 {
153 	printf("%s", program_usage);
154 }
155 
156 /* Parse command line parameters */
get_user_options(struct user_options * user_ops,int argc,char ** argv)157 static int get_user_options(struct user_options *user_ops, int argc, char **argv)
158 {
159 	int max_params = argc;
160 	int itr = 1;			/* skip program name */
161 	while (itr < max_params) {
162 		if (argv[itr][0] != '-')
163 			return -1;
164 
165 		switch (argv[itr++][1]) {
166 			case 'b':
167 				user_ops->run_as_daemon = TRUE;
168 				break;
169 
170 			case 'f':
171 				user_ops->run_as_daemon = FALSE;
172 				break;
173 
174 			case 'r':
175 				if (itr < max_params) {
176 					if (strlen(argv[itr]) < sizeof(user_ops->input_device_name))
177 						strcpy(user_ops->input_device_name, argv[itr++]);
178 					else
179 						return -1;
180 					break;
181 				}
182 				else
183 					return -1;
184 
185 			case 'o':
186 				if (itr < max_params) {
187 					if (strlen(argv[itr]) < sizeof(user_ops->output_device_name))
188 						strcpy(user_ops->output_device_name, argv[itr++]);
189 					else
190 						return -1;
191 					break;
192 				}
193 				else
194 					return -1;
195 
196 			case 'h':
197 				return -1;
198 
199 
200 			default:
201 				fprintf(stderr, "ERROR: Bad option: '%s'\n", argv[itr-1]);
202 				return -1;
203 		}
204 	}
205 	return 0;
206 }
207 
208 /* Only check FIPS 140-2 (Continuous Random Number Generator Test) */
fips_test(const unsigned char * buf,size_t size)209 static int fips_test(const unsigned char *buf, size_t size)
210 {
211 	unsigned long *buff_ul = (unsigned long *) buf;
212 	size_t size_ul = size >> 2;	/* convert byte to word size */
213 	unsigned long last_value;
214 	unsigned int rnd_ctr[256];
215 	int i;
216 
217 
218 	/* Continuous Random Number Generator Test */
219 	last_value = *(buff_ul++);
220 	size_ul--;
221 
222 	while (size_ul > 0) {
223 		if (*buff_ul == last_value) {
224 			log_print(ERROR, "ERROR: Bad word value from hardware.");
225 			return -1;
226 		} else
227 			last_value = *buff_ul;
228 		buff_ul++;
229 		size_ul--;
230 	}
231 
232 	/* count each random number */
233 	for (i = 0; i < size; ++i) {
234 		rnd_ctr[buf[i]]++;
235 	}
236 
237 	/* check random numbers to make sure they are not bogus */
238 	for (i = 0; i < 256; ++i) {
239 		if (rnd_ctr[i] == 0) {
240 			log_print(ERROR, "ERROR: Bad spectral random number sample.");
241 			return -1;
242 		}
243 	}
244 
245 	return 0;
246 }
247 
248 /* Read data from the hardware RNG source */
read_src(int fd,void * buf,size_t size)249 static int read_src(int fd, void *buf, size_t size)
250 {
251 	size_t offset = 0;
252 	char *chr = (char *) buf;
253 	ssize_t ret;
254 
255 	if (!size)
256 		return -1;
257 	do {
258 		ret = read(fd, chr + offset, size);
259 		/* any read failure is bad */
260 		if (ret == -1)
261 			return -1;
262 		size -= ret;
263 		offset += ret;
264 	} while (size > 0);
265 
266 	/* should have read in all of requested data */
267 	if (size > 0)
268 		return -1;
269 	return 0;
270 }
271 
272 /*Hold minimal permissions, so as to get IOCTL working*/
qrng_update_cap()273 static int qrng_update_cap()
274 {
275 	int retvalue = 0;
276 	struct __user_cap_header_struct header;
277 	struct __user_cap_data_struct cap;
278 
279 	memset(&header, 0, sizeof(header));
280 	memset(&cap, 0, sizeof(cap));
281 	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
282 	if( 0 != setgid(AID_SYSTEM)){
283 		fprintf(stderr, "setgid error\n");
284 		return -1;
285 	}
286 	if( 0 != setuid(AID_SYSTEM)){
287 		fprintf(stderr, "setuid error\n");
288 		return -1;
289 	}
290 	header.version = _LINUX_CAPABILITY_VERSION;
291 	header.pid = 0;
292 	cap.effective = (1 << CAP_SYS_ADMIN) | (1 << CAP_NET_RAW);
293 	cap.permitted = cap.effective;
294 	cap.inheritable = 0;
295 	retvalue = capset(&header, &cap);
296 	if(retvalue != 0){
297 		fprintf(stderr, "capset error\n");
298 		return -1;
299 	}
300 	return 0;
301 }
302 
303 /* The beginning of everything */
main(int argc,char ** argv)304 int main(int argc, char **argv)
305 {
306 	struct user_options user_ops;		/* holds user configuration data     */
307 	struct rand_pool_info *rand = NULL;	/* structure to pass entropy (IOCTL) */
308 	int random_fd = 0;			/* output file descriptor            */
309 	int random_hw_fd = 0;			/* input file descriptor             */
310 	int ent_count;				/* current system entropy            */
311 	int write_size;				/* max entropy data to pass          */
312 	struct pollfd fds[1];			/* used for polling file descriptor  */
313 	int ret;
314 	int exitval = 0;
315 
316 	/* set default parameters */
317 	user_ops.run_as_daemon = TRUE;
318 	strcpy(user_ops.input_device_name, RANDOM_DEVICE_HW);
319 	strcpy(user_ops.output_device_name, RANDOM_DEVICE);
320 
321 	/* display application header */
322 	title();
323 
324 	/* get user preferences */
325 	ret = get_user_options(&user_ops, argc, argv);
326 	if (ret < 0) {
327 		usage();
328 		exitval = 1;
329 		goto exit;
330 	}
331 
332 	/* open hardware random device */
333 	random_hw_fd = open(user_ops.input_device_name, O_RDONLY);
334 	if (random_hw_fd < 0) {
335 		fprintf(stderr, "Can't open hardware random device file %s\n", user_ops.input_device_name);
336 		exitval = 1;
337 		goto exit;
338 	}
339 
340 	/*Hold minimal permissions, just enough to get IOCTL working*/
341 	if(0 != qrng_update_cap()){
342 		log_print(ERROR, "qrngd permission reset failed, exiting\n");
343 		exitval = 1;
344 		goto exit;
345 	}
346 
347 	/* open random device */
348 	random_fd = open(user_ops.output_device_name, O_RDWR);
349 	if (random_fd < 0) {
350 		fprintf(stderr, "Can't open random device file %s\n", user_ops.output_device_name);
351 		exitval = 1;
352 		goto exit;
353 	}
354 
355 	/* allocate memory for ioctl data struct and buffer */
356 	rand = malloc(sizeof(struct rand_pool_info) + MAX_ENT_POOL_WRITES);
357 	if (!rand) {
358 		fprintf(stderr, "Can't allocate memory\n");
359 		exitval = 1;
360 		goto exit;
361 	}
362 
363 	/* setup poll() data */
364 	memset(fds, 0 , sizeof(fds));
365 	fds[0].fd = random_fd;
366 	fds[0].events = POLLOUT;
367 
368 	/* run as daemon if requested to do so */
369 	if (user_ops.run_as_daemon) {
370 		fprintf(stderr, "Starting daemon.\n");
371 		if (daemon(0, 0) < 0) {
372 			fprintf(stderr, "can't daemonize: %s\n", strerror(errno));
373 			exitval = 1;
374 			goto exit;
375 		}
376 #ifndef ANDROID_CHANGES
377 		openlog(APP_NAME, 0, LOG_DAEMON);
378 #endif
379 	}
380 
381 	/* log message */
382 	log_print(INFO, APP_NAME " has started:\n" "Reading device:'%s' updating entropy for device:'%s'",
383 		  user_ops.input_device_name,
384 		  user_ops.output_device_name);
385 
386 	/* main loop to get data from hardware and feed RNG entropy pool */
387 	while (1) {
388 
389 		/* Check for empty buffer and fill with hardware random generated numbers */
390 		if (buffsize == 0) {
391 			/* fill buffer with random data from hardware */
392 			ret = read_src(random_hw_fd, databuf, MAX_BUFFER);
393 			if (ret < 0) {
394 				log_print(ERROR, "ERROR: Can't read from hardware source.");
395 				exitval = 1;
396 				goto exit;
397 			}
398 			/* run FIPS test on buffer, if buffer fails then ditch it and get new data */
399 			ret = fips_test(databuf, MAX_BUFFER);
400 			if (ret < 0) {
401 				buffsize = 0;
402 				log_print(INFO, "ERROR: Failed FIPS test.");
403 			}
404 			/* everything good, reset buffer variables to indicate full buffer */
405 			else {
406 				buffsize = MAX_BUFFER;
407 				curridx  = 0;
408 			}
409 		}
410 		/* We should have data here, if not then something bad happened above and we should wait and try again */
411 		if (buffsize == 0) {
412 			log_print(ERROR, "ERROR: Timeout getting valid random data from hardware.");
413 			usleep(100000);	/* 100ms */
414 			continue;
415 		}
416 
417 		/* Get current entropy pool size in bits and convert to bytes */
418 		if (ioctl(random_fd, RNDGETENTCNT, &ent_count) != 0) {
419 			log_print(ERROR, "ERROR: Can't read entropy count.");
420 			exitval = 1;
421 			goto exit;
422 		}
423 		/* convert entropy bits to bytes */
424 		ent_count >>= 3;
425 
426 		/* fill entropy pool */
427 		write_size = min(buffsize, MAX_ENT_POOL_WRITES);
428 
429 		/* Write some data to the device */
430 		rand->entropy_count = write_size * 8;
431 		rand->buf_size      = write_size;
432 		memcpy(rand->buf, &databuf[curridx], write_size);
433 		curridx  += write_size;
434 		buffsize -= write_size;
435 
436 		/* Issue the ioctl to increase the entropy count */
437 		if (ioctl(random_fd, RNDADDENTROPY, rand) < 0) {
438 			log_print(ERROR,"ERROR: RNDADDENTROPY ioctl() failed.");
439 			exitval = 1;
440 			goto exit;
441 		}
442 
443 		/* Wait if entropy pool is full */
444 		ret = poll(fds, 1, -1);
445 		if (ret < 0) {
446 			log_print(ERROR,"ERROR: poll call failed.");
447 			/* wait if error */
448 			usleep(100000);
449 		}
450 	}
451 
452 exit:
453 	/* free other resources */
454 	if (rand)
455 		free(rand);
456 	if (random_fd)
457 		close(random_fd);
458 	if (random_hw_fd)
459 		close(random_hw_fd);
460 	return exitval;
461 }
462 
463