Guest User

OpenSSL 1.0.0 crypto/rand/rand_win.c

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