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