00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "copyright.h"
00012 #include "autoconf.h"
00013 #include "config.h"
00014 #include "externs.h"
00015
00016 #include "timeutil.h"
00017
00018 #include "svdhash.h"
00019 #include "svdrand.h"
00020
00021 #ifdef WIN32
00022 #include <wincrypt.h>
00023 typedef BOOL WINAPI FCRYPTACQUIRECONTEXT(HCRYPTPROV *, LPCTSTR, LPCTSTR, DWORD, DWORD);
00024 typedef BOOL WINAPI FCRYPTRELEASECONTEXT(HCRYPTPROV, DWORD);
00025 typedef BOOL WINAPI FCRYPTGENRANDOM(HCRYPTPROV, DWORD, BYTE *);
00026 #else // WIN32
00027 #include <sys/stat.h>
00028 #include <sys/types.h>
00029 #include <fcntl.h>
00030 #include <unistd.h>
00031 #endif // WIN32
00032
00033
00034
00035 static void sgenrand(UINT32);
00036 static void sgenrand_from_array(UINT32 *, int);
00037
00038
00039
00040 static UINT32 genrand(void);
00041
00042 #define NUM_RANDOM_UINT32 1024
00043
00044 bool bCryptoAPI = false;
00045 static bool bSeeded = false;
00046 void SeedRandomNumberGenerator(void)
00047 {
00048 if (bSeeded) return;
00049 bSeeded = true;
00050
00051 UINT32 aRandomSystemBytes[NUM_RANDOM_UINT32];
00052 unsigned int nRandomSystemBytes = 0;
00053
00054 #ifdef HAVE_DEV_URANDOM
00055
00056
00057
00058 int fd = open("/dev/urandom", O_RDONLY);
00059
00060 if (fd >= 0)
00061 {
00062 int len = read(fd, aRandomSystemBytes, sizeof aRandomSystemBytes);
00063 close(fd);
00064 if (len > 0)
00065 {
00066 nRandomSystemBytes = len/sizeof(UINT32);
00067 }
00068 }
00069 #endif // HAVE_DEV_URANDOM
00070 #ifdef WIN32
00071
00072
00073
00074
00075 bCryptoAPI = false;
00076 HINSTANCE hAdvAPI32 = LoadLibrary("advapi32");
00077 if (hAdvAPI32)
00078 {
00079 FCRYPTACQUIRECONTEXT *fpCryptAcquireContext;
00080 FCRYPTRELEASECONTEXT *fpCryptReleaseContext;
00081 FCRYPTGENRANDOM *fpCryptGenRandom;
00082
00083
00084
00085
00086 fpCryptAcquireContext = (FCRYPTACQUIRECONTEXT *)
00087 GetProcAddress(hAdvAPI32, "CryptAcquireContextA");
00088 fpCryptReleaseContext = (FCRYPTRELEASECONTEXT *)
00089 GetProcAddress(hAdvAPI32, "CryptReleaseContext");
00090 fpCryptGenRandom = (FCRYPTGENRANDOM *)
00091 GetProcAddress(hAdvAPI32, "CryptGenRandom");
00092
00093 if ( fpCryptAcquireContext
00094 && fpCryptReleaseContext
00095 && fpCryptGenRandom)
00096 {
00097 HCRYPTPROV hProv;
00098
00099 if ( fpCryptAcquireContext(&hProv, NULL, NULL, PROV_DSS, 0)
00100 || fpCryptAcquireContext(&hProv, NULL, NULL, PROV_DSS, CRYPT_NEWKEYSET))
00101 {
00102 if (fpCryptGenRandom(hProv, sizeof aRandomSystemBytes,
00103 (BYTE *)aRandomSystemBytes))
00104 {
00105 nRandomSystemBytes = NUM_RANDOM_UINT32;
00106 bCryptoAPI = true;
00107 }
00108 fpCryptReleaseContext(hProv, 0);
00109 }
00110 }
00111 FreeLibrary(hAdvAPI32);
00112 }
00113 #endif // WIN32
00114
00115 if (nRandomSystemBytes >= sizeof(UINT32))
00116 {
00117 unsigned int i;
00118 for (i = 0; i < nRandomSystemBytes; i++)
00119 {
00120 aRandomSystemBytes[i] &= 0xFFFFFFFFUL;
00121 }
00122 sgenrand_from_array(aRandomSystemBytes, nRandomSystemBytes);
00123 return;
00124 }
00125
00126
00127
00128 CLinearTimeAbsolute lsaNow;
00129 lsaNow.GetUTC();
00130 INT64 i64Seed = lsaNow.Return100ns();
00131 int pid = getpid();
00132
00133 UINT32 nSeed = CRC32_ProcessBuffer(0, &i64Seed, sizeof(INT64));
00134 nSeed = CRC32_ProcessBuffer(nSeed, &pid, sizeof(pid));
00135
00136 if (nSeed <= 1000)
00137 {
00138 nSeed += 22261048;
00139 }
00140
00141
00142
00143 sgenrand(nSeed);
00144 }
00145
00146
00147
00148 INT32 RandomINT32(INT32 lLow, INT32 lHigh)
00149 {
00150
00151
00152 if (lHigh < lLow)
00153 {
00154 return -1;
00155 }
00156 else if (lHigh == lLow)
00157 {
00158 return lLow;
00159 }
00160
00161 UINT32 x = lHigh-lLow;
00162 if (INT32_MAX_VALUE < x)
00163 {
00164 return -1;
00165 }
00166 x++;
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 UINT32 n;
00185 UINT32 nLimit = UINT32_MAX_VALUE - (UINT32_MAX_VALUE%x);
00186
00187 do
00188 {
00189 n = genrand();
00190 } while (n >= nLimit);
00191
00192 return lLow + (n % x);
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 #define N 624
00214 #define M 397
00215 #define MATRIX_A 0x9908b0dfUL
00216 #define UMASK 0x80000000UL // most significant w-r bits
00217 #define LMASK 0x7fffffffUL // least significant r bits
00218 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
00219 #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
00220
00221 static UINT32 mt[N];
00222 static int left = 1;
00223 static UINT32 *next;
00224
00225
00226
00227 static void sgenrand(UINT32 nSeed)
00228 {
00229 int j;
00230 mt[0] = nSeed & 0xffffffffUL;
00231 for (j = 1; j < N; j++)
00232 {
00233
00234
00235
00236
00237
00238 mt[j] = 1812433253UL * (mt[j-1] ^ (mt[j-1] >> 30)) + j;
00239 mt[j] &= 0xffffffffUL;
00240 }
00241 left = 1;
00242 }
00243
00244
00245
00246
00247
00248 static void sgenrand_from_array(UINT32 *init_key, int key_length)
00249 {
00250 sgenrand(19650218UL);
00251 int i = 1;
00252 int j = 0;
00253 int k = (N > key_length ? N : key_length);
00254 for (; k; k--)
00255 {
00256 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
00257 + init_key[j] + j;
00258 mt[i] &= 0xffffffffUL;
00259 i++;
00260 j++;
00261 if (i >= N)
00262 {
00263 mt[0] = mt[N-1];
00264 i = 1;
00265 }
00266 if (j >= key_length)
00267 {
00268 j = 0;
00269 }
00270 }
00271 for (k = N-1; k; k--)
00272 {
00273 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - i;
00274 mt[i] &= 0xffffffffUL;
00275 i++;
00276 if (i >= N)
00277 {
00278 mt[0] = mt[N-1];
00279 i = 1;
00280 }
00281 }
00282
00283 mt[0] = 0x80000000UL;
00284 left = 1;
00285 }
00286
00287 static void next_state(void)
00288 {
00289 UINT32 *p = mt;
00290 int j;
00291
00292 if (!bSeeded)
00293 {
00294 SeedRandomNumberGenerator();
00295 }
00296
00297 for (j = N-M+1; --j; p++)
00298 {
00299 *p = p[M] ^ TWIST(p[0], p[1]);
00300 }
00301
00302 for (j = M; --j; p++)
00303 {
00304 *p = p[M-N] ^ TWIST(p[0], p[1]);
00305 }
00306
00307 *p = p[M-N] ^ TWIST(p[0], mt[0]);
00308
00309 left = N;
00310 next = mt;
00311 }
00312
00313
00314
00315 static UINT32 genrand(void)
00316 {
00317 UINT32 y;
00318
00319 if (--left == 0)
00320 {
00321 next_state();
00322 }
00323 y = *next++;
00324
00325
00326
00327 y ^= (y >> 11);
00328 y ^= (y << 7) & 0x9d2c5680UL;
00329 y ^= (y << 15) & 0xefc60000UL;
00330 y ^= (y >> 18);
00331
00332 return y;
00333 }