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