rand_win.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. /* crypto/rand/rand_win.c */
  2. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  3. * All rights reserved.
  4. *
  5. * This package is an SSL implementation written
  6. * by Eric Young (eay@cryptsoft.com).
  7. * The implementation was written so as to conform with Netscapes SSL.
  8. *
  9. * This library is free for commercial and non-commercial use as long as
  10. * the following conditions are aheared to. The following conditions
  11. * apply to all code found in this distribution, be it the RC4, RSA,
  12. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  13. * included with this distribution is covered by the same copyright terms
  14. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  15. *
  16. * Copyright remains Eric Young's, and as such any Copyright notices in
  17. * the code are not to be removed.
  18. * If this package is used in a product, Eric Young should be given attribution
  19. * as the author of the parts of the library used.
  20. * This can be in the form of a textual message at program startup or
  21. * in documentation (online or textual) provided with the package.
  22. *
  23. * Redistribution and use in source and binary forms, with or without
  24. * modification, are permitted provided that the following conditions
  25. * are met:
  26. * 1. Redistributions of source code must retain the copyright
  27. * notice, this list of conditions and the following disclaimer.
  28. * 2. Redistributions in binary form must reproduce the above copyright
  29. * notice, this list of conditions and the following disclaimer in the
  30. * documentation and/or other materials provided with the distribution.
  31. * 3. All advertising materials mentioning features or use of this software
  32. * must display the following acknowledgement:
  33. * "This product includes cryptographic software written by
  34. * Eric Young (eay@cryptsoft.com)"
  35. * The word 'cryptographic' can be left out if the rouines from the library
  36. * being used are not cryptographic related :-).
  37. * 4. If you include any Windows specific code (or a derivative thereof) from
  38. * the apps directory (application code) you must include an acknowledgement:
  39. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  40. *
  41. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  42. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  45. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  46. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  47. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  49. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  50. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51. * SUCH DAMAGE.
  52. *
  53. * The licence and distribution terms for any publically available version or
  54. * derivative of this code cannot be changed. i.e. this code cannot simply be
  55. * copied and put under another distribution licence
  56. * [including the GNU Public Licence.]
  57. */
  58. /* ====================================================================
  59. * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
  60. *
  61. * Redistribution and use in source and binary forms, with or without
  62. * modification, are permitted provided that the following conditions
  63. * are met:
  64. *
  65. * 1. Redistributions of source code must retain the above copyright
  66. * notice, this list of conditions and the following disclaimer.
  67. *
  68. * 2. Redistributions in binary form must reproduce the above copyright
  69. * notice, this list of conditions and the following disclaimer in
  70. * the documentation and/or other materials provided with the
  71. * distribution.
  72. *
  73. * 3. All advertising materials mentioning features or use of this
  74. * software must display the following acknowledgment:
  75. * "This product includes software developed by the OpenSSL Project
  76. * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  77. *
  78. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  79. * endorse or promote products derived from this software without
  80. * prior written permission. For written permission, please contact
  81. * openssl-core@openssl.org.
  82. *
  83. * 5. Products derived from this software may not be called "OpenSSL"
  84. * nor may "OpenSSL" appear in their names without prior written
  85. * permission of the OpenSSL Project.
  86. *
  87. * 6. Redistributions of any form whatsoever must retain the following
  88. * acknowledgment:
  89. * "This product includes software developed by the OpenSSL Project
  90. * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  91. *
  92. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  93. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  94. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  95. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  96. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  97. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  98. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  99. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  100. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  101. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  102. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  103. * OF THE POSSIBILITY OF SUCH DAMAGE.
  104. * ====================================================================
  105. *
  106. * This product includes cryptographic software written by Eric Young
  107. * (eay@cryptsoft.com). This product includes software written by Tim
  108. * Hudson (tjh@cryptsoft.com).
  109. *
  110. */
  111. #include "cryptlib.h"
  112. #include <openssl/rand.h>
  113. #include "rand_lcl.h"
  114. #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
  115. #include <windows.h>
  116. #ifndef _WIN32_WINNT
  117. # define _WIN32_WINNT 0x0400
  118. #endif
  119. #include <wincrypt.h>
  120. #include <tlhelp32.h>
  121. /* Limit the time spent walking through the heap, processes, threads and modules to
  122. a maximum of 1000 miliseconds each, unless CryptoGenRandom failed */
  123. #define MAXDELAY 1000
  124. /* Intel hardware RNG CSP -- available from
  125. * http://developer.intel.com/design/security/rng/redist_license.htm
  126. */
  127. #define PROV_INTEL_SEC 22
  128. #define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider"
  129. static void readtimer(void);
  130. static void readscreen(void);
  131. /* It appears like CURSORINFO, PCURSORINFO and LPCURSORINFO are only defined
  132. when WINVER is 0x0500 and up, which currently only happens on Win2000.
  133. Unfortunately, those are typedefs, so they're a little bit difficult to
  134. detect properly. On the other hand, the macro CURSOR_SHOWING is defined
  135. within the same conditional, so it can be use to detect the absence of said
  136. typedefs. */
  137. #ifndef CURSOR_SHOWING
  138. /*
  139. * Information about the global cursor.
  140. */
  141. typedef struct tagCURSORINFO
  142. {
  143. DWORD cbSize;
  144. DWORD flags;
  145. HCURSOR hCursor;
  146. POINT ptScreenPos;
  147. } CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
  148. #define CURSOR_SHOWING 0x00000001
  149. #endif /* CURSOR_SHOWING */
  150. #if !defined(OPENSSL_SYS_WINCE)
  151. typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTW)(HCRYPTPROV *, LPCWSTR, LPCWSTR,
  152. DWORD, DWORD);
  153. typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV, DWORD, BYTE *);
  154. typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV, DWORD);
  155. typedef HWND (WINAPI *GETFOREGROUNDWINDOW)(VOID);
  156. typedef BOOL (WINAPI *GETCURSORINFO)(PCURSORINFO);
  157. typedef DWORD (WINAPI *GETQUEUESTATUS)(UINT);
  158. typedef HANDLE (WINAPI *CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD);
  159. typedef BOOL (WINAPI *CLOSETOOLHELP32SNAPSHOT)(HANDLE);
  160. typedef BOOL (WINAPI *HEAP32FIRST)(LPHEAPENTRY32, DWORD, size_t);
  161. typedef BOOL (WINAPI *HEAP32NEXT)(LPHEAPENTRY32);
  162. typedef BOOL (WINAPI *HEAP32LIST)(HANDLE, LPHEAPLIST32);
  163. typedef BOOL (WINAPI *PROCESS32)(HANDLE, LPPROCESSENTRY32);
  164. typedef BOOL (WINAPI *THREAD32)(HANDLE, LPTHREADENTRY32);
  165. typedef BOOL (WINAPI *MODULE32)(HANDLE, LPMODULEENTRY32);
  166. #include <lmcons.h>
  167. #include <lmstats.h>
  168. #if 1 /* The NET API is Unicode only. It requires the use of the UNICODE
  169. * macro. When UNICODE is defined LPTSTR becomes LPWSTR. LMSTR was
  170. * was added to the Platform SDK to allow the NET API to be used in
  171. * non-Unicode applications provided that Unicode strings were still
  172. * used for input. LMSTR is defined as LPWSTR.
  173. */
  174. typedef NET_API_STATUS (NET_API_FUNCTION * NETSTATGET)
  175. (LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE*);
  176. typedef NET_API_STATUS (NET_API_FUNCTION * NETFREE)(LPBYTE);
  177. #endif /* 1 */
  178. #endif /* !OPENSSL_SYS_WINCE */
  179. int RAND_poll(void)
  180. {
  181. MEMORYSTATUS m;
  182. HCRYPTPROV hProvider = 0;
  183. DWORD w;
  184. int good = 0;
  185. /* Determine the OS version we are on so we can turn off things
  186. * that do not work properly.
  187. */
  188. OSVERSIONINFO osverinfo ;
  189. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
  190. GetVersionEx( &osverinfo ) ;
  191. #if defined(OPENSSL_SYS_WINCE)
  192. # if defined(_WIN32_WCE) && _WIN32_WCE>=300
  193. /* Even though MSDN says _WIN32_WCE>=210, it doesn't seem to be available
  194. * in commonly available implementations prior 300... */
  195. {
  196. BYTE buf[64];
  197. /* poll the CryptoAPI PRNG */
  198. /* The CryptoAPI returns sizeof(buf) bytes of randomness */
  199. if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL,
  200. CRYPT_VERIFYCONTEXT))
  201. {
  202. if (CryptGenRandom(hProvider, sizeof(buf), buf))
  203. RAND_add(buf, sizeof(buf), sizeof(buf));
  204. CryptReleaseContext(hProvider, 0);
  205. }
  206. }
  207. # endif
  208. #else /* OPENSSL_SYS_WINCE */
  209. /*
  210. * None of below libraries are present on Windows CE, which is
  211. * why we #ifndef the whole section. This also excuses us from
  212. * handling the GetProcAddress issue. The trouble is that in
  213. * real Win32 API GetProcAddress is available in ANSI flavor
  214. * only. In WinCE on the other hand GetProcAddress is a macro
  215. * most commonly defined as GetProcAddressW, which accepts
  216. * Unicode argument. If we were to call GetProcAddress under
  217. * WinCE, I'd recommend to either redefine GetProcAddress as
  218. * GetProcAddressA (there seem to be one in common CE spec) or
  219. * implement own shim routine, which would accept ANSI argument
  220. * and expand it to Unicode.
  221. */
  222. {
  223. /* load functions dynamically - not available on all systems */
  224. HMODULE advapi = LoadLibrary(TEXT("ADVAPI32.DLL"));
  225. HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL"));
  226. HMODULE user = NULL;
  227. HMODULE netapi = LoadLibrary(TEXT("NETAPI32.DLL"));
  228. CRYPTACQUIRECONTEXTW acquire = NULL;
  229. CRYPTGENRANDOM gen = NULL;
  230. CRYPTRELEASECONTEXT release = NULL;
  231. NETSTATGET netstatget = NULL;
  232. NETFREE netfree = NULL;
  233. BYTE buf[64];
  234. if (netapi)
  235. {
  236. netstatget = (NETSTATGET) GetProcAddress(netapi,"NetStatisticsGet");
  237. netfree = (NETFREE) GetProcAddress(netapi,"NetApiBufferFree");
  238. }
  239. if (netstatget && netfree)
  240. {
  241. LPBYTE outbuf;
  242. /* NetStatisticsGet() is a Unicode only function
  243. * STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0
  244. * contains 17 fields. We treat each field as a source of
  245. * one byte of entropy.
  246. */
  247. if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0)
  248. {
  249. RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45);
  250. netfree(outbuf);
  251. }
  252. if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0)
  253. {
  254. RAND_add(outbuf, sizeof(STAT_SERVER_0), 17);
  255. netfree(outbuf);
  256. }
  257. }
  258. if (netapi)
  259. FreeLibrary(netapi);
  260. /* It appears like this can cause an exception deep within ADVAPI32.DLL
  261. * at random times on Windows 2000. Reported by Jeffrey Altman.
  262. * Only use it on NT.
  263. */
  264. /* Wolfgang Marczy <WMarczy@topcall.co.at> reports that
  265. * the RegQueryValueEx call below can hang on NT4.0 (SP6).
  266. * So we don't use this at all for now. */
  267. #if 0
  268. if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  269. osverinfo.dwMajorVersion < 5)
  270. {
  271. /* Read Performance Statistics from NT/2000 registry
  272. * The size of the performance data can vary from call
  273. * to call so we must guess the size of the buffer to use
  274. * and increase its size if we get an ERROR_MORE_DATA
  275. * return instead of ERROR_SUCCESS.
  276. */
  277. LONG rc=ERROR_MORE_DATA;
  278. char * buf=NULL;
  279. DWORD bufsz=0;
  280. DWORD length;
  281. while (rc == ERROR_MORE_DATA)
  282. {
  283. buf = realloc(buf,bufsz+8192);
  284. if (!buf)
  285. break;
  286. bufsz += 8192;
  287. length = bufsz;
  288. rc = RegQueryValueEx(HKEY_PERFORMANCE_DATA, TEXT("Global"),
  289. NULL, NULL, buf, &length);
  290. }
  291. if (rc == ERROR_SUCCESS)
  292. {
  293. /* For entropy count assume only least significant
  294. * byte of each DWORD is random.
  295. */
  296. RAND_add(&length, sizeof(length), 0);
  297. RAND_add(buf, length, length / 4.0);
  298. /* Close the Registry Key to allow Windows to cleanup/close
  299. * the open handle
  300. * Note: The 'HKEY_PERFORMANCE_DATA' key is implicitly opened
  301. * when the RegQueryValueEx above is done. However, if
  302. * it is not explicitly closed, it can cause disk
  303. * partition manipulation problems.
  304. */
  305. RegCloseKey(HKEY_PERFORMANCE_DATA);
  306. }
  307. if (buf)
  308. free(buf);
  309. }
  310. #endif
  311. if (advapi)
  312. {
  313. /*
  314. * If it's available, then it's available in both ANSI
  315. * and UNICODE flavors even in Win9x, documentation says.
  316. * We favor Unicode...
  317. */
  318. acquire = (CRYPTACQUIRECONTEXTW) GetProcAddress(advapi,
  319. "CryptAcquireContextW");
  320. gen = (CRYPTGENRANDOM) GetProcAddress(advapi,
  321. "CryptGenRandom");
  322. release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi,
  323. "CryptReleaseContext");
  324. }
  325. if (acquire && gen && release)
  326. {
  327. /* poll the CryptoAPI PRNG */
  328. /* The CryptoAPI returns sizeof(buf) bytes of randomness */
  329. if (acquire(&hProvider, NULL, NULL, PROV_RSA_FULL,
  330. CRYPT_VERIFYCONTEXT))
  331. {
  332. if (gen(hProvider, sizeof(buf), buf) != 0)
  333. {
  334. RAND_add(buf, sizeof(buf), 0);
  335. good = 1;
  336. #if 0
  337. printf("randomness from PROV_RSA_FULL\n");
  338. #endif
  339. }
  340. release(hProvider, 0);
  341. }
  342. /* poll the Pentium PRG with CryptoAPI */
  343. if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0))
  344. {
  345. if (gen(hProvider, sizeof(buf), buf) != 0)
  346. {
  347. RAND_add(buf, sizeof(buf), sizeof(buf));
  348. good = 1;
  349. #if 0
  350. printf("randomness from PROV_INTEL_SEC\n");
  351. #endif
  352. }
  353. release(hProvider, 0);
  354. }
  355. }
  356. if (advapi)
  357. FreeLibrary(advapi);
  358. if ((osverinfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
  359. !OPENSSL_isservice()) &&
  360. (user = LoadLibrary(TEXT("USER32.DLL"))))
  361. {
  362. GETCURSORINFO cursor;
  363. GETFOREGROUNDWINDOW win;
  364. GETQUEUESTATUS queue;
  365. win = (GETFOREGROUNDWINDOW) GetProcAddress(user, "GetForegroundWindow");
  366. cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo");
  367. queue = (GETQUEUESTATUS) GetProcAddress(user, "GetQueueStatus");
  368. if (win)
  369. {
  370. /* window handle */
  371. HWND h = win();
  372. RAND_add(&h, sizeof(h), 0);
  373. }
  374. if (cursor)
  375. {
  376. /* unfortunately, its not safe to call GetCursorInfo()
  377. * on NT4 even though it exists in SP3 (or SP6) and
  378. * higher.
  379. */
  380. if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  381. osverinfo.dwMajorVersion < 5)
  382. cursor = 0;
  383. }
  384. if (cursor)
  385. {
  386. /* cursor position */
  387. /* assume 2 bytes of entropy */
  388. CURSORINFO ci;
  389. ci.cbSize = sizeof(CURSORINFO);
  390. if (cursor(&ci))
  391. RAND_add(&ci, ci.cbSize, 2);
  392. }
  393. if (queue)
  394. {
  395. /* message queue status */
  396. /* assume 1 byte of entropy */
  397. w = queue(QS_ALLEVENTS);
  398. RAND_add(&w, sizeof(w), 1);
  399. }
  400. FreeLibrary(user);
  401. }
  402. /* Toolhelp32 snapshot: enumerate processes, threads, modules and heap
  403. * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm
  404. * (Win 9x and 2000 only, not available on NT)
  405. *
  406. * This seeding method was proposed in Peter Gutmann, Software
  407. * Generation of Practically Strong Random Numbers,
  408. * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html
  409. * revised version at http://www.cryptoengines.com/~peter/06_random.pdf
  410. * (The assignment of entropy estimates below is arbitrary, but based
  411. * on Peter's analysis the full poll appears to be safe. Additional
  412. * interactive seeding is encouraged.)
  413. */
  414. if (kernel)
  415. {
  416. CREATETOOLHELP32SNAPSHOT snap;
  417. CLOSETOOLHELP32SNAPSHOT close_snap;
  418. HANDLE handle;
  419. HEAP32FIRST heap_first;
  420. HEAP32NEXT heap_next;
  421. HEAP32LIST heaplist_first, heaplist_next;
  422. PROCESS32 process_first, process_next;
  423. THREAD32 thread_first, thread_next;
  424. MODULE32 module_first, module_next;
  425. HEAPLIST32 hlist;
  426. HEAPENTRY32 hentry;
  427. PROCESSENTRY32 p;
  428. THREADENTRY32 t;
  429. MODULEENTRY32 m;
  430. DWORD stoptime = 0;
  431. snap = (CREATETOOLHELP32SNAPSHOT)
  432. GetProcAddress(kernel, "CreateToolhelp32Snapshot");
  433. close_snap = (CLOSETOOLHELP32SNAPSHOT)
  434. GetProcAddress(kernel, "CloseToolhelp32Snapshot");
  435. heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First");
  436. heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next");
  437. heaplist_first = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst");
  438. heaplist_next = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext");
  439. process_first = (PROCESS32) GetProcAddress(kernel, "Process32First");
  440. process_next = (PROCESS32) GetProcAddress(kernel, "Process32Next");
  441. thread_first = (THREAD32) GetProcAddress(kernel, "Thread32First");
  442. thread_next = (THREAD32) GetProcAddress(kernel, "Thread32Next");
  443. module_first = (MODULE32) GetProcAddress(kernel, "Module32First");
  444. module_next = (MODULE32) GetProcAddress(kernel, "Module32Next");
  445. if (snap && heap_first && heap_next && heaplist_first &&
  446. heaplist_next && process_first && process_next &&
  447. thread_first && thread_next && module_first &&
  448. module_next && (handle = snap(TH32CS_SNAPALL,0))
  449. != INVALID_HANDLE_VALUE)
  450. {
  451. /* heap list and heap walking */
  452. /* HEAPLIST32 contains 3 fields that will change with
  453. * each entry. Consider each field a source of 1 byte
  454. * of entropy.
  455. * HEAPENTRY32 contains 5 fields that will change with
  456. * each entry. Consider each field a source of 1 byte
  457. * of entropy.
  458. */
  459. hlist.dwSize = sizeof(HEAPLIST32);
  460. if (good) stoptime = GetTickCount() + MAXDELAY;
  461. if (heaplist_first(handle, &hlist))
  462. do
  463. {
  464. RAND_add(&hlist, hlist.dwSize, 3);
  465. hentry.dwSize = sizeof(HEAPENTRY32);
  466. if (heap_first(&hentry,
  467. hlist.th32ProcessID,
  468. hlist.th32HeapID))
  469. {
  470. int entrycnt = 80;
  471. do
  472. RAND_add(&hentry,
  473. hentry.dwSize, 5);
  474. while (heap_next(&hentry)
  475. && --entrycnt > 0);
  476. }
  477. } while (heaplist_next(handle,
  478. &hlist) && GetTickCount() < stoptime);
  479. /* process walking */
  480. /* PROCESSENTRY32 contains 9 fields that will change
  481. * with each entry. Consider each field a source of
  482. * 1 byte of entropy.
  483. */
  484. p.dwSize = sizeof(PROCESSENTRY32);
  485. if (good) stoptime = GetTickCount() + MAXDELAY;
  486. if (process_first(handle, &p))
  487. do
  488. RAND_add(&p, p.dwSize, 9);
  489. while (process_next(handle, &p) && GetTickCount() < stoptime);
  490. /* thread walking */
  491. /* THREADENTRY32 contains 6 fields that will change
  492. * with each entry. Consider each field a source of
  493. * 1 byte of entropy.
  494. */
  495. t.dwSize = sizeof(THREADENTRY32);
  496. if (good) stoptime = GetTickCount() + MAXDELAY;
  497. if (thread_first(handle, &t))
  498. do
  499. RAND_add(&t, t.dwSize, 6);
  500. while (thread_next(handle, &t) && GetTickCount() < stoptime);
  501. /* module walking */
  502. /* MODULEENTRY32 contains 9 fields that will change
  503. * with each entry. Consider each field a source of
  504. * 1 byte of entropy.
  505. */
  506. m.dwSize = sizeof(MODULEENTRY32);
  507. if (good) stoptime = GetTickCount() + MAXDELAY;
  508. if (module_first(handle, &m))
  509. do
  510. RAND_add(&m, m.dwSize, 9);
  511. while (module_next(handle, &m)
  512. && (GetTickCount() < stoptime));
  513. if (close_snap)
  514. close_snap(handle);
  515. else
  516. CloseHandle(handle);
  517. }
  518. FreeLibrary(kernel);
  519. }
  520. }
  521. #endif /* !OPENSSL_SYS_WINCE */
  522. /* timer data */
  523. readtimer();
  524. /* memory usage statistics */
  525. GlobalMemoryStatus(&m);
  526. RAND_add(&m, sizeof(m), 1);
  527. /* process ID */
  528. w = GetCurrentProcessId();
  529. RAND_add(&w, sizeof(w), 1);
  530. #if 0
  531. printf("Exiting RAND_poll\n");
  532. #endif
  533. return(1);
  534. }
  535. int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
  536. {
  537. double add_entropy=0;
  538. switch (iMsg)
  539. {
  540. case WM_KEYDOWN:
  541. {
  542. static WPARAM key;
  543. if (key != wParam)
  544. add_entropy = 0.05;
  545. key = wParam;
  546. }
  547. break;
  548. case WM_MOUSEMOVE:
  549. {
  550. static int lastx,lasty,lastdx,lastdy;
  551. int x,y,dx,dy;
  552. x=LOWORD(lParam);
  553. y=HIWORD(lParam);
  554. dx=lastx-x;
  555. dy=lasty-y;
  556. if (dx != 0 && dy != 0 && dx-lastdx != 0 && dy-lastdy != 0)
  557. add_entropy=.2;
  558. lastx=x, lasty=y;
  559. lastdx=dx, lastdy=dy;
  560. }
  561. break;
  562. }
  563. readtimer();
  564. RAND_add(&iMsg, sizeof(iMsg), add_entropy);
  565. RAND_add(&wParam, sizeof(wParam), 0);
  566. RAND_add(&lParam, sizeof(lParam), 0);
  567. return (RAND_status());
  568. }
  569. void RAND_screen(void) /* function available for backward compatibility */
  570. {
  571. RAND_poll();
  572. readscreen();
  573. }
  574. /* feed timing information to the PRNG */
  575. static void readtimer(void)
  576. {
  577. DWORD w;
  578. LARGE_INTEGER l;
  579. static int have_perfc = 1;
  580. #if defined(_MSC_VER) && defined(_M_X86)
  581. static int have_tsc = 1;
  582. DWORD cyclecount;
  583. if (have_tsc) {
  584. __try {
  585. __asm {
  586. _emit 0x0f
  587. _emit 0x31
  588. mov cyclecount, eax
  589. }
  590. RAND_add(&cyclecount, sizeof(cyclecount), 1);
  591. } __except(EXCEPTION_EXECUTE_HANDLER) {
  592. have_tsc = 0;
  593. }
  594. }
  595. #else
  596. # define have_tsc 0
  597. #endif
  598. if (have_perfc) {
  599. if (QueryPerformanceCounter(&l) == 0)
  600. have_perfc = 0;
  601. else
  602. RAND_add(&l, sizeof(l), 0);
  603. }
  604. if (!have_tsc && !have_perfc) {
  605. w = GetTickCount();
  606. RAND_add(&w, sizeof(w), 0);
  607. }
  608. }
  609. /* feed screen contents to PRNG */
  610. /*****************************************************************************
  611. *
  612. * Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V.
  613. *
  614. * Code adapted from
  615. * <URL:http://support.microsoft.com/default.aspx?scid=kb;[LN];97193>;
  616. * the original copyright message is:
  617. *
  618. * (C) Copyright Microsoft Corp. 1993. All rights reserved.
  619. *
  620. * You have a royalty-free right to use, modify, reproduce and
  621. * distribute the Sample Files (and/or any modified version) in
  622. * any way you find useful, provided that you agree that
  623. * Microsoft has no warranty obligations or liability for any
  624. * Sample Application Files which are modified.
  625. */
  626. static void readscreen(void)
  627. {
  628. #if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN)
  629. HDC hScrDC; /* screen DC */
  630. HDC hMemDC; /* memory DC */
  631. HBITMAP hBitmap; /* handle for our bitmap */
  632. HBITMAP hOldBitmap; /* handle for previous bitmap */
  633. BITMAP bm; /* bitmap properties */
  634. unsigned int size; /* size of bitmap */
  635. char *bmbits; /* contents of bitmap */
  636. int w; /* screen width */
  637. int h; /* screen height */
  638. int y; /* y-coordinate of screen lines to grab */
  639. int n = 16; /* number of screen lines to grab at a time */
  640. if (GetVersion() >= 0x80000000 || !OPENSSL_isservice())
  641. return;
  642. /* Create a screen DC and a memory DC compatible to screen DC */
  643. hScrDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  644. hMemDC = CreateCompatibleDC(hScrDC);
  645. /* Get screen resolution */
  646. w = GetDeviceCaps(hScrDC, HORZRES);
  647. h = GetDeviceCaps(hScrDC, VERTRES);
  648. /* Create a bitmap compatible with the screen DC */
  649. hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
  650. /* Select new bitmap into memory DC */
  651. hOldBitmap = SelectObject(hMemDC, hBitmap);
  652. /* Get bitmap properties */
  653. GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
  654. size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
  655. bmbits = OPENSSL_malloc(size);
  656. if (bmbits) {
  657. /* Now go through the whole screen, repeatedly grabbing n lines */
  658. for (y = 0; y < h-n; y += n)
  659. {
  660. unsigned char md[MD_DIGEST_LENGTH];
  661. /* Bitblt screen DC to memory DC */
  662. BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY);
  663. /* Copy bitmap bits from memory DC to bmbits */
  664. GetBitmapBits(hBitmap, size, bmbits);
  665. /* Get the hash of the bitmap */
  666. MD(bmbits,size,md);
  667. /* Seed the random generator with the hash value */
  668. RAND_add(md, MD_DIGEST_LENGTH, 0);
  669. }
  670. OPENSSL_free(bmbits);
  671. }
  672. /* Select old bitmap back into memory DC */
  673. hBitmap = SelectObject(hMemDC, hOldBitmap);
  674. /* Clean up */
  675. DeleteObject(hBitmap);
  676. DeleteDC(hMemDC);
  677. DeleteDC(hScrDC);
  678. #endif /* !OPENSSL_SYS_WINCE */
  679. }
  680. #endif