tests: Allow use of random.c under Windows.
[libgcrypt.git] / tests / random.c
1 /* random.c - part of the Libgcrypt test suite.
2    Copyright (C) 2005 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17    USA.  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 #include <assert.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #ifndef HAVE_W32_SYSTEM
28 # include <signal.h>
29 # include <unistd.h>
30 # include <sys/wait.h>
31 #endif
32
33 #include "../src/gcrypt.h"
34
35 static int verbose;
36
37 static void
38 die (const char *format, ...)
39 {
40   va_list arg_ptr;
41
42   va_start (arg_ptr, format);
43   vfprintf (stderr, format, arg_ptr);
44   va_end (arg_ptr);
45   exit (1);
46 }
47
48
49 static void
50 inf (const char *format, ...)
51 {
52   va_list arg_ptr;
53
54   va_start (arg_ptr, format);
55   vfprintf (stderr, format, arg_ptr);
56   va_end (arg_ptr);
57 }
58
59
60 static void
61 print_hex (const char *text, const void *buf, size_t n)
62 {
63   const unsigned char *p = buf;
64
65   fputs (text, stdout);
66   for (; n; n--, p++)
67     printf ("%02X", *p);
68   putchar ('\n');
69 }
70
71
72 static int
73 writen (int fd, const void *buf, size_t nbytes)
74 {
75   size_t nleft = nbytes;
76   int nwritten;
77
78   while (nleft > 0)
79     {
80       nwritten = write (fd, buf, nleft);
81       if (nwritten < 0)
82         {
83           if (errno == EINTR)
84             nwritten = 0;
85           else
86             return -1;
87         }
88       nleft -= nwritten;
89       buf = (const char*)buf + nwritten;
90     }
91
92   return 0;
93 }
94
95 static int
96 readn (int fd, void *buf, size_t buflen, size_t *ret_nread)
97 {
98   size_t nleft = buflen;
99   int nread;
100
101   while ( nleft > 0 )
102     {
103       nread = read ( fd, buf, nleft );
104       if (nread < 0)
105         {
106           if (nread == EINTR)
107             nread = 0;
108           else
109             return -1;
110         }
111       else if (!nread)
112         break; /* EOF */
113       nleft -= nread;
114       buf = (char*)buf + nread;
115     }
116   if (ret_nread)
117     *ret_nread = buflen - nleft;
118   return 0;
119 }
120
121
122
123 /* Check that forking won't return the same random. */
124 static void
125 check_forking (void)
126 {
127 #ifdef HAVE_W32_SYSTEM
128   if (verbose)
129     inf ("check_forking skipped: not applicable on Windows\n");
130 #else /*!HAVE_W32_SYSTEM*/
131   pid_t pid;
132   int rp[2];
133   int i, status;
134   size_t nread;
135   char tmp1[16], tmp1c[16], tmp1p[16];
136
137   if (verbose)
138     inf ("checking that a fork won't cause the same random output\n");
139
140   /* We better make sure that the RNG has been initialzied. */
141   gcry_randomize (tmp1, sizeof tmp1, GCRY_STRONG_RANDOM);
142   if (verbose)
143     print_hex ("initial random: ", tmp1, sizeof tmp1);
144
145   if (pipe (rp) == -1)
146     die ("pipe failed: %s\n", strerror (errno));
147
148   pid = fork ();
149   if (pid == (pid_t)(-1))
150     die ("fork failed: %s\n", strerror (errno));
151   if (!pid)
152     {
153       gcry_randomize (tmp1c, sizeof tmp1c, GCRY_STRONG_RANDOM);
154       if (writen (rp[1], tmp1c, sizeof tmp1c))
155         die ("write failed: %s\n", strerror (errno));
156       if (verbose)
157         {
158           print_hex ("  child random: ", tmp1c, sizeof tmp1c);
159           fflush (stdout);
160         }
161       _exit (0);
162     }
163   gcry_randomize (tmp1p, sizeof tmp1p, GCRY_STRONG_RANDOM);
164   if (verbose)
165     print_hex (" parent random: ", tmp1p, sizeof tmp1p);
166
167   close (rp[1]);
168   if (readn (rp[0], tmp1c, sizeof tmp1c, &nread))
169     die ("read failed: %s\n", strerror (errno));
170   if (nread != sizeof tmp1c)
171     die ("read too short\n");
172
173   while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
174     ;
175   if (i != (pid_t)(-1)
176       && WIFEXITED (status) && !WEXITSTATUS (status))
177     ;
178   else
179     die ("child failed\n");
180
181   if (!memcmp (tmp1p, tmp1c, sizeof tmp1c))
182     die ("parent and child got the same random number\n");
183 #endif  /*!HAVE_W32_SYSTEM*/
184 }
185
186
187
188 /* Check that forking won't return the same nonce. */
189 static void
190 check_nonce_forking (void)
191 {
192 #ifdef HAVE_W32_SYSTEM
193   if (verbose)
194     inf ("check_nonce_forking skipped: not applicable on Windows\n");
195 #else /*!HAVE_W32_SYSTEM*/
196   pid_t pid;
197   int rp[2];
198   int i, status;
199   size_t nread;
200   char nonce1[10], nonce1c[10], nonce1p[10];
201
202   if (verbose)
203     inf ("checking that a fork won't cause the same nonce output\n");
204
205   /* We won't get the same nonce back if we never initialized the
206      nonce subsystem, thus we get one nonce here and forget about
207      it. */
208   gcry_create_nonce (nonce1, sizeof nonce1);
209   if (verbose)
210     print_hex ("initial nonce: ", nonce1, sizeof nonce1);
211
212   if (pipe (rp) == -1)
213     die ("pipe failed: %s\n", strerror (errno));
214
215   pid = fork ();
216   if (pid == (pid_t)(-1))
217     die ("fork failed: %s\n", strerror (errno));
218   if (!pid)
219     {
220       gcry_create_nonce (nonce1c, sizeof nonce1c);
221       if (writen (rp[1], nonce1c, sizeof nonce1c))
222         die ("write failed: %s\n", strerror (errno));
223       if (verbose)
224         {
225           print_hex ("  child nonce: ", nonce1c, sizeof nonce1c);
226           fflush (stdout);
227         }
228       _exit (0);
229     }
230   gcry_create_nonce (nonce1p, sizeof nonce1p);
231   if (verbose)
232     print_hex (" parent nonce: ", nonce1p, sizeof nonce1p);
233
234   close (rp[1]);
235   if (readn (rp[0], nonce1c, sizeof nonce1c, &nread))
236     die ("read failed: %s\n", strerror (errno));
237   if (nread != sizeof nonce1c)
238     die ("read too short\n");
239
240   while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
241     ;
242   if (i != (pid_t)(-1)
243       && WIFEXITED (status) && !WEXITSTATUS (status))
244     ;
245   else
246     die ("child failed\n");
247
248   if (!memcmp (nonce1p, nonce1c, sizeof nonce1c))
249     die ("parent and child got the same nonce\n");
250 #endif  /*!HAVE_W32_SYSTEM*/
251 }
252
253
254
255
256
257
258 int
259 main (int argc, char **argv)
260 {
261   int debug = 0;
262
263   if ((argc > 1) && (! strcmp (argv[1], "--verbose")))
264     verbose = 1;
265   else if ((argc > 1) && (! strcmp (argv[1], "--debug")))
266     verbose = debug = 1;
267
268 #ifndef HAVE_W32_SYSTEM
269   signal (SIGPIPE, SIG_IGN);
270 #endif
271
272   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
273   if (!gcry_check_version (GCRYPT_VERSION))
274     die ("version mismatch\n");
275
276   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
277   if (debug)
278     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
279
280   check_forking ();
281   check_nonce_forking ();
282
283   return 0;
284 }