Pastebin launched a little side project called HostCabi.net, check it out ;-)Don't like ads? PRO users don't see any ads ;-)
Guest

OpenSSL 0.9.8k crypto/rand/rand_win.c

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