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