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