random.c (4009B)
1 /* Mixmaster version 3.0 -- (C) 1999 - 2006 Anonymizer Inc. and others. 2 3 Mixmaster may be redistributed and modified under certain conditions. 4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 5 ANY KIND, either express or implied. See the file COPYRIGHT for 6 details. 7 8 Randomness 9 $Id: random.c 934 2006-06-24 13:40:39Z rabbi $ */ 10 11 12 #include "mix3.h" 13 #include "crypto.h" 14 #include <fcntl.h> 15 #ifdef POSIX 16 #include <sys/time.h> 17 #include <unistd.h> 18 #else /* end of POSIX */ 19 #include <io.h> 20 #include <process.h> 21 #endif /* else if not POSIX */ 22 #ifdef WIN32 23 #include <windows.h> 24 #endif /* WIN32 */ 25 #include <assert.h> 26 #include <string.h> 27 28 int rnd_state = RND_NOTSEEDED; 29 30 #ifdef USE_OPENSSL 31 int rnd_init(void) 32 { 33 char r[PATHMAX]; 34 int n; 35 LOCK *rndlock; 36 37 if (rnd_state == RND_SEEDED) 38 return(0); 39 rndlock = lockfile(MIXRAND); 40 mixfile(r, MIXRAND); 41 n = RAND_load_file(r, 1024); 42 if (n < 256 && rnd_seed() == -1) 43 goto err; 44 rnd_time(); 45 RAND_write_file(r); 46 rnd_state = RND_SEEDED; 47 err: 48 unlockfile(rndlock); 49 return (rnd_state == RND_SEEDED ? 0 : -1); 50 } 51 52 int rnd_final(void) 53 { 54 int err = 0; 55 char r[PATHMAX]; 56 LOCK *rndlock; 57 58 if (rnd_state != RND_SEEDED) 59 return(-1); 60 61 rnd_update(NULL, 0); 62 rndlock = lockfile(MIXRAND); 63 mixfile(r, MIXRAND); 64 RAND_load_file(r, 1024); /* add seed file again in case other instances 65 of the program have used it */ 66 if (RAND_write_file(r) < 1) 67 err = -1; 68 unlockfile(rndlock); 69 RAND_cleanup(); 70 return (err); 71 } 72 73 int rnd_add(byte *b, int l) 74 { 75 RAND_seed(b, l); 76 return (0); 77 } 78 #endif /* USE_OPENSSL */ 79 80 void rnd_time(void) 81 { 82 int pid; 83 84 #ifdef WIN32 85 SYSTEMTIME t; 86 #endif /* WIN32 */ 87 88 #ifdef HAVE_GETTIMEOFDAY 89 struct timeval tv; 90 91 gettimeofday(&tv, 0); 92 rnd_add((byte *) &tv, sizeof(tv)); 93 #elif defined(WIN32) /* end of HAVE_GETTIMEOFDAY */ 94 GetSystemTime(&t); 95 rnd_add((byte *) &t, sizeof(t)); 96 #else /* end of defined(WIN32) */ 97 rnd_add((byte *) time(NULL), sizeof(time_t)); 98 #endif /* else if not defined(WIN32), HAVE_GETTIMEOFDAY */ 99 pid = getpid(); 100 rnd_add((byte *) &pid, sizeof(pid)); 101 } 102 103 void rnd_update(byte *seed, int l) 104 { 105 int fd = -1; 106 byte b[512]; 107 108 rnd_time(); 109 if (seed) 110 rnd_add(seed, l); 111 #ifdef DEV_URANDOM 112 fd = open(DEV_URANDOM, O_RDONLY); 113 if (fd != -1) { 114 ssize_t ret; 115 116 ret = read(fd, b, sizeof(b)); 117 if (ret > 0) { 118 rnd_add(b, ret); 119 } 120 close(fd); 121 } 122 #endif /* DEV_URANDOM */ 123 } 124 125 int rnd_bytes(byte *b, int n) 126 { 127 /* we frequently need to get small amounts of random data. 128 speed up by pre-generating dating data */ 129 130 static byte rand[BUFSIZE]; 131 static int idx = BUFSIZE; 132 133 if (rnd_state != RND_SEEDED) 134 rnd_error(); 135 136 if (n + idx < BUFSIZE) { 137 memcpy(b, rand + idx, n); 138 idx += n; 139 } else 140 RAND_bytes(b, n); 141 142 if (idx + 256 > BUFSIZE) { 143 RAND_bytes(rand, BUFSIZE); 144 idx = 0; 145 } 146 return (0); 147 } 148 149 int rnd_number(int n) 150 { 151 int r; 152 153 assert(n > 0); 154 if (n > 65535) 155 do 156 r = rnd_byte() * 65536 + 157 rnd_byte() * 256 + rnd_byte(); 158 while (r >= n); 159 else if (n > 255) 160 do 161 r = rnd_byte() * 256 + rnd_byte(); 162 while (r >= n); 163 else 164 do 165 r = rnd_byte(); 166 while (r >= n); 167 return r; 168 } 169 170 byte rnd_byte() 171 { 172 byte b; 173 174 rnd_bytes(&b, 1); 175 return b; 176 } 177 178 void rnd_initialized(void) 179 { 180 rnd_state = RND_SEEDED; 181 } 182 183 #ifdef WIN32 184 185 #define NEEDED 256 186 187 int rnd_mouse(UINT i, WPARAM w, LPARAM l) 188 { 189 static int entropy = 0; 190 static int x, y, dx, dy; 191 int newx, newy, newdx, newdy; 192 int rnd[4]; 193 194 if (i == WM_MOUSEMOVE) { 195 newx = LOWORD(l); 196 newy = HIWORD(l); 197 newdx = x - newx; 198 newdy = y - newy; 199 if (dx != 0 && dy != 0 && dx - newdx != 0 && dy - newdy != 0) { 200 entropy++; 201 if (entropy >= NEEDED) 202 rnd_state = RND_SEEDED; 203 } 204 x = newx, y = newy, dx = newdx, dy = newdy; 205 rnd[0] = x; rnd[1] = y; rnd[2] = dx; rnd[3] = dy; 206 rnd_update((byte*)rnd, 4 * sizeof(int)); 207 } 208 return (rnd_state == RND_SEEDED ? 100 : entropy * 100 / NEEDED); 209 } 210 #endif /* WIN32 */