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#include <signal.h> 28#include <unistd.h> 29#include <sys/wait.h> 30 31#include "../src/gcrypt.h" 32 33static int verbose; 34 35static void 36die (const char *format, ...) 37{ 38 va_list arg_ptr; 39 40 va_start (arg_ptr, format); 41 vfprintf (stderr, format, arg_ptr); 42 va_end (arg_ptr); 43 exit (1); 44} 45 46 47static void 48print_hex (const char *text, const void *buf, size_t n) 49{ 50 const unsigned char *p = buf; 51 52 fputs (text, stdout); 53 for (; n; n--, p++) 54 printf ("%02X", *p); 55 putchar ('\n'); 56} 57 58 59static int 60writen (int fd, const void *buf, size_t nbytes) 61{ 62 size_t nleft = nbytes; 63 int nwritten; 64 65 while (nleft > 0) 66 { 67 nwritten = write (fd, buf, nleft); 68 if (nwritten < 0) 69 { 70 if (errno == EINTR) 71 nwritten = 0; 72 else 73 return -1; 74 } 75 nleft -= nwritten; 76 buf = (const char*)buf + nwritten; 77 } 78 79 return 0; 80} 81 82static int 83readn (int fd, void *buf, size_t buflen, size_t *ret_nread) 84{ 85 size_t nleft = buflen; 86 int nread; 87 88 while ( nleft > 0 ) 89 { 90 nread = read ( fd, buf, nleft ); 91 if (nread < 0) 92 { 93 if (nread == EINTR) 94 nread = 0; 95 else 96 return -1; 97 } 98 else if (!nread) 99 break; /* EOF */ 100 nleft -= nread; 101 buf = (char*)buf + nread; 102 } 103 if (ret_nread) 104 *ret_nread = buflen - nleft; 105 return 0; 106} 107 108 109 110/* Check that forking won't return the same random. */ 111static void 112check_forking (void) 113{ 114 pid_t pid; 115 int rp[2]; 116 int i, status; 117 size_t nread; 118 char tmp1[16], tmp1c[16], tmp1p[16]; 119 120 /* We better make sure that the RNG has been initialzied. */ 121 gcry_randomize (tmp1, sizeof tmp1, GCRY_STRONG_RANDOM); 122 if (verbose) 123 print_hex ("initial random: ", tmp1, sizeof tmp1); 124 125 if (pipe (rp) == -1) 126 die ("pipe failed: %s\n", strerror (errno)); 127 128 pid = fork (); 129 if (pid == (pid_t)(-1)) 130 die ("fork failed: %s\n", strerror (errno)); 131 if (!pid) 132 { 133 gcry_randomize (tmp1c, sizeof tmp1c, GCRY_STRONG_RANDOM); 134 if (writen (rp[1], tmp1c, sizeof tmp1c)) 135 die ("write failed: %s\n", strerror (errno)); 136 if (verbose) 137 { 138 print_hex (" child random: ", tmp1c, sizeof tmp1c); 139 fflush (stdout); 140 } 141 _exit (0); 142 } 143 gcry_randomize (tmp1p, sizeof tmp1p, GCRY_STRONG_RANDOM); 144 if (verbose) 145 print_hex (" parent random: ", tmp1p, sizeof tmp1p); 146 147 close (rp[1]); 148 if (readn (rp[0], tmp1c, sizeof tmp1c, &nread)) 149 die ("read failed: %s\n", strerror (errno)); 150 if (nread != sizeof tmp1c) 151 die ("read too short\n"); 152 153 while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) 154 ; 155 if (i != (pid_t)(-1) 156 && WIFEXITED (status) && !WEXITSTATUS (status)) 157 ; 158 else 159 die ("child failed\n"); 160 161 if (!memcmp (tmp1p, tmp1c, sizeof tmp1c)) 162 die ("parent and child got the same random number\n"); 163} 164 165 166 167/* Check that forking won't return the same nonce. */ 168static void 169check_nonce_forking (void) 170{ 171 pid_t pid; 172 int rp[2]; 173 int i, status; 174 size_t nread; 175 char nonce1[10], nonce1c[10], nonce1p[10]; 176 177 /* We won't get the same nonce back if we never initialized the 178 nonce subsystem, thus we get one nonce here and forget about 179 it. */ 180 gcry_create_nonce (nonce1, sizeof nonce1); 181 if (verbose) 182 print_hex ("initial nonce: ", nonce1, sizeof nonce1); 183 184 if (pipe (rp) == -1) 185 die ("pipe failed: %s\n", strerror (errno)); 186 187 pid = fork (); 188 if (pid == (pid_t)(-1)) 189 die ("fork failed: %s\n", strerror (errno)); 190 if (!pid) 191 { 192 gcry_create_nonce (nonce1c, sizeof nonce1c); 193 if (writen (rp[1], nonce1c, sizeof nonce1c)) 194 die ("write failed: %s\n", strerror (errno)); 195 if (verbose) 196 { 197 print_hex (" child nonce: ", nonce1c, sizeof nonce1c); 198 fflush (stdout); 199 } 200 _exit (0); 201 } 202 gcry_create_nonce (nonce1p, sizeof nonce1p); 203 if (verbose) 204 print_hex (" parent nonce: ", nonce1p, sizeof nonce1p); 205 206 close (rp[1]); 207 if (readn (rp[0], nonce1c, sizeof nonce1c, &nread)) 208 die ("read failed: %s\n", strerror (errno)); 209 if (nread != sizeof nonce1c) 210 die ("read too short\n"); 211 212 while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) 213 ; 214 if (i != (pid_t)(-1) 215 && WIFEXITED (status) && !WEXITSTATUS (status)) 216 ; 217 else 218 die ("child failed\n"); 219 220 if (!memcmp (nonce1p, nonce1c, sizeof nonce1c)) 221 die ("parent and child got the same nonce\n"); 222} 223 224 225 226 227 228 229int 230main (int argc, char **argv) 231{ 232 int debug = 0; 233 234 if ((argc > 1) && (! strcmp (argv[1], "--verbose"))) 235 verbose = 1; 236 else if ((argc > 1) && (! strcmp (argv[1], "--debug"))) 237 verbose = debug = 1; 238 239 signal (SIGPIPE, SIG_IGN); 240 241 gcry_control (GCRYCTL_DISABLE_SECMEM, 0); 242 if (!gcry_check_version (GCRYPT_VERSION)) 243 die ("version mismatch\n"); 244 245 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); 246 if (debug) 247 gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); 248 249 check_forking (); 250 check_nonce_forking (); 251 252 return 0; 253} 254