xref: /minix3/crypto/external/bsd/heimdal/dist/lib/hcrypto/rand-timer.c (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1 /*	$NetBSD: rand-timer.c,v 1.1.1.1 2011/04/13 18:14:50 elric 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 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <rand.h>
41 
42 #include <krb5/roken.h>
43 
44 #include "randi.h"
45 
46 #ifndef WIN32 /* don't bother with this on windows */
47 
48 static volatile int counter;
49 static volatile unsigned char *gdata; /* Global data */
50 static volatile int igdata;	/* Index into global data */
51 static int gsize;
52 
53 static
54 RETSIGTYPE
sigALRM(int sig)55 sigALRM(int sig)
56 {
57     if (igdata < gsize)
58 	gdata[igdata++] ^= counter & 0xff;
59 
60 #ifndef HAVE_SIGACTION
61     signal(SIGALRM, sigALRM); /* Reinstall SysV signal handler */
62 #endif
63     SIGRETURN(0);
64 }
65 
66 #ifndef HAVE_SETITIMER
67 static void
pacemaker(struct timeval * tv)68 pacemaker(struct timeval *tv)
69 {
70     fd_set fds;
71     pid_t pid;
72     pid = getppid();
73     while(1){
74 	FD_ZERO(&fds);
75 	FD_SET(0, &fds);
76 	select(1, &fds, NULL, NULL, tv);
77 	kill(pid, SIGALRM);
78     }
79 }
80 #endif
81 
82 #ifdef HAVE_SIGACTION
83 /* XXX ugly hack, should perhaps use function from roken */
84 static RETSIGTYPE
fake_signal(int sig,RETSIGTYPE (* f)(int))85 (*fake_signal(int sig, RETSIGTYPE (*f)(int)))(int)
86 {
87     struct sigaction sa, osa;
88     sa.sa_handler = f;
89     sa.sa_flags = 0;
90     sigemptyset(&sa.sa_mask);
91     sigaction(sig, &sa, &osa);
92     return osa.sa_handler;
93 }
94 #define signal(S, F) fake_signal((S), (F))
95 #endif
96 
97 #endif /* WIN32*/
98 
99 /*
100  *
101  */
102 
103 static void
timer_seed(const void * indata,int size)104 timer_seed(const void *indata, int size)
105 {
106 }
107 
108 static int
timer_bytes(unsigned char * outdata,int size)109 timer_bytes(unsigned char *outdata, int size)
110 {
111 #ifdef WIN32
112     return 0;
113 #else /* WIN32 */
114     struct itimerval tv, otv;
115     RETSIGTYPE (*osa)(int);
116     int i, j;
117 #ifndef HAVE_SETITIMER
118     RETSIGTYPE (*ochld)(int);
119     pid_t pid;
120 #endif
121 
122     gdata = outdata;
123     gsize = size;
124     igdata = 0;
125 
126     osa = signal(SIGALRM, sigALRM);
127 
128     /* Start timer */
129     tv.it_value.tv_sec = 0;
130     tv.it_value.tv_usec = 10 * 1000; /* 10 ms */
131     tv.it_interval = tv.it_value;
132 #ifdef HAVE_SETITIMER
133     setitimer(ITIMER_REAL, &tv, &otv);
134 #else
135     ochld = signal(SIGCHLD, SIG_IGN);
136     pid = fork();
137     if(pid == -1){
138 	signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL);
139 	des_not_rand_data(data, size);
140 	return;
141     }
142     if(pid == 0)
143 	pacemaker(&tv.it_interval);
144 #endif
145 
146     for(i = 0; i < 4; i++) {
147 	for (igdata = 0; igdata < size;) /* igdata++ in sigALRM */
148 	    counter++;
149 	for (j = 0; j < size; j++) /* Only use 2 bits each lap */
150 	    gdata[j] = (gdata[j]>>2) | (gdata[j]<<6);
151     }
152 #ifdef HAVE_SETITIMER
153     setitimer(ITIMER_REAL, &otv, 0);
154 #else
155     kill(pid, SIGKILL);
156     while(waitpid(pid, NULL, 0) != pid);
157     signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL);
158 #endif
159     signal(SIGALRM, osa != SIG_ERR ? osa : SIG_DFL);
160 
161     return 1;
162 #endif
163 }
164 
165 static void
timer_cleanup(void)166 timer_cleanup(void)
167 {
168 }
169 
170 static void
timer_add(const void * indata,int size,double entropi)171 timer_add(const void *indata, int size, double entropi)
172 {
173 }
174 
175 static int
timer_pseudorand(unsigned char * outdata,int size)176 timer_pseudorand(unsigned char *outdata, int size)
177 {
178     return timer_bytes(outdata, size);
179 }
180 
181 static int
timer_status(void)182 timer_status(void)
183 {
184 #ifdef WIN32
185     return 0;
186 #else
187     return 1;
188 #endif
189 }
190 
191 const RAND_METHOD hc_rand_timer_method = {
192     timer_seed,
193     timer_bytes,
194     timer_cleanup,
195     timer_add,
196     timer_pseudorand,
197     timer_status
198 };
199 
200 const RAND_METHOD *
RAND_timer_method(void)201 RAND_timer_method(void)
202 {
203     return &hc_rand_timer_method;
204 }
205