PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/Common/Random.c

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