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 200#if defined(OPENSSL_SYS_WINCE) 201# if defined(_WIN32_WCE) && _WIN32_WCE>=300 202/* Even though MSDN says _WIN32_WCE>=210, it doesn't seem to be available 203 * in commonly available implementations prior 300... */ 204 { 205 BYTE buf[64]; 206 /* poll the CryptoAPI PRNG */ 207 /* The CryptoAPI returns sizeof(buf) bytes of randomness */ 208 if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, 209 CRYPT_VERIFYCONTEXT)) 210 { 211 if (CryptGenRandom(hProvider, sizeof(buf), buf)) 212 RAND_add(buf, sizeof(buf), sizeof(buf)); 213 CryptReleaseContext(hProvider, 0); 214 } 215 } 216# endif 217#else /* OPENSSL_SYS_WINCE */ 218 /* 219 * None of below libraries are present on Windows CE, which is 220 * why we #ifndef the whole section. This also excuses us from 221 * handling the GetProcAddress issue. The trouble is that in 222 * real Win32 API GetProcAddress is available in ANSI flavor 223 * only. In WinCE on the other hand GetProcAddress is a macro 224 * most commonly defined as GetProcAddressW, which accepts 225 * Unicode argument. If we were to call GetProcAddress under 226 * WinCE, I'd recommend to either redefine GetProcAddress as 227 * GetProcAddressA (there seem to be one in common CE spec) or 228 * implement own shim routine, which would accept ANSI argument 229 * and expand it to Unicode. 230 */ 231 { 232 /* load functions dynamically - not available on all systems */ 233 HMODULE advapi = LoadLibrary(TEXT("ADVAPI32.DLL")); 234 HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL")); 235 HMODULE user = NULL; 236 HMODULE netapi = LoadLibrary(TEXT("NETAPI32.DLL")); 237 CRYPTACQUIRECONTEXTW acquire = NULL; 238 CRYPTGENRANDOM gen = NULL; 239 CRYPTRELEASECONTEXT release = NULL; 240 NETSTATGET netstatget = NULL; 241 NETFREE netfree = NULL; 242 BYTE buf[64]; 243 244 if (netapi) 245 { 246 netstatget = (NETSTATGET) GetProcAddress(netapi,"NetStatisticsGet"); 247 netfree = (NETFREE) GetProcAddress(netapi,"NetApiBufferFree"); 248 } 249 250 if (netstatget && netfree) 251 { 252 LPBYTE outbuf; 253 /* NetStatisticsGet() is a Unicode only function 254 * STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0 255 * contains 17 fields. We treat each field as a source of 256 * one byte of entropy. 257 */ 258 259 if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0) 260 { 261 RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45); 262 netfree(outbuf); 263 } 264 if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0) 265 { 266 RAND_add(outbuf, sizeof(STAT_SERVER_0), 17); 267 netfree(outbuf); 268 } 269 } 270 271 if (netapi) 272 FreeLibrary(netapi); 273 274 /* It appears like this can cause an exception deep within ADVAPI32.DLL 275 * at random times on Windows 2000. Reported by Jeffrey Altman. 276 * Only use it on NT. 277 */ 278 279 if (advapi) 280 { 281 /* 282 * If it's available, then it's available in both ANSI 283 * and UNICODE flavors even in Win9x, documentation says. 284 * We favor Unicode... 285 */ 286 acquire = (CRYPTACQUIRECONTEXTW) GetProcAddress(advapi, 287 "CryptAcquireContextW"); 288 gen = (CRYPTGENRANDOM) GetProcAddress(advapi, 289 "CryptGenRandom"); 290 release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi, 291 "CryptReleaseContext"); 292 } 293 294 if (acquire && gen && release) 295 { 296 /* poll the CryptoAPI PRNG */ 297 /* The CryptoAPI returns sizeof(buf) bytes of randomness */ 298 if (acquire(&hProvider, NULL, NULL, PROV_RSA_FULL, 299 CRYPT_VERIFYCONTEXT)) 300 { 301 if (gen(hProvider, sizeof(buf), buf) != 0) 302 { 303 RAND_add(buf, sizeof(buf), 0); 304 good = 1; 305#if 0 306 printf("randomness from PROV_RSA_FULL\n"); 307#endif 308 } 309 release(hProvider, 0); 310 } 311 312 /* poll the Pentium PRG with CryptoAPI */ 313 if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0)) 314 { 315 if (gen(hProvider, sizeof(buf), buf) != 0) 316 { 317 RAND_add(buf, sizeof(buf), sizeof(buf)); 318 good = 1; 319#if 0 320 printf("randomness from PROV_INTEL_SEC\n"); 321#endif 322 } 323 release(hProvider, 0); 324 } 325 } 326 327 if (advapi) 328 FreeLibrary(advapi); 329 330 if ((!check_winnt() || 331 !OPENSSL_isservice()) && 332 (user = LoadLibrary(TEXT("USER32.DLL")))) 333 { 334 GETCURSORINFO cursor; 335 GETFOREGROUNDWINDOW win; 336 GETQUEUESTATUS queue; 337 338 win = (GETFOREGROUNDWINDOW) GetProcAddress(user, "GetForegroundWindow"); 339 cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo"); 340 queue = (GETQUEUESTATUS) GetProcAddress(user, "GetQueueStatus"); 341 342 if (win) 343 { 344 /* window handle */ 345 HWND h = win(); 346 RAND_add(&h, sizeof(h), 0); 347 } 348 if (cursor) 349 { 350 /* unfortunately, its not safe to call GetCursorInfo() 351 * on NT4 even though it exists in SP3 (or SP6) and 352 * higher. 353 */ 354 if (check_winnt() && !check_win_minplat(5)) 355 cursor = 0; 356 } 357 if (cursor) 358 { 359 /* cursor position */ 360 /* assume 2 bytes of entropy */ 361 CURSORINFO ci; 362 ci.cbSize = sizeof(CURSORINFO); 363 if (cursor(&ci)) 364 RAND_add(&ci, ci.cbSize, 2); 365 } 366 367 if (queue) 368 { 369 /* message queue status */ 370 /* assume 1 byte of entropy */ 371 w = queue(QS_ALLEVENTS); 372 RAND_add(&w, sizeof(w), 1); 373 } 374 375 FreeLibrary(user); 376 } 377 378 /* Toolhelp32 snapshot: enumerate processes, threads, modules and heap 379 * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm 380 * (Win 9x and 2000 only, not available on NT) 381 * 382 * This seeding method was proposed in Peter Gutmann, Software 383 * Generation of Practically Strong Random Numbers, 384 * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html 385 * revised version at http://www.cryptoengines.com/~peter/06_random.pdf 386 * (The assignment of entropy estimates below is arbitrary, but based 387 * on Peter's analysis the full poll appears to be safe. Additional 388 * interactive seeding is encouraged.) 389 */ 390 391 if (kernel) 392 { 393 CREATETOOLHELP32SNAPSHOT snap; 394 CLOSETOOLHELP32SNAPSHOT close_snap; 395 HANDLE handle; 396 397 HEAP32FIRST heap_first; 398 HEAP32NEXT heap_next; 399 HEAP32LIST heaplist_first, heaplist_next; 400 PROCESS32 process_first, process_next; 401 THREAD32 thread_first, thread_next; 402 MODULE32 module_first, module_next; 403 404 HEAPLIST32 hlist; 405 HEAPENTRY32 hentry; 406 PROCESSENTRY32 p; 407 THREADENTRY32 t; 408 MODULEENTRY32 m; 409 DWORD starttime = 0; 410 411 snap = (CREATETOOLHELP32SNAPSHOT) 412 GetProcAddress(kernel, "CreateToolhelp32Snapshot"); 413 close_snap = (CLOSETOOLHELP32SNAPSHOT) 414 GetProcAddress(kernel, "CloseToolhelp32Snapshot"); 415 heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First"); 416 heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next"); 417 heaplist_first = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst"); 418 heaplist_next = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext"); 419 process_first = (PROCESS32) GetProcAddress(kernel, "Process32First"); 420 process_next = (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 { 432 /* heap list and heap walking */ 433 /* HEAPLIST32 contains 3 fields that will change with 434 * each entry. Consider each field a source of 1 byte 435 * of entropy. 436 * HEAPENTRY32 contains 5 fields that will change with 437 * each entry. Consider each field a source of 1 byte 438 * of entropy. 439 */ 440 ZeroMemory(&hlist, sizeof(HEAPLIST32)); 441 hlist.dwSize = sizeof(HEAPLIST32); 442 if (good) starttime = GetTickCount(); 443#ifdef _MSC_VER 444 if (heaplist_first(handle, &hlist)) 445 { 446 /* 447 following discussion on dev ML, exception on WinCE (or other Win 448 platform) is theoretically of unknown origin; prevent infinite 449 loop here when this theoretical case occurs; otherwise cope with 450 the expected (MSDN documented) exception-throwing behaviour of 451 Heap32Next() on WinCE. 452 453 based on patch in original message by Tanguy Fautré (2009/03/02) 454 Subject: RAND_poll() and CreateToolhelp32Snapshot() stability 455 */ 456 int ex_cnt_limit = 42; 457 do 458 { 459 RAND_add(&hlist, hlist.dwSize, 3); 460 __try 461 { 462 ZeroMemory(&hentry, sizeof(HEAPENTRY32)); 463 hentry.dwSize = sizeof(HEAPENTRY32); 464 if (heap_first(&hentry, 465 hlist.th32ProcessID, 466 hlist.th32HeapID)) 467 { 468 int entrycnt = 80; 469 do 470 RAND_add(&hentry, 471 hentry.dwSize, 5); 472 while (heap_next(&hentry) 473 && (!good || (GetTickCount()-starttime)<MAXDELAY) 474 && --entrycnt > 0); 475 } 476 } 477 __except (EXCEPTION_EXECUTE_HANDLER) 478 { 479 /* ignore access violations when walking the heap list */ 480 ex_cnt_limit--; 481 } 482 } while (heaplist_next(handle, &hlist) 483 && (!good || (GetTickCount()-starttime)<MAXDELAY) 484 && ex_cnt_limit > 0); 485 } 486 487#else 488 if (heaplist_first(handle, &hlist)) 489 { 490 do 491 { 492 RAND_add(&hlist, hlist.dwSize, 3); 493 hentry.dwSize = sizeof(HEAPENTRY32); 494 if (heap_first(&hentry, 495 hlist.th32ProcessID, 496 hlist.th32HeapID)) 497 { 498 int entrycnt = 80; 499 do 500 RAND_add(&hentry, 501 hentry.dwSize, 5); 502 while (heap_next(&hentry) 503 && --entrycnt > 0); 504 } 505 } while (heaplist_next(handle, &hlist) 506 && (!good || (GetTickCount()-starttime)<MAXDELAY)); 507 } 508#endif 509 510 /* process walking */ 511 /* PROCESSENTRY32 contains 9 fields that will change 512 * with each entry. Consider each field a source of 513 * 1 byte of entropy. 514 */ 515 p.dwSize = sizeof(PROCESSENTRY32); 516 517 if (good) starttime = GetTickCount(); 518 if (process_first(handle, &p)) 519 do 520 RAND_add(&p, p.dwSize, 9); 521 while (process_next(handle, &p) && (!good || (GetTickCount()-starttime)<MAXDELAY)); 522 523 /* thread walking */ 524 /* THREADENTRY32 contains 6 fields that will change 525 * with each entry. Consider each field a source of 526 * 1 byte of entropy. 527 */ 528 t.dwSize = sizeof(THREADENTRY32); 529 if (good) starttime = GetTickCount(); 530 if (thread_first(handle, &t)) 531 do 532 RAND_add(&t, t.dwSize, 6); 533 while (thread_next(handle, &t) && (!good || (GetTickCount()-starttime)<MAXDELAY)); 534 535 /* module walking */ 536 /* MODULEENTRY32 contains 9 fields that will change 537 * with each entry. Consider each field a source of 538 * 1 byte of entropy. 539 */ 540 m.dwSize = sizeof(MODULEENTRY32); 541 if (good) starttime = GetTickCount(); 542 if (module_first(handle, &m)) 543 do 544 RAND_add(&m, m.dwSize, 9); 545 while (module_next(handle, &m) 546 && (!good || (GetTickCount()-starttime)<MAXDELAY)); 547 if (close_snap) 548 close_snap(handle); 549 else 550 CloseHandle(handle); 551 552 } 553 554 FreeLibrary(kernel); 555 } 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 if (check_winnt() && OPENSSL_isservice()>0) 697 return; 698 699 /* Create a screen DC and a memory DC compatible to screen DC */ 700 hScrDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); 701 hMemDC = CreateCompatibleDC(hScrDC); 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 /* Select new bitmap into memory DC */ 711 hOldBitmap = SelectObject(hMemDC, hBitmap); 712 713 /* Get bitmap properties */ 714 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm); 715 size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes; 716 717 bmbits = OPENSSL_malloc(size); 718 if (bmbits) { 719 /* Now go through the whole screen, repeatedly grabbing n lines */ 720 for (y = 0; y < h-n; y += n) 721 { 722 unsigned char md[MD_DIGEST_LENGTH]; 723 724 /* Bitblt screen DC to memory DC */ 725 BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY); 726 727 /* Copy bitmap bits from memory DC to bmbits */ 728 GetBitmapBits(hBitmap, size, bmbits); 729 730 /* Get the hash of the bitmap */ 731 MD(bmbits,size,md); 732 733 /* Seed the random generator with the hash value */ 734 RAND_add(md, MD_DIGEST_LENGTH, 0); 735 } 736 737 OPENSSL_free(bmbits); 738 } 739 740 /* Select old bitmap back into memory DC */ 741 hBitmap = SelectObject(hMemDC, hOldBitmap); 742 743 /* Clean up */ 744 DeleteObject(hBitmap); 745 DeleteDC(hMemDC); 746 DeleteDC(hScrDC); 747#endif /* !OPENSSL_SYS_WINCE */ 748} 749 750#endif 751