From eb9b92ec8efd81abf4642b65c34cc542197a545a Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Fri, 11 Dec 2015 17:53:03 -0800 Subject: [PATCH] - remove insane heap walk and kernel loading code; clean up style and calling conventions Reviewed-by: Matt Caswell Reviewed-by: Tim Hudson Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/1079) --- crypto/rand/rand_win.c | 362 ++--------------------------------------- 1 file changed, 13 insertions(+), 349 deletions(-) diff --git a/crypto/rand/rand_win.c b/crypto/rand/rand_win.c index cb0c1edf09..87869985d9 100644 --- a/crypto/rand/rand_win.c +++ b/crypto/rand/rand_win.c @@ -97,360 +97,24 @@ int RAND_poll(void) MEMORYSTATUS mst; HCRYPTPROV hProvider = 0; DWORD w; - int good = 0; - -# if defined(OPENSSL_SYS_WINCE) -# if defined(_WIN32_WCE) && _WIN32_WCE>=300 - /* - * Even though MSDN says _WIN32_WCE>=210, it doesn't seem to be available - * in commonly available implementations prior 300... - */ - { - BYTE buf[64]; - /* poll the CryptoAPI PRNG */ - /* The CryptoAPI returns sizeof(buf) bytes of randomness */ - if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - if (CryptGenRandom(hProvider, sizeof(buf), buf)) - RAND_add(buf, sizeof(buf), sizeof(buf)); - CryptReleaseContext(hProvider, 0); - } - } -# endif -# else /* OPENSSL_SYS_WINCE */ - /* - * None of below libraries are present on Windows CE, which is - * why we #ifndef the whole section. This also excuses us from - * handling the GetProcAddress issue. The trouble is that in - * real Win32 API GetProcAddress is available in ANSI flavor - * only. In WinCE on the other hand GetProcAddress is a macro - * most commonly defined as GetProcAddressW, which accepts - * Unicode argument. If we were to call GetProcAddress under - * WinCE, I'd recommend to either redefine GetProcAddress as - * GetProcAddressA (there seem to be one in common CE spec) or - * implement own shim routine, which would accept ANSI argument - * and expand it to Unicode. - */ - { - /* load functions dynamically - not available on all systems */ - HMODULE advapi = LoadLibrary(TEXT("ADVAPI32.DLL")); - HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL")); - HMODULE user = NULL; - HMODULE netapi = LoadLibrary(TEXT("NETAPI32.DLL")); - CRYPTACQUIRECONTEXTW acquire = NULL; - CRYPTGENRANDOM gen = NULL; - CRYPTRELEASECONTEXT release = NULL; - NETSTATGET netstatget = NULL; - NETFREE netfree = NULL; - BYTE buf[64]; - - if (netapi) { - netstatget = - (NETSTATGET) GetProcAddress(netapi, "NetStatisticsGet"); - netfree = (NETFREE) GetProcAddress(netapi, "NetApiBufferFree"); - } + BYTE buf[64]; - if (netstatget && netfree) { - LPBYTE outbuf; - /* - * NetStatisticsGet() is a Unicode only function - * STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0 - * contains 17 fields. We treat each field as a source of one - * byte of entropy. - */ - - if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0) { - RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45); - netfree(outbuf); - } - if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0) { - RAND_add(outbuf, sizeof(STAT_SERVER_0), 17); - netfree(outbuf); - } - } - - if (netapi) - FreeLibrary(netapi); - - /* - * It appears like this can cause an exception deep within - * ADVAPI32.DLL at random times on Windows 2000. Reported by Jeffrey - * Altman. Only use it on NT. - */ - - if (advapi) { - /* - * If it's available, then it's available in both ANSI - * and UNICODE flavors even in Win9x, documentation says. - * We favor Unicode... - */ - acquire = (CRYPTACQUIRECONTEXTW) GetProcAddress(advapi, - "CryptAcquireContextW"); - gen = (CRYPTGENRANDOM) GetProcAddress(advapi, "CryptGenRandom"); - release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi, - "CryptReleaseContext"); - } - - if (acquire && gen && release) { - /* poll the CryptoAPI PRNG */ - /* The CryptoAPI returns sizeof(buf) bytes of randomness */ - if (acquire(&hProvider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - if (gen(hProvider, sizeof(buf), buf) != 0) { - RAND_add(buf, sizeof(buf), 0); - good = 1; - } - release(hProvider, 0); - } - - /* poll the Pentium PRG with CryptoAPI */ - if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0)) { - if (gen(hProvider, sizeof(buf), buf) != 0) { - RAND_add(buf, sizeof(buf), sizeof(buf)); - good = 1; - } - release(hProvider, 0); - } - } - - if (advapi) - FreeLibrary(advapi); - - if ((!check_winnt() || - !OPENSSL_isservice()) && - (user = LoadLibrary(TEXT("USER32.DLL")))) { - GETCURSORINFO cursor; - GETFOREGROUNDWINDOW win; - GETQUEUESTATUS queue; - - win = - (GETFOREGROUNDWINDOW) GetProcAddress(user, - "GetForegroundWindow"); - cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo"); - queue = (GETQUEUESTATUS) GetProcAddress(user, "GetQueueStatus"); - - if (win) { - /* window handle */ - HWND h = win(); - RAND_add(&h, sizeof(h), 0); - } - if (cursor) { - /* - * unfortunately, its not safe to call GetCursorInfo() on NT4 - * even though it exists in SP3 (or SP6) and higher. - */ - if (check_winnt() && !check_win_minplat(5)) - cursor = 0; - } - if (cursor) { - /* cursor position */ - /* assume 2 bytes of entropy */ - CURSORINFO ci; - ci.cbSize = sizeof(CURSORINFO); - if (cursor(&ci)) - RAND_add(&ci, ci.cbSize, 2); - } - - if (queue) { - /* message queue status */ - /* assume 1 byte of entropy */ - w = queue(QS_ALLEVENTS); - RAND_add(&w, sizeof(w), 1); - } - - FreeLibrary(user); + /* poll the CryptoAPI PRNG */ + /* The CryptoAPI returns sizeof(buf) bytes of randomness */ + if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + if (CryptGenRandom(hProvider, sizeof(buf), buf) != 0) { + RAND_add(buf, sizeof(buf), sizeof(buf)); } + CryptReleaseContext(hProvider, 0); + } - /*- - * Toolhelp32 snapshot: enumerate processes, threads, modules and heap - * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm - * (Win 9x and 2000 only, not available on NT) - * - * This seeding method was proposed in Peter Gutmann, Software - * Generation of Practically Strong Random Numbers, - * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html - * revised version at http://www.cryptoengines.com/~peter/06_random.pdf - * (The assignment of entropy estimates below is arbitrary, but based - * on Peter's analysis the full poll appears to be safe. Additional - * interactive seeding is encouraged.) - */ - - if (kernel) { - CREATETOOLHELP32SNAPSHOT snap; - CLOSETOOLHELP32SNAPSHOT close_snap; - HANDLE handle; - - HEAP32FIRST heap_first; - HEAP32NEXT heap_next; - HEAP32LIST heaplist_first, heaplist_next; - PROCESS32 process_first, process_next; - THREAD32 thread_first, thread_next; - MODULE32 module_first, module_next; - - HEAPLIST32 hlist; - HEAPENTRY32 hentry; - PROCESSENTRY32 p; - THREADENTRY32 t; - MODULEENTRY32 m; - DWORD starttime = 0; - - snap = (CREATETOOLHELP32SNAPSHOT) - GetProcAddress(kernel, "CreateToolhelp32Snapshot"); - close_snap = (CLOSETOOLHELP32SNAPSHOT) - GetProcAddress(kernel, "CloseToolhelp32Snapshot"); - heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First"); - heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next"); - heaplist_first = - (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst"); - heaplist_next = - (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext"); - process_first = - (PROCESS32) GetProcAddress(kernel, "Process32First"); - process_next = - (PROCESS32) GetProcAddress(kernel, "Process32Next"); - thread_first = (THREAD32) GetProcAddress(kernel, "Thread32First"); - thread_next = (THREAD32) GetProcAddress(kernel, "Thread32Next"); - module_first = (MODULE32) GetProcAddress(kernel, "Module32First"); - module_next = (MODULE32) GetProcAddress(kernel, "Module32Next"); - - if (snap && heap_first && heap_next && heaplist_first && - heaplist_next && process_first && process_next && - thread_first && thread_next && module_first && - module_next && (handle = snap(TH32CS_SNAPALL, 0)) - != INVALID_HANDLE_VALUE) { - /* heap list and heap walking */ - /* - * HEAPLIST32 contains 3 fields that will change with each - * entry. Consider each field a source of 1 byte of entropy. - * HEAPENTRY32 contains 5 fields that will change with each - * entry. Consider each field a source of 1 byte of entropy. - */ - ZeroMemory(&hlist, sizeof(HEAPLIST32)); - hlist.dwSize = sizeof(HEAPLIST32); - if (good) - starttime = GetTickCount(); -# ifdef _MSC_VER - if (heaplist_first(handle, &hlist)) { - /* - * following discussion on dev ML, exception on WinCE (or - * other Win platform) is theoretically of unknown - * origin; prevent infinite loop here when this - * theoretical case occurs; otherwise cope with the - * expected (MSDN documented) exception-throwing - * behaviour of Heap32Next() on WinCE. - * - * based on patch in original message by Tanguy Fautré - * (2009/03/02) Subject: RAND_poll() and - * CreateToolhelp32Snapshot() stability - */ - int ex_cnt_limit = 42; - do { - RAND_add(&hlist, hlist.dwSize, 3); - __try { - ZeroMemory(&hentry, sizeof(HEAPENTRY32)); - hentry.dwSize = sizeof(HEAPENTRY32); - if (heap_first(&hentry, - hlist.th32ProcessID, - hlist.th32HeapID)) { - int entrycnt = 80; - do - RAND_add(&hentry, hentry.dwSize, 5); - while (heap_next(&hentry) - && (!good - || (GetTickCount() - starttime) < - MAXDELAY) - && --entrycnt > 0); - } - } - __except(EXCEPTION_EXECUTE_HANDLER) { - /* - * ignore access violations when walking the heap - * list - */ - ex_cnt_limit--; - } - } while (heaplist_next(handle, &hlist) - && (!good - || (GetTickCount() - starttime) < MAXDELAY) - && ex_cnt_limit > 0); - } -# else - if (heaplist_first(handle, &hlist)) { - do { - RAND_add(&hlist, hlist.dwSize, 3); - hentry.dwSize = sizeof(HEAPENTRY32); - if (heap_first(&hentry, - hlist.th32ProcessID, - hlist.th32HeapID)) { - int entrycnt = 80; - do - RAND_add(&hentry, hentry.dwSize, 5); - while (heap_next(&hentry) - && --entrycnt > 0); - } - } while (heaplist_next(handle, &hlist) - && (!good - || (GetTickCount() - starttime) < MAXDELAY)); - } -# endif - - /* process walking */ - /* - * PROCESSENTRY32 contains 9 fields that will change with - * each entry. Consider each field a source of 1 byte of - * entropy. - */ - p.dwSize = sizeof(PROCESSENTRY32); - - if (good) - starttime = GetTickCount(); - if (process_first(handle, &p)) - do - RAND_add(&p, p.dwSize, 9); - while (process_next(handle, &p) - && (!good - || (GetTickCount() - starttime) < MAXDELAY)); - - /* thread walking */ - /* - * THREADENTRY32 contains 6 fields that will change with each - * entry. Consider each field a source of 1 byte of entropy. - */ - t.dwSize = sizeof(THREADENTRY32); - if (good) - starttime = GetTickCount(); - if (thread_first(handle, &t)) - do - RAND_add(&t, t.dwSize, 6); - while (thread_next(handle, &t) - && (!good - || (GetTickCount() - starttime) < MAXDELAY)); - - /* module walking */ - /* - * MODULEENTRY32 contains 9 fields that will change with each - * entry. Consider each field a source of 1 byte of entropy. - */ - m.dwSize = sizeof(MODULEENTRY32); - if (good) - starttime = GetTickCount(); - if (module_first(handle, &m)) - do - RAND_add(&m, m.dwSize, 9); - while (module_next(handle, &m) - && (!good - || (GetTickCount() - starttime) < MAXDELAY)); - if (close_snap) - close_snap(handle); - else - CloseHandle(handle); - - } - - FreeLibrary(kernel); + /* poll the Pentium PRG with CryptoAPI */ + if (CryptAcquireContextW(&hProvider, NULL, INTEL_DEF_PROV, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT)) { + if (CryptGenRandom(hProvider, sizeof(buf), buf) != 0) { + RAND_add(buf, sizeof(buf), sizeof(buf)); } + CryptReleaseContext(hProvider, 0); } -# endif /* !OPENSSL_SYS_WINCE */ /* timer data */ readtimer(); -- GitLab