|
|
1.1.1.10 root 1: /* 1.1.1.12! root 2: Legal Notice: Some portions of the source code contained in this file were ! 3: derived from the source code of Encryption for the Masses 2.02a, which is ! 4: Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License ! 5: Agreement for Encryption for the Masses'. Modifications and additions to ! 6: the original source code (contained in this file) and all other portions of ! 7: this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed ! 8: by the TrueCrypt License 2.4 the full text of which is contained in the ! 9: file License.txt included in TrueCrypt binary and source code distribution 1.1.1.10 root 10: packages. */ 1.1 root 11: 1.1.1.9 root 12: #include <stdlib.h> 13: #include <stdio.h> 1.1.1.10 root 14: #include <string.h> 1.1.1.9 root 15: #include <fcntl.h> 1.1.1.6 root 16: #include "Tcdefs.h" 17: #include "Crc.h" 18: #include "Random.h" 19: #include "Apidrvr.h" 1.1 root 20: 1.1.1.9 root 21: unsigned __int8 buffer[RNG_POOL_SIZE]; 1.1 root 22: unsigned char *pRandPool = NULL; 1.1.1.9 root 23: static BOOL bRandDidInit = FALSE; 1.1.1.2 root 24: int nRandIndex = 0, randPoolReadIndex = 0; 1.1.1.9 root 25: int HashFunction = DEFAULT_HASH_ALGORITHM; 26: BOOL bDidSlowPoll = FALSE; /* We do the slow poll only once */ 27: BOOL volatile bFastPollEnabled = TRUE; /* Used to reduce CPU load when performing benchmarks */ 28: BOOL volatile bRandmixEnabled = TRUE; /* Used to reduce CPU load when performing benchmarks */ 1.1.1.3 root 29: 1.1 root 30: /* Macro to add a single byte to the pool */ 31: #define RandaddByte(x) {\ 1.1.1.6 root 32: if (nRandIndex == RNG_POOL_SIZE) nRandIndex = 0;\ 1.1 root 33: pRandPool[nRandIndex] = (unsigned char) ((unsigned char)x + pRandPool[nRandIndex]); \ 1.1.1.12! root 34: if (nRandIndex % RANDMIX_BYTE_INTERVAL == 0) Randmix();\ 1.1 root 35: nRandIndex++; \ 36: } 37: 38: /* Macro to add four bytes to the pool */ 1.1.1.9 root 39: #define RandaddInt32(x) RandAddInt((unsigned __int32)x); 1.1 root 40: 1.1.1.9 root 41: void RandAddInt (unsigned __int32 x) 1.1 root 42: { 43: RandaddByte(x); 44: RandaddByte((x >> 8)); 45: RandaddByte((x >> 16)); 46: RandaddByte((x >> 24)); 47: } 48: 1.1.1.9 root 49: #ifdef _WIN32 50: 51: #include <tlhelp32.h> 52: #include "Dlgcode.h" 53: 1.1 root 54: HHOOK hMouse = NULL; /* Mouse hook for the random number generator */ 1.1.1.6 root 55: HHOOK hKeyboard = NULL; /* Keyboard hook for the random number generator */ 1.1 root 56: 57: /* Variables for thread control, the thread is used to gather up info about 58: the system in in the background */ 59: CRITICAL_SECTION critRandProt; /* The critical section */ 1.1.1.6 root 60: BOOL volatile bThreadTerminate = FALSE; /* This variable is shared among thread's so its made volatile */ 1.1 root 61: 1.1.1.9 root 62: /* Network library handle for the SlowPoll function */ 1.1 root 63: HANDLE hNetAPI32 = NULL; 64: 1.1.1.4 root 65: // CryptoAPI 66: HCRYPTPROV hCryptProv; 67: 1.1.1.9 root 68: #endif // _WIN32 1.1 root 69: 70: /* Init the random number generator, setup the hooks, and start the thread */ 71: int 72: Randinit () 73: { 1.1.1.6 root 74: if(bRandDidInit) return 0; 1.1 root 75: 1.1.1.9 root 76: #ifdef _WIN32 1.1 root 77: InitializeCriticalSection (&critRandProt); 1.1.1.9 root 78: #endif 1.1 root 79: 80: bRandDidInit = TRUE; 81: 82: pRandPool = (unsigned char *) TCalloc (RANDOMPOOL_ALLOCSIZE); 83: if (pRandPool == NULL) 84: goto error; 85: else 86: memset (pRandPool, 0, RANDOMPOOL_ALLOCSIZE); 87: 1.1.1.9 root 88: #ifdef _WIN32 1.1.1.2 root 89: VirtualLock (pRandPool, RANDOMPOOL_ALLOCSIZE); 90: 1.1 root 91: hKeyboard = SetWindowsHookEx (WH_KEYBOARD, (HOOKPROC)&KeyboardProc, NULL, GetCurrentThreadId ()); 1.1.1.4 root 92: if (hKeyboard == 0) handleWin32Error (0); 93: 94: hMouse = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)&MouseProc, NULL, GetCurrentThreadId ()); 95: if (hMouse == 0) 96: { 97: handleWin32Error (0); 1.1 root 98: goto error; 1.1.1.4 root 99: } 100: 101: if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0) 102: && !CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) 103: { 1.1.1.6 root 104: hCryptProv = 0; 1.1.1.4 root 105: } 1.1 root 106: 1.1.1.9 root 107: if (_beginthread (ThreadSafeThreadFunction, 8192, NULL) == -1) 1.1 root 108: goto error; 1.1.1.9 root 109: #endif 1.1 root 110: 111: return 0; 112: 1.1.1.4 root 113: error: 1.1 root 114: Randfree (); 115: return 1; 116: } 117: 118: /* Close everything down, including the thread which is closed down by 119: setting a flag which eventually causes the thread function to exit */ 120: void 121: Randfree () 122: { 123: if (bRandDidInit == FALSE) 124: return; 125: 1.1.1.9 root 126: #ifdef _WIN32 1.1 root 127: EnterCriticalSection (&critRandProt); 128: 129: if (hMouse != 0) 130: UnhookWindowsHookEx (hMouse); 131: if (hKeyboard != 0) 132: UnhookWindowsHookEx (hKeyboard); 133: 134: bThreadTerminate = TRUE; 135: 136: LeaveCriticalSection (&critRandProt); 137: 138: for (;;) 139: { 140: Sleep (250); 141: EnterCriticalSection (&critRandProt); 142: if (bThreadTerminate == FALSE) 143: { 144: LeaveCriticalSection (&critRandProt); 145: break; 146: } 147: LeaveCriticalSection (&critRandProt); 148: } 149: 150: if (hNetAPI32 != 0) 151: { 152: FreeLibrary (hNetAPI32); 153: hNetAPI32 = NULL; 154: } 155: 1.1.1.4 root 156: if (hCryptProv) 157: { 158: CryptReleaseContext (hCryptProv, 0); 159: hCryptProv = 0; 160: } 161: 1.1 root 162: hMouse = NULL; 163: hKeyboard = NULL; 164: bThreadTerminate = FALSE; 165: DeleteCriticalSection (&critRandProt); 1.1.1.9 root 166: 167: #endif // _WIN32 168: 169: if (pRandPool != NULL) 170: { 171: burn (pRandPool, RANDOMPOOL_ALLOCSIZE); 172: TCfree (pRandPool); 173: pRandPool = NULL; 174: } 175: 176: nRandIndex = 0; 1.1 root 177: bRandDidInit = FALSE; 178: } 179: 1.1.1.9 root 180: 1.1.1.6 root 181: void RandSetHashFunction (int hash_algo_id) 1.1.1.3 root 182: { 1.1.1.9 root 183: HashFunction = hash_algo_id; 1.1.1.3 root 184: } 185: 1.1.1.6 root 186: int RandGetHashFunction (void) 187: { 1.1.1.9 root 188: return HashFunction; 1.1.1.6 root 189: } 190: 191: /* The random pool mixing function */ 1.1.1.12! root 192: BOOL Randmix () 1.1 root 193: { 1.1.1.6 root 194: if (bRandmixEnabled) 1.1 root 195: { 1.1.1.6 root 196: unsigned char hashOutputBuffer [MAX_DIGESTSIZE]; 197: WHIRLPOOL_CTX wctx; 198: RMD160_CTX rctx; 1.1.1.12! root 199: sha512_ctx sctx; 1.1.1.6 root 200: int poolIndex, digestIndex, digestSize; 201: 1.1.1.9 root 202: switch (HashFunction) 1.1.1.6 root 203: { 204: case RIPEMD160: 205: digestSize = RIPEMD160_DIGESTSIZE; 206: break; 207: 1.1.1.12! root 208: case SHA512: ! 209: digestSize = SHA512_DIGESTSIZE; ! 210: break; ! 211: 1.1.1.6 root 212: case WHIRLPOOL: 213: digestSize = WHIRLPOOL_DIGESTSIZE; 214: break; 1.1.1.9 root 215: 216: default: 217: return FALSE; 1.1.1.6 root 218: } 1.1.1.3 root 219: 1.1.1.12! root 220: if (RNG_POOL_SIZE % digestSize) ! 221: TC_THROW_FATAL_EXCEPTION; ! 222: 1.1.1.6 root 223: for (poolIndex = 0; poolIndex < RNG_POOL_SIZE; poolIndex += digestSize) 224: { 225: /* Compute the message digest of the entire pool using the selected hash function. */ 1.1.1.9 root 226: switch (HashFunction) 1.1.1.6 root 227: { 228: case RIPEMD160: 229: RMD160Init(&rctx); 230: RMD160Update(&rctx, pRandPool, RNG_POOL_SIZE); 231: RMD160Final(hashOutputBuffer, &rctx); 232: break; 233: 1.1.1.12! root 234: case SHA512: ! 235: sha512_begin (&sctx); ! 236: sha512_hash (pRandPool, RNG_POOL_SIZE, &sctx); ! 237: sha512_end (hashOutputBuffer, &sctx); ! 238: break; ! 239: 1.1.1.6 root 240: case WHIRLPOOL: 241: WHIRLPOOL_init (&wctx); 242: WHIRLPOOL_add (pRandPool, RNG_POOL_SIZE * 8, &wctx); 243: WHIRLPOOL_finalize (&wctx, hashOutputBuffer); 244: break; 1.1.1.12! root 245: ! 246: default: ! 247: // Unknown/wrong ID ! 248: TC_THROW_FATAL_EXCEPTION; 1.1.1.6 root 249: } 250: 251: /* XOR the resultant message digest to the pool at the poolIndex position. */ 252: for (digestIndex = 0; digestIndex < digestSize; digestIndex++) 253: { 254: pRandPool [poolIndex + digestIndex] ^= hashOutputBuffer [digestIndex]; 255: } 256: } 257: 258: /* Prevent leaks */ 1.1.1.12! root 259: burn (hashOutputBuffer, MAX_DIGESTSIZE); 1.1.1.9 root 260: switch (HashFunction) 1.1.1.6 root 261: { 1.1.1.12! root 262: case RIPEMD160: ! 263: burn (&rctx, sizeof(rctx)); 1.1.1.6 root 264: break; 265: 1.1.1.12! root 266: case SHA512: ! 267: burn (&sctx, sizeof(sctx)); 1.1.1.6 root 268: break; 269: 270: case WHIRLPOOL: 1.1.1.12! root 271: burn (&wctx, sizeof(wctx)); 1.1.1.6 root 272: break; 1.1.1.12! root 273: ! 274: default: ! 275: // Unknown/wrong ID ! 276: TC_THROW_FATAL_EXCEPTION; 1.1.1.6 root 277: } 1.1 root 278: } 1.1.1.9 root 279: return TRUE; 1.1 root 280: } 281: 282: /* Add a buffer to the pool */ 283: void 284: RandaddBuf (void *buf, int len) 285: { 286: int i; 287: for (i = 0; i < len; i++) 288: { 289: RandaddByte (((unsigned char *) buf)[i]); 290: } 291: } 292: 1.1.1.9 root 293: #ifdef _WIN32 1.1.1.8 root 294: BOOL 1.1.1.4 root 295: RandpeekBytes (unsigned char *buf, int len) 1.1 root 296: { 1.1.1.6 root 297: if (len > RNG_POOL_SIZE) 1.1.1.7 root 298: { 299: Error ("ERR_NOT_ENOUGH_RANDOM_DATA"); 1.1.1.6 root 300: len = RNG_POOL_SIZE; 1.1.1.7 root 301: } 1.1.1.6 root 302: 1.1 root 303: EnterCriticalSection (&critRandProt); 304: memcpy (buf, pRandPool, len); 305: LeaveCriticalSection (&critRandProt); 1.1.1.8 root 306: 307: return TRUE; 1.1 root 308: } 1.1.1.9 root 309: #endif 310: 1.1 root 311: 1.1.1.6 root 312: /* Get len random bytes from the pool (max. RNG_POOL_SIZE bytes per a single call) */ 1.1.1.8 root 313: BOOL 1.1.1.4 root 314: RandgetBytes (unsigned char *buf, int len, BOOL forceSlowPoll) 1.1 root 315: { 316: int i; 1.1.1.9 root 317: BOOL ret = TRUE; 318: 319: if (HashFunction == 0) 320: return FALSE; 1.1 root 321: 1.1.1.9 root 322: #ifdef _WIN32 1.1 root 323: EnterCriticalSection (&critRandProt); 1.1.1.9 root 324: #endif 1.1 root 325: 1.1.1.2 root 326: if (bDidSlowPoll == FALSE || forceSlowPoll) 1.1 root 327: { 1.1.1.9 root 328: if (!SlowPoll ()) 329: ret = FALSE; 330: else 331: bDidSlowPoll = TRUE; 1.1 root 332: } 1.1.1.2 root 333: 1.1.1.9 root 334: if (!FastPoll ()) 335: ret = FALSE; 1.1 root 336: 1.1.1.6 root 337: /* There's never more than RNG_POOL_SIZE worth of randomess */ 338: if (len > RNG_POOL_SIZE) 339: { 1.1.1.9 root 340: #ifdef _WIN32 1.1.1.6 root 341: Error ("ERR_NOT_ENOUGH_RANDOM_DATA"); 342: len = RNG_POOL_SIZE; 1.1.1.9 root 343: #else 344: return FALSE; 345: #endif 1.1.1.6 root 346: } 1.1 root 347: 1.1.1.2 root 348: // Requested number of bytes is copied from pool to output buffer, 349: // pool is rehashed, and output buffer is XORed with new data from pool 350: for (i = 0; i < len; i++) 351: { 352: buf[i] = pRandPool[randPoolReadIndex++]; 1.1.1.6 root 353: if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; 1.1.1.2 root 354: } 355: 1.1.1.6 root 356: /* Invert the pool */ 357: for (i = 0; i < RNG_POOL_SIZE / 4; i++) 1.1 root 358: { 1.1.1.6 root 359: ((unsigned __int32 *) pRandPool)[i] = ~((unsigned __int32 *) pRandPool)[i]; 1.1 root 360: } 361: 1.1.1.6 root 362: // Mix the pool 1.1.1.9 root 363: if (!FastPoll ()) 364: ret = FALSE; 1.1.1.4 root 365: 1.1.1.6 root 366: // XOR the current pool content into the output buffer to prevent pool state leaks 1.1.1.4 root 367: for (i = 0; i < len; i++) 368: { 369: buf[i] ^= pRandPool[randPoolReadIndex++]; 1.1.1.6 root 370: if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; 1.1.1.4 root 371: } 1.1 root 372: 1.1.1.9 root 373: #ifdef _WIN32 1.1 root 374: LeaveCriticalSection (&critRandProt); 1.1.1.9 root 375: #endif 376: return ret; 1.1 root 377: } 378: 1.1.1.9 root 379: #ifdef _WIN32 1.1 root 380: /* Capture the mouse, and as long as the event is not the same as the last 1.1.1.6 root 381: two events, add the crc of the event, and the crc of the time difference 1.1.1.9 root 382: between this event and the last + the current time to the pool. 383: The role of CRC-32 is merely to perform diffusion. Note that the output 384: of CRC-32 is subsequently processed using a cryptographically secure hash 385: algorithm. */ 1.1 root 386: LRESULT CALLBACK 387: MouseProc (int nCode, WPARAM wParam, LPARAM lParam) 388: { 389: static DWORD dwLastTimer; 1.1.1.6 root 390: static unsigned __int32 lastCrc, lastCrc2; 1.1 root 391: MOUSEHOOKSTRUCT *lpMouse = (MOUSEHOOKSTRUCT *) lParam; 392: 393: if (nCode < 0) 394: return CallNextHookEx (hMouse, nCode, wParam, lParam); 395: else 396: { 397: DWORD dwTimer = GetTickCount (); 398: DWORD j = dwLastTimer - dwTimer; 1.1.1.6 root 399: unsigned __int32 crc = 0L; 1.1 root 400: int i; 401: 402: dwLastTimer = dwTimer; 403: 404: for (i = 0; i < sizeof (MOUSEHOOKSTRUCT); i++) 405: { 406: crc = UPDC32 (((unsigned char *) lpMouse)[i], crc); 407: } 408: 409: if (crc != lastCrc && crc != lastCrc2) 410: { 1.1.1.6 root 411: unsigned __int32 timeCrc = 0L; 1.1 root 412: 413: for (i = 0; i < 4; i++) 414: { 415: timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc); 416: } 417: 418: for (i = 0; i < 4; i++) 419: { 420: timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc); 421: } 422: 423: EnterCriticalSection (&critRandProt); 1.1.1.6 root 424: RandaddInt32 ((unsigned __int32) (crc + timeCrc)); 1.1 root 425: LeaveCriticalSection (&critRandProt); 426: } 427: lastCrc2 = lastCrc; 428: lastCrc = crc; 429: 430: } 431: return 0; 432: } 433: 434: /* Capture the keyboard, as long as the event is not the same as the last two 1.1.1.6 root 435: events, add the crc of the event to the pool along with the crc of the time 1.1.1.9 root 436: difference between this event and the last. The role of CRC-32 is merely to 437: perform diffusion. Note that the output of CRC-32 is subsequently processed 438: using a cryptographically secure hash algorithm. */ 1.1 root 439: LRESULT CALLBACK 440: KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam) 441: { 442: static int lLastKey, lLastKey2; 443: static DWORD dwLastTimer; 444: int nKey = (lParam & 0x00ff0000) >> 16; 445: int nCapture = 0; 446: 447: if (nCode < 0) 448: return CallNextHookEx (hMouse, nCode, wParam, lParam); 449: 450: if ((lParam & 0x0000ffff) == 1 && !(lParam & 0x20000000) && 451: (lParam & 0x80000000)) 452: { 453: if (nKey != lLastKey) 454: nCapture = 1; /* Capture this key */ 455: else if (nKey != lLastKey2) 456: nCapture = 1; /* Allow for one repeat */ 457: } 458: if (nCapture) 459: { 460: DWORD dwTimer = GetTickCount (); 461: DWORD j = dwLastTimer - dwTimer; 1.1.1.6 root 462: unsigned __int32 timeCrc = 0L; 1.1 root 463: int i; 464: 465: dwLastTimer = dwTimer; 466: lLastKey2 = lLastKey; 467: lLastKey = nKey; 468: 469: for (i = 0; i < 4; i++) 470: { 471: timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc); 472: } 473: 474: for (i = 0; i < 4; i++) 475: { 476: timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc); 477: } 478: 479: EnterCriticalSection (&critRandProt); 1.1.1.6 root 480: RandaddInt32 ((unsigned __int32) (crc32int(&lParam) + timeCrc)); 1.1 root 481: LeaveCriticalSection (&critRandProt); 482: } 1.1.1.9 root 483: 484: return CallNextHookEx (hMouse, nCode, wParam, lParam); 1.1 root 485: } 486: 487: /* This is the thread function which will poll the system for randomness */ 488: void 489: ThreadSafeThreadFunction (void *dummy) 490: { 491: if (dummy); /* Remove unused parameter warning */ 492: 493: for (;;) 494: { 495: EnterCriticalSection (&critRandProt); 496: 1.1.1.6 root 497: if (bThreadTerminate) 1.1 root 498: { 499: bThreadTerminate = FALSE; 500: LeaveCriticalSection (&critRandProt); 501: _endthread (); 502: } 1.1.1.6 root 503: else if (bFastPollEnabled) 1.1 root 504: { 505: FastPoll (); 506: } 507: 508: LeaveCriticalSection (&critRandProt); 509: 1.1.1.12! root 510: Sleep (FASTPOLL_INTERVAL); 1.1 root 511: } 512: } 513: 514: /* Type definitions for function pointers to call NetAPI32 functions */ 515: 516: typedef 517: DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService, 518: DWORD dwLevel, DWORD dwOptions, 519: LPBYTE * lpBuffer); 520: typedef 521: DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer); 522: typedef 523: DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer); 524: 525: NETSTATISTICSGET pNetStatisticsGet = NULL; 526: NETAPIBUFFERSIZE pNetApiBufferSize = NULL; 527: NETAPIBUFFERFREE pNetApiBufferFree = NULL; 528: 1.1.1.9 root 529: #endif // _WIN32 530: 1.1 root 531: /* This is the slowpoll function which gathers up network/hard drive 532: performance data for the random pool */ 1.1.1.9 root 533: BOOL SlowPoll (void) 1.1 root 534: { 1.1.1.9 root 535: int i; 536: #ifdef _WIN32 1.1 root 537: static int isWorkstation = -1; 538: static int cbPerfData = 0x10000; 539: HANDLE hDevice; 540: LPBYTE lpBuffer; 541: DWORD dwSize, status; 542: LPWSTR lpszLanW, lpszLanS; 1.1.1.9 root 543: int nDrive; 1.1 root 544: 545: /* Find out whether this is an NT server or workstation if necessary */ 546: if (isWorkstation == -1) 547: { 548: HKEY hKey; 549: 550: if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, 551: "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 552: 0, KEY_READ, &hKey) == ERROR_SUCCESS) 553: { 554: unsigned char szValue[32]; 555: dwSize = sizeof (szValue); 556: 557: isWorkstation = TRUE; 558: status = RegQueryValueEx (hKey, "ProductType", 0, NULL, 559: szValue, &dwSize); 560: 561: if (status == ERROR_SUCCESS && _stricmp ((char *) szValue, "WinNT")) 562: /* Note: There are (at least) three cases for 563: ProductType: WinNT = NT Workstation, 564: ServerNT = NT Server, LanmanNT = NT Server 565: acting as a Domain Controller */ 566: isWorkstation = FALSE; 567: 568: RegCloseKey (hKey); 569: } 570: } 571: /* Initialize the NetAPI32 function pointers if necessary */ 572: if (hNetAPI32 == NULL) 573: { 574: /* Obtain a handle to the module containing the Lan Manager 575: functions */ 576: hNetAPI32 = LoadLibrary ("NETAPI32.DLL"); 577: if (hNetAPI32 != NULL) 578: { 579: /* Now get pointers to the functions */ 580: pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32, 581: "NetStatisticsGet"); 582: pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32, 583: "NetApiBufferSize"); 584: pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32, 585: "NetApiBufferFree"); 586: 587: /* Make sure we got valid pointers for every NetAPI32 588: function */ 589: if (pNetStatisticsGet == NULL || 590: pNetApiBufferSize == NULL || 591: pNetApiBufferFree == NULL) 592: { 593: /* Free the library reference and reset the 594: static handle */ 595: FreeLibrary (hNetAPI32); 596: hNetAPI32 = NULL; 597: } 598: } 599: } 600: 601: /* Get network statistics. Note: Both NT Workstation and NT Server 602: by default will be running both the workstation and server 603: services. The heuristic below is probably useful though on the 604: assumption that the majority of the network traffic will be via 605: the appropriate service */ 606: lpszLanW = (LPWSTR) WIDE ("LanmanWorkstation"); 607: lpszLanS = (LPWSTR) WIDE ("LanmanServer"); 608: if (hNetAPI32 && 609: pNetStatisticsGet (NULL, 610: isWorkstation ? lpszLanW : lpszLanS, 611: 0, 0, &lpBuffer) == 0) 612: { 613: pNetApiBufferSize (lpBuffer, &dwSize); 614: RandaddBuf ((unsigned char *) lpBuffer, dwSize); 615: pNetApiBufferFree (lpBuffer); 616: } 617: 618: /* Get disk I/O statistics for all the hard drives */ 619: for (nDrive = 0;; nDrive++) 620: { 621: DISK_PERFORMANCE diskPerformance; 622: char szDevice[24]; 623: 624: /* Check whether we can access this device */ 625: sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive); 626: hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 627: NULL, OPEN_EXISTING, 0, NULL); 628: if (hDevice == INVALID_HANDLE_VALUE) 629: break; 630: 631: 632: /* Note: This only works if you have turned on the disk 633: performance counters with 'diskperf -y'. These counters 634: are off by default */ 635: if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, 636: &diskPerformance, sizeof (DISK_PERFORMANCE), 637: &dwSize, NULL)) 638: { 639: RandaddBuf ((unsigned char *) &diskPerformance, dwSize); 640: } 641: CloseHandle (hDevice); 642: } 643: 1.1.1.4 root 644: // CryptoAPI 1.1.1.7 root 645: for (i = 0; i < 100; i++) 1.1.1.4 root 646: { 1.1.1.6 root 647: if (hCryptProv && CryptGenRandom(hCryptProv, sizeof (buffer), buffer)) 1.1.1.4 root 648: RandaddBuf (buffer, sizeof (buffer)); 1.1 root 649: } 650: 1.1.1.9 root 651: #else // _WIN32 652: 653: // Read all bytes available in /dev/random up to buffer size 654: int f = open ("/dev/random", O_RDONLY | O_NONBLOCK); 655: if (f == -1) 656: { 657: perror ("Cannot open /dev/random"); 658: return FALSE; 659: } 660: 661: i = read (f, buffer, sizeof (buffer)); 662: RandaddBuf (buffer, i); 663: close (f); 664: 665: FastPoll (); 666: 667: #endif // #else _WIN32 668: 669: burn(buffer, sizeof (buffer)); 1.1.1.6 root 670: Randmix(); 1.1.1.9 root 671: return TRUE; 1.1 root 672: } 673: 674: 1.1.1.6 root 675: /* This is the fastpoll function which gathers up info by calling various api's */ 1.1.1.9 root 676: BOOL FastPoll (void) 1.1 root 677: { 1.1.1.9 root 678: int nOriginalRandIndex = nRandIndex; 679: #ifdef _WIN32 1.1 root 680: static BOOL addedFixedItems = FALSE; 681: FILETIME creationTime, exitTime, kernelTime, userTime; 682: DWORD minimumWorkingSetSize, maximumWorkingSetSize; 683: LARGE_INTEGER performanceCount; 684: MEMORYSTATUS memoryStatus; 685: HANDLE handle; 686: POINT point; 687: 688: /* Get various basic pieces of system information */ 1.1.1.6 root 689: RandaddInt32 (GetActiveWindow ()); /* Handle of active window */ 690: RandaddInt32 (GetCapture ()); /* Handle of window with mouse 1.1 root 691: capture */ 1.1.1.6 root 692: RandaddInt32 (GetClipboardOwner ()); /* Handle of clipboard owner */ 693: RandaddInt32 (GetClipboardViewer ()); /* Handle of start of 1.1 root 694: clpbd.viewer list */ 1.1.1.6 root 695: RandaddInt32 (GetCurrentProcess ()); /* Pseudohandle of current 1.1 root 696: process */ 1.1.1.6 root 697: RandaddInt32 (GetCurrentProcessId ()); /* Current process ID */ 698: RandaddInt32 (GetCurrentThread ()); /* Pseudohandle of current 1.1 root 699: thread */ 1.1.1.6 root 700: RandaddInt32 (GetCurrentThreadId ()); /* Current thread ID */ 701: RandaddInt32 (GetCurrentTime ()); /* Milliseconds since Windows 1.1 root 702: started */ 1.1.1.6 root 703: RandaddInt32 (GetDesktopWindow ()); /* Handle of desktop window */ 704: RandaddInt32 (GetFocus ()); /* Handle of window with kb.focus */ 705: RandaddInt32 (GetInputState ()); /* Whether sys.queue has any events */ 706: RandaddInt32 (GetMessagePos ()); /* Cursor pos.for last message */ 707: RandaddInt32 (GetMessageTime ()); /* 1 ms time for last message */ 708: RandaddInt32 (GetOpenClipboardWindow ()); /* Handle of window with 1.1 root 709: clpbd.open */ 1.1.1.6 root 710: RandaddInt32 (GetProcessHeap ()); /* Handle of process heap */ 711: RandaddInt32 (GetProcessWindowStation ()); /* Handle of procs 1.1 root 712: window station */ 1.1.1.6 root 713: RandaddInt32 (GetQueueStatus (QS_ALLEVENTS)); /* Types of events in 1.1 root 714: input queue */ 715: 716: /* Get multiword system information */ 717: GetCaretPos (&point); /* Current caret position */ 718: RandaddBuf ((unsigned char *) &point, sizeof (POINT)); 719: GetCursorPos (&point); /* Current mouse cursor position */ 720: RandaddBuf ((unsigned char *) &point, sizeof (POINT)); 721: 722: /* Get percent of memory in use, bytes of physical memory, bytes of 723: free physical memory, bytes in paging file, free bytes in paging 724: file, user bytes of address space, and free user bytes */ 725: memoryStatus.dwLength = sizeof (MEMORYSTATUS); 726: GlobalMemoryStatus (&memoryStatus); 727: RandaddBuf ((unsigned char *) &memoryStatus, sizeof (MEMORYSTATUS)); 728: 729: /* Get thread and process creation time, exit time, time in kernel 730: mode, and time in user mode in 100ns intervals */ 731: handle = GetCurrentThread (); 732: GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); 733: RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME)); 734: RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME)); 735: RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME)); 736: RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME)); 737: handle = GetCurrentProcess (); 738: GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); 739: RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME)); 740: RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME)); 741: RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME)); 742: RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME)); 743: 744: /* Get the minimum and maximum working set size for the current 745: process */ 746: GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, 747: &maximumWorkingSetSize); 1.1.1.6 root 748: RandaddInt32 (minimumWorkingSetSize); 749: RandaddInt32 (maximumWorkingSetSize); 1.1 root 750: 751: /* The following are fixed for the lifetime of the process so we only 752: add them once */ 753: if (addedFixedItems == 0) 754: { 755: STARTUPINFO startupInfo; 756: 757: /* Get name of desktop, console window title, new window 758: position and size, window flags, and handles for stdin, 759: stdout, and stderr */ 760: startupInfo.cb = sizeof (STARTUPINFO); 761: GetStartupInfo (&startupInfo); 762: RandaddBuf ((unsigned char *) &startupInfo, sizeof (STARTUPINFO)); 763: addedFixedItems = TRUE; 764: } 765: /* The docs say QPC can fail if appropriate hardware is not 766: available. It works on 486 & Pentium boxes, but hasn't been tested 767: for 386 or RISC boxes */ 768: if (QueryPerformanceCounter (&performanceCount)) 769: RandaddBuf ((unsigned char *) &performanceCount, sizeof (LARGE_INTEGER)); 770: else 771: { 772: /* Millisecond accuracy at best... */ 773: DWORD dwTicks = GetTickCount (); 774: RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks)); 775: } 1.1.1.4 root 776: 777: // CryptoAPI 1.1.1.6 root 778: if (hCryptProv && CryptGenRandom(hCryptProv, sizeof (buffer), buffer)) 1.1.1.4 root 779: RandaddBuf (buffer, sizeof (buffer)); 1.1.1.6 root 780: 1.1.1.9 root 781: #else // _WIN32 782: 783: // /dev/urandom 784: 785: int f = open ("/dev/urandom", 0); 786: 787: if (f == -1) 788: { 789: perror ("Cannot open /dev/urandom"); 790: return FALSE; 791: } 792: 793: if (read (f, buffer, sizeof (buffer)) != sizeof (buffer)) 794: { 795: perror ("Read from /dev/urandom failed"); 796: close (f); 797: return FALSE; 798: } 799: 800: close (f); 801: RandaddBuf (buffer, sizeof (buffer)); 802: 803: #endif // #else _WIN32 804: 1.1.1.6 root 805: /* Apply the pool mixing function */ 806: Randmix(); 807: 808: /* Restore the original pool cursor position. If this wasn't done, mouse coordinates 809: could be written to a limited area of the pool, especially when moving the mouse 810: uninterruptedly. The severity of the problem would depend on the length of data 811: written by FastPoll (if it was equal to the size of the pool, mouse coordinates 812: would be written only to a particular 4-byte area, whenever moving the mouse 813: uninterruptedly). */ 814: nRandIndex = nOriginalRandIndex; 1.1.1.9 root 815: 816: return TRUE; 1.1 root 817: } 1.1.1.9 root 818:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.