1/* $NetBSD: rand-timer.c,v 1.2 2017/01/28 21:31:47 christos Exp $ */ 2 3/* 4 * Copyright (c) 1995, 1996, 1997, 1999, 2007 Kungliga Tekniska H��gskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <config.h> 37#include <krb5/roken.h> 38 39#include <rand.h> 40 41#include "randi.h" 42 43#ifndef WIN32 /* don't bother with this on windows */ 44 45static volatile int counter; 46static volatile unsigned char *gdata; /* Global data */ 47static volatile int igdata; /* Index into global data */ 48static int gsize; 49 50static 51RETSIGTYPE 52sigALRM(int sig) 53{ 54 if (igdata < gsize) 55 gdata[igdata++] ^= counter & 0xff; 56 57#ifndef HAVE_SIGACTION 58 signal(SIGALRM, sigALRM); /* Reinstall SysV signal handler */ 59#endif 60 SIGRETURN(0); 61} 62 63#ifndef HAVE_SETITIMER 64static void 65pacemaker(struct timeval *tv) 66{ 67 fd_set fds; 68 pid_t pid; 69 pid = getppid(); 70 while(1){ 71 FD_ZERO(&fds); 72 FD_SET(0, &fds); 73 select(1, &fds, NULL, NULL, tv); 74 kill(pid, SIGALRM); 75 } 76} 77#endif 78 79#ifdef HAVE_SIGACTION 80/* XXX ugly hack, should perhaps use function from roken */ 81static RETSIGTYPE 82(*fake_signal(int sig, RETSIGTYPE (*f)(int)))(int) 83{ 84 struct sigaction sa, osa; 85 sa.sa_handler = f; 86 sa.sa_flags = 0; 87 sigemptyset(&sa.sa_mask); 88 sigaction(sig, &sa, &osa); 89 return osa.sa_handler; 90} 91#define signal(S, F) fake_signal((S), (F)) 92#endif 93 94#endif /* WIN32*/ 95 96/* 97 * 98 */ 99 100static void 101timer_seed(const void *indata, int size) 102{ 103} 104 105static int 106timer_bytes(unsigned char *outdata, int size) 107{ 108#ifdef WIN32 109 return 0; 110#else /* WIN32 */ 111 struct itimerval tv, otv; 112 RETSIGTYPE (*osa)(int); 113 int i, j; 114#ifndef HAVE_SETITIMER 115 RETSIGTYPE (*ochld)(int); 116 pid_t pid; 117#endif 118 119 gdata = outdata; 120 gsize = size; 121 igdata = 0; 122 123 osa = signal(SIGALRM, sigALRM); 124 125 /* Start timer */ 126 tv.it_value.tv_sec = 0; 127 tv.it_value.tv_usec = 10 * 1000; /* 10 ms */ 128 tv.it_interval = tv.it_value; 129#ifdef HAVE_SETITIMER 130 setitimer(ITIMER_REAL, &tv, &otv); 131#else 132 ochld = signal(SIGCHLD, SIG_IGN); 133 pid = fork(); 134 if(pid == -1){ 135 signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL); 136 des_not_rand_data(data, size); 137 return; 138 } 139 if(pid == 0) 140 pacemaker(&tv.it_interval); 141#endif 142 143 for(i = 0; i < 4; i++) { 144 for (igdata = 0; igdata < size;) /* igdata++ in sigALRM */ 145 counter++; 146 for (j = 0; j < size; j++) /* Only use 2 bits each lap */ 147 gdata[j] = (gdata[j]>>2) | (gdata[j]<<6); 148 } 149#ifdef HAVE_SETITIMER 150 setitimer(ITIMER_REAL, &otv, 0); 151#else 152 kill(pid, SIGKILL); 153 while(waitpid(pid, NULL, 0) != pid); 154 signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL); 155#endif 156 signal(SIGALRM, osa != SIG_ERR ? osa : SIG_DFL); 157 158 return 1; 159#endif 160} 161 162static void 163timer_cleanup(void) 164{ 165} 166 167static void 168timer_add(const void *indata, int size, double entropi) 169{ 170} 171 172static int 173timer_pseudorand(unsigned char *outdata, int size) 174{ 175 return timer_bytes(outdata, size); 176} 177 178static int 179timer_status(void) 180{ 181#ifdef WIN32 182 return 0; 183#else 184 return 1; 185#endif 186} 187 188#if defined(__GNUC__) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) 189const RAND_METHOD hc_rand_timer_method = { 190 .seed = timer_seed, 191 .bytes = timer_bytes, 192 .cleanup = timer_cleanup, 193 .add = timer_add, 194 .pseudorand = timer_pseudorand, 195 .status = timer_status 196}; 197#else 198const RAND_METHOD hc_rand_timer_method = { 199 timer_seed, 200 timer_bytes, 201 timer_cleanup, 202 timer_add, 203 timer_pseudorand, 204 timer_status 205}; 206#endif 207 208const RAND_METHOD * 209RAND_timer_method(void) 210{ 211 return &hc_rand_timer_method; 212} 213