1 /* crypto/rand/rand_win.c */ 2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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 (at) 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 (at) cryptsoft.com). This product includes software written by Tim 108 * Hudson (tjh (at) 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 134 static void readtimer(void); 135 static 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 */ 148 typedef 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) 160 typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTW)(HCRYPTPROV *, LPCWSTR, LPCWSTR, 161 DWORD, DWORD); 162 typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV, DWORD, BYTE *); 163 typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV, DWORD); 164 165 typedef HWND (WINAPI *GETFOREGROUNDWINDOW)(VOID); 166 typedef BOOL (WINAPI *GETCURSORINFO)(PCURSORINFO); 167 typedef DWORD (WINAPI *GETQUEUESTATUS)(UINT); 168 169 typedef HANDLE (WINAPI *CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD); 170 typedef BOOL (WINAPI *CLOSETOOLHELP32SNAPSHOT)(HANDLE); 171 typedef BOOL (WINAPI *HEAP32FIRST)(LPHEAPENTRY32, DWORD, size_t); 172 typedef BOOL (WINAPI *HEAP32NEXT)(LPHEAPENTRY32); 173 typedef BOOL (WINAPI *HEAP32LIST)(HANDLE, LPHEAPLIST32); 174 typedef BOOL (WINAPI *PROCESS32)(HANDLE, LPPROCESSENTRY32); 175 typedef BOOL (WINAPI *THREAD32)(HANDLE, LPTHREADENTRY32); 176 typedef 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 */ 186 typedef NET_API_STATUS (NET_API_FUNCTION * NETSTATGET) 187 (LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE*); 188 typedef NET_API_STATUS (NET_API_FUNCTION * NETFREE)(LPBYTE); 189 #endif /* 1 */ 190 #endif /* !OPENSSL_SYS_WINCE */ 191 192 int 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 (at) 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 starttime = 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 ZeroMemory(&hlist, sizeof(HEAPLIST32)); 498 hlist.dwSize = sizeof(HEAPLIST32); 499 if (good) starttime = GetTickCount(); 500 #ifdef _MSC_VER 501 if (heaplist_first(handle, &hlist)) 502 { 503 /* 504 following discussion on dev ML, exception on WinCE (or other Win 505 platform) is theoretically of unknown origin; prevent infinite 506 loop here when this theoretical case occurs; otherwise cope with 507 the expected (MSDN documented) exception-throwing behaviour of 508 Heap32Next() on WinCE. 509 510 based on patch in original message by Tanguy Fautr (2009/03/02) 511 Subject: RAND_poll() and CreateToolhelp32Snapshot() stability 512 */ 513 int ex_cnt_limit = 42; 514 do 515 { 516 RAND_add(&hlist, hlist.dwSize, 3); 517 __try 518 { 519 ZeroMemory(&hentry, sizeof(HEAPENTRY32)); 520 hentry.dwSize = sizeof(HEAPENTRY32); 521 if (heap_first(&hentry, 522 hlist.th32ProcessID, 523 hlist.th32HeapID)) 524 { 525 int entrycnt = 80; 526 do 527 RAND_add(&hentry, 528 hentry.dwSize, 5); 529 while (heap_next(&hentry) 530 && (!good || (GetTickCount()-starttime)<MAXDELAY) 531 && --entrycnt > 0); 532 } 533 } 534 __except (EXCEPTION_EXECUTE_HANDLER) 535 { 536 /* ignore access violations when walking the heap list */ 537 ex_cnt_limit--; 538 } 539 } while (heaplist_next(handle, &hlist) 540 && (!good || (GetTickCount()-starttime)<MAXDELAY) 541 && ex_cnt_limit > 0); 542 } 543 544 #else 545 if (heaplist_first(handle, &hlist)) 546 { 547 do 548 { 549 RAND_add(&hlist, hlist.dwSize, 3); 550 hentry.dwSize = sizeof(HEAPENTRY32); 551 if (heap_first(&hentry, 552 hlist.th32ProcessID, 553 hlist.th32HeapID)) 554 { 555 int entrycnt = 80; 556 do 557 RAND_add(&hentry, 558 hentry.dwSize, 5); 559 while (heap_next(&hentry) 560 && --entrycnt > 0); 561 } 562 } while (heaplist_next(handle, &hlist) 563 && (!good || (GetTickCount()-starttime)<MAXDELAY)); 564 } 565 #endif 566 567 /* process walking */ 568 /* PROCESSENTRY32 contains 9 fields that will change 569 * with each entry. Consider each field a source of 570 * 1 byte of entropy. 571 */ 572 p.dwSize = sizeof(PROCESSENTRY32); 573 574 if (good) starttime = GetTickCount(); 575 if (process_first(handle, &p)) 576 do 577 RAND_add(&p, p.dwSize, 9); 578 while (process_next(handle, &p) && (!good || (GetTickCount()-starttime)<MAXDELAY)); 579 580 /* thread walking */ 581 /* THREADENTRY32 contains 6 fields that will change 582 * with each entry. Consider each field a source of 583 * 1 byte of entropy. 584 */ 585 t.dwSize = sizeof(THREADENTRY32); 586 if (good) starttime = GetTickCount(); 587 if (thread_first(handle, &t)) 588 do 589 RAND_add(&t, t.dwSize, 6); 590 while (thread_next(handle, &t) && (!good || (GetTickCount()-starttime)<MAXDELAY)); 591 592 /* module walking */ 593 /* MODULEENTRY32 contains 9 fields that will change 594 * with each entry. Consider each field a source of 595 * 1 byte of entropy. 596 */ 597 m.dwSize = sizeof(MODULEENTRY32); 598 if (good) starttime = GetTickCount(); 599 if (module_first(handle, &m)) 600 do 601 RAND_add(&m, m.dwSize, 9); 602 while (module_next(handle, &m) 603 && (!good || (GetTickCount()-starttime)<MAXDELAY)); 604 if (close_snap) 605 close_snap(handle); 606 else 607 CloseHandle(handle); 608 609 } 610 611 FreeLibrary(kernel); 612 } 613 } 614 #endif /* !OPENSSL_SYS_WINCE */ 615 616 /* timer data */ 617 readtimer(); 618 619 /* memory usage statistics */ 620 GlobalMemoryStatus(&m); 621 RAND_add(&m, sizeof(m), 1); 622 623 /* process ID */ 624 w = GetCurrentProcessId(); 625 RAND_add(&w, sizeof(w), 1); 626 627 #if 0 628 printf("Exiting RAND_poll\n"); 629 #endif 630 631 return(1); 632 } 633 634 int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam) 635 { 636 double add_entropy=0; 637 638 switch (iMsg) 639 { 640 case WM_KEYDOWN: 641 { 642 static WPARAM key; 643 if (key != wParam) 644 add_entropy = 0.05; 645 key = wParam; 646 } 647 break; 648 case WM_MOUSEMOVE: 649 { 650 static int lastx,lasty,lastdx,lastdy; 651 int x,y,dx,dy; 652 653 x=LOWORD(lParam); 654 y=HIWORD(lParam); 655 dx=lastx-x; 656 dy=lasty-y; 657 if (dx != 0 && dy != 0 && dx-lastdx != 0 && dy-lastdy != 0) 658 add_entropy=.2; 659 lastx=x, lasty=y; 660 lastdx=dx, lastdy=dy; 661 } 662 break; 663 } 664 665 readtimer(); 666 RAND_add(&iMsg, sizeof(iMsg), add_entropy); 667 RAND_add(&wParam, sizeof(wParam), 0); 668 RAND_add(&lParam, sizeof(lParam), 0); 669 670 return (RAND_status()); 671 } 672 673 674 void RAND_screen(void) /* function available for backward compatibility */ 675 { 676 RAND_poll(); 677 readscreen(); 678 } 679 680 681 /* feed timing information to the PRNG */ 682 static void readtimer(void) 683 { 684 DWORD w; 685 LARGE_INTEGER l; 686 static int have_perfc = 1; 687 #if defined(_MSC_VER) && defined(_M_X86) 688 static int have_tsc = 1; 689 DWORD cyclecount; 690 691 if (have_tsc) { 692 __try { 693 __asm { 694 _emit 0x0f 695 _emit 0x31 696 mov cyclecount, eax 697 } 698 RAND_add(&cyclecount, sizeof(cyclecount), 1); 699 } __except(EXCEPTION_EXECUTE_HANDLER) { 700 have_tsc = 0; 701 } 702 } 703 #else 704 # define have_tsc 0 705 #endif 706 707 if (have_perfc) { 708 if (QueryPerformanceCounter(&l) == 0) 709 have_perfc = 0; 710 else 711 RAND_add(&l, sizeof(l), 0); 712 } 713 714 if (!have_tsc && !have_perfc) { 715 w = GetTickCount(); 716 RAND_add(&w, sizeof(w), 0); 717 } 718 } 719 720 /* feed screen contents to PRNG */ 721 /***************************************************************************** 722 * 723 * Created 960901 by Gertjan van Oosten, gertjan (at) West.NL, West Consulting B.V. 724 * 725 * Code adapted from 726 * <URL:http://support.microsoft.com/default.aspx?scid=kb;[LN];97193>; 727 * the original copyright message is: 728 * 729 * (C) Copyright Microsoft Corp. 1993. All rights reserved. 730 * 731 * You have a royalty-free right to use, modify, reproduce and 732 * distribute the Sample Files (and/or any modified version) in 733 * any way you find useful, provided that you agree that 734 * Microsoft has no warranty obligations or liability for any 735 * Sample Application Files which are modified. 736 */ 737 738 static void readscreen(void) 739 { 740 #if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN) 741 HDC hScrDC; /* screen DC */ 742 HDC hMemDC; /* memory DC */ 743 HBITMAP hBitmap; /* handle for our bitmap */ 744 HBITMAP hOldBitmap; /* handle for previous bitmap */ 745 BITMAP bm; /* bitmap properties */ 746 unsigned int size; /* size of bitmap */ 747 char *bmbits; /* contents of bitmap */ 748 int w; /* screen width */ 749 int h; /* screen height */ 750 int y; /* y-coordinate of screen lines to grab */ 751 int n = 16; /* number of screen lines to grab at a time */ 752 753 if (GetVersion() < 0x80000000 && OPENSSL_isservice()>0) 754 return; 755 756 /* Create a screen DC and a memory DC compatible to screen DC */ 757 hScrDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); 758 hMemDC = CreateCompatibleDC(hScrDC); 759 760 /* Get screen resolution */ 761 w = GetDeviceCaps(hScrDC, HORZRES); 762 h = GetDeviceCaps(hScrDC, VERTRES); 763 764 /* Create a bitmap compatible with the screen DC */ 765 hBitmap = CreateCompatibleBitmap(hScrDC, w, n); 766 767 /* Select new bitmap into memory DC */ 768 hOldBitmap = SelectObject(hMemDC, hBitmap); 769 770 /* Get bitmap properties */ 771 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm); 772 size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes; 773 774 bmbits = OPENSSL_malloc(size); 775 if (bmbits) { 776 /* Now go through the whole screen, repeatedly grabbing n lines */ 777 for (y = 0; y < h-n; y += n) 778 { 779 unsigned char md[MD_DIGEST_LENGTH]; 780 781 /* Bitblt screen DC to memory DC */ 782 BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY); 783 784 /* Copy bitmap bits from memory DC to bmbits */ 785 GetBitmapBits(hBitmap, size, bmbits); 786 787 /* Get the hash of the bitmap */ 788 MD(bmbits,size,md); 789 790 /* Seed the random generator with the hash value */ 791 RAND_add(md, MD_DIGEST_LENGTH, 0); 792 } 793 794 OPENSSL_free(bmbits); 795 } 796 797 /* Select old bitmap back into memory DC */ 798 hBitmap = SelectObject(hMemDC, hOldBitmap); 799 800 /* Clean up */ 801 DeleteObject(hBitmap); 802 DeleteDC(hMemDC); 803 DeleteDC(hScrDC); 804 #endif /* !OPENSSL_SYS_WINCE */ 805 } 806 807 #endif 808