diff options
author | Jay Threeth | 2011-04-04 11:48:26 -0700 |
---|---|---|
committer | Jay Threeth | 2011-04-04 11:48:26 -0700 |
commit | 3c9cc506f741b980565ff5b3b001cd8b6ee36b12 (patch) | |
tree | cb862c57b3d5f74177cde3bd962a53fc377166f6 /linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndw32.c | |
parent | build fixes, might build on linux now (diff) | |
download | meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.zip meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.tar.gz meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.tar.bz2 meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.tar.xz |
add source to libraries, and cruft for building under windows
Diffstat (limited to 'linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndw32.c')
-rwxr-xr-x | linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndw32.c | 690 |
1 files changed, 690 insertions, 0 deletions
diff --git a/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndw32.c b/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndw32.c new file mode 100755 index 0000000..cbd44e6 --- /dev/null +++ b/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndw32.c | |||
@@ -0,0 +1,690 @@ | |||
1 | /* rndw32.c - W32 entropy gatherer | ||
2 | * Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc. | ||
3 | * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-1999 | ||
4 | * | ||
5 | * This file is part of Libgcrypt. | ||
6 | * | ||
7 | ************************************************************************* | ||
8 | * The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann. | ||
9 | * Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this | ||
10 | * copyright notice: | ||
11 | * | ||
12 | * This module is part of the cryptlib continuously seeded pseudorandom | ||
13 | * number generator. For usage conditions, see lib_rand.c | ||
14 | * | ||
15 | * [Here is the notice from lib_rand.c, which is now called dev_sys.c] | ||
16 | * | ||
17 | * This module and the misc/rnd*.c modules represent the cryptlib | ||
18 | * continuously seeded pseudorandom number generator (CSPRNG) as described in | ||
19 | * my 1998 Usenix Security Symposium paper "The generation of random numbers | ||
20 | * for cryptographic purposes". | ||
21 | * | ||
22 | * The CSPRNG code is copyright Peter Gutmann (and various others) 1996, | ||
23 | * 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG | ||
24 | * modules and use in source and binary forms, with or without modification, | ||
25 | * are permitted provided that the following conditions are met: | ||
26 | * | ||
27 | * 1. Redistributions of source code must retain the above copyright notice | ||
28 | * and this permission notice in its entirety. | ||
29 | * | ||
30 | * 2. Redistributions in binary form must reproduce the copyright notice in | ||
31 | * the documentation and/or other materials provided with the distribution. | ||
32 | * | ||
33 | * 3. A copy of any bugfixes or enhancements made must be provided to the | ||
34 | * author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the | ||
35 | * baseline version of the code. | ||
36 | * | ||
37 | * ALTERNATIVELY, the code may be distributed under the terms of the GNU | ||
38 | * General Public License, version 2 or any later version published by the | ||
39 | * Free Software Foundation, in which case the provisions of the GNU GPL are | ||
40 | * required INSTEAD OF the above restrictions. | ||
41 | * | ||
42 | * Although not required under the terms of the GPL, it would still be nice if | ||
43 | * you could make any changes available to the author to allow a consistent | ||
44 | * code base to be maintained | ||
45 | ************************************************************************* | ||
46 | */ | ||
47 | |||
48 | #include <config.h> | ||
49 | #include <stdio.h> | ||
50 | #include <stdlib.h> | ||
51 | #include <assert.h> | ||
52 | #include <errno.h> | ||
53 | #include <string.h> | ||
54 | |||
55 | #include <windows.h> | ||
56 | |||
57 | |||
58 | #include "types.h" | ||
59 | #include "g10lib.h" | ||
60 | #include "rand-internal.h" | ||
61 | |||
62 | |||
63 | static int debug_me; | ||
64 | |||
65 | /* | ||
66 | * Definitions which are missing from the current GNU Windows32Api | ||
67 | */ | ||
68 | |||
69 | #ifndef TH32CS_SNAPHEAPLIST | ||
70 | #define TH32CS_SNAPHEAPLIST 1 | ||
71 | #define TH32CS_SNAPPROCESS 2 | ||
72 | #define TH32CS_SNAPTHREAD 4 | ||
73 | #define TH32CS_SNAPMODULE 8 | ||
74 | #define TH32CS_SNAPALL (1|2|4|8) | ||
75 | #define TH32CS_INHERIT 0x80000000 | ||
76 | #endif /*TH32CS_SNAPHEAPLIST*/ | ||
77 | |||
78 | #ifndef IOCTL_DISK_PERFORMANCE | ||
79 | #define IOCTL_DISK_PERFORMANCE 0x00070020 | ||
80 | #endif | ||
81 | #ifndef VER_PLATFORM_WIN32_WINDOWS | ||
82 | #define VER_PLATFORM_WIN32_WINDOWS 1 | ||
83 | #endif | ||
84 | |||
85 | /* This used to be (6*8+5*4+8*2), but Peter Gutmann figured a larger | ||
86 | value in a newer release. So we use a far larger value. */ | ||
87 | #define SIZEOF_DISK_PERFORMANCE_STRUCT 256 | ||
88 | |||
89 | |||
90 | typedef struct { | ||
91 | DWORD dwSize; | ||
92 | DWORD th32ProcessID; | ||
93 | DWORD th32HeapID; | ||
94 | DWORD dwFlags; | ||
95 | } HEAPLIST32; | ||
96 | |||
97 | typedef struct { | ||
98 | DWORD dwSize; | ||
99 | HANDLE hHandle; | ||
100 | DWORD dwAddress; | ||
101 | DWORD dwBlockSize; | ||
102 | DWORD dwFlags; | ||
103 | DWORD dwLockCount; | ||
104 | DWORD dwResvd; | ||
105 | DWORD th32ProcessID; | ||
106 | DWORD th32HeapID; | ||
107 | } HEAPENTRY32; | ||
108 | |||
109 | typedef struct { | ||
110 | DWORD dwSize; | ||
111 | DWORD cntUsage; | ||
112 | DWORD th32ProcessID; | ||
113 | DWORD th32DefaultHeapID; | ||
114 | DWORD th32ModuleID; | ||
115 | DWORD cntThreads; | ||
116 | DWORD th32ParentProcessID; | ||
117 | LONG pcPriClassBase; | ||
118 | DWORD dwFlags; | ||
119 | char szExeFile[260]; | ||
120 | } PROCESSENTRY32; | ||
121 | |||
122 | typedef struct { | ||
123 | DWORD dwSize; | ||
124 | DWORD cntUsage; | ||
125 | DWORD th32ThreadID; | ||
126 | DWORD th32OwnerProcessID; | ||
127 | LONG tpBasePri; | ||
128 | LONG tpDeltaPri; | ||
129 | DWORD dwFlags; | ||
130 | } THREADENTRY32; | ||
131 | |||
132 | typedef struct { | ||
133 | DWORD dwSize; | ||
134 | DWORD th32ModuleID; | ||
135 | DWORD th32ProcessID; | ||
136 | DWORD GlblcntUsage; | ||
137 | DWORD ProccntUsage; | ||
138 | BYTE *modBaseAddr; | ||
139 | DWORD modBaseSize; | ||
140 | HMODULE hModule; | ||
141 | char szModule[256]; | ||
142 | char szExePath[260]; | ||
143 | } MODULEENTRY32; | ||
144 | |||
145 | |||
146 | |||
147 | /* Type definitions for function pointers to call Toolhelp32 functions | ||
148 | * used with the windows95 gatherer */ | ||
149 | typedef BOOL (WINAPI * MODULEWALK) (HANDLE hSnapshot, MODULEENTRY32 *lpme); | ||
150 | typedef BOOL (WINAPI * THREADWALK) (HANDLE hSnapshot, THREADENTRY32 *lpte); | ||
151 | typedef BOOL (WINAPI * PROCESSWALK) (HANDLE hSnapshot, PROCESSENTRY32 *lppe); | ||
152 | typedef BOOL (WINAPI * HEAPLISTWALK) (HANDLE hSnapshot, HEAPLIST32 *lphl); | ||
153 | typedef BOOL (WINAPI * HEAPFIRST) (HEAPENTRY32 *lphe, DWORD th32ProcessID, | ||
154 | DWORD th32HeapID); | ||
155 | typedef BOOL (WINAPI * HEAPNEXT) (HEAPENTRY32 *lphe); | ||
156 | typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD dwFlags, DWORD th32ProcessID); | ||
157 | |||
158 | /* Type definitions for function pointers to call NetAPI32 functions */ | ||
159 | typedef DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService, | ||
160 | DWORD dwLevel, DWORD dwOptions, | ||
161 | LPBYTE * lpBuffer); | ||
162 | typedef DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer); | ||
163 | typedef DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer); | ||
164 | |||
165 | |||
166 | /* When we query the performance counters, we allocate an initial buffer and | ||
167 | * then reallocate it as required until RegQueryValueEx() stops returning | ||
168 | * ERROR_MORE_DATA. The following values define the initial buffer size and | ||
169 | * step size by which the buffer is increased | ||
170 | */ | ||
171 | #define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */ | ||
172 | #define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */ | ||
173 | |||
174 | |||
175 | static void | ||
176 | slow_gatherer_windows95( void (*add)(const void*, size_t, int), int requester ) | ||
177 | { | ||
178 | static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL; | ||
179 | static MODULEWALK pModule32First = NULL; | ||
180 | static MODULEWALK pModule32Next = NULL; | ||
181 | static PROCESSWALK pProcess32First = NULL; | ||
182 | static PROCESSWALK pProcess32Next = NULL; | ||
183 | static THREADWALK pThread32First = NULL; | ||
184 | static THREADWALK pThread32Next = NULL; | ||
185 | static HEAPLISTWALK pHeap32ListFirst = NULL; | ||
186 | static HEAPLISTWALK pHeap32ListNext = NULL; | ||
187 | static HEAPFIRST pHeap32First = NULL; | ||
188 | static HEAPNEXT pHeap32Next = NULL; | ||
189 | HANDLE hSnapshot; | ||
190 | |||
191 | |||
192 | /* initialize the Toolhelp32 function pointers */ | ||
193 | if ( !pCreateToolhelp32Snapshot ) { | ||
194 | HANDLE hKernel; | ||
195 | |||
196 | if ( debug_me ) | ||
197 | log_debug ("rndw32#slow_gatherer_95: init toolkit\n" ); | ||
198 | |||
199 | /* Obtain the module handle of the kernel to retrieve the addresses | ||
200 | * of the Toolhelp32 functions */ | ||
201 | if ( ( !(hKernel = GetModuleHandle ("KERNEL32.DLL"))) ) { | ||
202 | log_fatal ( "rndw32: can't get module handle\n" ); | ||
203 | } | ||
204 | |||
205 | /* Now get pointers to the functions */ | ||
206 | pCreateToolhelp32Snapshot = (CREATESNAPSHOT) GetProcAddress (hKernel, | ||
207 | "CreateToolhelp32Snapshot"); | ||
208 | pModule32First = (MODULEWALK) GetProcAddress (hKernel, "Module32First"); | ||
209 | pModule32Next = (MODULEWALK) GetProcAddress (hKernel, "Module32Next"); | ||
210 | pProcess32First = (PROCESSWALK) GetProcAddress (hKernel, | ||
211 | "Process32First"); | ||
212 | pProcess32Next = (PROCESSWALK) GetProcAddress (hKernel, | ||
213 | "Process32Next"); | ||
214 | pThread32First = (THREADWALK) GetProcAddress (hKernel, "Thread32First"); | ||
215 | pThread32Next = (THREADWALK) GetProcAddress (hKernel, "Thread32Next"); | ||
216 | pHeap32ListFirst = (HEAPLISTWALK) GetProcAddress (hKernel, | ||
217 | "Heap32ListFirst"); | ||
218 | pHeap32ListNext = (HEAPLISTWALK) GetProcAddress (hKernel, | ||
219 | "Heap32ListNext"); | ||
220 | pHeap32First = (HEAPFIRST) GetProcAddress (hKernel, "Heap32First"); | ||
221 | pHeap32Next = (HEAPNEXT) GetProcAddress (hKernel, "Heap32Next"); | ||
222 | |||
223 | if ( !pCreateToolhelp32Snapshot | ||
224 | || !pModule32First || !pModule32Next | ||
225 | || !pProcess32First || !pProcess32Next | ||
226 | || !pThread32First || !pThread32Next | ||
227 | || !pHeap32ListFirst || !pHeap32ListNext | ||
228 | || !pHeap32First || !pHeap32Next ) { | ||
229 | log_fatal ( "rndw32: failed to get a toolhelp function\n" ); | ||
230 | } | ||
231 | } | ||
232 | |||
233 | /* Take a snapshot of everything we can get to which is currently | ||
234 | * in the system */ | ||
235 | if ( !(hSnapshot = pCreateToolhelp32Snapshot (TH32CS_SNAPALL, 0)) ) { | ||
236 | log_fatal ( "rndw32: failed to take a toolhelp snapshot\n" ); | ||
237 | } | ||
238 | |||
239 | /* Walk through the local heap */ | ||
240 | { HEAPLIST32 hl32; | ||
241 | DWORD dwHeapsAdded = 0; | ||
242 | const DWORD maxHeapsToAdd = 500; | ||
243 | hl32.dwSize = sizeof (HEAPLIST32); | ||
244 | if (pHeap32ListFirst (hSnapshot, &hl32)) { | ||
245 | if ( debug_me ) | ||
246 | log_debug ("rndw32#slow_gatherer_95: walk heap\n" ); | ||
247 | do { | ||
248 | HEAPENTRY32 he32; | ||
249 | |||
250 | /* First add the information from the basic Heaplist32 struct */ | ||
251 | (*add) ( &hl32, sizeof (hl32), requester ); | ||
252 | |||
253 | /* Now walk through the heap blocks getting information | ||
254 | * on each of them */ | ||
255 | he32.dwSize = sizeof (HEAPENTRY32); | ||
256 | if (pHeap32First (&he32, hl32.th32ProcessID, hl32.th32HeapID)){ | ||
257 | do { | ||
258 | (*add) ( &he32, sizeof (he32), requester ); | ||
259 | if (++dwHeapsAdded == maxHeapsToAdd) { | ||
260 | goto doneheap; | ||
261 | } | ||
262 | } while (pHeap32Next (&he32)); | ||
263 | } | ||
264 | } while (pHeap32ListNext (hSnapshot, &hl32)); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | doneheap: | ||
269 | |||
270 | /* Walk through all processes */ | ||
271 | { PROCESSENTRY32 pe32; | ||
272 | pe32.dwSize = sizeof (PROCESSENTRY32); | ||
273 | if (pProcess32First (hSnapshot, &pe32)) { | ||
274 | if ( debug_me ) | ||
275 | log_debug ("rndw32#slow_gatherer_95: walk processes\n" ); | ||
276 | do { | ||
277 | (*add) ( &pe32, sizeof (pe32), requester ); | ||
278 | } while (pProcess32Next (hSnapshot, &pe32)); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | /* Walk through all threads */ | ||
283 | { THREADENTRY32 te32; | ||
284 | te32.dwSize = sizeof (THREADENTRY32); | ||
285 | if (pThread32First (hSnapshot, &te32)) { | ||
286 | if ( debug_me ) | ||
287 | log_debug ("rndw32#slow_gatherer_95: walk threads\n" ); | ||
288 | do { | ||
289 | (*add) ( &te32, sizeof (te32), requester ); | ||
290 | } while (pThread32Next (hSnapshot, &te32)); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /* Walk through all modules associated with the process */ | ||
295 | { MODULEENTRY32 me32; | ||
296 | me32.dwSize = sizeof (MODULEENTRY32); | ||
297 | if (pModule32First (hSnapshot, &me32)) { | ||
298 | if ( debug_me ) | ||
299 | log_debug ("rndw32#slow_gatherer_95: walk modules\n" ); | ||
300 | do { | ||
301 | (*add) ( &me32, sizeof (me32), requester ); | ||
302 | } while (pModule32Next (hSnapshot, &me32)); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | CloseHandle (hSnapshot); | ||
307 | } | ||
308 | |||
309 | |||
310 | |||
311 | static void | ||
312 | slow_gatherer_windowsNT( void (*add)(const void*, size_t, int), int requester ) | ||
313 | { | ||
314 | static int is_initialized = 0; | ||
315 | static NETSTATISTICSGET pNetStatisticsGet = NULL; | ||
316 | static NETAPIBUFFERSIZE pNetApiBufferSize = NULL; | ||
317 | static NETAPIBUFFERFREE pNetApiBufferFree = NULL; | ||
318 | static int is_workstation = 1; | ||
319 | |||
320 | static int cbPerfData = PERFORMANCE_BUFFER_SIZE; | ||
321 | PERF_DATA_BLOCK *pPerfData; | ||
322 | HANDLE hDevice, hNetAPI32 = NULL; | ||
323 | DWORD dwSize, status; | ||
324 | int nDrive; | ||
325 | |||
326 | if ( !is_initialized ) { | ||
327 | HKEY hKey; | ||
328 | |||
329 | if ( debug_me ) | ||
330 | log_debug ("rndw32#slow_gatherer_nt: init toolkit\n" ); | ||
331 | /* Find out whether this is an NT server or workstation if necessary */ | ||
332 | if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, | ||
333 | "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", | ||
334 | 0, KEY_READ, &hKey) == ERROR_SUCCESS) { | ||
335 | BYTE szValue[32]; | ||
336 | dwSize = sizeof (szValue); | ||
337 | |||
338 | if ( debug_me ) | ||
339 | log_debug ("rndw32#slow_gatherer_nt: check product options\n" ); | ||
340 | status = RegQueryValueEx (hKey, "ProductType", 0, NULL, | ||
341 | szValue, &dwSize); | ||
342 | if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT")) { | ||
343 | /* Note: There are (at least) three cases for ProductType: | ||
344 | * WinNT = NT Workstation, ServerNT = NT Server, LanmanNT = | ||
345 | * NT Server acting as a Domain Controller */ | ||
346 | is_workstation = 0; | ||
347 | if ( debug_me ) | ||
348 | log_debug ("rndw32: this is a NT server\n"); | ||
349 | } | ||
350 | RegCloseKey (hKey); | ||
351 | } | ||
352 | |||
353 | /* Initialize the NetAPI32 function pointers if necessary */ | ||
354 | if ( (hNetAPI32 = LoadLibrary ("NETAPI32.DLL")) ) { | ||
355 | if ( debug_me ) | ||
356 | log_debug ("rndw32#slow_gatherer_nt: netapi32 loaded\n" ); | ||
357 | pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32, | ||
358 | "NetStatisticsGet"); | ||
359 | pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32, | ||
360 | "NetApiBufferSize"); | ||
361 | pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32, | ||
362 | "NetApiBufferFree"); | ||
363 | |||
364 | if ( !pNetStatisticsGet | ||
365 | || !pNetApiBufferSize || !pNetApiBufferFree ) { | ||
366 | FreeLibrary (hNetAPI32); | ||
367 | hNetAPI32 = NULL; | ||
368 | log_debug ("rndw32: No NETAPI found\n" ); | ||
369 | } | ||
370 | } | ||
371 | |||
372 | is_initialized = 1; | ||
373 | } | ||
374 | |||
375 | /* Get network statistics. Note: Both NT Workstation and NT Server by | ||
376 | * default will be running both the workstation and server services. The | ||
377 | * heuristic below is probably useful though on the assumption that the | ||
378 | * majority of the network traffic will be via the appropriate service. | ||
379 | * In any case the network statistics return almost no randomness */ | ||
380 | { LPBYTE lpBuffer; | ||
381 | if (hNetAPI32 && !pNetStatisticsGet (NULL, | ||
382 | is_workstation ? L"LanmanWorkstation" : | ||
383 | L"LanmanServer", 0, 0, &lpBuffer) ) { | ||
384 | if ( debug_me ) | ||
385 | log_debug ("rndw32#slow_gatherer_nt: get netstats\n" ); | ||
386 | pNetApiBufferSize (lpBuffer, &dwSize); | ||
387 | (*add) ( lpBuffer, dwSize,requester ); | ||
388 | pNetApiBufferFree (lpBuffer); | ||
389 | } | ||
390 | } | ||
391 | |||
392 | /* Get disk I/O statistics for all the hard drives */ | ||
393 | for (nDrive = 0;; nDrive++) { | ||
394 | char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT]; | ||
395 | char szDevice[50]; | ||
396 | |||
397 | /* Check whether we can access this device */ | ||
398 | sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive); | ||
399 | hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, | ||
400 | NULL, OPEN_EXISTING, 0, NULL); | ||
401 | if (hDevice == INVALID_HANDLE_VALUE) | ||
402 | break; | ||
403 | |||
404 | /* Note: This only works if you have turned on the disk performance | ||
405 | * counters with 'diskperf -y'. These counters are off by default */ | ||
406 | if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, | ||
407 | &diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT, | ||
408 | &dwSize, NULL)) | ||
409 | { | ||
410 | if ( debug_me ) | ||
411 | log_debug ("rndw32#slow_gatherer_nt: iostats drive %d\n", | ||
412 | nDrive ); | ||
413 | (*add) (diskPerformance, dwSize, requester ); | ||
414 | } | ||
415 | else { | ||
416 | log_info ("NOTE: you should run 'diskperf -y' " | ||
417 | "to enable the disk statistics\n"); | ||
418 | } | ||
419 | CloseHandle (hDevice); | ||
420 | } | ||
421 | |||
422 | #if 0 /* we don't need this in GnuPG */ | ||
423 | /* Wait for any async keyset driver binding to complete. You may be | ||
424 | * wondering what this call is doing here... the reason it's necessary is | ||
425 | * because RegQueryValueEx() will hang indefinitely if the async driver | ||
426 | * bind is in progress. The problem occurs in the dynamic loading and | ||
427 | * linking of driver DLL's, which work as follows: | ||
428 | * | ||
429 | * hDriver = LoadLibrary( DRIVERNAME ); | ||
430 | * pFunction1 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC1 ); | ||
431 | * pFunction2 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC2 ); | ||
432 | * | ||
433 | * If RegQueryValueEx() is called while the GetProcAddress()'s are in | ||
434 | * progress, it will hang indefinitely. This is probably due to some | ||
435 | * synchronisation problem in the NT kernel where the GetProcAddress() | ||
436 | * calls affect something like a module reference count or function | ||
437 | * reference count while RegQueryValueEx() is trying to take a snapshot | ||
438 | * of the statistics, which include the reference counts. Because of | ||
439 | * this, we have to wait until any async driver bind has completed | ||
440 | * before we can call RegQueryValueEx() */ | ||
441 | waitSemaphore (SEMAPHORE_DRIVERBIND); | ||
442 | #endif | ||
443 | |||
444 | /* Get information from the system performance counters. This can take | ||
445 | * a few seconds to do. In some environments the call to | ||
446 | * RegQueryValueEx() can produce an access violation at some random time | ||
447 | * in the future, adding a short delay after the following code block | ||
448 | * makes the problem go away. This problem is extremely difficult to | ||
449 | * reproduce, I haven't been able to get it to occur despite running it | ||
450 | * on a number of machines. The best explanation for the problem is that | ||
451 | * on the machine where it did occur, it was caused by an external driver | ||
452 | * or other program which adds its own values under the | ||
453 | * HKEY_PERFORMANCE_DATA key. The NT kernel calls the required external | ||
454 | * modules to map in the data, if there's a synchronisation problem the | ||
455 | * external module would write its data at an inappropriate moment, | ||
456 | * causing the access violation. A low-level memory checker indicated | ||
457 | * that ExpandEnvironmentStrings() in KERNEL32.DLL, called an | ||
458 | * interminable number of calls down inside RegQueryValueEx(), was | ||
459 | * overwriting memory (it wrote twice the allocated size of a buffer to a | ||
460 | * buffer allocated by the NT kernel). This may be what's causing the | ||
461 | * problem, but since it's in the kernel there isn't much which can be | ||
462 | * done. | ||
463 | * | ||
464 | * In addition to these problems the code in RegQueryValueEx() which | ||
465 | * estimates the amount of memory required to return the performance | ||
466 | * counter information isn't very accurate, since it always returns a | ||
467 | * worst-case estimate which is usually nowhere near the actual amount | ||
468 | * required. For example it may report that 128K of memory is required, | ||
469 | * but only return 64K of data */ | ||
470 | { pPerfData = gcry_xmalloc (cbPerfData); | ||
471 | for (;;) { | ||
472 | dwSize = cbPerfData; | ||
473 | if ( debug_me ) | ||
474 | log_debug ("rndw32#slow_gatherer_nt: get perf data\n" ); | ||
475 | status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL, | ||
476 | NULL, (LPBYTE) pPerfData, &dwSize); | ||
477 | if (status == ERROR_SUCCESS) { | ||
478 | if (!memcmp (pPerfData->Signature, L"PERF", 8)) { | ||
479 | (*add) ( pPerfData, dwSize, requester ); | ||
480 | } | ||
481 | else | ||
482 | log_debug ( "rndw32: no PERF signature\n"); | ||
483 | break; | ||
484 | } | ||
485 | else if (status == ERROR_MORE_DATA) { | ||
486 | cbPerfData += PERFORMANCE_BUFFER_STEP; | ||
487 | pPerfData = gcry_realloc (pPerfData, cbPerfData); | ||
488 | } | ||
489 | else { | ||
490 | log_debug ( "rndw32: get performance data problem\n"); | ||
491 | break; | ||
492 | } | ||
493 | } | ||
494 | gcry_free (pPerfData); | ||
495 | } | ||
496 | /* Although this isn't documented in the Win32 API docs, it's necessary | ||
497 | to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's | ||
498 | implicitly opened on the first call to RegQueryValueEx()). If this | ||
499 | isn't done then any system components which provide performance data | ||
500 | can't be removed or changed while the handle remains active */ | ||
501 | RegCloseKey (HKEY_PERFORMANCE_DATA); | ||
502 | } | ||
503 | |||
504 | |||
505 | int | ||
506 | _gcry_rndw32_gather_random( void (*add)(const void*, size_t, int), | ||
507 | int requester, | ||
508 | size_t length, int level ) | ||
509 | { | ||
510 | static int is_initialized; | ||
511 | static int is_windowsNT, has_toolhelp; | ||
512 | |||
513 | |||
514 | if( !level ) | ||
515 | return 0; | ||
516 | /* We don't differentiate between level 1 and 2 here because | ||
517 | * there is no internal entropy pool as a scary resource. It may | ||
518 | * all work slower, but because our entropy source will never | ||
519 | * block but deliver some not easy to measure entropy, we assume level 2 | ||
520 | */ | ||
521 | |||
522 | |||
523 | if ( !is_initialized ) { | ||
524 | OSVERSIONINFO osvi = { sizeof( osvi ) }; | ||
525 | DWORD platform; | ||
526 | |||
527 | GetVersionEx( &osvi ); | ||
528 | platform = osvi.dwPlatformId; | ||
529 | is_windowsNT = platform == VER_PLATFORM_WIN32_NT; | ||
530 | has_toolhelp = (platform == VER_PLATFORM_WIN32_WINDOWS | ||
531 | || (is_windowsNT && osvi.dwMajorVersion >= 5)); | ||
532 | |||
533 | if ( platform == VER_PLATFORM_WIN32s ) { | ||
534 | log_fatal("can't run on a W32s platform\n" ); | ||
535 | } | ||
536 | is_initialized = 1; | ||
537 | if ( debug_me ) | ||
538 | log_debug ("rndw32#gather_random: platform=%d\n", (int)platform ); | ||
539 | } | ||
540 | |||
541 | |||
542 | if ( debug_me ) | ||
543 | log_debug ("rndw32#gather_random: req=%d len=%u lvl=%d\n", | ||
544 | requester, (unsigned int)length, level ); | ||
545 | |||
546 | if ( is_windowsNT ) { | ||
547 | slow_gatherer_windowsNT ( add, requester ); | ||
548 | } | ||
549 | else if ( has_toolhelp ) { | ||
550 | slow_gatherer_windows95 ( add, requester ); | ||
551 | } | ||
552 | |||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | |||
558 | int | ||
559 | _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, int), | ||
560 | int requester ) | ||
561 | { | ||
562 | static int addedFixedItems = 0; | ||
563 | |||
564 | if ( debug_me ) | ||
565 | log_debug ("rndw32#gather_random_fast: req=%d\n", requester ); | ||
566 | |||
567 | /* Get various basic pieces of system information: Handle of active | ||
568 | * window, handle of window with mouse capture, handle of clipboard owner | ||
569 | * handle of start of clpboard viewer list, pseudohandle of current | ||
570 | * process, current process ID, pseudohandle of current thread, current | ||
571 | * thread ID, handle of desktop window, handle of window with keyboard | ||
572 | * focus, whether system queue has any events, cursor position for last | ||
573 | * message, 1 ms time for last message, handle of window with clipboard | ||
574 | * open, handle of process heap, handle of procs window station, types of | ||
575 | * events in input queue, and milliseconds since Windows was started */ | ||
576 | { byte buffer[20*sizeof(ulong)], *bufptr; | ||
577 | bufptr = buffer; | ||
578 | #define ADD(f) do { ulong along = (ulong)(f); \ | ||
579 | memcpy (bufptr, &along, sizeof (along) ); \ | ||
580 | bufptr += sizeof (along); } while (0) | ||
581 | ADD ( GetActiveWindow ()); | ||
582 | ADD ( GetCapture ()); | ||
583 | ADD ( GetClipboardOwner ()); | ||
584 | ADD ( GetClipboardViewer ()); | ||
585 | ADD ( GetCurrentProcess ()); | ||
586 | ADD ( GetCurrentProcessId ()); | ||
587 | ADD ( GetCurrentThread ()); | ||
588 | ADD ( GetCurrentThreadId ()); | ||
589 | ADD ( GetDesktopWindow ()); | ||
590 | ADD ( GetFocus ()); | ||
591 | ADD ( GetInputState ()); | ||
592 | ADD ( GetMessagePos ()); | ||
593 | ADD ( GetMessageTime ()); | ||
594 | ADD ( GetOpenClipboardWindow ()); | ||
595 | ADD ( GetProcessHeap ()); | ||
596 | ADD ( GetProcessWindowStation ()); | ||
597 | ADD ( GetQueueStatus (QS_ALLEVENTS)); | ||
598 | ADD ( GetTickCount ()); | ||
599 | |||
600 | assert ( bufptr-buffer < sizeof (buffer) ); | ||
601 | (*add) ( buffer, bufptr-buffer, requester ); | ||
602 | #undef ADD | ||
603 | } | ||
604 | |||
605 | /* Get multiword system information: Current caret position, current | ||
606 | * mouse cursor position */ | ||
607 | { POINT point; | ||
608 | GetCaretPos (&point); | ||
609 | (*add) ( &point, sizeof (point), requester ); | ||
610 | GetCursorPos (&point); | ||
611 | (*add) ( &point, sizeof (point), requester ); | ||
612 | } | ||
613 | |||
614 | /* Get percent of memory in use, bytes of physical memory, bytes of free | ||
615 | * physical memory, bytes in paging file, free bytes in paging file, user | ||
616 | * bytes of address space, and free user bytes */ | ||
617 | { MEMORYSTATUS memoryStatus; | ||
618 | memoryStatus.dwLength = sizeof (MEMORYSTATUS); | ||
619 | GlobalMemoryStatus (&memoryStatus); | ||
620 | (*add) ( &memoryStatus, sizeof (memoryStatus), requester ); | ||
621 | } | ||
622 | |||
623 | /* Get thread and process creation time, exit time, time in kernel mode, | ||
624 | and time in user mode in 100ns intervals */ | ||
625 | { HANDLE handle; | ||
626 | FILETIME creationTime, exitTime, kernelTime, userTime; | ||
627 | DWORD minimumWorkingSetSize, maximumWorkingSetSize; | ||
628 | |||
629 | handle = GetCurrentThread (); | ||
630 | GetThreadTimes (handle, &creationTime, &exitTime, | ||
631 | &kernelTime, &userTime); | ||
632 | (*add) ( &creationTime, sizeof (creationTime), requester ); | ||
633 | (*add) ( &exitTime, sizeof (exitTime), requester ); | ||
634 | (*add) ( &kernelTime, sizeof (kernelTime), requester ); | ||
635 | (*add) ( &userTime, sizeof (userTime), requester ); | ||
636 | |||
637 | handle = GetCurrentProcess (); | ||
638 | GetProcessTimes (handle, &creationTime, &exitTime, | ||
639 | &kernelTime, &userTime); | ||
640 | (*add) ( &creationTime, sizeof (creationTime), requester ); | ||
641 | (*add) ( &exitTime, sizeof (exitTime), requester ); | ||
642 | (*add) ( &kernelTime, sizeof (kernelTime), requester ); | ||
643 | (*add) ( &userTime, sizeof (userTime), requester ); | ||
644 | |||
645 | /* Get the minimum and maximum working set size for the | ||
646 | current process */ | ||
647 | GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, | ||
648 | &maximumWorkingSetSize); | ||
649 | (*add) ( &minimumWorkingSetSize, | ||
650 | sizeof (minimumWorkingSetSize), requester ); | ||
651 | (*add) ( &maximumWorkingSetSize, | ||
652 | sizeof (maximumWorkingSetSize), requester ); | ||
653 | } | ||
654 | |||
655 | |||
656 | /* The following are fixed for the lifetime of the process so we only | ||
657 | * add them once */ | ||
658 | if (!addedFixedItems) { | ||
659 | STARTUPINFO startupInfo; | ||
660 | |||
661 | /* Get name of desktop, console window title, new window position and | ||
662 | * size, window flags, and handles for stdin, stdout, and stderr */ | ||
663 | startupInfo.cb = sizeof (STARTUPINFO); | ||
664 | GetStartupInfo (&startupInfo); | ||
665 | (*add) ( &startupInfo, sizeof (STARTUPINFO), requester ); | ||
666 | addedFixedItems = 1; | ||
667 | } | ||
668 | |||
669 | /* The performance of QPC varies depending on the architecture it's | ||
670 | * running on and on the OS. Under NT it reads the CPU's 64-bit timestamp | ||
671 | * counter (at least on a Pentium and newer '486's, it hasn't been tested | ||
672 | * on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC | ||
673 | * timer. There are vague mumblings in the docs that it may fail if the | ||
674 | * appropriate hardware isn't available (possibly '386's or MIPS machines | ||
675 | * running NT), but who's going to run NT on a '386? */ | ||
676 | { LARGE_INTEGER performanceCount; | ||
677 | if (QueryPerformanceCounter (&performanceCount)) { | ||
678 | if ( debug_me ) | ||
679 | log_debug ("rndw32#gather_random_fast: perf data\n"); | ||
680 | (*add) (&performanceCount, sizeof (performanceCount), requester); | ||
681 | } | ||
682 | else { /* Millisecond accuracy at best... */ | ||
683 | DWORD aword = GetTickCount (); | ||
684 | (*add) (&aword, sizeof (aword), requester ); | ||
685 | } | ||
686 | } | ||
687 | |||
688 | return 0; | ||
689 | } | ||
690 | |||