Home | History | Annotate | Download | only in qrngd
      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 */
    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 
    146 static void title(void)
    147 {
    148 	printf("%s", program_version);
    149 }
    150 
    151 static void usage(void)
    152 {
    153 	printf("%s", program_usage);
    154 }
    155 
    156 /* Parse command line parameters */
    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) */
    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 */
    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*/
    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 */
    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