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