rand_win.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:25k
源码类别:

其他游戏

开发平台:

Visual C++

  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_FULLn");
  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_SECn");
  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_polln");
  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.  
  568. return (RAND_status());
  569. }
  570. void RAND_screen(void) /* function available for backward compatibility */
  571. {
  572. RAND_poll();
  573. readscreen();
  574. }
  575. /* feed timing information to the PRNG */
  576. static void readtimer(void)
  577. {
  578. DWORD w;
  579. LARGE_INTEGER l;
  580. static int have_perfc = 1;
  581. #if defined(_MSC_VER) && defined(_M_X86)
  582. static int have_tsc = 1;
  583. DWORD cyclecount;
  584. if (have_tsc) {
  585.   __try {
  586.     __asm {
  587.       _emit 0x0f
  588.       _emit 0x31
  589.       mov cyclecount, eax
  590.       }
  591.     RAND_add(&cyclecount, sizeof(cyclecount), 1);
  592.   } __except(EXCEPTION_EXECUTE_HANDLER) {
  593.     have_tsc = 0;
  594.   }
  595. }
  596. #else
  597. # define have_tsc 0
  598. #endif
  599. if (have_perfc) {
  600.   if (QueryPerformanceCounter(&l) == 0)
  601.     have_perfc = 0;
  602.   else
  603.     RAND_add(&l, sizeof(l), 0);
  604. }
  605. if (!have_tsc && !have_perfc) {
  606.   w = GetTickCount();
  607.   RAND_add(&w, sizeof(w), 0);
  608. }
  609. }
  610. /* feed screen contents to PRNG */
  611. /*****************************************************************************
  612.  *
  613.  * Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V.
  614.  *
  615.  * Code adapted from
  616.  * <URL:http://support.microsoft.com/default.aspx?scid=kb;[LN];97193>;
  617.  * the original copyright message is:
  618.  *
  619.  *   (C) Copyright Microsoft Corp. 1993.  All rights reserved.
  620.  *
  621.  *   You have a royalty-free right to use, modify, reproduce and
  622.  *   distribute the Sample Files (and/or any modified version) in
  623.  *   any way you find useful, provided that you agree that
  624.  *   Microsoft has no warranty obligations or liability for any
  625.  *   Sample Application Files which are modified.
  626.  */
  627. static void readscreen(void)
  628. {
  629. #if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN)
  630.   HDC hScrDC; /* screen DC */
  631.   HDC hMemDC; /* memory DC */
  632.   HBITMAP hBitmap; /* handle for our bitmap */
  633.   HBITMAP hOldBitmap; /* handle for previous bitmap */
  634.   BITMAP bm; /* bitmap properties */
  635.   unsigned int size; /* size of bitmap */
  636.   char *bmbits; /* contents of bitmap */
  637.   int w; /* screen width */
  638.   int h; /* screen height */
  639.   int y; /* y-coordinate of screen lines to grab */
  640.   int n = 16; /* number of screen lines to grab at a time */
  641.   if (GetVersion() >= 0x80000000 || !OPENSSL_isservice())
  642.     return;
  643.   /* Create a screen DC and a memory DC compatible to screen DC */
  644.   hScrDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  645.   hMemDC = CreateCompatibleDC(hScrDC);
  646.   /* Get screen resolution */
  647.   w = GetDeviceCaps(hScrDC, HORZRES);
  648.   h = GetDeviceCaps(hScrDC, VERTRES);
  649.   /* Create a bitmap compatible with the screen DC */
  650.   hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
  651.   /* Select new bitmap into memory DC */
  652.   hOldBitmap = SelectObject(hMemDC, hBitmap);
  653.   /* Get bitmap properties */
  654.   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
  655.   size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
  656.   bmbits = OPENSSL_malloc(size);
  657.   if (bmbits) {
  658.     /* Now go through the whole screen, repeatedly grabbing n lines */
  659.     for (y = 0; y < h-n; y += n)
  660.      {
  661. unsigned char md[MD_DIGEST_LENGTH];
  662. /* Bitblt screen DC to memory DC */
  663. BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY);
  664. /* Copy bitmap bits from memory DC to bmbits */
  665. GetBitmapBits(hBitmap, size, bmbits);
  666. /* Get the hash of the bitmap */
  667. MD(bmbits,size,md);
  668. /* Seed the random generator with the hash value */
  669. RAND_add(md, MD_DIGEST_LENGTH, 0);
  670. }
  671.     OPENSSL_free(bmbits);
  672.   }
  673.   /* Select old bitmap back into memory DC */
  674.   hBitmap = SelectObject(hMemDC, hOldBitmap);
  675.   /* Clean up */
  676.   DeleteObject(hBitmap);
  677.   DeleteDC(hMemDC);
  678.   DeleteDC(hScrDC);
  679. #endif /* !OPENSSL_SYS_WINCE */
  680. }
  681. #endif