Fix one more instance of incorrect OPENSSL_API_COMPAT value
[openssl.git] / crypto / rand / rand_win.c
index 5dc186f78d8116a35f526126ae9db5d645a7cdd8..1be0ed3c9a58b3d1b04f2b41f885416aedefe49a 100644 (file)
-/* crypto/rand/rand_win.c */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- * 
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
  */
 
-#include "cryptlib.h"
+#include "internal/cryptlib.h"
 #include <openssl/rand.h>
 #include "rand_lcl.h"
 
-#if defined(WINDOWS) || defined(WIN32)
-#include <windows.h>
-#ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0400
-#endif
-#include <wincrypt.h>
-#include <tlhelp32.h>
-
-/* Intel hardware RNG CSP -- available from
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+# include <windows.h>
+/* On Windows 7 or higher use BCrypt instead of the legacy CryptoAPI */
+# if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0601
+#  define RAND_WINDOWS_USE_BCRYPT
+# endif
+
+# ifdef RAND_WINDOWS_USE_BCRYPT
+#  include <bcrypt.h>
+#  pragma comment(lib, "bcrypt.lib")
+#  ifndef STATUS_SUCCESS
+#   define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+#  endif
+# else
+#  include <wincrypt.h>
+/*
+ * Intel hardware RNG CSP -- available from
  * http://developer.intel.com/design/security/rng/redist_license.htm
  */
-#define PROV_INTEL_SEC 22
-#define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider"
+#  define PROV_INTEL_SEC 22
+#  define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider"
+# endif
 
 static void readtimer(void);
-static void readscreen(void);
-
-/* It appears like CURSORINFO, PCURSORINFO and LPCURSORINFO are only defined
-   when WINVER is 0x0500 and up, which currently only happens on Win2000.
-   Unfortunately, those are typedefs, so they're a little bit difficult to
-   detect properly.  On the other hand, the macro CURSOR_SHOWING is defined
-   within the same conditional, so it can be use to detect the absence of said
-   typedefs. */
-
-#ifndef CURSOR_SHOWING
-/*
- * Information about the global cursor.
- */
-typedef struct tagCURSORINFO
-{
-    DWORD   cbSize;
-    DWORD   flags;
-    HCURSOR hCursor;
-    POINT   ptScreenPos;
-} CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
-
-#define CURSOR_SHOWING     0x00000001
-#endif /* CURSOR_SHOWING */
-
-typedef BOOL (WINAPI *CRYPTACQUIRECONTEXT)(HCRYPTPROV *, LPCTSTR, LPCTSTR,
-                                   DWORD, DWORD);
-typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV, DWORD, BYTE *);
-typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV, DWORD);
-
-typedef HWND (WINAPI *GETFOREGROUNDWINDOW)(VOID);
-typedef BOOL (WINAPI *GETCURSORINFO)(PCURSORINFO);
-typedef DWORD (WINAPI *GETQUEUESTATUS)(UINT);
-
-typedef HANDLE (WINAPI *CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD);
-typedef BOOL (WINAPI *HEAP32FIRST)(LPHEAPENTRY32, DWORD, DWORD);
-typedef BOOL (WINAPI *HEAP32NEXT)(LPHEAPENTRY32);
-typedef BOOL (WINAPI *HEAP32LIST)(HANDLE, LPHEAPLIST32);
-typedef BOOL (WINAPI *PROCESS32)(HANDLE, LPPROCESSENTRY32);
-typedef BOOL (WINAPI *THREAD32)(HANDLE, LPTHREADENTRY32);
-typedef BOOL (WINAPI *MODULE32)(HANDLE, LPMODULEENTRY32);
 
 int RAND_poll(void)
 {
-       MEMORYSTATUS m;
-       HCRYPTPROV hProvider = 0;
-       BYTE buf[64];
-       DWORD w;
-       HWND h;
-
-       HMODULE advapi, kernel, user;
-       CRYPTACQUIRECONTEXT acquire;
-       CRYPTGENRANDOM gen;
-       CRYPTRELEASECONTEXT release;
-
-       /* load functions dynamically - not available on all systems */
-       advapi = GetModuleHandle("ADVAPI32.DLL");
-       kernel = GetModuleHandle("KERNEL32.DLL");
-       user = GetModuleHandle("USER32.DLL");
-
-       if (advapi)
-               {
-               acquire = (CRYPTACQUIRECONTEXT) GetProcAddress(advapi,
-                       "CryptAcquireContextA");
-               gen = (CRYPTGENRANDOM) GetProcAddress(advapi,
-                       "CryptGenRandom");
-               release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi,
-                       "CryptReleaseContext");
-               }
-
-       if (acquire && gen && release)
-               {
-               /* poll the CryptoAPI PRNG */
-               if (acquire(&hProvider, 0, 0, PROV_RSA_FULL,
-                       CRYPT_VERIFYCONTEXT))
-                       {
-                       if (gen(hProvider, sizeof(buf), buf) != 0)
-                               {
-                               RAND_add(buf, sizeof(buf), 0);
-#ifdef DEBUG
-                               printf("randomness from PROV_RSA_FULL\n");
-#endif
-                               }
-                       release(hProvider, 0); 
-                       }
-               
-               /* poll the Pentium PRG with CryptoAPI */
-               if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0))
-                       {
-                       if (gen(hProvider, sizeof(buf), buf) != 0)
-                               {
-                               RAND_add(buf, sizeof(buf), 0);
-#ifdef DEBUG
-                               printf("randomness from PROV_INTEL_SEC\n");
-#endif
-                               }
-                       release(hProvider, 0);
-                       }
-               }
-
-       /* timer data */
-       readtimer();
-       
-       /* memory usage statistics */
-       GlobalMemoryStatus(&m);
-       RAND_add(&m, sizeof(m), 1);
-
-       /* process ID */
-       w = GetCurrentProcessId();
-       RAND_add(&w, sizeof(w), 0);
-
-       if (user)
-               {
-               GETCURSORINFO cursor;
-               GETFOREGROUNDWINDOW win;
-
-               win = (GETFOREGROUNDWINDOW) GetProcAddress(user, "GetForegroundWindow");
-               cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo");
-
-               if (win)
-               {
-                       /* window handle */
-                       h = win();
-                       RAND_add(&h, sizeof(h), 0);
-               }
-
-               if (cursor)
-                       {
-                       /* cursor position */
-                        PCURSORINFO p = (PCURSORINFO) buf;
-                        p->cbSize = sizeof(CURSORINFO);
-                       if (cursor(p))
-                            RAND_add(p+sizeof(p->cbSize), p->cbSize-sizeof(p->cbSize), 0);
-                       }
-               }
-
-       /* Toolhelp32 snapshot: enumerate processes, threads, modules and heap
-        * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm
-        * (Win 9x only, not available on NT)
-        *
-        * This seeding method was proposed in Peter Gutmann, Software
-        * Generation of Practically Strong Random Numbers,
-        * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html
-     * revised version at http://www.cryptoengines.com/~peter/06_random.pdf
-        * (The assignment of entropy estimates below is arbitrary, but based
-        * on Peter's analysis the full poll appears to be safe. Additional
-        * interactive seeding is encouraged.)
-        */
-
-       if (kernel)
-               {
-               CREATETOOLHELP32SNAPSHOT snap;
-               HANDLE handle;
-
-               HEAP32FIRST heap_first;
-               HEAP32NEXT heap_next;
-               HEAP32LIST heaplist_first, heaplist_next;
-               PROCESS32 process_first, process_next;
-               THREAD32 thread_first, thread_next;
-               MODULE32 module_first, module_next;
-
-               HEAPLIST32 hlist;
-               HEAPENTRY32 hentry;
-               PROCESSENTRY32 p;
-               THREADENTRY32 t;
-               MODULEENTRY32 m;
-
-               snap = (CREATETOOLHELP32SNAPSHOT)
-                 GetProcAddress(kernel, "CreateToolhelp32Snapshot");
-               heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First");
-               heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next");
-               heaplist_first = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst");
-               heaplist_next = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext");
-               process_first = (PROCESS32) GetProcAddress(kernel, "Process32First");
-               process_next = (PROCESS32) GetProcAddress(kernel, "Process32Next");
-               thread_first = (THREAD32) GetProcAddress(kernel, "Thread32First");
-               thread_next = (THREAD32) GetProcAddress(kernel, "Thread32Next");
-               module_first = (MODULE32) GetProcAddress(kernel, "Module32First");
-               module_next = (MODULE32) GetProcAddress(kernel, "Module32Next");
-
-               if (snap && heap_first && heap_next && heaplist_first &&
-                       heaplist_next && process_first && process_next &&
-                       thread_first && thread_next && module_first &&
-                       module_next && (handle = snap(TH32CS_SNAPALL,0))
-                       != NULL)
-                       {
-                       /* heap list and heap walking */
-                       hlist.dwSize = sizeof(HEAPLIST32);              
-                       if (heaplist_first(handle, &hlist))
-                               do
-                                       {
-                                       RAND_add(&hlist, hlist.dwSize, 0);
-                                       hentry.dwSize = sizeof(HEAPENTRY32);
-                                       if (heap_first(&hentry,
-                                               hlist.th32ProcessID,
-                                               hlist.th32HeapID))
-                                               {
-                                               int entrycnt = 50;
-                                               do
-                                                       RAND_add(&hentry,
-                                                               hentry.dwSize, 0);
-                                               while (heap_next(&hentry)
-                                                       && --entrycnt > 0);
-                                               }
-                                       } while (heaplist_next(handle,
-                                               &hlist));
-
-                       /* process walking */
-                       p.dwSize = sizeof(PROCESSENTRY32);
-                       if (process_first(handle, &p))
-                               do
-                                       RAND_add(&p, p.dwSize, 0);
-                               while (process_next(handle, &p));
-                       
-                       /* thread walking */
-                       t.dwSize = sizeof(THREADENTRY32);
-                       if (thread_first(handle, &t))
-                               do
-                                       RAND_add(&t, t.dwSize, 0);
-                               while (thread_next(handle, &t));
-                       
-                       /* module walking */
-                       m.dwSize = sizeof(MODULEENTRY32);
-                       if (module_first(handle, &m))
-                               do
-                                       RAND_add(&m, m.dwSize, 1);
-                               while (module_next(handle, &m));
-                       
-                       CloseHandle(handle);
-                       }
-               }
-
-#ifdef DEBUG
-       printf("Exiting RAND_poll\n");
-#endif
-
-       return(1);
+    MEMORYSTATUS mst;
+# ifndef RAND_WINDOWS_USE_BCRYPT
+    HCRYPTPROV hProvider;
+# endif
+    DWORD w;
+    BYTE buf[64];
+
+# ifdef RAND_WINDOWS_USE_BCRYPT
+    if (BCryptGenRandom(NULL, buf, (ULONG)sizeof(buf), BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) {
+        RAND_add(buf, sizeof(buf), sizeof(buf));
+    }
+# else
+    /* poll the CryptoAPI PRNG */
+    /* The CryptoAPI returns sizeof(buf) bytes of randomness */
+    if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+        if (CryptGenRandom(hProvider, (DWORD)sizeof(buf), buf) != 0) {
+            RAND_add(buf, sizeof(buf), sizeof(buf));
+        }
+        CryptReleaseContext(hProvider, 0);
+    }
+
+    /* poll the Pentium PRG with CryptoAPI */
+    if (CryptAcquireContextW(&hProvider, NULL, INTEL_DEF_PROV, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+        if (CryptGenRandom(hProvider, (DWORD)sizeof(buf), buf) != 0) {
+            RAND_add(buf, sizeof(buf), sizeof(buf));
+        }
+        CryptReleaseContext(hProvider, 0);
+    }
+# endif
+
+    /* timer data */
+    readtimer();
+
+    /* memory usage statistics */
+    GlobalMemoryStatus(&mst);
+    RAND_add(&mst, sizeof(mst), 1);
+
+    /* process ID */
+    w = GetCurrentProcessId();
+    RAND_add(&w, sizeof(w), 1);
+
+    return (1);
 }
 
+#if OPENSSL_API_COMPAT < 0x10100000L
 int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
-        {
-        double add_entropy=0;
-
-        switch (iMsg)
-                {
-        case WM_KEYDOWN:
-                        {
-                        static WPARAM key;
-                        if (key != wParam)
-                                add_entropy = 0.05;
-                        key = wParam;
-                        }
-                        break;
-       case WM_MOUSEMOVE:
-                        {
-                        static int lastx,lasty,lastdx,lastdy;
-                        int x,y,dx,dy;
-
-                        x=LOWORD(lParam);
-                        y=HIWORD(lParam);
-                        dx=lastx-x;
-                        dy=lasty-y;
-                        if (dx != 0 && dy != 0 && dx-lastdx != 0 && dy-lastdy != 0)
-                                add_entropy=.2;
-                        lastx=x, lasty=y;
-                        lastdx=dx, lastdy=dy;
-                        }
-               break;
-               }
-
-       readtimer();
-        RAND_add(&iMsg, sizeof(iMsg), add_entropy);
-       RAND_add(&wParam, sizeof(wParam), 0);
-       RAND_add(&lParam, sizeof(lParam), 0);
-       return (RAND_status());
-       }
-
-
-void RAND_screen(void) /* function available for backward compatibility */
 {
-       RAND_poll();
-       readscreen();
+    RAND_poll();
+    return RAND_status();
 }
 
-
-/* feed timing information to the PRNG */
-static void readtimer(void)
+void RAND_screen(void)
 {
-       DWORD w, cyclecount;
-       LARGE_INTEGER l;
-       static int have_perfc = 1;
-#ifndef __GNUC__
-       static int have_tsc = 1;
-
-       if (have_tsc) {
-         __try {
-           __asm {
-             rdtsc
-             mov cyclecount, eax
-             }
-           RAND_add(&cyclecount, sizeof(cyclecount), 1);
-         } __except(EXCEPTION_EXECUTE_HANDLER) {
-           have_tsc = 0;
-         }
-       }
-#else
-# define have_tsc 0
-#endif
-
-       if (have_perfc) {
-         if (QueryPerformanceCounter(&l) == 0)
-           have_perfc = 0;
-         else
-           RAND_add(&l, sizeof(l), 0);
-       }
-
-       if (!have_tsc && !have_perfc) {
-         w = GetTickCount();
-         RAND_add(&w, sizeof(w), 0);
-       }
+    RAND_poll();
 }
-
-/* feed screen contents to PRNG */
-/*****************************************************************************
- *
- * Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V.
- *
- * Code adapted from
- * <URL:http://www.microsoft.com/kb/developr/win_dk/q97193.htm>;
- * the original copyright message is:
- *
- *   (C) Copyright Microsoft Corp. 1993.  All rights reserved.
- *
- *   You have a royalty-free right to use, modify, reproduce and
- *   distribute the Sample Files (and/or any modified version) in
- *   any way you find useful, provided that you agree that
- *   Microsoft has no warranty obligations or liability for any
- *   Sample Application Files which are modified.
- */
-
-static void readscreen(void)
-{
-  HDC          hScrDC;         /* screen DC */
-  HDC          hMemDC;         /* memory DC */
-  HBITMAP      hBitmap;        /* handle for our bitmap */
-  HBITMAP      hOldBitmap;     /* handle for previous bitmap */
-  BITMAP       bm;             /* bitmap properties */
-  unsigned int size;           /* size of bitmap */
-  char         *bmbits;        /* contents of bitmap */
-  int          w;              /* screen width */
-  int          h;              /* screen height */
-  int          y;              /* y-coordinate of screen lines to grab */
-  int          n = 16;         /* number of screen lines to grab at a time */
-
-  /* Create a screen DC and a memory DC compatible to screen DC */
-  hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
-  hMemDC = CreateCompatibleDC(hScrDC);
-
-  /* Get screen resolution */
-  w = GetDeviceCaps(hScrDC, HORZRES);
-  h = GetDeviceCaps(hScrDC, VERTRES);
-
-  /* Create a bitmap compatible with the screen DC */
-  hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
-
-  /* Select new bitmap into memory DC */
-  hOldBitmap = SelectObject(hMemDC, hBitmap);
-
-  /* Get bitmap properties */
-  GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
-  size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
-
-  bmbits = OPENSSL_malloc(size);
-  if (bmbits) {
-    /* Now go through the whole screen, repeatedly grabbing n lines */
-    for (y = 0; y < h-n; y += n)
-       {
-       unsigned char md[MD_DIGEST_LENGTH];
-
-       /* Bitblt screen DC to memory DC */
-       BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY);
-
-       /* Copy bitmap bits from memory DC to bmbits */
-       GetBitmapBits(hBitmap, size, bmbits);
-
-       /* Get the hash of the bitmap */
-       MD(bmbits,size,md);
-
-       /* Seed the random generator with the hash value */
-       RAND_add(md, MD_DIGEST_LENGTH, 0);
-       }
-
-    OPENSSL_free(bmbits);
-  }
-
-  /* Select old bitmap back into memory DC */
-  hBitmap = SelectObject(hMemDC, hOldBitmap);
-
-  /* Clean up */
-  DeleteObject(hBitmap);
-  DeleteDC(hMemDC);
-  DeleteDC(hScrDC);
-}
-
-#else /* Unix version */
-
-#include <time.h>
-
-int RAND_poll(void)
-{
-       unsigned long l;
-       pid_t curr_pid = getpid();
-#ifdef DEVRANDOM
-       FILE *fh;
-#endif
-
-#ifdef DEVRANDOM
-       /* Use a random entropy pool device. Linux, FreeBSD and OpenBSD
-        * have this. Use /dev/urandom if you can as /dev/random may block
-        * if it runs out of random entries.  */
-
-       if ((fh = fopen(DEVRANDOM, "r")) != NULL)
-               {
-               unsigned char tmpbuf[ENTROPY_NEEDED];
-               int n;
-               
-               setvbuf(fh, NULL, _IONBF, 0);
-               n=fread((unsigned char *)tmpbuf,1,ENTROPY_NEEDED,fh);
-               fclose(fh);
-               RAND_add(tmpbuf,sizeof tmpbuf,n);
-               memset(tmpbuf,0,n);
-               }
 #endif
 
-       /* put in some default random data, we need more than just this */
-       l=curr_pid;
-       RAND_add(&l,sizeof(l),0);
-       l=getuid();
-       RAND_add(&l,sizeof(l),0);
-
-       l=time(NULL);
-       RAND_add(&l,sizeof(l),0);
-
-#ifdef DEVRANDOM
-       return 1;
-#endif
-       return 0;
+/* feed timing information to the PRNG */
+static void readtimer(void)
+{
+    DWORD w;
+    LARGE_INTEGER l;
+    static int have_perfc = 1;
+# if defined(_MSC_VER) && defined(_M_X86)
+    static int have_tsc = 1;
+    DWORD cyclecount;
+
+    if (have_tsc) {
+        __try {
+            __asm {
+            _emit 0x0f _emit 0x31 mov cyclecount, eax}
+            RAND_add(&cyclecount, sizeof(cyclecount), 1);
+        }
+        __except(EXCEPTION_EXECUTE_HANDLER) {
+            have_tsc = 0;
+        }
+    }
+# else
+#  define have_tsc 0
+# endif
+
+    if (have_perfc) {
+        if (QueryPerformanceCounter(&l) == 0)
+            have_perfc = 0;
+        else
+            RAND_add(&l, sizeof(l), 0);
+    }
+
+    if (!have_tsc && !have_perfc) {
+        w = GetTickCount();
+        RAND_add(&w, sizeof(w), 0);
+    }
 }
 
 #endif