Support WindowsCE.
[libgcrypt.git] / random / rndw32.c
1 /* rndw32.c  -  W32 entropy gatherer
2  * Copyright (C) 1999, 2000, 2002, 2003, 2007,
3  *               2010 Free Software Foundation, Inc.
4  * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2006
5  *
6  * This file is part of Libgcrypt.
7  *
8  *************************************************************************
9  * The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann.
10  * Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this
11  * copyright notice:
12  *
13  * This module is part of the cryptlib continuously seeded pseudorandom
14  * number generator.  For usage conditions, see lib_rand.c
15  *
16  * [Here is the notice from lib_rand.c, which is now called dev_sys.c]
17  *
18  * This module and the misc/rnd*.c modules represent the cryptlib
19  * continuously seeded pseudorandom number generator (CSPRNG) as described in
20  * my 1998 Usenix Security Symposium paper "The generation of random numbers
21  * for cryptographic purposes".
22  *
23  * The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
24  * 1997, 1998, 1999, all rights reserved.  Redistribution of the CSPRNG
25  * modules and use in source and binary forms, with or without modification,
26  * are permitted provided that the following conditions are met:
27  *
28  * 1. Redistributions of source code must retain the above copyright notice
29  *    and this permission notice in its entirety.
30  *
31  * 2. Redistributions in binary form must reproduce the copyright notice in
32  *    the documentation and/or other materials provided with the distribution.
33  *
34  * 3. A copy of any bugfixes or enhancements made must be provided to the
35  *    author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
36  *    baseline version of the code.
37  *
38  * ALTERNATIVELY, the code may be distributed under the terms of the
39  * GNU Lesser General Public License, version 2.1 or any later version
40  * published by the Free Software Foundation, in which case the
41  * provisions of the GNU LGPL are required INSTEAD OF the above
42  * restrictions.
43  *
44  * Although not required under the terms of the LGPL, it would still
45  * be nice if you could make any changes available to the author to
46  * allow a consistent code base to be maintained.
47  *************************************************************************
48  * The above alternative was changed from GPL to LGPL on 2007-08-22 with
49  * permission from Peter Gutmann:
50  *==========
51  From: pgut001 <pgut001@cs.auckland.ac.nz>
52  Subject: Re: LGPL for the windows entropy gatherer
53  To: wk@gnupg.org
54  Date: Wed, 22 Aug 2007 03:05:42 +1200
55
56  Hi,
57
58  >As of now libgcrypt is GPL under Windows due to that module and some people
59  >would really like to see it under LGPL too.  Can you do such a license change
60  >to LGPL version 2?  Note that LGPL give the user the option to relicense it
61  >under GPL, so the change would be pretty easy and backwar compatible.
62
63  Sure.  I assumed that since GPG was GPLd, you'd prefer the GPL for the entropy
64  code as well, but Ian asked for LGPL as an option so as of the next release
65  I'll have LGPL in there.  You can consider it to be retroactive, so your
66  current version will be LGPLd as well.
67
68  Peter.
69  *==========
70  */
71
72 #include <config.h>
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <errno.h>
76 #include <string.h>
77 #ifdef __GNUC__  
78 #include <stdint.h>
79 #endif
80
81 #include <windows.h>
82
83
84 #include "types.h"
85 #include "g10lib.h"
86 #include "rand-internal.h"
87
88
89 /* Definitions which are missing from the current GNU Windows32Api.  */
90 #ifndef IOCTL_DISK_PERFORMANCE
91 #define IOCTL_DISK_PERFORMANCE  0x00070020
92 #endif
93
94 /* This used to be (6*8+5*4+8*2), but Peter Gutmann figured a larger
95    value in a newer release. So we use a far larger value. */
96 #define SIZEOF_DISK_PERFORMANCE_STRUCT 256
97
98 /* We don't include wincrypt.h so define it here.  */
99 #define HCRYPTPROV  HANDLE
100
101
102 /* When we query the performance counters, we allocate an initial buffer and
103  * then reallocate it as required until RegQueryValueEx() stops returning
104  * ERROR_MORE_DATA.  The following values define the initial buffer size and
105  * step size by which the buffer is increased
106  */
107 #define PERFORMANCE_BUFFER_SIZE         65536   /* Start at 64K */
108 #define PERFORMANCE_BUFFER_STEP         16384   /* Step by 16K */
109
110
111 /* The number of bytes to read from the system RNG on each slow poll.  */
112 #define SYSTEMRNG_BYTES 64
113
114 /* Intel Chipset CSP type and name */
115 #define PROV_INTEL_SEC  22
116 #define INTEL_DEF_PROV  "Intel Hardware Cryptographic Service Provider"
117
118
119
120
121 /* Type definitions for function pointers to call NetAPI32 functions.  */
122 typedef DWORD (WINAPI *NETSTATISTICSGET)(LPWSTR szServer, LPWSTR szService,
123                                          DWORD dwLevel, DWORD dwOptions,
124                                          LPBYTE *lpBuffer);
125 typedef DWORD (WINAPI *NETAPIBUFFERSIZE)(LPVOID lpBuffer, LPDWORD cbBuffer);
126 typedef DWORD (WINAPI *NETAPIBUFFERFREE)(LPVOID lpBuffer);
127
128 /* Type definitions for function pointers to call native NT functions.  */
129 typedef DWORD (WINAPI *NTQUERYSYSTEMINFORMATION)(DWORD systemInformationClass,
130                                                  PVOID systemInformation,
131                                                  ULONG systemInformationLength,
132                                                  PULONG returnLength);
133 typedef DWORD (WINAPI *NTQUERYINFORMATIONPROCESS)
134      (HANDLE processHandle, DWORD processInformationClass,
135       PVOID processInformation, ULONG processInformationLength,
136       PULONG returnLength);
137 typedef DWORD (WINAPI *NTPOWERINFORMATION)
138      (DWORD powerInformationClass, PVOID inputBuffer,
139       ULONG inputBufferLength, PVOID outputBuffer, ULONG outputBufferLength );
140
141 /* Type definitions for function pointers to call CryptoAPI functions. */
142 typedef BOOL (WINAPI *CRYPTACQUIRECONTEXT)(HCRYPTPROV *phProv,
143                                            LPCTSTR pszContainer,
144                                            LPCTSTR pszProvider, 
145                                            DWORD dwProvType,
146                                            DWORD dwFlags);
147 typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,
148                                       BYTE *pbBuffer);
149 typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags);
150
151 /* Somewhat alternative functionality available as a direct call, for 
152    Windows XP and newer.  This is the CryptoAPI RNG, which isn't anywhere
153    near as good as the HW RNG, but we use it if it's present on the basis
154    that at least it can't make things any worse.  This direct access version 
155    is only available under Windows XP, we don't go out of our way to access
156    the more general CryptoAPI one since the main purpose of using it is to 
157    take advantage of any possible future hardware RNGs that may be added, 
158    for example via TCPA devices.  */
159 typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer, 
160                                     ULONG RandomBufferLength);
161
162
163
164 /* MBM data structures, originally by Alexander van Kaam, converted to C by
165    Anders@Majland.org, finally updated by Chris Zahrt <techn0@iastate.edu> */
166 #define BusType         char
167 #define SMBType         char
168 #define SensorType      char
169
170 typedef struct 
171 {
172   SensorType iType;               /* Type of sensor.  */
173   int Count;                      /* Number of sensor for that type.  */
174 } SharedIndex;
175
176 typedef struct 
177 {
178   SensorType ssType;              /* Type of sensor */
179   unsigned char ssName[12];       /* Name of sensor */
180   char sspadding1[3];             /* Padding of 3 bytes */
181   double ssCurrent;               /* Current value */
182   double ssLow;                   /* Lowest readout */
183   double ssHigh;                  /* Highest readout */
184   long ssCount;                   /* Total number of readout */
185   char sspadding2[4];             /* Padding of 4 bytes */
186   long double ssTotal;            /* Total amout of all readouts */
187   char sspadding3[6];             /* Padding of 6 bytes */
188   double ssAlarm1;                /* Temp & fan: high alarm; voltage: % off */
189   double ssAlarm2;                /* Temp: low alarm */
190 } SharedSensor;
191
192 typedef struct
193 {
194   short siSMB_Base;               /* SMBus base address */
195   BusType siSMB_Type;             /* SMBus/Isa bus used to access chip */
196   SMBType siSMB_Code;             /* SMBus sub type, Intel, AMD or ALi */
197   char siSMB_Addr;                /* Address of sensor chip on SMBus */
198   unsigned char siSMB_Name[41];   /* Nice name for SMBus */
199   short siISA_Base;               /* ISA base address of sensor chip on ISA */
200   int siChipType;                 /* Chip nr, connects with Chipinfo.ini */
201   char siVoltageSubType;          /* Subvoltage option selected */
202 } SharedInfo;
203
204 typedef struct
205 {
206   double sdVersion;               /* Version number (example: 51090) */
207   SharedIndex sdIndex[10];        /* Sensor index */
208   SharedSensor sdSensor[100];     /* Sensor info */
209   SharedInfo sdInfo;              /* Misc.info */
210   unsigned char sdStart[41];      /* Start time */
211
212   /* We don't use the next two fields both because they're not random
213      and because it provides a nice safety margin in case of data size
214      mis- estimates (we always under-estimate the buffer size).  */
215 #if 0
216   unsigned char sdCurrent[41];    /* Current time */
217   unsigned char sdPath[256];      /* MBM path */
218 #endif /*0*/
219 } SharedData;
220
221
222
223 /* One time intialized handles and function pointers.  We use dynamic
224    loading of the DLLs to do without them in case libgcrypt does not
225    need any random.  */
226 static HANDLE hNetAPI32;
227 static NETSTATISTICSGET pNetStatisticsGet;
228 static NETAPIBUFFERSIZE pNetApiBufferSize;
229 static NETAPIBUFFERFREE pNetApiBufferFree;
230
231 static HANDLE hNTAPI;
232 static NTQUERYSYSTEMINFORMATION  pNtQuerySystemInformation;
233 static NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess;
234 static NTPOWERINFORMATION        pNtPowerInformation;
235
236 static HANDLE hAdvAPI32;
237 static CRYPTACQUIRECONTEXT pCryptAcquireContext;
238 static CRYPTGENRANDOM      pCryptGenRandom;
239 static CRYPTRELEASECONTEXT pCryptReleaseContext;
240 static RTLGENRANDOM        pRtlGenRandom;
241
242
243 /* Other module global variables.  */
244 static int system_rng_available; /* Whether a system RNG is available.  */
245 static HCRYPTPROV hRNGProv;      /* Handle to Intel RNG CSP. */
246
247 static int debug_me;  /* Debug flag.  */
248
249 static int system_is_w2000;     /* True if running on W2000.  */
250
251
252
253 \f
254 /* Try and connect to the system RNG if there's one present. */
255 static void 
256 init_system_rng (void)
257 {
258   system_rng_available = 0;
259   hRNGProv = NULL;
260
261   hAdvAPI32 = GetModuleHandle ("AdvAPI32.dll");
262   if (!hAdvAPI32)
263     return;
264
265   pCryptAcquireContext = (CRYPTACQUIRECONTEXT)
266     GetProcAddress (hAdvAPI32, "CryptAcquireContextA");
267   pCryptGenRandom = (CRYPTGENRANDOM)
268     GetProcAddress (hAdvAPI32, "CryptGenRandom");
269   pCryptReleaseContext = (CRYPTRELEASECONTEXT)
270     GetProcAddress (hAdvAPI32, "CryptReleaseContext");
271   
272   /* Get a pointer to the native randomness function if it's available.  
273      This isn't exported by name, so we have to get it by ordinal.  */
274   pRtlGenRandom = (RTLGENRANDOM)
275     GetProcAddress (hAdvAPI32, "SystemFunction036");
276
277   /* Try and connect to the PIII RNG CSP.  The AMD 768 southbridge (from 
278      the 760 MP chipset) also has a hardware RNG, but there doesn't appear 
279      to be any driver support for this as there is for the Intel RNG so we 
280      can't do much with it.  OTOH the Intel RNG is also effectively dead 
281      as well, mostly due to virtually nonexistant support/marketing by 
282      Intel, it's included here mostly for form's sake.  */
283   if ( (!pCryptAcquireContext || !pCryptGenRandom || !pCryptReleaseContext
284         || !pCryptAcquireContext (&hRNGProv, NULL, INTEL_DEF_PROV,
285                                   PROV_INTEL_SEC, 0) )
286        && !pRtlGenRandom)
287     {
288       hAdvAPI32 = NULL;
289     }
290   else
291     system_rng_available = 1;
292 }
293
294
295 /* Read data from the system RNG if availavle.  */
296 static void 
297 read_system_rng (void (*add)(const void*, size_t, enum random_origins),
298                  enum random_origins requester)
299 {
300   BYTE buffer[ SYSTEMRNG_BYTES + 8 ];
301   int quality = 0;
302
303   if (!system_rng_available)
304     return;
305
306   /* Read SYSTEMRNG_BYTES bytes from the system RNG.  We don't rely on
307      this for all our randomness requirements (particularly the
308      software RNG) in case it's broken in some way.  */
309   if (hRNGProv)
310     {
311       if (pCryptGenRandom (hRNGProv, SYSTEMRNG_BYTES, buffer))
312         quality = 80;
313     }
314   else if (pRtlGenRandom)
315     {
316       if ( pRtlGenRandom (buffer, SYSTEMRNG_BYTES))
317         quality = 50;
318     }
319   if (quality > 0)
320     {
321       if (debug_me)
322         log_debug ("rndw32#read_system_rng: got %d bytes of quality %d\n",
323                    SYSTEMRNG_BYTES, quality);
324       (*add) (buffer, SYSTEMRNG_BYTES, requester);
325       wipememory (buffer, SYSTEMRNG_BYTES);
326     }
327 }
328
329
330 /* Read data from MBM.  This communicates via shared memory, so all we
331    need to do is map a file and read the data out.  */
332 #ifndef HAVE_W32CE_SYSTEM
333 static void
334 read_mbm_data (void (*add)(const void*, size_t, enum random_origins), 
335                enum random_origins requester)
336 {
337   HANDLE hMBMData;
338   SharedData *mbmDataPtr;
339
340   hMBMData = OpenFileMapping (FILE_MAP_READ, FALSE, "$M$B$M$5$S$D$" );
341   if (hMBMData)
342     {
343       mbmDataPtr = (SharedData*)MapViewOfFile (hMBMData, FILE_MAP_READ,0,0,0);
344       if (mbmDataPtr)
345         {
346           if (debug_me)
347             log_debug ("rndw32#read_mbm_data: got %d bytes\n",
348                        (int)sizeof (SharedData));
349           (*add) (mbmDataPtr, sizeof (SharedData), requester);
350           UnmapViewOfFile (mbmDataPtr);
351         }
352       CloseHandle (hMBMData);
353     }
354 }
355 #endif /*!HAVE_W32CE_SYSTEM*/
356
357
358 /* Fallback method using the registry to poll the statistics.  */
359 static void
360 registry_poll (void (*add)(const void*, size_t, enum random_origins), 
361                enum random_origins requester)
362 {
363   static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
364   int iterations;
365   DWORD dwSize, status;
366   PERF_DATA_BLOCK *pPerfData;
367
368   /* Get information from the system performance counters.  This can take a
369      few seconds to do.  In some environments the call to RegQueryValueEx()
370      can produce an access violation at some random time in the future, in
371      some cases adding a short delay after the following code block makes
372      the problem go away.  This problem is extremely difficult to
373      reproduce, I haven't been able to get it to occur despite running it
374      on a number of machines.  MS knowledge base article Q178887 covers
375      this type of problem, it's typically caused by an external driver or
376      other program that adds its own values under the
377      HKEY_PERFORMANCE_DATA key.  The NT kernel, via Advapi32.dll, calls the
378      required external module to map in the data inside an SEH try/except
379      block, so problems in the module's collect function don't pop up until
380      after it has finished, so the fault appears to occur in Advapi32.dll.
381      There may be problems in the NT kernel as well though, a low-level
382      memory checker indicated that ExpandEnvironmentStrings() in
383      Kernel32.dll, called an interminable number of calls down inside
384      RegQueryValueEx(), was overwriting memory (it wrote twice the
385      allocated size of a buffer to a buffer allocated by the NT kernel).
386      OTOH this could be coming from the external module calling back into
387      the kernel, which eventually causes the problem described above.
388
389      Possibly as an extension of the problem that the krnlWaitSemaphore()
390      call above works around, running two instances of cryptlib (e.g. two
391      applications that use it) under NT4 can result in one of them hanging
392      in the RegQueryValueEx() call.  This happens only under NT4 and is
393      hard to reproduce in any consistent manner.
394
395      One workaround that helps a bit is to read the registry as a remote
396      (rather than local) registry, it's possible that the use of a network
397      RPC call isolates the calling app from the problem in that whatever
398      service handles the RPC is taking the hit and not affecting the
399      calling app.  Since this would require another round of extensive
400      testing to verify and the NT native API call is working fine, we'll
401      stick with the native API call for now.
402
403      Some versions of NT4 had a problem where the amount of data returned
404      was mis-reported and would never settle down, because of this the code
405      below includes a safety-catch that bails out after 10 attempts have
406      been made, this results in no data being returned but at does ensure
407      that the thread will terminate.
408
409      In addition to these problems the code in RegQueryValueEx() that
410      estimates the amount of memory required to return the performance
411      counter information isn't very accurate (it's much worse than the
412      "slightly-inaccurate" level that the MS docs warn about, it's usually
413      wildly off) since it always returns a worst-case estimate which is
414      usually nowhere near the actual amount required.  For example it may
415      report that 128K of memory is required, but only return 64K of data.
416
417      Even worse than the registry-based performance counters is the
418      performance data helper (PDH) shim that tries to make the counters
419      look like the old Win16 API (which is also used by Win95).  Under NT
420      this can consume tens of MB of memory and huge amounts of CPU time
421      while it gathers its data, and even running once can still consume
422      about 1/2MB of memory */
423   pPerfData = gcry_xmalloc (cbPerfData);
424   for (iterations=0; iterations < 10; iterations++)
425     {
426       dwSize = cbPerfData;
427       if ( debug_me )
428         log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
429
430       status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
431                                 NULL, (LPBYTE) pPerfData, &dwSize);
432       if (status == ERROR_SUCCESS)
433         {
434           if (!memcmp (pPerfData->Signature, L"PERF", 8))
435             (*add) ( pPerfData, dwSize, requester );
436           else
437             log_debug ("rndw32: no PERF signature\n");
438           break;
439         }
440       else if (status == ERROR_MORE_DATA)
441         {
442           cbPerfData += PERFORMANCE_BUFFER_STEP;
443           pPerfData = gcry_xrealloc (pPerfData, cbPerfData);
444         }
445       else
446         {
447           static int been_here;
448
449           /* Silence the error message.  In particular under Wine (as
450              of 2008) we would get swamped with such diagnotiscs.  One
451              such diagnotiscs should be enough.  */
452           if (been_here != status)
453             {
454               been_here = status;
455               log_debug ("rndw32: get performance data problem: ec=%ld\n",
456                          status);
457             }
458           break;
459         }
460     }
461   gcry_free (pPerfData);
462
463   /* Although this isn't documented in the Win32 API docs, it's necessary
464      to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
465      implicitly opened on the first call to RegQueryValueEx()).  If this
466      isn't done then any system components which provide performance data
467      can't be removed or changed while the handle remains active.  */
468   RegCloseKey (HKEY_PERFORMANCE_DATA);
469 }
470
471
472 static void
473 slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), 
474                 enum random_origins requester )
475 {
476   static int is_initialized = 0;
477   static int is_workstation = 1;
478   HANDLE hDevice;
479   DWORD dwType, dwSize, dwResult;
480   ULONG ulSize;
481   int drive_no, status;
482   int no_results = 0;
483   void *buffer;
484
485   if ( !is_initialized )
486     {
487       HKEY hKey;
488
489       if ( debug_me )
490         log_debug ("rndw32#slow_gatherer: init toolkit\n" );
491       /* Find out whether this is an NT server or workstation if necessary */
492       if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
493                         "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
494                         0, KEY_READ, &hKey) == ERROR_SUCCESS)
495         {
496           BYTE szValue[32 + 8];
497           dwSize = 32;
498
499           if ( debug_me )
500             log_debug ("rndw32#slow_gatherer: check product options\n" );
501
502           status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
503                                     szValue, &dwSize);
504           if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT"))
505             {
506               /* Note: There are (at least) three cases for ProductType:
507                  WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
508                  NT Server acting as a Domain Controller.  */
509               is_workstation = 0;
510               if ( debug_me )
511                 log_debug ("rndw32: this is a NT server\n");
512             }
513           RegCloseKey (hKey);
514         }
515
516       /* The following are fixed for the lifetime of the process so we
517          only add them once */
518       /* readPnPData ();  - we have not implemented that.  */
519
520       /* Initialize the NetAPI32 function pointers if necessary */
521       hNetAPI32 = LoadLibrary ("NETAPI32.DLL");
522       if (hNetAPI32)
523         {
524           if (debug_me)
525             log_debug ("rndw32#slow_gatherer: netapi32 loaded\n" );
526           pNetStatisticsGet = (NETSTATISTICSGET)
527             GetProcAddress (hNetAPI32, "NetStatisticsGet");
528           pNetApiBufferSize = (NETAPIBUFFERSIZE)
529             GetProcAddress (hNetAPI32, "NetApiBufferSize");
530           pNetApiBufferFree = (NETAPIBUFFERFREE)
531             GetProcAddress (hNetAPI32, "NetApiBufferFree");
532
533           if (!pNetStatisticsGet || !pNetApiBufferSize || !pNetApiBufferFree)
534             {
535               FreeLibrary (hNetAPI32);
536               hNetAPI32 = NULL;
537               log_debug ("rndw32: No NETAPI found\n" );
538             }
539         }
540
541       /* Initialize the NT kernel native API function pointers if necessary */
542       hNTAPI = GetModuleHandle ("NTDll.dll");
543       if (hNTAPI)
544         {
545           /* Get a pointer to the NT native information query functions */
546           pNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)
547             GetProcAddress (hNTAPI, "NtQuerySystemInformation");
548           pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)
549             GetProcAddress (hNTAPI, "NtQueryInformationProcess");
550           pNtPowerInformation = (NTPOWERINFORMATION)
551             GetProcAddress(hNTAPI, "NtPowerInformation");
552
553           if (!pNtQuerySystemInformation || !pNtQueryInformationProcess)
554             hNTAPI = NULL;
555         }
556
557
558       is_initialized = 1;
559     }
560   
561   read_system_rng ( add, requester );
562 #ifndef HAVE_W32CE_SYSTEM
563   read_mbm_data ( add, requester );
564 #endif  
565
566   /* Get network statistics.    Note: Both NT Workstation and NT Server by
567      default will be running both the workstation and server services.  The
568      heuristic below is probably useful though on the assumption that the
569      majority of the network traffic will be via the appropriate service.
570      In any case the network statistics return almost no randomness.  */
571   {
572     LPBYTE lpBuffer;
573     
574     if (hNetAPI32
575         && !pNetStatisticsGet (NULL,
576                                is_workstation ? L"LanmanWorkstation" :
577                                L"LanmanServer", 0, 0, &lpBuffer))
578       {
579         if ( debug_me )
580           log_debug ("rndw32#slow_gatherer: get netstats\n" );
581         pNetApiBufferSize (lpBuffer, &dwSize);
582         (*add) ( lpBuffer, dwSize, requester );
583         pNetApiBufferFree (lpBuffer);
584       }
585   }
586
587   /* Get disk I/O statistics for all the hard drives.  100 is an
588      arbitrary failsafe limit.  */
589   for (drive_no = 0; drive_no < 100 ; drive_no++)
590     {
591       char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT + 8];
592       char szDevice[50];
593       
594       /* Check whether we can access this device.  */
595       snprintf (szDevice, sizeof szDevice, "\\\\.\\PhysicalDrive%d",
596                 drive_no);
597       hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
598                             NULL, OPEN_EXISTING, 0, NULL);
599       if (hDevice == INVALID_HANDLE_VALUE)
600         break; /* No more drives.  */
601         
602       /* Note: This only works if you have turned on the disk performance
603          counters with 'diskperf -y'.  These counters are off by default. */
604       dwSize = sizeof diskPerformance;
605       if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
606                            diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT,
607                            &dwSize, NULL))
608         {
609           if ( debug_me )
610             log_debug ("rndw32#slow_gatherer: iostat drive %d\n",
611                        drive_no);
612           (*add) (diskPerformance, dwSize, requester);
613         }
614       else
615         {
616           log_info ("NOTE: you should run 'diskperf -y' "
617                     "to enable the disk statistics\n");
618         }
619       CloseHandle (hDevice);
620     }
621
622   /* In theory we should be using the Win32 performance query API to obtain
623      unpredictable data from the system, however this is so unreliable (see
624      the multiple sets of comments in registryPoll()) that it's too risky
625      to rely on it except as a fallback in emergencies.  Instead, we rely
626      mostly on the NT native API function NtQuerySystemInformation(), which
627      has the dual advantages that it doesn't have as many (known) problems
628      as the Win32 equivalent and that it doesn't access the data indirectly
629      via pseudo-registry keys, which means that it's much faster.  Note
630      that the Win32 equivalent actually works almost all of the time, the
631      problem is that on one or two systems it can fail in strange ways that
632      are never the same and can't be reproduced on any other system, which
633      is why we use the native API here.  Microsoft officially documented
634      this function in early 2003, so it'll be fairly safe to use.  */
635   if ( !hNTAPI )
636     {
637       registry_poll (add, requester);
638       return;
639     }
640
641
642   /* Scan the first 64 possible information types (we don't bother with
643      increasing the buffer size as we do with the Win32 version of the
644      performance data read, we may miss a few classes but it's no big deal).
645      This scan typically yields around 20 pieces of data, there's nothing
646      in the range 65...128 so chances are there won't be anything above
647      there either.  */
648   buffer = gcry_xmalloc (PERFORMANCE_BUFFER_SIZE);
649   for (dwType = 0; dwType < 64; dwType++)
650     {
651       switch (dwType)
652         {
653           /* ID 17 = SystemObjectInformation hangs on some win2k systems.  */
654         case 17:
655           if (system_is_w2000)
656             continue;
657           break;
658
659           /* Some information types are write-only (the IDs are shared with
660              a set-information call), we skip these.  */
661         case 26: case 27: case 38: case 46: case 47: case 48: case 52:
662           continue;
663
664           /* ID 53 = SystemSessionProcessInformation reads input from the
665              output buffer, which has to contain a session ID and pointer
666              to the actual buffer in which to store the session information.
667              Because this isn't a standard query, we skip this.  */
668         case  53:
669           continue;
670         }
671
672       /* Query the info for this ID.  Some results (for example for
673          ID = 6, SystemCallCounts) are only available in checked builds
674          of the kernel.  A smaller subcless of results require that
675          certain system config flags be set, for example
676          SystemObjectInformation requires that the
677          FLG_MAINTAIN_OBJECT_TYPELIST be set in NtGlobalFlags.  To avoid
678          having to special-case all of these, we try reading each one and
679          only use those for which we get a success status.  */
680       dwResult = pNtQuerySystemInformation (dwType, buffer,
681                                             PERFORMANCE_BUFFER_SIZE - 2048,
682                                             &ulSize);
683       if (dwResult != ERROR_SUCCESS)
684         continue;
685
686       /* Some calls (e.g. ID = 23, SystemProcessorStatistics, and ID = 24,
687          SystemDpcInformation) incorrectly return a length of zero, so we
688          manually adjust the length to the correct value.  */
689       if ( !ulSize )
690         {
691           if (dwType == 23)
692             ulSize = 6 * sizeof (ULONG);
693           else if (dwType == 24)
694             ulSize = 5 * sizeof (ULONG);
695         }
696
697       /* If we got some data back, add it to the entropy pool.  */
698       if (ulSize > 0 && ulSize <= PERFORMANCE_BUFFER_SIZE - 2048)
699         {
700           if (debug_me)
701             log_debug ("rndw32#slow_gatherer: %lu bytes from sysinfo %ld\n",
702                        ulSize, dwType);
703           (*add) (buffer, ulSize, requester);
704           no_results++;
705         }
706     }
707
708   /* Now we would do the same for the process information.  This
709      call would rather ugly in that it requires an exact length
710      match for the data returned, failing with a
711      STATUS_INFO_LENGTH_MISMATCH error code (0xC0000004) if the
712      length isn't an exact match.  It requires a compiler to handle
713      complex nested structs, alignment issues, and so on, and
714      without the headers in which the entries are declared it's
715      almost impossible to do.  Thus we don't.  */
716
717
718   /* Finally, do the same for the system power status information.  There
719      are only a limited number of useful information types available so we
720      restrict ourselves to the useful types.  In addition since this
721      function doesn't return length information, we have to hardcode in
722      length data.  */
723   if (pNtPowerInformation)
724     {
725       static const struct { int type; int size; } powerInfo[] = {
726         { 0, 128 },     /* SystemPowerPolicyAc */
727         { 1, 128 },     /* SystemPowerPolicyDc */
728         { 4, 64 },      /* SystemPowerCapabilities */
729         { 5, 48 },      /* SystemBatteryState */
730         { 11, 48 },     /* ProcessorInformation */
731         { 12, 24 },     /* SystemPowerInformation */
732         { -1, -1 }
733       };
734       int i;
735
736       /* The 100 is a failsafe limit.  */
737       for (i = 0; powerInfo[i].type != -1 && i < 100; i++ )
738         {
739           /* Query the info for this ID */
740           dwResult = pNtPowerInformation (powerInfo[i].type, NULL, 0, buffer,
741                                           PERFORMANCE_BUFFER_SIZE - 2048);
742           if (dwResult != ERROR_SUCCESS)
743             continue;
744           if (debug_me)
745             log_debug ("rndw32#slow_gatherer: %u bytes from powerinfo %d\n",
746                        powerInfo[i].size, i);
747           (*add) (buffer, powerInfo[i].size, requester);
748           no_results++;
749         }
750       gcry_assert (i < 100);
751     }
752   gcry_free (buffer);
753
754   /* We couldn't get enough results from the kernel, fall back to the
755      somewhat troublesome registry poll.  */
756   if (no_results < 15)
757     registry_poll (add, requester);
758 }
759
760
761 int
762 _gcry_rndw32_gather_random (void (*add)(const void*, size_t,
763                                         enum random_origins),
764                             enum random_origins origin,
765                             size_t length, int level )
766 {
767   static int is_initialized;
768
769   if (!level)
770     return 0;
771
772   /* We don't differentiate between level 1 and 2 here because there
773      is no internal entropy pool as a scary resource.  It may all work
774      slower, but because our entropy source will never block but
775      deliver some not easy to measure entropy, we assume level 2.  */
776
777   if (!is_initialized)
778     {
779       OSVERSIONINFO osvi = { sizeof( osvi ) };
780
781       GetVersionEx( &osvi );
782 #ifdef HAVE_W32CE_SYSTEM
783       if (osvi.dwPlatformId != VER_PLATFORM_WIN32_CE)
784         log_fatal ("can only run on a Windows CE platform\n" );
785 #else
786       if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
787         log_fatal ("can only run on a Windows NT platform\n" );
788 #endif
789       system_is_w2000 = (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0);
790       init_system_rng ();
791       is_initialized = 1;
792     }
793
794   if (debug_me)
795     log_debug ("rndw32#gather_random: ori=%d len=%u lvl=%d\n",
796                origin, (unsigned int)length, level );
797
798   slow_gatherer (add, origin);
799
800   return 0;
801 }
802
803
804
805 void
806 _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
807                                              enum random_origins),
808                                  enum random_origins origin)
809 {
810   static int addedFixedItems = 0;
811
812   if ( debug_me )
813     log_debug ("rndw32#gather_random_fast: ori=%d\n", origin );
814
815   /* Get various basic pieces of system information: Handle of active
816      window, handle of window with mouse capture, handle of clipboard
817      owner handle of start of clpboard viewer list, pseudohandle of
818      current process, current process ID, pseudohandle of current
819      thread, current thread ID, handle of desktop window, handle of
820      window with keyboard focus, whether system queue has any events,
821      cursor position for last message, 1 ms time for last message,
822      handle of window with clipboard open, handle of process heap,
823      handle of procs window station, types of events in input queue,
824      and milliseconds since Windows was started.  */
825
826   {
827     byte buffer[20*sizeof(ulong)], *bufptr;
828
829     bufptr = buffer;
830 #define ADD(f)  do { ulong along = (ulong)(f);                  \
831                      memcpy (bufptr, &along, sizeof (along) );  \
832                      bufptr += sizeof (along);                  \
833                    } while (0)
834 #ifdef HAVE_W32CE_SYSTEM
835 # define ADD_NO_CE(f)
836 #else
837 # define ADD_NO_CE(f)  ADD(f)
838 #endif
839
840     ADD ( GetActiveWindow ());
841     ADD ( GetCapture ());
842     ADD ( GetClipboardOwner ());
843     ADD_NO_CE ( GetClipboardViewer ());
844     ADD ( GetCurrentProcess ());
845     ADD ( GetCurrentProcessId ());
846     ADD ( GetCurrentThread ());
847     ADD ( GetCurrentThreadId ());
848     ADD ( GetDesktopWindow ());
849     ADD ( GetFocus ());
850     ADD_NO_CE ( GetInputState ());
851     ADD ( GetMessagePos ());
852     ADD_NO_CE ( GetMessageTime ());
853     ADD ( GetOpenClipboardWindow ());
854     ADD ( GetProcessHeap ());
855     ADD_NO_CE ( GetProcessWindowStation ());
856     ADD ( GetQueueStatus (QS_ALLEVENTS));
857     ADD ( GetTickCount ());
858
859     gcry_assert ( bufptr-buffer < sizeof (buffer) );
860     (*add) ( buffer, bufptr-buffer, origin );
861 #undef ADD
862   }
863
864   /* Get multiword system information: Current caret position, current
865      mouse cursor position.  */
866   {
867     POINT point;
868
869     GetCaretPos (&point);
870     (*add) ( &point, sizeof (point), origin );
871     GetCursorPos (&point);
872     (*add) ( &point, sizeof (point), origin );
873   }
874
875   /* Get percent of memory in use, bytes of physical memory, bytes of
876      free physical memory, bytes in paging file, free bytes in paging
877      file, user bytes of address space, and free user bytes.  */
878   {
879     MEMORYSTATUS memoryStatus;
880
881     memoryStatus.dwLength = sizeof (MEMORYSTATUS);
882     GlobalMemoryStatus (&memoryStatus);
883     (*add) ( &memoryStatus, sizeof (memoryStatus), origin );
884   }
885
886   /* Get thread and process creation time, exit time, time in kernel
887      mode, and time in user mode in 100ns intervals.  */
888   {
889     HANDLE handle;
890     FILETIME creationTime, exitTime, kernelTime, userTime;
891     DWORD minimumWorkingSetSize, maximumWorkingSetSize;
892
893     handle = GetCurrentThread ();
894     GetThreadTimes (handle, &creationTime, &exitTime,
895                     &kernelTime, &userTime);
896     (*add) ( &creationTime, sizeof (creationTime), origin );
897     (*add) ( &exitTime, sizeof (exitTime), origin );
898     (*add) ( &kernelTime, sizeof (kernelTime), origin );
899     (*add) ( &userTime, sizeof (userTime), origin );
900
901 #ifdef HAVE_W32CE_SYSTEM
902     handle = GetCurrentThread ();
903     GetThreadTimes (handle, &creationTime, &exitTime,
904                      &kernelTime, &userTime);
905 #else
906     handle = GetCurrentProcess ();
907     GetProcessTimes (handle, &creationTime, &exitTime,
908                      &kernelTime, &userTime);
909 #endif
910     (*add) ( &creationTime, sizeof (creationTime), origin );
911     (*add) ( &exitTime, sizeof (exitTime), origin );
912     (*add) ( &kernelTime, sizeof (kernelTime), origin );
913     (*add) ( &userTime, sizeof (userTime), origin );
914
915     /* Get the minimum and maximum working set size for the current
916        process.  */
917 #ifndef HAVE_W32CE_SYSTEM
918     GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
919                               &maximumWorkingSetSize);
920     (*add) ( &minimumWorkingSetSize,
921              sizeof (minimumWorkingSetSize), origin );
922     (*add) ( &maximumWorkingSetSize,
923              sizeof (maximumWorkingSetSize), origin );
924 #endif /*!HAVE_W32CE_SYSTEM*/
925   }
926
927
928   /* The following are fixed for the lifetime of the process so we only
929    * add them once */
930 #ifndef HAVE_W32CE_SYSTEM
931   if (!addedFixedItems)
932     {
933       STARTUPINFO startupInfo;
934
935       /* Get name of desktop, console window title, new window
936          position and size, window flags, and handles for stdin,
937          stdout, and stderr.  */
938       startupInfo.cb = sizeof (STARTUPINFO);
939       GetStartupInfo (&startupInfo);
940       (*add) ( &startupInfo, sizeof (STARTUPINFO), origin );
941       addedFixedItems = 1;
942     }
943 #endif /*!HAVE_W32CE_SYSTEM*/
944
945   /* The performance of QPC varies depending on the architecture it's
946      running on and on the OS, the MS documentation is vague about the
947      details because it varies so much.  Under Win9x/ME it reads the
948      1.193180 MHz PIC timer.  Under NT/Win2K/XP it may or may not read the
949      64-bit TSC depending on the HAL and assorted other circumstances,
950      generally on machines with a uniprocessor HAL
951      KeQueryPerformanceCounter() uses a 3.579545MHz timer and on machines
952      with a multiprocessor or APIC HAL it uses the TSC (the exact time
953      source is controlled by the HalpUse8254 flag in the kernel).  That
954      choice of time sources is somewhat peculiar because on a
955      multiprocessor machine it's theoretically possible to get completely
956      different TSC readings depending on which CPU you're currently
957      running on, while for uniprocessor machines it's not a problem.
958      However, the kernel appears to synchronise the TSCs across CPUs at
959      boot time (it resets the TSC as part of its system init), so this
960      shouldn't really be a problem.  Under WinCE it's completely platform-
961      dependant, if there's no hardware performance counter available, it
962      uses the 1ms system timer.
963      
964      Another feature of the TSC (although it doesn't really affect us here)
965      is that mobile CPUs will turn off the TSC when they idle, Pentiums
966      will change the rate of the counter when they clock-throttle (to
967      match the current CPU speed), and hyperthreading Pentiums will turn
968      it off when both threads are idle (this more or less makes sense,
969      since the CPU will be in the halted state and not executing any
970      instructions to count).
971      
972      To make things unambiguous, we detect a CPU new enough to call RDTSC
973      directly by checking for CPUID capabilities, and fall back to QPC if
974      this isn't present.  */
975 #ifdef __GNUC__  
976 /*   FIXME: We would need to implement the CPU feature tests first.  */
977 /*   if (cpu_has_feature_rdtsc) */
978 /*     { */
979 /*       uint32_t lo, hi; */
980       /* We cannot use "=A", since this would use %rax on x86_64. */
981 /*       __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); */
982       /* Ignore high 32 bits, hwich are >1s res.  */
983 /*       (*add) (&lo, 4, origin ); */
984 /*     } */
985 /*   else */
986 #endif /*!__GNUC__*/
987     {
988       LARGE_INTEGER performanceCount;
989       
990       if (QueryPerformanceCounter (&performanceCount))
991         {
992           if ( debug_me )
993           log_debug ("rndw32#gather_random_fast: perf data\n");
994           (*add) (&performanceCount, sizeof (performanceCount), origin);
995         }
996       else
997         {
998           /* Millisecond accuracy at best... */
999           DWORD aword = GetTickCount ();
1000           (*add) (&aword, sizeof (aword), origin );
1001         }
1002     }
1003
1004
1005 }