2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #include "internal/cryptlib.h"
11 #include <openssl/rand.h>
14 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
17 # define _WIN32_WINNT 0x0400
19 # include <wincrypt.h>
20 # include <tlhelp32.h>
23 * Limit the time spent walking through the heap, processes, threads and
24 * modules to a maximum of 1000 milliseconds each, unless CryptoGenRandom
27 # define MAXDELAY 1000
30 * Intel hardware RNG CSP -- available from
31 * http://developer.intel.com/design/security/rng/redist_license.htm
33 # define PROV_INTEL_SEC 22
34 # define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider"
36 static void readtimer(void);
37 static void readscreen(void);
40 * It appears like CURSORINFO, PCURSORINFO and LPCURSORINFO are only defined
41 * when WINVER is 0x0500 and up, which currently only happens on Win2000.
42 * Unfortunately, those are typedefs, so they're a little bit difficult to
43 * detect properly. On the other hand, the macro CURSOR_SHOWING is defined
44 * within the same conditional, so it can be use to detect the absence of
48 # ifndef CURSOR_SHOWING
50 * Information about the global cursor.
52 typedef struct tagCURSORINFO {
57 } CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
59 # define CURSOR_SHOWING 0x00000001
60 # endif /* CURSOR_SHOWING */
62 # if !defined(OPENSSL_SYS_WINCE)
63 typedef BOOL(WINAPI *CRYPTACQUIRECONTEXTW) (HCRYPTPROV *, LPCWSTR, LPCWSTR,
65 typedef BOOL(WINAPI *CRYPTGENRANDOM) (HCRYPTPROV, DWORD, BYTE *);
66 typedef BOOL(WINAPI *CRYPTRELEASECONTEXT) (HCRYPTPROV, DWORD);
68 typedef HWND(WINAPI *GETFOREGROUNDWINDOW) (VOID);
69 typedef BOOL(WINAPI *GETCURSORINFO) (PCURSORINFO);
70 typedef DWORD(WINAPI *GETQUEUESTATUS) (UINT);
72 typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
73 typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
74 typedef BOOL(WINAPI *HEAP32FIRST) (LPHEAPENTRY32, DWORD, size_t);
75 typedef BOOL(WINAPI *HEAP32NEXT) (LPHEAPENTRY32);
76 typedef BOOL(WINAPI *HEAP32LIST) (HANDLE, LPHEAPLIST32);
77 typedef BOOL(WINAPI *PROCESS32) (HANDLE, LPPROCESSENTRY32);
78 typedef BOOL(WINAPI *THREAD32) (HANDLE, LPTHREADENTRY32);
79 typedef BOOL(WINAPI *MODULE32) (HANDLE, LPMODULEENTRY32);
84 * The NET API is Unicode only. It requires the use of the UNICODE macro.
85 * When UNICODE is defined LPTSTR becomes LPWSTR. LMSTR was was added to the
86 * Platform SDK to allow the NET API to be used in non-Unicode applications
87 * provided that Unicode strings were still used for input. LMSTR is defined
90 typedef NET_API_STATUS(NET_API_FUNCTION *NETSTATGET)
91 (LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE *);
92 typedef NET_API_STATUS(NET_API_FUNCTION *NETFREE) (LPBYTE);
93 # endif /* !OPENSSL_SYS_WINCE */
98 HCRYPTPROV hProvider = 0;
102 # if defined(OPENSSL_SYS_WINCE)
103 # if defined(_WIN32_WCE) && _WIN32_WCE>=300
105 * Even though MSDN says _WIN32_WCE>=210, it doesn't seem to be available
106 * in commonly available implementations prior 300...
110 /* poll the CryptoAPI PRNG */
111 /* The CryptoAPI returns sizeof(buf) bytes of randomness */
112 if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL,
113 CRYPT_VERIFYCONTEXT)) {
114 if (CryptGenRandom(hProvider, sizeof(buf), buf))
115 RAND_add(buf, sizeof(buf), sizeof(buf));
116 CryptReleaseContext(hProvider, 0);
120 # else /* OPENSSL_SYS_WINCE */
122 * None of below libraries are present on Windows CE, which is
123 * why we #ifndef the whole section. This also excuses us from
124 * handling the GetProcAddress issue. The trouble is that in
125 * real Win32 API GetProcAddress is available in ANSI flavor
126 * only. In WinCE on the other hand GetProcAddress is a macro
127 * most commonly defined as GetProcAddressW, which accepts
128 * Unicode argument. If we were to call GetProcAddress under
129 * WinCE, I'd recommend to either redefine GetProcAddress as
130 * GetProcAddressA (there seem to be one in common CE spec) or
131 * implement own shim routine, which would accept ANSI argument
132 * and expand it to Unicode.
135 /* load functions dynamically - not available on all systems */
136 HMODULE advapi = LoadLibrary(TEXT("ADVAPI32.DLL"));
137 HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL"));
139 HMODULE netapi = LoadLibrary(TEXT("NETAPI32.DLL"));
140 CRYPTACQUIRECONTEXTW acquire = NULL;
141 CRYPTGENRANDOM gen = NULL;
142 CRYPTRELEASECONTEXT release = NULL;
143 NETSTATGET netstatget = NULL;
144 NETFREE netfree = NULL;
149 (NETSTATGET) GetProcAddress(netapi, "NetStatisticsGet");
150 netfree = (NETFREE) GetProcAddress(netapi, "NetApiBufferFree");
153 if (netstatget && netfree) {
156 * NetStatisticsGet() is a Unicode only function
157 * STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0
158 * contains 17 fields. We treat each field as a source of one
162 if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0) {
163 RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45);
166 if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0) {
167 RAND_add(outbuf, sizeof(STAT_SERVER_0), 17);
176 * It appears like this can cause an exception deep within
177 * ADVAPI32.DLL at random times on Windows 2000. Reported by Jeffrey
178 * Altman. Only use it on NT.
183 * If it's available, then it's available in both ANSI
184 * and UNICODE flavors even in Win9x, documentation says.
185 * We favor Unicode...
187 acquire = (CRYPTACQUIRECONTEXTW) GetProcAddress(advapi,
188 "CryptAcquireContextW");
189 gen = (CRYPTGENRANDOM) GetProcAddress(advapi, "CryptGenRandom");
190 release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi,
191 "CryptReleaseContext");
194 if (acquire && gen && release) {
195 /* poll the CryptoAPI PRNG */
196 /* The CryptoAPI returns sizeof(buf) bytes of randomness */
197 if (acquire(&hProvider, NULL, NULL, PROV_RSA_FULL,
198 CRYPT_VERIFYCONTEXT)) {
199 if (gen(hProvider, sizeof(buf), buf) != 0) {
200 RAND_add(buf, sizeof(buf), 0);
203 release(hProvider, 0);
206 /* poll the Pentium PRG with CryptoAPI */
207 if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0)) {
208 if (gen(hProvider, sizeof(buf), buf) != 0) {
209 RAND_add(buf, sizeof(buf), sizeof(buf));
212 release(hProvider, 0);
219 if ((!check_winnt() ||
220 !OPENSSL_isservice()) &&
221 (user = LoadLibrary(TEXT("USER32.DLL")))) {
222 GETCURSORINFO cursor;
223 GETFOREGROUNDWINDOW win;
224 GETQUEUESTATUS queue;
227 (GETFOREGROUNDWINDOW) GetProcAddress(user,
228 "GetForegroundWindow");
229 cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo");
230 queue = (GETQUEUESTATUS) GetProcAddress(user, "GetQueueStatus");
235 RAND_add(&h, sizeof(h), 0);
239 * unfortunately, its not safe to call GetCursorInfo() on NT4
240 * even though it exists in SP3 (or SP6) and higher.
242 if (check_winnt() && !check_win_minplat(5))
246 /* cursor position */
247 /* assume 2 bytes of entropy */
249 ci.cbSize = sizeof(CURSORINFO);
251 RAND_add(&ci, ci.cbSize, 2);
255 /* message queue status */
256 /* assume 1 byte of entropy */
257 w = queue(QS_ALLEVENTS);
258 RAND_add(&w, sizeof(w), 1);
265 * Toolhelp32 snapshot: enumerate processes, threads, modules and heap
266 * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm
267 * (Win 9x and 2000 only, not available on NT)
269 * This seeding method was proposed in Peter Gutmann, Software
270 * Generation of Practically Strong Random Numbers,
271 * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html
272 * revised version at http://www.cryptoengines.com/~peter/06_random.pdf
273 * (The assignment of entropy estimates below is arbitrary, but based
274 * on Peter's analysis the full poll appears to be safe. Additional
275 * interactive seeding is encouraged.)
279 CREATETOOLHELP32SNAPSHOT snap;
280 CLOSETOOLHELP32SNAPSHOT close_snap;
283 HEAP32FIRST heap_first;
284 HEAP32NEXT heap_next;
285 HEAP32LIST heaplist_first, heaplist_next;
286 PROCESS32 process_first, process_next;
287 THREAD32 thread_first, thread_next;
288 MODULE32 module_first, module_next;
297 snap = (CREATETOOLHELP32SNAPSHOT)
298 GetProcAddress(kernel, "CreateToolhelp32Snapshot");
299 close_snap = (CLOSETOOLHELP32SNAPSHOT)
300 GetProcAddress(kernel, "CloseToolhelp32Snapshot");
301 heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First");
302 heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next");
304 (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst");
306 (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext");
308 (PROCESS32) GetProcAddress(kernel, "Process32First");
310 (PROCESS32) GetProcAddress(kernel, "Process32Next");
311 thread_first = (THREAD32) GetProcAddress(kernel, "Thread32First");
312 thread_next = (THREAD32) GetProcAddress(kernel, "Thread32Next");
313 module_first = (MODULE32) GetProcAddress(kernel, "Module32First");
314 module_next = (MODULE32) GetProcAddress(kernel, "Module32Next");
316 if (snap && heap_first && heap_next && heaplist_first &&
317 heaplist_next && process_first && process_next &&
318 thread_first && thread_next && module_first &&
319 module_next && (handle = snap(TH32CS_SNAPALL, 0))
320 != INVALID_HANDLE_VALUE) {
321 /* heap list and heap walking */
323 * HEAPLIST32 contains 3 fields that will change with each
324 * entry. Consider each field a source of 1 byte of entropy.
325 * HEAPENTRY32 contains 5 fields that will change with each
326 * entry. Consider each field a source of 1 byte of entropy.
328 ZeroMemory(&hlist, sizeof(HEAPLIST32));
329 hlist.dwSize = sizeof(HEAPLIST32);
331 starttime = GetTickCount();
333 if (heaplist_first(handle, &hlist)) {
335 * following discussion on dev ML, exception on WinCE (or
336 * other Win platform) is theoretically of unknown
337 * origin; prevent infinite loop here when this
338 * theoretical case occurs; otherwise cope with the
339 * expected (MSDN documented) exception-throwing
340 * behaviour of Heap32Next() on WinCE.
342 * based on patch in original message by Tanguy Fautré
343 * (2009/03/02) Subject: RAND_poll() and
344 * CreateToolhelp32Snapshot() stability
346 int ex_cnt_limit = 42;
348 RAND_add(&hlist, hlist.dwSize, 3);
350 ZeroMemory(&hentry, sizeof(HEAPENTRY32));
351 hentry.dwSize = sizeof(HEAPENTRY32);
352 if (heap_first(&hentry,
357 RAND_add(&hentry, hentry.dwSize, 5);
358 while (heap_next(&hentry)
360 || (GetTickCount() - starttime) <
365 __except(EXCEPTION_EXECUTE_HANDLER) {
367 * ignore access violations when walking the heap
372 } while (heaplist_next(handle, &hlist)
374 || (GetTickCount() - starttime) < MAXDELAY)
375 && ex_cnt_limit > 0);
378 if (heaplist_first(handle, &hlist)) {
380 RAND_add(&hlist, hlist.dwSize, 3);
381 hentry.dwSize = sizeof(HEAPENTRY32);
382 if (heap_first(&hentry,
387 RAND_add(&hentry, hentry.dwSize, 5);
388 while (heap_next(&hentry)
391 } while (heaplist_next(handle, &hlist)
393 || (GetTickCount() - starttime) < MAXDELAY));
397 /* process walking */
399 * PROCESSENTRY32 contains 9 fields that will change with
400 * each entry. Consider each field a source of 1 byte of
403 p.dwSize = sizeof(PROCESSENTRY32);
406 starttime = GetTickCount();
407 if (process_first(handle, &p))
409 RAND_add(&p, p.dwSize, 9);
410 while (process_next(handle, &p)
412 || (GetTickCount() - starttime) < MAXDELAY));
416 * THREADENTRY32 contains 6 fields that will change with each
417 * entry. Consider each field a source of 1 byte of entropy.
419 t.dwSize = sizeof(THREADENTRY32);
421 starttime = GetTickCount();
422 if (thread_first(handle, &t))
424 RAND_add(&t, t.dwSize, 6);
425 while (thread_next(handle, &t)
427 || (GetTickCount() - starttime) < MAXDELAY));
431 * MODULEENTRY32 contains 9 fields that will change with each
432 * entry. Consider each field a source of 1 byte of entropy.
434 m.dwSize = sizeof(MODULEENTRY32);
436 starttime = GetTickCount();
437 if (module_first(handle, &m))
439 RAND_add(&m, m.dwSize, 9);
440 while (module_next(handle, &m)
442 || (GetTickCount() - starttime) < MAXDELAY));
453 # endif /* !OPENSSL_SYS_WINCE */
458 /* memory usage statistics */
459 GlobalMemoryStatus(&mst);
460 RAND_add(&mst, sizeof(mst), 1);
463 w = GetCurrentProcessId();
464 RAND_add(&w, sizeof(w), 1);
469 int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
471 double add_entropy = 0;
484 static int lastx, lasty, lastdx, lastdy;
491 if (dx != 0 && dy != 0 && dx - lastdx != 0 && dy - lastdy != 0)
493 lastx = x, lasty = y;
494 lastdx = dx, lastdy = dy;
500 RAND_add(&iMsg, sizeof(iMsg), add_entropy);
501 RAND_add(&wParam, sizeof(wParam), 0);
502 RAND_add(&lParam, sizeof(lParam), 0);
504 return (RAND_status());
507 void RAND_screen(void)
508 { /* function available for backward
514 /* feed timing information to the PRNG */
515 static void readtimer(void)
519 static int have_perfc = 1;
520 # if defined(_MSC_VER) && defined(_M_X86)
521 static int have_tsc = 1;
527 _emit 0x0f _emit 0x31 mov cyclecount, eax}
528 RAND_add(&cyclecount, sizeof(cyclecount), 1);
530 __except(EXCEPTION_EXECUTE_HANDLER) {
539 if (QueryPerformanceCounter(&l) == 0)
542 RAND_add(&l, sizeof(l), 0);
545 if (!have_tsc && !have_perfc) {
547 RAND_add(&w, sizeof(w), 0);
551 /* feed screen contents to PRNG */
552 /*****************************************************************************
554 * Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V.
557 * <URL:http://support.microsoft.com/default.aspx?scid=kb;[LN];97193>;
558 * the original copyright message is:
560 * (C) Copyright Microsoft Corp. 1993. All rights reserved.
562 * You have a royalty-free right to use, modify, reproduce and
563 * distribute the Sample Files (and/or any modified version) in
564 * any way you find useful, provided that you agree that
565 * Microsoft has no warranty obligations or liability for any
566 * Sample Application Files which are modified.
569 static void readscreen(void)
571 # if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN)
572 HDC hScrDC; /* screen DC */
573 HBITMAP hBitmap; /* handle for our bitmap */
574 BITMAP bm; /* bitmap properties */
575 unsigned int size; /* size of bitmap */
576 char *bmbits; /* contents of bitmap */
577 int w; /* screen width */
578 int h; /* screen height */
579 int y; /* y-coordinate of screen lines to grab */
580 int n = 16; /* number of screen lines to grab at a time */
581 BITMAPINFOHEADER bi; /* info about the bitmap */
583 if (check_winnt() && OPENSSL_isservice() > 0)
586 /* Get a reference to the screen DC */
587 hScrDC = GetDC(NULL);
589 /* Get screen resolution */
590 w = GetDeviceCaps(hScrDC, HORZRES);
591 h = GetDeviceCaps(hScrDC, VERTRES);
593 /* Create a bitmap compatible with the screen DC */
594 hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
596 /* Get bitmap properties */
597 GetObject(hBitmap, sizeof(BITMAP), (LPSTR) & bm);
598 size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
600 bi.biSize = sizeof(BITMAPINFOHEADER);
601 bi.biWidth = bm.bmWidth;
602 bi.biHeight = bm.bmHeight;
603 bi.biPlanes = bm.bmPlanes;
604 bi.biBitCount = bm.bmBitsPixel;
605 bi.biCompression = BI_RGB;
607 bi.biXPelsPerMeter = 0;
608 bi.biYPelsPerMeter = 0;
610 bi.biClrImportant = 0;
612 bmbits = OPENSSL_malloc(size);
613 if (bmbits != NULL) {
614 /* Now go through the whole screen, repeatedly grabbing n lines */
615 for (y = 0; y < h - n; y += n) {
616 unsigned char md[MD_DIGEST_LENGTH];
618 /* Copy the bits of the current line range into the buffer */
619 GetDIBits(hScrDC, hBitmap, y, n,
620 bmbits, (BITMAPINFO *) & bi, DIB_RGB_COLORS);
622 /* Get the hash of the bitmap */
623 MD(bmbits, size, md);
625 /* Seed the random generator with the hash value */
626 RAND_add(md, MD_DIGEST_LENGTH, 0);
629 OPENSSL_free(bmbits);
633 DeleteObject(hBitmap);
634 ReleaseDC(NULL, hScrDC);
635 # endif /* !OPENSSL_SYS_WINCE */