Advertisement
Guest User

OpenSSL 0.9.8k crypto/rand/rand_win.c

a guest
May 24th, 2010
516
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 25.53 KB | None
  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
Advertisement
RAW Paste Data Copied
Advertisement