Changes by Jeffrey Altman <jaltman@columbia.edu> to make RAND_poll()

work better in Win32.  Verified by zhu qun-ying <qyzhu@krdl.org.sg>.
This commit is contained in:
Richard Levitte 2000-09-21 07:02:27 +00:00
parent c19b6c922a
commit 10bb0dbfec

View File

@ -171,13 +171,16 @@ typedef BOOL (WINAPI *MODULE32)(HANDLE, LPMODULEENTRY32);
#include <lmcons.h> #include <lmcons.h>
#include <lmstats.h> #include <lmstats.h>
#if 0 /* Some compilers use LMSTR, others (VC6, for example) use LPTSTR. #if 1 /* The NET API is Unicode only. It requires the use of the UNICODE
* This part is disabled until a fix is found. * macro. When UNICODE is defined LPTSTR becomes LPWSTR. LMSTR was
* was added to the Platform SDK to allow the NET API to be used in
* non-Unicode applications provided that Unicode strings were still
* used for input. LMSTR is defined as LPWSTR.
*/ */
typedef NET_API_STATUS (NET_API_FUNCTION * NETSTATGET) typedef NET_API_STATUS (NET_API_FUNCTION * NETSTATGET)
(LMSTR, LMSTR, DWORD, DWORD, LPBYTE*); (LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE*);
typedef NET_API_STATUS (NET_API_FUNCTION * NETFREE)(LPBYTE); typedef NET_API_STATUS (NET_API_FUNCTION * NETFREE)(LPBYTE);
#endif /* 0 */ #endif /* 1 */
int RAND_poll(void) int RAND_poll(void)
{ {
@ -191,12 +194,20 @@ int RAND_poll(void)
CRYPTACQUIRECONTEXT acquire = 0; CRYPTACQUIRECONTEXT acquire = 0;
CRYPTGENRANDOM gen = 0; CRYPTGENRANDOM gen = 0;
CRYPTRELEASECONTEXT release = 0; CRYPTRELEASECONTEXT release = 0;
#if 0 /* This part is disabled until a fix for the problem with the #if 1 /* There was previously a problem with NETSTATGET. Currently, this
* definition of NETSTATGET is found. * section is still experimental, but if all goes well, this conditional
* will be removed
*/ */
NETSTATGET netstatget = 0; NETSTATGET netstatget = 0;
NETFREE netfree = 0; NETFREE netfree = 0;
#endif /* 0 */ #endif /* 1 */
/* Determine the OS version we are on so we can turn off things
* that do not work properly.
*/
OSVERSIONINFO osverinfo ;
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
GetVersionEx( &osverinfo ) ;
/* load functions dynamically - not available on all systems */ /* load functions dynamically - not available on all systems */
advapi = LoadLibrary("ADVAPI32.DLL"); advapi = LoadLibrary("ADVAPI32.DLL");
@ -204,9 +215,9 @@ int RAND_poll(void)
user = LoadLibrary("USER32.DLL"); user = LoadLibrary("USER32.DLL");
netapi = LoadLibrary("NETAPI32.DLL"); netapi = LoadLibrary("NETAPI32.DLL");
#if 0 /* This part is disabled until a fix for the problem with the #if 1 /* There was previously a problem with NETSTATGET. Currently, this
* definition of NETSTATGET is found. Also, note that VC6 doesn't * section is still experimental, but if all goes well, this conditional
* understand strings starting with L". * will be removed
*/ */
if (netapi) if (netapi)
{ {
@ -217,32 +228,41 @@ int RAND_poll(void)
if (netstatget && netfree) if (netstatget && netfree)
{ {
LPBYTE outbuf; LPBYTE outbuf;
/* NetStatisticsGet() is a Unicode only function */ /* 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) if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0)
{ {
RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 0); RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45);
netfree(outbuf); netfree(outbuf);
} }
if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0) if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0)
{ {
RAND_add(outbuf, sizeof(STAT_SERVER_0), 0); RAND_add(outbuf, sizeof(STAT_SERVER_0), 17);
netfree(outbuf); netfree(outbuf);
} }
} }
if (netapi) if (netapi)
FreeLibrary(netapi); FreeLibrary(netapi);
#endif /* 0 */ #endif /* 1 */
#if 0 /* It appears like this can cause an exception deep within ADVAPI32.DLL /* It appears like this can cause an exception deep within ADVAPI32.DLL
* at random times. Reported by Jeffrey Altman. * at random times on Windows 2000. Reported by Jeffrey Altman.
* Only use it on NT.
*/ */
/* Read Performance Statistics from NT/2000 registry */ if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
/* The size of the performance data can vary from call to call */ osverinfo.dwMajorVersion < 5)
/* so we must guess the size of the buffer to use and increase */
/* its size if we get an ERROR_MORE_DATA return instead of */
/* ERROR_SUCCESS. */
{ {
/* Read Performance Statistics from NT/2000 registry
* The size of the performance data can vary from call
* to call so we must guess the size of the buffer to use
* and increase its size if we get an ERROR_MORE_DATA
* return instead of ERROR_SUCCESS.
*/
LONG rc=ERROR_MORE_DATA; LONG rc=ERROR_MORE_DATA;
char * buf=NULL; char * buf=NULL;
DWORD bufsz=0; DWORD bufsz=0;
@ -261,13 +281,15 @@ int RAND_poll(void)
} }
if (rc == ERROR_SUCCESS) if (rc == ERROR_SUCCESS)
{ {
/* For entropy count assume only least significant
* byte of each DWORD is random.
*/
RAND_add(&length, sizeof(length), 0); RAND_add(&length, sizeof(length), 0);
RAND_add(buf, length, 0); RAND_add(buf, length, length / 4.0);
} }
if (buf) if (buf)
free(buf); free(buf);
} }
#endif /* 0 */
if (advapi) if (advapi)
{ {
@ -282,12 +304,13 @@ int RAND_poll(void)
if (acquire && gen && release) if (acquire && gen && release)
{ {
/* poll the CryptoAPI PRNG */ /* poll the CryptoAPI PRNG */
/* The CryptoAPI returns sizeof(buf) bytes of randomness */
if (acquire(&hProvider, 0, 0, PROV_RSA_FULL, if (acquire(&hProvider, 0, 0, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) CRYPT_VERIFYCONTEXT))
{ {
if (gen(hProvider, sizeof(buf), buf) != 0) if (gen(hProvider, sizeof(buf), buf) != 0)
{ {
RAND_add(buf, sizeof(buf), 0); RAND_add(buf, sizeof(buf), sizeof(buf));
#ifdef DEBUG #ifdef DEBUG
printf("randomness from PROV_RSA_FULL\n"); printf("randomness from PROV_RSA_FULL\n");
#endif #endif
@ -300,7 +323,7 @@ int RAND_poll(void)
{ {
if (gen(hProvider, sizeof(buf), buf) != 0) if (gen(hProvider, sizeof(buf), buf) != 0)
{ {
RAND_add(buf, sizeof(buf), 0); RAND_add(buf, sizeof(buf), sizeof(buf));
#ifdef DEBUG #ifdef DEBUG
printf("randomness from PROV_INTEL_SEC\n"); printf("randomness from PROV_INTEL_SEC\n");
#endif #endif
@ -321,7 +344,7 @@ int RAND_poll(void)
/* process ID */ /* process ID */
w = GetCurrentProcessId(); w = GetCurrentProcessId();
RAND_add(&w, sizeof(w), 0); RAND_add(&w, sizeof(w), 1);
if (user) if (user)
{ {
@ -339,36 +362,32 @@ int RAND_poll(void)
h = win(); h = win();
RAND_add(&h, sizeof(h), 0); RAND_add(&h, sizeof(h), 0);
} }
if (cursor) if (cursor)
{ {
/* unfortunately, its not safe to call GetCursorInfo() /* unfortunately, its not safe to call GetCursorInfo()
* on NT4 even though it exists in SP3 (or SP6) and * on NT4 even though it exists in SP3 (or SP6) and
* higher. * higher.
*/ */
OSVERSIONINFO osverinfo ;
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
GetVersionEx( &osverinfo ) ;
if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT && if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
osverinfo.dwMajorVersion < 5) osverinfo.dwMajorVersion < 5)
cursor = 0; cursor = 0;
} }
if (cursor) if (cursor)
{ {
/* cursor position */ /* cursor position */
/* assume 2 bytes of entropy */
CURSORINFO ci; CURSORINFO ci;
ci.cbSize = sizeof(CURSORINFO); ci.cbSize = sizeof(CURSORINFO);
if (cursor(&ci)) if (cursor(&ci))
RAND_add(&ci, ci.cbSize, 0); RAND_add(&ci, ci.cbSize, 2);
} }
if (queue) if (queue)
{ {
/* message queue status */ /* message queue status */
/* assume 1 byte of entropy */
w = queue(QS_ALLEVENTS); w = queue(QS_ALLEVENTS);
RAND_add(&w, sizeof(w), 0); RAND_add(&w, sizeof(w), 1);
} }
FreeLibrary(user); FreeLibrary(user);
@ -425,11 +444,18 @@ int RAND_poll(void)
!= NULL) != NULL)
{ {
/* heap list and heap walking */ /* 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.
*/
hlist.dwSize = sizeof(HEAPLIST32); hlist.dwSize = sizeof(HEAPLIST32);
if (heaplist_first(handle, &hlist)) if (heaplist_first(handle, &hlist))
do do
{ {
RAND_add(&hlist, hlist.dwSize, 0); RAND_add(&hlist, hlist.dwSize, 3);
hentry.dwSize = sizeof(HEAPENTRY32); hentry.dwSize = sizeof(HEAPENTRY32);
if (heap_first(&hentry, if (heap_first(&hentry,
hlist.th32ProcessID, hlist.th32ProcessID,
@ -438,7 +464,7 @@ int RAND_poll(void)
int entrycnt = 50; int entrycnt = 50;
do do
RAND_add(&hentry, RAND_add(&hentry,
hentry.dwSize, 0); hentry.dwSize, 5);
while (heap_next(&hentry) while (heap_next(&hentry)
&& --entrycnt > 0); && --entrycnt > 0);
} }
@ -446,24 +472,36 @@ int RAND_poll(void)
&hlist)); &hlist));
/* process walking */ /* 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); p.dwSize = sizeof(PROCESSENTRY32);
if (process_first(handle, &p)) if (process_first(handle, &p))
do do
RAND_add(&p, p.dwSize, 0); RAND_add(&p, p.dwSize, 9);
while (process_next(handle, &p)); while (process_next(handle, &p));
/* thread walking */ /* 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); t.dwSize = sizeof(THREADENTRY32);
if (thread_first(handle, &t)) if (thread_first(handle, &t))
do do
RAND_add(&t, t.dwSize, 0); RAND_add(&t, t.dwSize, 6);
while (thread_next(handle, &t)); while (thread_next(handle, &t));
/* module walking */ /* 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); m.dwSize = sizeof(MODULEENTRY32);
if (module_first(handle, &m)) if (module_first(handle, &m))
do do
RAND_add(&m, m.dwSize, 1); RAND_add(&m, m.dwSize, 9);
while (module_next(handle, &m)); while (module_next(handle, &m));
CloseHandle(handle); CloseHandle(handle);