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