Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

OpenSSL 1.0.0 crypto/rand/rand_win.c

By: a guest on May 24th, 2010  |  syntax: C++  |  size: 25.53 KB  |  views: 283  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  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