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