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