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