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