| OLD | NEW |
| (Empty) |
| 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 | |
| 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,"NetStatisticsGe
t"); | |
| 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/cl
ose | |
| 322 * the open handle | |
| 323 * Note: The 'HKEY_PERFORMANCE_DATA' key is implicitly o
pened | |
| 324 * when the RegQueryValueEx above is done. Howeve
r, 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, "GetForegroundW
indow"); | |
| 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, "Heap32List
First"); | |
| 475 heaplist_next = (HEAP32LIST) GetProcAddress(kernel, "Heap32ListN
ext"); | |
| 476 process_first = (PROCESS32) GetProcAddress(kernel, "Process32Fir
st"); | |
| 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-thro
wing 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 CreateToolhelp32Snap
shot() 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(HEAPE
NTRY32)); | |
| 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()-sta
rttime)<MAXDELAY) | |
| 531 && --entrycnt > 0); | |
| 532 } | |
| 533 } | |
| 534 __except (EXCEPTION_EXECUTE_HANDLER) | |
| 535 { | |
| 536 /* ignore access violati
ons when walking the heap list */ | |
| 537 ex_cnt_limit--; | |
| 538 } | |
| 539 } while (heaplist_next(handle, &hlist) | |
| 540 && (!good || (GetTickCount()-sta
rttime)<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()-sta
rttime)<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 || (Ge
tTickCount()-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 || (Get
TickCount()-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()-sta
rttime)<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@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 | |
| OLD | NEW |