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.  
  112. #include "cryptlib.h"
  113. #include <openssl/rand.h>
  114. #include "rand_lcl.h"
  115.  
  116. #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
  117. #include <windows.h>
  118. #ifndef _WIN32_WINNT
  119. # define _WIN32_WINNT 0x0400
  120. #endif
  121. #include <wincrypt.h>
  122. #include <tlhelp32.h>
  123.  
  124. /* Limit the time spent walking through the heap, processes, threads and modules to
  125.    a maximum of 1000 miliseconds each, unless CryptoGenRandom failed */
  126. #define MAXDELAY 1000
  127.  
  128. /* Intel hardware RNG CSP -- available from
  129.  * http://developer.intel.com/design/security/rng/redist_license.htm
  130.  */
  131. #define PROV_INTEL_SEC 22
  132. #define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider"
  133.  
  134. static void readtimer(void);
  135. static void readscreen(void);
  136.  
  137. /* It appears like CURSORINFO, PCURSORINFO and LPCURSORINFO are only defined
  138.    when WINVER is 0x0500 and up, which currently only happens on Win2000.
  139.    Unfortunately, those are typedefs, so they're a little bit difficult to
  140.    detect properly.  On the other hand, the macro CURSOR_SHOWING is defined
  141.    within the same conditional, so it can be use to detect the absence of said
  142.    typedefs. */
  143.  
  144. #ifndef CURSOR_SHOWING
  145. /*
  146.  * Information about the global cursor.
  147.  */
  148. typedef struct tagCURSORINFO
  149. {
  150.     DWORD   cbSize;
  151.     DWORD   flags;
  152.     HCURSOR hCursor;
  153.     POINT   ptScreenPos;
  154. } CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
  155.  
  156. #define CURSOR_SHOWING     0x00000001
  157. #endif /* CURSOR_SHOWING */
  158.  
  159. #if !defined(OPENSSL_SYS_WINCE)
  160. typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTW)(HCRYPTPROV *, LPCWSTR, LPCWSTR,
  161.                     DWORD, DWORD);
  162. typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV, DWORD, BYTE *);
  163. typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV, DWORD);
  164.  
  165. typedef HWND (WINAPI *GETFOREGROUNDWINDOW)(VOID);
  166. typedef BOOL (WINAPI *GETCURSORINFO)(PCURSORINFO);
  167. typedef DWORD (WINAPI *GETQUEUESTATUS)(UINT);
  168.  
  169. typedef HANDLE (WINAPI *CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD);
  170. typedef BOOL (WINAPI *CLOSETOOLHELP32SNAPSHOT)(HANDLE);
  171. typedef BOOL (WINAPI *HEAP32FIRST)(LPHEAPENTRY32, DWORD, size_t);
  172. typedef BOOL (WINAPI *HEAP32NEXT)(LPHEAPENTRY32);
  173. typedef BOOL (WINAPI *HEAP32LIST)(HANDLE, LPHEAPLIST32);
  174. typedef BOOL (WINAPI *PROCESS32)(HANDLE, LPPROCESSENTRY32);
  175. typedef BOOL (WINAPI *THREAD32)(HANDLE, LPTHREADENTRY32);
  176. typedef BOOL (WINAPI *MODULE32)(HANDLE, LPMODULEENTRY32);
  177.  
  178. #include <lmcons.h>
  179. #include <lmstats.h>
  180. #if 1 /* The NET API is Unicode only.  It requires the use of the UNICODE
  181.        * macro.  When UNICODE is defined LPTSTR becomes LPWSTR.  LMSTR was
  182.        * was added to the Platform SDK to allow the NET API to be used in
  183.        * non-Unicode applications provided that Unicode strings were still
  184.        * used for input.  LMSTR is defined as LPWSTR.
  185.        */
  186. typedef NET_API_STATUS (NET_API_FUNCTION * NETSTATGET)
  187.         (LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE*);
  188. typedef NET_API_STATUS (NET_API_FUNCTION * NETFREE)(LPBYTE);
  189. #endif /* 1 */
  190. #endif /* !OPENSSL_SYS_WINCE */
  191.  
  192. int RAND_poll(void)
  193. {
  194.     MEMORYSTATUS m;
  195.     HCRYPTPROV hProvider = 0;
  196.     DWORD w;
  197.     int good = 0;
  198.  
  199.     /* Determine the OS version we are on so we can turn off things
  200.      * that do not work properly.
  201.      */
  202.         OSVERSIONINFO osverinfo ;
  203.         osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
  204.         GetVersionEx( &osverinfo ) ;
  205.  
  206. #if defined(OPENSSL_SYS_WINCE)
  207. # if defined(_WIN32_WCE) && _WIN32_WCE>=300
  208. /* Even though MSDN says _WIN32_WCE>=210, it doesn't seem to be available
  209.  * in commonly available implementations prior 300... */
  210.     {
  211.     BYTE buf[64];
  212.     /* poll the CryptoAPI PRNG */
  213.     /* The CryptoAPI returns sizeof(buf) bytes of randomness */
  214.     if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL,
  215.                 CRYPT_VERIFYCONTEXT))
  216.         {
  217.         if (CryptGenRandom(hProvider, sizeof(buf), buf))
  218.             RAND_add(buf, sizeof(buf), sizeof(buf));
  219.         CryptReleaseContext(hProvider, 0);
  220.         }
  221.     }
  222. # endif
  223. #else   /* OPENSSL_SYS_WINCE */
  224.     /*
  225.      * None of below libraries are present on Windows CE, which is
  226.      * why we #ifndef the whole section. This also excuses us from
  227.      * handling the GetProcAddress issue. The trouble is that in
  228.      * real Win32 API GetProcAddress is available in ANSI flavor
  229.      * only. In WinCE on the other hand GetProcAddress is a macro
  230.      * most commonly defined as GetProcAddressW, which accepts
  231.      * Unicode argument. If we were to call GetProcAddress under
  232.      * WinCE, I'd recommend to either redefine GetProcAddress as
  233.      * GetProcAddressA (there seem to be one in common CE spec) or
  234.      * implement own shim routine, which would accept ANSI argument
  235.      * and expand it to Unicode.
  236.      */
  237.     {
  238.     /* load functions dynamically - not available on all systems */
  239.     HMODULE advapi = LoadLibrary(TEXT("ADVAPI32.DLL"));
  240.     HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL"));
  241.     HMODULE user = NULL;
  242.     HMODULE netapi = LoadLibrary(TEXT("NETAPI32.DLL"));
  243.     CRYPTACQUIRECONTEXTW acquire = NULL;
  244.     CRYPTGENRANDOM gen = NULL;
  245.     CRYPTRELEASECONTEXT release = NULL;
  246.     NETSTATGET netstatget = NULL;
  247.     NETFREE netfree = NULL;
  248.     BYTE buf[64];
  249.  
  250.     if (netapi)
  251.         {
  252.         netstatget = (NETSTATGET) GetProcAddress(netapi,"NetStatisticsGet");
  253.         netfree = (NETFREE) GetProcAddress(netapi,"NetApiBufferFree");
  254.         }
  255.  
  256.     if (netstatget && netfree)
  257.         {
  258.         LPBYTE outbuf;
  259.         /* NetStatisticsGet() is a Unicode only function
  260.          * STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0
  261.          * contains 17 fields.  We treat each field as a source of
  262.          * one byte of entropy.
  263.                  */
  264.  
  265.         if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0)
  266.             {
  267.             RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45);
  268.             netfree(outbuf);
  269.             }
  270.         if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0)
  271.             {
  272.             RAND_add(outbuf, sizeof(STAT_SERVER_0), 17);
  273.             netfree(outbuf);
  274.             }
  275.         }
  276.  
  277.     if (netapi)
  278.         FreeLibrary(netapi);
  279.  
  280.         /* It appears like this can cause an exception deep within ADVAPI32.DLL
  281.          * at random times on Windows 2000.  Reported by Jeffrey Altman.  
  282.          * Only use it on NT.
  283.      */
  284.     /* Wolfgang Marczy <WMarczy@topcall.co.at> reports that
  285.      * the RegQueryValueEx call below can hang on NT4.0 (SP6).
  286.      * So we don't use this at all for now. */
  287. #if 0
  288.         if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  289.         osverinfo.dwMajorVersion < 5)
  290.         {
  291.         /* Read Performance Statistics from NT/2000 registry
  292.          * The size of the performance data can vary from call
  293.          * to call so we must guess the size of the buffer to use
  294.          * and increase its size if we get an ERROR_MORE_DATA
  295.          * return instead of ERROR_SUCCESS.
  296.          */
  297.         LONG   rc=ERROR_MORE_DATA;
  298.         char * buf=NULL;
  299.         DWORD bufsz=0;
  300.         DWORD length;
  301.  
  302.         while (rc == ERROR_MORE_DATA)
  303.             {
  304.             buf = realloc(buf,bufsz+8192);
  305.             if (!buf)
  306.                 break;
  307.             bufsz += 8192;
  308.  
  309.             length = bufsz;
  310.             rc = RegQueryValueEx(HKEY_PERFORMANCE_DATA, TEXT("Global"),
  311.                 NULL, NULL, buf, &length);
  312.             }
  313.         if (rc == ERROR_SUCCESS)
  314.             {
  315.                         /* For entropy count assume only least significant
  316.              * byte of each DWORD is random.
  317.              */
  318.             RAND_add(&length, sizeof(length), 0);
  319.             RAND_add(buf, length, length / 4.0);
  320.  
  321.             /* Close the Registry Key to allow Windows to cleanup/close
  322.              * the open handle
  323.              * Note: The 'HKEY_PERFORMANCE_DATA' key is implicitly opened
  324.              *       when the RegQueryValueEx above is done.  However, if
  325.              *       it is not explicitly closed, it can cause disk
  326.              *       partition manipulation problems.
  327.              */
  328.             RegCloseKey(HKEY_PERFORMANCE_DATA);
  329.             }
  330.         if (buf)
  331.             free(buf);
  332.         }
  333. #endif
  334.  
  335.     if (advapi)
  336.         {
  337.         /*
  338.          * If it's available, then it's available in both ANSI
  339.          * and UNICODE flavors even in Win9x, documentation says.
  340.          * We favor Unicode...
  341.          */
  342.         acquire = (CRYPTACQUIRECONTEXTW) GetProcAddress(advapi,
  343.             "CryptAcquireContextW");
  344.         gen = (CRYPTGENRANDOM) GetProcAddress(advapi,
  345.             "CryptGenRandom");
  346.         release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi,
  347.             "CryptReleaseContext");
  348.         }
  349.  
  350.     if (acquire && gen && release)
  351.         {
  352.         /* poll the CryptoAPI PRNG */
  353.                 /* The CryptoAPI returns sizeof(buf) bytes of randomness */
  354.         if (acquire(&hProvider, NULL, NULL, PROV_RSA_FULL,
  355.             CRYPT_VERIFYCONTEXT))
  356.             {
  357.             if (gen(hProvider, sizeof(buf), buf) != 0)
  358.                 {
  359.                 RAND_add(buf, sizeof(buf), 0);
  360.                 good = 1;
  361. #if 0
  362.                 printf("randomness from PROV_RSA_FULL\n");
  363. #endif
  364.                 }
  365.             release(hProvider, 0);
  366.             }
  367.        
  368.         /* poll the Pentium PRG with CryptoAPI */
  369.         if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0))
  370.             {
  371.             if (gen(hProvider, sizeof(buf), buf) != 0)
  372.                 {
  373.                 RAND_add(buf, sizeof(buf), sizeof(buf));
  374.                 good = 1;
  375. #if 0
  376.                 printf("randomness from PROV_INTEL_SEC\n");
  377. #endif
  378.                 }
  379.             release(hProvider, 0);
  380.             }
  381.         }
  382.  
  383.         if (advapi)
  384.         FreeLibrary(advapi);
  385.  
  386.     if ((osverinfo.dwPlatformId != VER_PLATFORM_WIN32_NT ||
  387.          !OPENSSL_isservice()) &&
  388.         (user = LoadLibrary(TEXT("USER32.DLL"))))
  389.         {
  390.         GETCURSORINFO cursor;
  391.         GETFOREGROUNDWINDOW win;
  392.         GETQUEUESTATUS queue;
  393.  
  394.         win = (GETFOREGROUNDWINDOW) GetProcAddress(user, "GetForegroundWindow");
  395.         cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo");
  396.         queue = (GETQUEUESTATUS) GetProcAddress(user, "GetQueueStatus");
  397.  
  398.         if (win)
  399.             {
  400.             /* window handle */
  401.             HWND h = win();
  402.             RAND_add(&h, sizeof(h), 0);
  403.             }
  404.         if (cursor)
  405.             {
  406.             /* unfortunately, its not safe to call GetCursorInfo()
  407.              * on NT4 even though it exists in SP3 (or SP6) and
  408.              * higher.
  409.              */
  410.             if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  411.                 osverinfo.dwMajorVersion < 5)
  412.                 cursor = 0;
  413.             }
  414.         if (cursor)
  415.             {
  416.             /* cursor position */
  417.                         /* assume 2 bytes of entropy */
  418.             CURSORINFO ci;
  419.             ci.cbSize = sizeof(CURSORINFO);
  420.             if (cursor(&ci))
  421.                 RAND_add(&ci, ci.cbSize, 2);
  422.             }
  423.  
  424.         if (queue)
  425.             {
  426.             /* message queue status */
  427.                         /* assume 1 byte of entropy */
  428.             w = queue(QS_ALLEVENTS);
  429.             RAND_add(&w, sizeof(w), 1);
  430.             }
  431.  
  432.         FreeLibrary(user);
  433.         }
  434.  
  435.     /* Toolhelp32 snapshot: enumerate processes, threads, modules and heap
  436.      * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm
  437.      * (Win 9x and 2000 only, not available on NT)
  438.      *
  439.      * This seeding method was proposed in Peter Gutmann, Software
  440.      * Generation of Practically Strong Random Numbers,
  441.      * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html
  442.      * revised version at http://www.cryptoengines.com/~peter/06_random.pdf
  443.      * (The assignment of entropy estimates below is arbitrary, but based
  444.      * on Peter's analysis the full poll appears to be safe. Additional
  445.      * interactive seeding is encouraged.)
  446.      */
  447.  
  448.     if (kernel)
  449.         {
  450.         CREATETOOLHELP32SNAPSHOT snap;
  451.         CLOSETOOLHELP32SNAPSHOT close_snap;
  452.         HANDLE handle;
  453.  
  454.         HEAP32FIRST heap_first;
  455.         HEAP32NEXT heap_next;
  456.         HEAP32LIST heaplist_first, heaplist_next;
  457.         PROCESS32 process_first, process_next;
  458.         THREAD32 thread_first, thread_next;
  459.         MODULE32 module_first, module_next;
  460.  
  461.         HEAPLIST32 hlist;
  462.         HEAPENTRY32 hentry;
  463.         PROCESSENTRY32 p;
  464.         THREADENTRY32 t;
  465.         MODULEENTRY32 m;
  466.         DWORD stoptime = 0;
  467.  
  468.         snap = (CREATETOOLHELP32SNAPSHOT)
  469.             GetProcAddress(kernel, "CreateToolhelp32Snapshot");
  470.         close_snap = (CLOSETOOLHELP32SNAPSHOT)
  471.             GetProcAddress(kernel, "CloseToolhelp32Snapshot");
  472.         heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First");
  473.         heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next");
  474.         heaplist_first = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst");
  475.         heaplist_next = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext");
  476.         process_first = (PROCESS32) GetProcAddress(kernel, "Process32First");
  477.         process_next = (PROCESS32) GetProcAddress(kernel, "Process32Next");
  478.         thread_first = (THREAD32) GetProcAddress(kernel, "Thread32First");
  479.         thread_next = (THREAD32) GetProcAddress(kernel, "Thread32Next");
  480.         module_first = (MODULE32) GetProcAddress(kernel, "Module32First");
  481.         module_next = (MODULE32) GetProcAddress(kernel, "Module32Next");
  482.  
  483.         if (snap && heap_first && heap_next && heaplist_first &&
  484.             heaplist_next && process_first && process_next &&
  485.             thread_first && thread_next && module_first &&
  486.             module_next && (handle = snap(TH32CS_SNAPALL,0))
  487.             != INVALID_HANDLE_VALUE)
  488.             {
  489.             /* heap list and heap walking */
  490.                         /* HEAPLIST32 contains 3 fields that will change with
  491.                          * each entry.  Consider each field a source of 1 byte
  492.                          * of entropy.
  493.                          * HEAPENTRY32 contains 5 fields that will change with
  494.                          * each entry.  Consider each field a source of 1 byte
  495.                          * of entropy.
  496.                          */
  497.             hlist.dwSize = sizeof(HEAPLIST32);     
  498.             if (good) stoptime = GetTickCount() + MAXDELAY;
  499.             if (heaplist_first(handle, &hlist))
  500.                 do
  501.                     {
  502.                     RAND_add(&hlist, hlist.dwSize, 3);
  503.                     hentry.dwSize = sizeof(HEAPENTRY32);
  504.                     if (heap_first(&hentry,
  505.                         hlist.th32ProcessID,
  506.                         hlist.th32HeapID))
  507.                         {
  508.                         int entrycnt = 80;
  509.                         do
  510.                             RAND_add(&hentry,
  511.                                 hentry.dwSize, 5);
  512.                         while (heap_next(&hentry)
  513.                             && --entrycnt > 0);
  514.                         }
  515.                     } while (heaplist_next(handle,
  516.                         &hlist) && GetTickCount() < stoptime);
  517.  
  518.             /* process walking */
  519.                         /* PROCESSENTRY32 contains 9 fields that will change
  520.                          * with each entry.  Consider each field a source of
  521.                          * 1 byte of entropy.
  522.                          */
  523.             p.dwSize = sizeof(PROCESSENTRY32);
  524.        
  525.             if (good) stoptime = GetTickCount() + MAXDELAY;
  526.             if (process_first(handle, &p))
  527.                 do
  528.                     RAND_add(&p, p.dwSize, 9);
  529.                 while (process_next(handle, &p) && GetTickCount() < stoptime);
  530.  
  531.             /* thread walking */
  532.                         /* THREADENTRY32 contains 6 fields that will change
  533.                          * with each entry.  Consider each field a source of
  534.                          * 1 byte of entropy.
  535.                          */
  536.             t.dwSize = sizeof(THREADENTRY32);
  537.             if (good) stoptime = GetTickCount() + MAXDELAY;
  538.             if (thread_first(handle, &t))
  539.                 do
  540.                     RAND_add(&t, t.dwSize, 6);
  541.                 while (thread_next(handle, &t) && GetTickCount() < stoptime);
  542.  
  543.             /* module walking */
  544.                         /* MODULEENTRY32 contains 9 fields that will change
  545.                          * with each entry.  Consider each field a source of
  546.                          * 1 byte of entropy.
  547.                          */
  548.             m.dwSize = sizeof(MODULEENTRY32);
  549.             if (good) stoptime = GetTickCount() + MAXDELAY;
  550.             if (module_first(handle, &m))
  551.                 do
  552.                     RAND_add(&m, m.dwSize, 9);
  553.                 while (module_next(handle, &m)
  554.                             && (GetTickCount() < stoptime));
  555.             if (close_snap)
  556.                 close_snap(handle);
  557.             else
  558.                 CloseHandle(handle);
  559.  
  560.             }
  561.  
  562.         FreeLibrary(kernel);
  563.         }
  564.     }
  565. #endif /* !OPENSSL_SYS_WINCE */
  566.  
  567.     /* timer data */
  568.     readtimer();
  569.    
  570.     /* memory usage statistics */
  571.     GlobalMemoryStatus(&m);
  572.     RAND_add(&m, sizeof(m), 1);
  573.  
  574.     /* process ID */
  575.     w = GetCurrentProcessId();
  576.     RAND_add(&w, sizeof(w), 1);
  577.  
  578. #if 0
  579.     printf("Exiting RAND_poll\n");
  580. #endif
  581.  
  582.     return(1);
  583. }
  584.  
  585. int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
  586.         {
  587.         double add_entropy=0;
  588.  
  589.         switch (iMsg)
  590.                 {
  591.         case WM_KEYDOWN:
  592.                         {
  593.                         static WPARAM key;
  594.                         if (key != wParam)
  595.                                 add_entropy = 0.05;
  596.                         key = wParam;
  597.                         }
  598.                         break;
  599.     case WM_MOUSEMOVE:
  600.                         {
  601.                         static int lastx,lasty,lastdx,lastdy;
  602.                         int x,y,dx,dy;
  603.  
  604.                         x=LOWORD(lParam);
  605.                         y=HIWORD(lParam);
  606.                         dx=lastx-x;
  607.                         dy=lasty-y;
  608.                         if (dx != 0 && dy != 0 && dx-lastdx != 0 && dy-lastdy != 0)
  609.                                 add_entropy=.2;
  610.                         lastx=x, lasty=y;
  611.                         lastdx=dx, lastdy=dy;
  612.                         }
  613.         break;
  614.         }
  615.  
  616.     readtimer();
  617.         RAND_add(&iMsg, sizeof(iMsg), add_entropy);
  618.     RAND_add(&wParam, sizeof(wParam), 0);
  619.     RAND_add(&lParam, sizeof(lParam), 0);
  620.  
  621.     return (RAND_status());
  622.     }
  623.  
  624.  
  625. void RAND_screen(void) /* function available for backward compatibility */
  626. {
  627.     RAND_poll();
  628.     readscreen();
  629. }
  630.  
  631.  
  632. /* feed timing information to the PRNG */
  633. static void readtimer(void)
  634. {
  635.     DWORD w;
  636.     LARGE_INTEGER l;
  637.     static int have_perfc = 1;
  638. #if defined(_MSC_VER) && defined(_M_X86)
  639.     static int have_tsc = 1;
  640.     DWORD cyclecount;
  641.  
  642.     if (have_tsc) {
  643.       __try {
  644.         __asm {
  645.           _emit 0x0f
  646.           _emit 0x31
  647.           mov cyclecount, eax
  648.           }
  649.         RAND_add(&cyclecount, sizeof(cyclecount), 1);
  650.       } __except(EXCEPTION_EXECUTE_HANDLER) {
  651.         have_tsc = 0;
  652.       }
  653.     }
  654. #else
  655. # define have_tsc 0
  656. #endif
  657.  
  658.     if (have_perfc) {
  659.       if (QueryPerformanceCounter(&l) == 0)
  660.         have_perfc = 0;
  661.       else
  662.         RAND_add(&l, sizeof(l), 0);
  663.     }
  664.  
  665.     if (!have_tsc && !have_perfc) {
  666.       w = GetTickCount();
  667.       RAND_add(&w, sizeof(w), 0);
  668.     }
  669. }
  670.  
  671. /* feed screen contents to PRNG */
  672. /*****************************************************************************
  673.  *
  674.  * Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V.
  675.  *
  676.  * Code adapted from
  677.  * <URL:http://support.microsoft.com/default.aspx?scid=kb;[LN];97193>;
  678.  * the original copyright message is:
  679.  *
  680.  *   (C) Copyright Microsoft Corp. 1993.  All rights reserved.
  681.  *
  682.  *   You have a royalty-free right to use, modify, reproduce and
  683.  *   distribute the Sample Files (and/or any modified version) in
  684.  *   any way you find useful, provided that you agree that
  685.  *   Microsoft has no warranty obligations or liability for any
  686.  *   Sample Application Files which are modified.
  687.  */
  688.  
  689. static void readscreen(void)
  690. {
  691. #if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN)
  692.   HDC       hScrDC;     /* screen DC */
  693.   HDC       hMemDC;     /* memory DC */
  694.   HBITMAP   hBitmap;    /* handle for our bitmap */
  695.   HBITMAP   hOldBitmap; /* handle for previous bitmap */
  696.   BITMAP    bm;     /* bitmap properties */
  697.   unsigned int  size;       /* size of bitmap */
  698.   char      *bmbits;    /* contents of bitmap */
  699.   int       w;      /* screen width */
  700.   int       h;      /* screen height */
  701.   int       y;      /* y-coordinate of screen lines to grab */
  702.   int       n = 16;     /* number of screen lines to grab at a time */
  703.  
  704.   if (GetVersion() >= 0x80000000 || !OPENSSL_isservice())
  705.     return;
  706.  
  707.   /* Create a screen DC and a memory DC compatible to screen DC */
  708.   hScrDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  709.   hMemDC = CreateCompatibleDC(hScrDC);
  710.  
  711.   /* Get screen resolution */
  712.   w = GetDeviceCaps(hScrDC, HORZRES);
  713.   h = GetDeviceCaps(hScrDC, VERTRES);
  714.  
  715.   /* Create a bitmap compatible with the screen DC */
  716.   hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
  717.  
  718.   /* Select new bitmap into memory DC */
  719.   hOldBitmap = SelectObject(hMemDC, hBitmap);
  720.  
  721.   /* Get bitmap properties */
  722.   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
  723.   size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
  724.  
  725.   bmbits = OPENSSL_malloc(size);
  726.   if (bmbits) {
  727.     /* Now go through the whole screen, repeatedly grabbing n lines */
  728.     for (y = 0; y < h-n; y += n)
  729.         {
  730.     unsigned char md[MD_DIGEST_LENGTH];
  731.  
  732.     /* Bitblt screen DC to memory DC */
  733.     BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY);
  734.  
  735.     /* Copy bitmap bits from memory DC to bmbits */
  736.     GetBitmapBits(hBitmap, size, bmbits);
  737.  
  738.     /* Get the hash of the bitmap */
  739.     MD(bmbits,size,md);
  740.  
  741.     /* Seed the random generator with the hash value */
  742.     RAND_add(md, MD_DIGEST_LENGTH, 0);
  743.     }
  744.  
  745.     OPENSSL_free(bmbits);
  746.   }
  747.  
  748.   /* Select old bitmap back into memory DC */
  749.   hBitmap = SelectObject(hMemDC, hOldBitmap);
  750.  
  751.   /* Clean up */
  752.   DeleteObject(hBitmap);
  753.   DeleteDC(hMemDC);
  754.   DeleteDC(hScrDC);
  755. #endif /* !OPENSSL_SYS_WINCE */
  756. }
  757.  
  758. #endif