|
|
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
1.1.1.19 root 6: the original source code (contained in this file) and all other portions
7: of this file are Copyright (c) 2003-2009 TrueCrypt Developers Association
1.1.1.20! root 8: and are governed by the TrueCrypt License 3.0 the full text of which is
1.1.1.19 root 9: contained in the file License.txt included in TrueCrypt binary and source
10: code distribution 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 */
1.1.1.20! root 66: int Randinit ()
1.1 root 67: {
1.1.1.20! root 68: if (GetMaxPkcs5OutSize() > RNG_POOL_SIZE)
! 69: TC_THROW_FATAL_EXCEPTION;
! 70:
! 71: if(bRandDidInit)
! 72: return 0;
1.1 root 73:
74: InitializeCriticalSection (&critRandProt);
75:
76: bRandDidInit = TRUE;
77:
78: if (pRandPool == NULL)
1.1.1.16 root 79: {
80: pRandPool = (unsigned char *) TCalloc (RANDOMPOOL_ALLOCSIZE);
81: if (pRandPool == NULL)
82: goto error;
1.1 root 83:
1.1.1.16 root 84: bDidSlowPoll = FALSE;
85: RandomPoolEnrichedByUser = FALSE;
86:
87: memset (pRandPool, 0, RANDOMPOOL_ALLOCSIZE);
88: VirtualLock (pRandPool, RANDOMPOOL_ALLOCSIZE);
89: }
1.1.1.2 root 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))
1.1.1.16 root 103: CryptoAPIAvailable = FALSE;
104: else
105: CryptoAPIAvailable = TRUE;
1.1 root 106:
1.1.1.18 root 107: if (!(PeriodicFastPollThreadHandle = (HANDLE) _beginthreadex (NULL, 0, PeriodicFastPollThreadProc, NULL, 0, NULL)))
1.1 root 108: goto error;
109:
110: return 0;
111:
1.1.1.4 root 112: error:
1.1.1.16 root 113: RandStop (TRUE);
1.1 root 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 */
1.1.1.16 root 119: void RandStop (BOOL freePool)
1.1 root 120: {
1.1.1.16 root 121: if (!bRandDidInit && freePool && pRandPool)
122: goto freePool;
123:
1.1 root 124: if (bRandDidInit == FALSE)
125: return;
126:
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:
1.1.1.18 root 138: if (PeriodicFastPollThreadHandle)
139: WaitForSingleObject (PeriodicFastPollThreadHandle, INFINITE);
1.1 root 140:
141: if (hNetAPI32 != 0)
142: {
143: FreeLibrary (hNetAPI32);
144: hNetAPI32 = NULL;
145: }
146:
1.1.1.16 root 147: if (CryptoAPIAvailable)
1.1.1.4 root 148: {
149: CryptReleaseContext (hCryptProv, 0);
1.1.1.16 root 150: CryptoAPIAvailable = FALSE;
1.1.1.4 root 151: }
152:
1.1 root 153: hMouse = NULL;
154: hKeyboard = NULL;
155: bThreadTerminate = FALSE;
156: DeleteCriticalSection (&critRandProt);
1.1.1.9 root 157:
1.1.1.15 root 158: bRandDidInit = FALSE;
159:
1.1.1.16 root 160: freePool:
161: if (freePool)
1.1.1.9 root 162: {
1.1.1.16 root 163: bDidSlowPoll = FALSE;
164: RandomPoolEnrichedByUser = FALSE;
1.1.1.9 root 165:
1.1.1.16 root 166: if (pRandPool != NULL)
167: {
168: burn (pRandPool, RANDOMPOOL_ALLOCSIZE);
169: TCfree (pRandPool);
170: pRandPool = NULL;
171: }
172: }
1.1 root 173: }
174:
1.1.1.16 root 175: BOOL IsRandomNumberGeneratorStarted ()
176: {
177: return bRandDidInit;
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.16 root 182: if (HashIsDeprecated (hash_algo_id))
183: hash_algo_id = DEFAULT_HASH_ALGORITHM;
184:
1.1.1.9 root 185: HashFunction = hash_algo_id;
1.1.1.3 root 186: }
187:
1.1.1.6 root 188: int RandGetHashFunction (void)
189: {
1.1.1.9 root 190: return HashFunction;
1.1.1.6 root 191: }
192:
1.1.1.16 root 193: void SetRandomPoolEnrichedByUserStatus (BOOL enriched)
194: {
195: RandomPoolEnrichedByUser = enriched;
196: }
197:
198: BOOL IsRandomPoolEnrichedByUser ()
199: {
200: return RandomPoolEnrichedByUser;
201: }
202:
1.1.1.6 root 203: /* The random pool mixing function */
1.1.1.12 root 204: BOOL Randmix ()
1.1 root 205: {
1.1.1.6 root 206: if (bRandmixEnabled)
1.1 root 207: {
1.1.1.6 root 208: unsigned char hashOutputBuffer [MAX_DIGESTSIZE];
209: WHIRLPOOL_CTX wctx;
210: RMD160_CTX rctx;
1.1.1.12 root 211: sha512_ctx sctx;
1.1.1.6 root 212: int poolIndex, digestIndex, digestSize;
213:
1.1.1.9 root 214: switch (HashFunction)
1.1.1.6 root 215: {
216: case RIPEMD160:
217: digestSize = RIPEMD160_DIGESTSIZE;
218: break;
219:
1.1.1.12 root 220: case SHA512:
221: digestSize = SHA512_DIGESTSIZE;
222: break;
223:
1.1.1.6 root 224: case WHIRLPOOL:
225: digestSize = WHIRLPOOL_DIGESTSIZE;
226: break;
1.1.1.9 root 227:
228: default:
1.1.1.16 root 229: TC_THROW_FATAL_EXCEPTION;
1.1.1.6 root 230: }
1.1.1.3 root 231:
1.1.1.12 root 232: if (RNG_POOL_SIZE % digestSize)
233: TC_THROW_FATAL_EXCEPTION;
234:
1.1.1.6 root 235: for (poolIndex = 0; poolIndex < RNG_POOL_SIZE; poolIndex += digestSize)
236: {
237: /* Compute the message digest of the entire pool using the selected hash function. */
1.1.1.9 root 238: switch (HashFunction)
1.1.1.6 root 239: {
240: case RIPEMD160:
241: RMD160Init(&rctx);
242: RMD160Update(&rctx, pRandPool, RNG_POOL_SIZE);
243: RMD160Final(hashOutputBuffer, &rctx);
244: break;
245:
1.1.1.12 root 246: case SHA512:
247: sha512_begin (&sctx);
248: sha512_hash (pRandPool, RNG_POOL_SIZE, &sctx);
249: sha512_end (hashOutputBuffer, &sctx);
250: break;
251:
1.1.1.6 root 252: case WHIRLPOOL:
253: WHIRLPOOL_init (&wctx);
254: WHIRLPOOL_add (pRandPool, RNG_POOL_SIZE * 8, &wctx);
255: WHIRLPOOL_finalize (&wctx, hashOutputBuffer);
256: break;
1.1.1.12 root 257:
258: default:
259: // Unknown/wrong ID
260: TC_THROW_FATAL_EXCEPTION;
1.1.1.6 root 261: }
262:
263: /* XOR the resultant message digest to the pool at the poolIndex position. */
264: for (digestIndex = 0; digestIndex < digestSize; digestIndex++)
265: {
266: pRandPool [poolIndex + digestIndex] ^= hashOutputBuffer [digestIndex];
267: }
268: }
269:
270: /* Prevent leaks */
1.1.1.12 root 271: burn (hashOutputBuffer, MAX_DIGESTSIZE);
1.1.1.9 root 272: switch (HashFunction)
1.1.1.6 root 273: {
1.1.1.12 root 274: case RIPEMD160:
275: burn (&rctx, sizeof(rctx));
1.1.1.6 root 276: break;
277:
1.1.1.12 root 278: case SHA512:
279: burn (&sctx, sizeof(sctx));
1.1.1.6 root 280: break;
281:
282: case WHIRLPOOL:
1.1.1.12 root 283: burn (&wctx, sizeof(wctx));
1.1.1.6 root 284: break;
1.1.1.12 root 285:
286: default:
287: // Unknown/wrong ID
288: TC_THROW_FATAL_EXCEPTION;
1.1.1.6 root 289: }
1.1 root 290: }
1.1.1.9 root 291: return TRUE;
1.1 root 292: }
293:
294: /* Add a buffer to the pool */
1.1.1.20! root 295: void RandaddBuf (void *buf, int len)
1.1 root 296: {
297: int i;
298: for (i = 0; i < len; i++)
299: {
300: RandaddByte (((unsigned char *) buf)[i]);
301: }
302: }
303:
1.1.1.20! root 304: BOOL RandpeekBytes (unsigned char *buf, int len)
1.1 root 305: {
1.1.1.15 root 306: if (!bRandDidInit)
307: return FALSE;
308:
1.1.1.6 root 309: if (len > RNG_POOL_SIZE)
1.1.1.7 root 310: {
311: Error ("ERR_NOT_ENOUGH_RANDOM_DATA");
1.1.1.6 root 312: len = RNG_POOL_SIZE;
1.1.1.7 root 313: }
1.1.1.6 root 314:
1.1 root 315: EnterCriticalSection (&critRandProt);
316: memcpy (buf, pRandPool, len);
317: LeaveCriticalSection (&critRandProt);
1.1.1.8 root 318:
319: return TRUE;
1.1 root 320: }
1.1.1.9 root 321:
1.1 root 322:
1.1.1.6 root 323: /* Get len random bytes from the pool (max. RNG_POOL_SIZE bytes per a single call) */
1.1.1.20! root 324: BOOL 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.1.20! root 392: LRESULT CALLBACK MouseProc (int nCode, WPARAM wParam, LPARAM lParam)
1.1 root 393: {
394: static DWORD dwLastTimer;
1.1.1.6 root 395: static unsigned __int32 lastCrc, lastCrc2;
1.1 root 396: MOUSEHOOKSTRUCT *lpMouse = (MOUSEHOOKSTRUCT *) lParam;
397:
398: if (nCode < 0)
399: return CallNextHookEx (hMouse, nCode, wParam, lParam);
400: else
401: {
402: DWORD dwTimer = GetTickCount ();
403: DWORD j = dwLastTimer - dwTimer;
1.1.1.6 root 404: unsigned __int32 crc = 0L;
1.1 root 405: int i;
406:
407: dwLastTimer = dwTimer;
408:
409: for (i = 0; i < sizeof (MOUSEHOOKSTRUCT); i++)
410: {
411: crc = UPDC32 (((unsigned char *) lpMouse)[i], crc);
412: }
413:
414: if (crc != lastCrc && crc != lastCrc2)
415: {
1.1.1.6 root 416: unsigned __int32 timeCrc = 0L;
1.1 root 417:
418: for (i = 0; i < 4; i++)
419: {
420: timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc);
421: }
422:
423: for (i = 0; i < 4; i++)
424: {
425: timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc);
426: }
427:
428: EnterCriticalSection (&critRandProt);
1.1.1.6 root 429: RandaddInt32 ((unsigned __int32) (crc + timeCrc));
1.1 root 430: LeaveCriticalSection (&critRandProt);
431: }
432: lastCrc2 = lastCrc;
433: lastCrc = crc;
434:
435: }
436: return 0;
437: }
438:
439: /* Capture the keyboard, as long as the event is not the same as the last two
1.1.1.6 root 440: events, add the crc of the event to the pool along with the crc of the time
1.1.1.9 root 441: difference between this event and the last. The role of CRC-32 is merely to
442: perform diffusion. Note that the output of CRC-32 is subsequently processed
443: using a cryptographically secure hash algorithm. */
1.1.1.20! root 444: LRESULT CALLBACK KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam)
1.1 root 445: {
446: static int lLastKey, lLastKey2;
447: static DWORD dwLastTimer;
448: int nKey = (lParam & 0x00ff0000) >> 16;
449: int nCapture = 0;
450:
451: if (nCode < 0)
452: return CallNextHookEx (hMouse, nCode, wParam, lParam);
453:
454: if ((lParam & 0x0000ffff) == 1 && !(lParam & 0x20000000) &&
455: (lParam & 0x80000000))
456: {
457: if (nKey != lLastKey)
458: nCapture = 1; /* Capture this key */
459: else if (nKey != lLastKey2)
460: nCapture = 1; /* Allow for one repeat */
461: }
462: if (nCapture)
463: {
464: DWORD dwTimer = GetTickCount ();
465: DWORD j = dwLastTimer - dwTimer;
1.1.1.6 root 466: unsigned __int32 timeCrc = 0L;
1.1 root 467: int i;
468:
469: dwLastTimer = dwTimer;
470: lLastKey2 = lLastKey;
471: lLastKey = nKey;
472:
473: for (i = 0; i < 4; i++)
474: {
475: timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc);
476: }
477:
478: for (i = 0; i < 4; i++)
479: {
480: timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc);
481: }
482:
483: EnterCriticalSection (&critRandProt);
1.1.1.6 root 484: RandaddInt32 ((unsigned __int32) (crc32int(&lParam) + timeCrc));
1.1 root 485: LeaveCriticalSection (&critRandProt);
486: }
1.1.1.9 root 487:
488: return CallNextHookEx (hMouse, nCode, wParam, lParam);
1.1 root 489: }
490:
491: /* This is the thread function which will poll the system for randomness */
1.1.1.18 root 492: static unsigned __stdcall PeriodicFastPollThreadProc (void *dummy)
1.1 root 493: {
494: if (dummy); /* Remove unused parameter warning */
495:
496: for (;;)
497: {
498: EnterCriticalSection (&critRandProt);
499:
1.1.1.6 root 500: if (bThreadTerminate)
1.1 root 501: {
502: bThreadTerminate = FALSE;
503: LeaveCriticalSection (&critRandProt);
1.1.1.18 root 504: _endthreadex (0);
1.1 root 505: }
1.1.1.6 root 506: else if (bFastPollEnabled)
1.1 root 507: {
508: FastPoll ();
509: }
510:
511: LeaveCriticalSection (&critRandProt);
512:
1.1.1.12 root 513: Sleep (FASTPOLL_INTERVAL);
1.1 root 514: }
515: }
516:
517: /* Type definitions for function pointers to call NetAPI32 functions */
518:
519: typedef
520: DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService,
521: DWORD dwLevel, DWORD dwOptions,
522: LPBYTE * lpBuffer);
523: typedef
524: DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer);
525: typedef
526: DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer);
527:
528: NETSTATISTICSGET pNetStatisticsGet = NULL;
529: NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
530: NETAPIBUFFERFREE pNetApiBufferFree = NULL;
531:
1.1.1.9 root 532:
1.1 root 533: /* This is the slowpoll function which gathers up network/hard drive
534: performance data for the random pool */
1.1.1.9 root 535: BOOL SlowPoll (void)
1.1 root 536: {
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.16 root 645: if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer))
646: RandaddBuf (buffer, sizeof (buffer));
1.1 root 647:
1.1.1.9 root 648: burn(buffer, sizeof (buffer));
1.1.1.6 root 649: Randmix();
1.1.1.9 root 650: return TRUE;
1.1 root 651: }
652:
653:
1.1.1.6 root 654: /* This is the fastpoll function which gathers up info by calling various api's */
1.1.1.9 root 655: BOOL FastPoll (void)
1.1 root 656: {
1.1.1.9 root 657: int nOriginalRandIndex = nRandIndex;
1.1 root 658: static BOOL addedFixedItems = FALSE;
659: FILETIME creationTime, exitTime, kernelTime, userTime;
660: DWORD minimumWorkingSetSize, maximumWorkingSetSize;
661: LARGE_INTEGER performanceCount;
662: MEMORYSTATUS memoryStatus;
663: HANDLE handle;
664: POINT point;
665:
666: /* Get various basic pieces of system information */
1.1.1.6 root 667: RandaddInt32 (GetActiveWindow ()); /* Handle of active window */
668: RandaddInt32 (GetCapture ()); /* Handle of window with mouse
1.1 root 669: capture */
1.1.1.6 root 670: RandaddInt32 (GetClipboardOwner ()); /* Handle of clipboard owner */
671: RandaddInt32 (GetClipboardViewer ()); /* Handle of start of
1.1 root 672: clpbd.viewer list */
1.1.1.6 root 673: RandaddInt32 (GetCurrentProcess ()); /* Pseudohandle of current
1.1 root 674: process */
1.1.1.6 root 675: RandaddInt32 (GetCurrentProcessId ()); /* Current process ID */
676: RandaddInt32 (GetCurrentThread ()); /* Pseudohandle of current
1.1 root 677: thread */
1.1.1.6 root 678: RandaddInt32 (GetCurrentThreadId ()); /* Current thread ID */
679: RandaddInt32 (GetCurrentTime ()); /* Milliseconds since Windows
1.1 root 680: started */
1.1.1.6 root 681: RandaddInt32 (GetDesktopWindow ()); /* Handle of desktop window */
682: RandaddInt32 (GetFocus ()); /* Handle of window with kb.focus */
683: RandaddInt32 (GetInputState ()); /* Whether sys.queue has any events */
684: RandaddInt32 (GetMessagePos ()); /* Cursor pos.for last message */
685: RandaddInt32 (GetMessageTime ()); /* 1 ms time for last message */
686: RandaddInt32 (GetOpenClipboardWindow ()); /* Handle of window with
1.1 root 687: clpbd.open */
1.1.1.6 root 688: RandaddInt32 (GetProcessHeap ()); /* Handle of process heap */
689: RandaddInt32 (GetProcessWindowStation ()); /* Handle of procs
1.1 root 690: window station */
1.1.1.6 root 691: RandaddInt32 (GetQueueStatus (QS_ALLEVENTS)); /* Types of events in
1.1 root 692: input queue */
693:
694: /* Get multiword system information */
695: GetCaretPos (&point); /* Current caret position */
696: RandaddBuf ((unsigned char *) &point, sizeof (POINT));
697: GetCursorPos (&point); /* Current mouse cursor position */
698: RandaddBuf ((unsigned char *) &point, sizeof (POINT));
699:
700: /* Get percent of memory in use, bytes of physical memory, bytes of
701: free physical memory, bytes in paging file, free bytes in paging
702: file, user bytes of address space, and free user bytes */
703: memoryStatus.dwLength = sizeof (MEMORYSTATUS);
704: GlobalMemoryStatus (&memoryStatus);
705: RandaddBuf ((unsigned char *) &memoryStatus, sizeof (MEMORYSTATUS));
706:
707: /* Get thread and process creation time, exit time, time in kernel
708: mode, and time in user mode in 100ns intervals */
709: handle = GetCurrentThread ();
710: GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime);
711: RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME));
712: RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME));
713: RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME));
714: RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME));
715: handle = GetCurrentProcess ();
716: GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime);
717: RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME));
718: RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME));
719: RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME));
720: RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME));
721:
722: /* Get the minimum and maximum working set size for the current
723: process */
724: GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
725: &maximumWorkingSetSize);
1.1.1.6 root 726: RandaddInt32 (minimumWorkingSetSize);
727: RandaddInt32 (maximumWorkingSetSize);
1.1 root 728:
729: /* The following are fixed for the lifetime of the process so we only
730: add them once */
731: if (addedFixedItems == 0)
732: {
733: STARTUPINFO startupInfo;
734:
735: /* Get name of desktop, console window title, new window
736: position and size, window flags, and handles for stdin,
737: stdout, and stderr */
738: startupInfo.cb = sizeof (STARTUPINFO);
739: GetStartupInfo (&startupInfo);
740: RandaddBuf ((unsigned char *) &startupInfo, sizeof (STARTUPINFO));
741: addedFixedItems = TRUE;
742: }
743: /* The docs say QPC can fail if appropriate hardware is not
744: available. It works on 486 & Pentium boxes, but hasn't been tested
745: for 386 or RISC boxes */
746: if (QueryPerformanceCounter (&performanceCount))
747: RandaddBuf ((unsigned char *) &performanceCount, sizeof (LARGE_INTEGER));
748: else
749: {
750: /* Millisecond accuracy at best... */
751: DWORD dwTicks = GetTickCount ();
752: RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks));
753: }
1.1.1.4 root 754:
755: // CryptoAPI
1.1.1.16 root 756: if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer))
1.1.1.4 root 757: RandaddBuf (buffer, sizeof (buffer));
1.1.1.6 root 758:
759: /* Apply the pool mixing function */
760: Randmix();
761:
762: /* Restore the original pool cursor position. If this wasn't done, mouse coordinates
763: could be written to a limited area of the pool, especially when moving the mouse
764: uninterruptedly. The severity of the problem would depend on the length of data
765: written by FastPoll (if it was equal to the size of the pool, mouse coordinates
766: would be written only to a particular 4-byte area, whenever moving the mouse
767: uninterruptedly). */
768: nRandIndex = nOriginalRandIndex;
1.1.1.9 root 769:
770: return TRUE;
1.1 root 771: }
1.1.1.9 root 772:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.