1
/* rndw32.c - W32 entropy gatherer
2
* Copyright (C) 1999, 2000, 2002, 2003, 2007 Free Software Foundation, Inc.
3
* Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2006
5
* This file is part of Libgcrypt.
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
12
* This module is part of the cryptlib continuously seeded pseudorandom
13
* number generator. For usage conditions, see lib_rand.c
15
* [Here is the notice from lib_rand.c, which is now called dev_sys.c]
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".
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:
27
* 1. Redistributions of source code must retain the above copyright notice
28
* and this permission notice in its entirety.
30
* 2. Redistributions in binary form must reproduce the copyright notice in
31
* the documentation and/or other materials provided with the distribution.
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.
37
* ALTERNATIVELY, the code may be distributed under the terms of the
38
* GNU Lesser General Public License, version 2.1 or any later version
39
* published by the Free Software Foundation, in which case the
40
* provisions of the GNU LGPL are required INSTEAD OF the above
43
* Although not required under the terms of the LGPL, it would still
44
* be nice if you could make any changes available to the author to
45
* allow a consistent code base to be maintained.
46
*************************************************************************
47
* The above alternative was changed from GPL to LGPL on 2007-08-22 with
48
* permission from Peter Gutmann:
50
From: pgut001 <pgut001@cs.auckland.ac.nz>
51
Subject: Re: LGPL for the windows entropy gatherer
53
Date: Wed, 22 Aug 2007 03:05:42 +1200
57
>As of now libgcrypt is GPL under Windows due to that module and some people
58
>would really like to see it under LGPL too. Can you do such a license change
59
>to LGPL version 2? Note that LGPL give the user the option to relicense it
60
>under GPL, so the change would be pretty easy and backwar compatible.
62
Sure. I assumed that since GPG was GPLd, you'd prefer the GPL for the entropy
63
code as well, but Ian asked for LGPL as an option so as of the next release
64
I'll have LGPL in there. You can consider it to be retroactive, so your
65
current version will be LGPLd as well.
85
#include "rand-internal.h"
88
/* Definitions which are missing from the current GNU Windows32Api. */
89
#ifndef IOCTL_DISK_PERFORMANCE
90
#define IOCTL_DISK_PERFORMANCE 0x00070020
93
/* This used to be (6*8+5*4+8*2), but Peter Gutmann figured a larger
94
value in a newer release. So we use a far larger value. */
95
#define SIZEOF_DISK_PERFORMANCE_STRUCT 256
97
/* We don't include wincrypt.h so define it here. */
98
#define HCRYPTPROV HANDLE
101
/* When we query the performance counters, we allocate an initial buffer and
102
* then reallocate it as required until RegQueryValueEx() stops returning
103
* ERROR_MORE_DATA. The following values define the initial buffer size and
104
* step size by which the buffer is increased
106
#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */
107
#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */
110
/* The number of bytes to read from the system RNG on each slow poll. */
111
#define SYSTEMRNG_BYTES 64
113
/* Intel Chipset CSP type and name */
114
#define PROV_INTEL_SEC 22
115
#define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider"
120
/* Type definitions for function pointers to call NetAPI32 functions. */
121
typedef DWORD (WINAPI *NETSTATISTICSGET)(LPWSTR szServer, LPWSTR szService,
122
DWORD dwLevel, DWORD dwOptions,
124
typedef DWORD (WINAPI *NETAPIBUFFERSIZE)(LPVOID lpBuffer, LPDWORD cbBuffer);
125
typedef DWORD (WINAPI *NETAPIBUFFERFREE)(LPVOID lpBuffer);
127
/* Type definitions for function pointers to call native NT functions. */
128
typedef DWORD (WINAPI *NTQUERYSYSTEMINFORMATION)(DWORD systemInformationClass,
129
PVOID systemInformation,
130
ULONG systemInformationLength,
131
PULONG returnLength);
132
typedef DWORD (WINAPI *NTQUERYINFORMATIONPROCESS)
133
(HANDLE processHandle, DWORD processInformationClass,
134
PVOID processInformation, ULONG processInformationLength,
135
PULONG returnLength);
136
typedef DWORD (WINAPI *NTPOWERINFORMATION)
137
(DWORD powerInformationClass, PVOID inputBuffer,
138
ULONG inputBufferLength, PVOID outputBuffer, ULONG outputBufferLength );
140
/* Type definitions for function pointers to call CryptoAPI functions. */
141
typedef BOOL (WINAPI *CRYPTACQUIRECONTEXT)(HCRYPTPROV *phProv,
142
LPCTSTR pszContainer,
146
typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,
148
typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags);
150
/* Somewhat alternative functionality available as a direct call, for
151
Windows XP and newer. This is the CryptoAPI RNG, which isn't anywhere
152
near as good as the HW RNG, but we use it if it's present on the basis
153
that at least it can't make things any worse. This direct access version
154
is only available under Windows XP, we don't go out of our way to access
155
the more general CryptoAPI one since the main purpose of using it is to
156
take advantage of any possible future hardware RNGs that may be added,
157
for example via TCPA devices. */
158
typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer,
159
ULONG RandomBufferLength);
163
/* MBM data structures, originally by Alexander van Kaam, converted to C by
164
Anders@Majland.org, finally updated by Chris Zahrt <techn0@iastate.edu> */
167
#define SensorType char
171
SensorType iType; /* Type of sensor. */
172
int Count; /* Number of sensor for that type. */
177
SensorType ssType; /* Type of sensor */
178
unsigned char ssName[12]; /* Name of sensor */
179
char sspadding1[3]; /* Padding of 3 bytes */
180
double ssCurrent; /* Current value */
181
double ssLow; /* Lowest readout */
182
double ssHigh; /* Highest readout */
183
long ssCount; /* Total number of readout */
184
char sspadding2[4]; /* Padding of 4 bytes */
185
long double ssTotal; /* Total amout of all readouts */
186
char sspadding3[6]; /* Padding of 6 bytes */
187
double ssAlarm1; /* Temp & fan: high alarm; voltage: % off */
188
double ssAlarm2; /* Temp: low alarm */
193
short siSMB_Base; /* SMBus base address */
194
BusType siSMB_Type; /* SMBus/Isa bus used to access chip */
195
SMBType siSMB_Code; /* SMBus sub type, Intel, AMD or ALi */
196
char siSMB_Addr; /* Address of sensor chip on SMBus */
197
unsigned char siSMB_Name[41]; /* Nice name for SMBus */
198
short siISA_Base; /* ISA base address of sensor chip on ISA */
199
int siChipType; /* Chip nr, connects with Chipinfo.ini */
200
char siVoltageSubType; /* Subvoltage option selected */
205
double sdVersion; /* Version number (example: 51090) */
206
SharedIndex sdIndex[10]; /* Sensor index */
207
SharedSensor sdSensor[100]; /* Sensor info */
208
SharedInfo sdInfo; /* Misc.info */
209
unsigned char sdStart[41]; /* Start time */
211
/* We don't use the next two fields both because they're not random
212
and because it provides a nice safety margin in case of data size
213
mis- estimates (we always under-estimate the buffer size). */
215
unsigned char sdCurrent[41]; /* Current time */
216
unsigned char sdPath[256]; /* MBM path */
222
/* One time intialized handles and function pointers. We use dynamic
223
loading of the DLLs to do without them in case libgcrypt does not
225
static HANDLE hNetAPI32;
226
static NETSTATISTICSGET pNetStatisticsGet;
227
static NETAPIBUFFERSIZE pNetApiBufferSize;
228
static NETAPIBUFFERFREE pNetApiBufferFree;
230
static HANDLE hNTAPI;
231
static NTQUERYSYSTEMINFORMATION pNtQuerySystemInformation;
232
static NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess;
233
static NTPOWERINFORMATION pNtPowerInformation;
235
static HANDLE hAdvAPI32;
236
static CRYPTACQUIRECONTEXT pCryptAcquireContext;
237
static CRYPTGENRANDOM pCryptGenRandom;
238
static CRYPTRELEASECONTEXT pCryptReleaseContext;
239
static RTLGENRANDOM pRtlGenRandom;
242
/* Other module global variables. */
243
static int system_rng_available; /* Whether a system RNG is available. */
244
static HCRYPTPROV hRNGProv; /* Handle to Intel RNG CSP. */
246
static int debug_me; /* Debug flag. */
251
/* Try and connect to the system RNG if there's one present. */
253
init_system_rng (void)
255
system_rng_available = 0;
258
hAdvAPI32 = GetModuleHandle ("AdvAPI32.dll");
262
pCryptAcquireContext = (CRYPTACQUIRECONTEXT)
263
GetProcAddress (hAdvAPI32, "CryptAcquireContextA");
264
pCryptGenRandom = (CRYPTGENRANDOM)
265
GetProcAddress (hAdvAPI32, "CryptGenRandom");
266
pCryptReleaseContext = (CRYPTRELEASECONTEXT)
267
GetProcAddress (hAdvAPI32, "CryptReleaseContext");
269
/* Get a pointer to the native randomness function if it's available.
270
This isn't exported by name, so we have to get it by ordinal. */
271
pRtlGenRandom = (RTLGENRANDOM)
272
GetProcAddress (hAdvAPI32, "SystemFunction036");
274
/* Try and connect to the PIII RNG CSP. The AMD 768 southbridge (from
275
the 760 MP chipset) also has a hardware RNG, but there doesn't appear
276
to be any driver support for this as there is for the Intel RNG so we
277
can't do much with it. OTOH the Intel RNG is also effectively dead
278
as well, mostly due to virtually nonexistant support/marketing by
279
Intel, it's included here mostly for form's sake. */
280
if ( (!pCryptAcquireContext || !pCryptGenRandom || !pCryptReleaseContext
281
|| !pCryptAcquireContext (&hRNGProv, NULL, INTEL_DEF_PROV,
288
system_rng_available = 1;
292
/* Read data from the system RNG if availavle. */
294
read_system_rng (void (*add)(const void*, size_t, enum random_origins),
295
enum random_origins requester)
297
BYTE buffer[ SYSTEMRNG_BYTES + 8 ];
300
if (!system_rng_available)
303
/* Read SYSTEMRNG_BYTES bytes from the system RNG. We don't rely on
304
this for all our randomness requirements (particularly the
305
software RNG) in case it's broken in some way. */
308
if (pCryptGenRandom (hRNGProv, SYSTEMRNG_BYTES, buffer))
311
else if (pRtlGenRandom)
313
if ( pRtlGenRandom (buffer, SYSTEMRNG_BYTES))
319
log_debug ("rndw32#read_system_rng: got %d bytes of quality %d\n",
320
SYSTEMRNG_BYTES, quality);
321
(*add) (buffer, SYSTEMRNG_BYTES, requester);
322
wipememory (buffer, SYSTEMRNG_BYTES);
327
/* Read data from MBM. This communicates via shared memory, so all we
328
need to do is map a file and read the data out. */
330
read_mbm_data (void (*add)(const void*, size_t, enum random_origins),
331
enum random_origins requester)
334
SharedData *mbmDataPtr;
336
hMBMData = OpenFileMapping (FILE_MAP_READ, FALSE, "$M$B$M$5$S$D$" );
339
mbmDataPtr = (SharedData*)MapViewOfFile (hMBMData, FILE_MAP_READ,0,0,0);
343
log_debug ("rndw32#read_mbm_data: got %d bytes\n",
344
(int)sizeof (SharedData));
345
(*add) (mbmDataPtr, sizeof (SharedData), requester);
346
UnmapViewOfFile (mbmDataPtr);
348
CloseHandle (hMBMData);
353
/* Fallback method using the registry to poll the statistics. */
355
registry_poll (void (*add)(const void*, size_t, enum random_origins),
356
enum random_origins requester)
358
static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
360
DWORD dwSize, status;
361
PERF_DATA_BLOCK *pPerfData;
363
/* Get information from the system performance counters. This can take a
364
few seconds to do. In some environments the call to RegQueryValueEx()
365
can produce an access violation at some random time in the future, in
366
some cases adding a short delay after the following code block makes
367
the problem go away. This problem is extremely difficult to
368
reproduce, I haven't been able to get it to occur despite running it
369
on a number of machines. MS knowledge base article Q178887 covers
370
this type of problem, it's typically caused by an external driver or
371
other program that adds its own values under the
372
HKEY_PERFORMANCE_DATA key. The NT kernel, via Advapi32.dll, calls the
373
required external module to map in the data inside an SEH try/except
374
block, so problems in the module's collect function don't pop up until
375
after it has finished, so the fault appears to occur in Advapi32.dll.
376
There may be problems in the NT kernel as well though, a low-level
377
memory checker indicated that ExpandEnvironmentStrings() in
378
Kernel32.dll, called an interminable number of calls down inside
379
RegQueryValueEx(), was overwriting memory (it wrote twice the
380
allocated size of a buffer to a buffer allocated by the NT kernel).
381
OTOH this could be coming from the external module calling back into
382
the kernel, which eventually causes the problem described above.
384
Possibly as an extension of the problem that the krnlWaitSemaphore()
385
call above works around, running two instances of cryptlib (e.g. two
386
applications that use it) under NT4 can result in one of them hanging
387
in the RegQueryValueEx() call. This happens only under NT4 and is
388
hard to reproduce in any consistent manner.
390
One workaround that helps a bit is to read the registry as a remote
391
(rather than local) registry, it's possible that the use of a network
392
RPC call isolates the calling app from the problem in that whatever
393
service handles the RPC is taking the hit and not affecting the
394
calling app. Since this would require another round of extensive
395
testing to verify and the NT native API call is working fine, we'll
396
stick with the native API call for now.
398
Some versions of NT4 had a problem where the amount of data returned
399
was mis-reported and would never settle down, because of this the code
400
below includes a safety-catch that bails out after 10 attempts have
401
been made, this results in no data being returned but at does ensure
402
that the thread will terminate.
404
In addition to these problems the code in RegQueryValueEx() that
405
estimates the amount of memory required to return the performance
406
counter information isn't very accurate (it's much worse than the
407
"slightly-inaccurate" level that the MS docs warn about, it's usually
408
wildly off) since it always returns a worst-case estimate which is
409
usually nowhere near the actual amount required. For example it may
410
report that 128K of memory is required, but only return 64K of data.
412
Even worse than the registry-based performance counters is the
413
performance data helper (PDH) shim that tries to make the counters
414
look like the old Win16 API (which is also used by Win95). Under NT
415
this can consume tens of MB of memory and huge amounts of CPU time
416
while it gathers its data, and even running once can still consume
417
about 1/2MB of memory */
418
pPerfData = gcry_xmalloc (cbPerfData);
419
for (iterations=0; iterations < 10; iterations++)
423
log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
425
status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
426
NULL, (LPBYTE) pPerfData, &dwSize);
427
if (status == ERROR_SUCCESS)
429
if (!memcmp (pPerfData->Signature, L"PERF", 8))
430
(*add) ( pPerfData, dwSize, requester );
432
log_debug ("rndw32: no PERF signature\n");
435
else if (status == ERROR_MORE_DATA)
437
cbPerfData += PERFORMANCE_BUFFER_STEP;
438
pPerfData = gcry_xrealloc (pPerfData, cbPerfData);
442
static int been_here;
444
/* Silence the error message. In particular under Wine (as
445
of 2008) we would get swamped with such diagnotiscs. One
446
such diagnotiscs should be enough. */
447
if (been_here != status)
450
log_debug ("rndw32: get performance data problem: ec=%ld\n",
456
gcry_free (pPerfData);
458
/* Although this isn't documented in the Win32 API docs, it's necessary
459
to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
460
implicitly opened on the first call to RegQueryValueEx()). If this
461
isn't done then any system components which provide performance data
462
can't be removed or changed while the handle remains active. */
463
RegCloseKey (HKEY_PERFORMANCE_DATA);
468
slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
469
enum random_origins requester )
471
static int is_initialized = 0;
472
static int is_workstation = 1;
474
DWORD dwType, dwSize, dwResult;
476
int drive_no, status;
480
if ( !is_initialized )
485
log_debug ("rndw32#slow_gatherer: init toolkit\n" );
486
/* Find out whether this is an NT server or workstation if necessary */
487
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
488
"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
489
0, KEY_READ, &hKey) == ERROR_SUCCESS)
491
BYTE szValue[32 + 8];
495
log_debug ("rndw32#slow_gatherer: check product options\n" );
497
status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
499
if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT"))
501
/* Note: There are (at least) three cases for ProductType:
502
WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
503
NT Server acting as a Domain Controller. */
506
log_debug ("rndw32: this is a NT server\n");
511
/* The following are fixed for the lifetime of the process so we
512
only add them once */
513
/* readPnPData (); - we have not implemented that. */
515
/* Initialize the NetAPI32 function pointers if necessary */
516
hNetAPI32 = LoadLibrary ("NETAPI32.DLL");
520
log_debug ("rndw32#slow_gatherer: netapi32 loaded\n" );
521
pNetStatisticsGet = (NETSTATISTICSGET)
522
GetProcAddress (hNetAPI32, "NetStatisticsGet");
523
pNetApiBufferSize = (NETAPIBUFFERSIZE)
524
GetProcAddress (hNetAPI32, "NetApiBufferSize");
525
pNetApiBufferFree = (NETAPIBUFFERFREE)
526
GetProcAddress (hNetAPI32, "NetApiBufferFree");
528
if (!pNetStatisticsGet || !pNetApiBufferSize || !pNetApiBufferFree)
530
FreeLibrary (hNetAPI32);
532
log_debug ("rndw32: No NETAPI found\n" );
536
/* Initialize the NT kernel native API function pointers if necessary */
537
hNTAPI = GetModuleHandle ("NTDll.dll");
540
/* Get a pointer to the NT native information query functions */
541
pNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)
542
GetProcAddress (hNTAPI, "NtQuerySystemInformation");
543
pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)
544
GetProcAddress (hNTAPI, "NtQueryInformationProcess");
545
pNtPowerInformation = (NTPOWERINFORMATION)
546
GetProcAddress(hNTAPI, "NtPowerInformation");
548
if (!pNtQuerySystemInformation || !pNtQueryInformationProcess)
556
read_system_rng ( add, requester );
557
read_mbm_data ( add, requester );
559
/* Get network statistics. Note: Both NT Workstation and NT Server by
560
default will be running both the workstation and server services. The
561
heuristic below is probably useful though on the assumption that the
562
majority of the network traffic will be via the appropriate service.
563
In any case the network statistics return almost no randomness. */
568
&& !pNetStatisticsGet (NULL,
569
is_workstation ? L"LanmanWorkstation" :
570
L"LanmanServer", 0, 0, &lpBuffer))
573
log_debug ("rndw32#slow_gatherer: get netstats\n" );
574
pNetApiBufferSize (lpBuffer, &dwSize);
575
(*add) ( lpBuffer, dwSize, requester );
576
pNetApiBufferFree (lpBuffer);
580
/* Get disk I/O statistics for all the hard drives. 100 is an
581
arbitrary failsafe limit. */
582
for (drive_no = 0; drive_no < 100 ; drive_no++)
584
char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT + 8];
587
/* Check whether we can access this device. */
588
snprintf (szDevice, sizeof szDevice, "\\\\.\\PhysicalDrive%d",
590
hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
591
NULL, OPEN_EXISTING, 0, NULL);
592
if (hDevice == INVALID_HANDLE_VALUE)
593
break; /* No more drives. */
595
/* Note: This only works if you have turned on the disk performance
596
counters with 'diskperf -y'. These counters are off by default. */
597
dwSize = sizeof diskPerformance;
598
if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
599
diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT,
603
log_debug ("rndw32#slow_gatherer: iostat drive %d\n",
605
(*add) (diskPerformance, dwSize, requester);
609
log_info ("NOTE: you should run 'diskperf -y' "
610
"to enable the disk statistics\n");
612
CloseHandle (hDevice);
615
/* In theory we should be using the Win32 performance query API to obtain
616
unpredictable data from the system, however this is so unreliable (see
617
the multiple sets of comments in registryPoll()) that it's too risky
618
to rely on it except as a fallback in emergencies. Instead, we rely
619
mostly on the NT native API function NtQuerySystemInformation(), which
620
has the dual advantages that it doesn't have as many (known) problems
621
as the Win32 equivalent and that it doesn't access the data indirectly
622
via pseudo-registry keys, which means that it's much faster. Note
623
that the Win32 equivalent actually works almost all of the time, the
624
problem is that on one or two systems it can fail in strange ways that
625
are never the same and can't be reproduced on any other system, which
626
is why we use the native API here. Microsoft officially documented
627
this function in early 2003, so it'll be fairly safe to use. */
630
registry_poll (add, requester);
635
/* Scan the first 64 possible information types (we don't bother with
636
increasing the buffer size as we do with the Win32 version of the
637
performance data read, we may miss a few classes but it's no big deal).
638
This scan typically yields around 20 pieces of data, there's nothing
639
in the range 65...128 so chances are there won't be anything above
641
buffer = gcry_xmalloc (PERFORMANCE_BUFFER_SIZE);
642
for (dwType = 0; dwType < 64; dwType++)
646
/* Some information types are write-only (the IDs are shared with
647
a set-information call), we skip these. */
648
case 26: case 27: case 38: case 46: case 47: case 48: case 52:
651
/* ID 53 = SystemSessionProcessInformation reads input from the
652
output buffer, which has to contain a session ID and pointer
653
to the actual buffer in which to store the session information.
654
Because this isn't a standard query, we skip this. */
659
/* Query the info for this ID. Some results (for example for
660
ID = 6, SystemCallCounts) are only available in checked builds
661
of the kernel. A smaller subcless of results require that
662
certain system config flags be set, for example
663
SystemObjectInformation requires that the
664
FLG_MAINTAIN_OBJECT_TYPELIST be set in NtGlobalFlags. To avoid
665
having to special-case all of these, we try reading each one and
666
only use those for which we get a success status. */
667
dwResult = pNtQuerySystemInformation (dwType, buffer,
668
PERFORMANCE_BUFFER_SIZE - 2048,
670
if (dwResult != ERROR_SUCCESS)
673
/* Some calls (e.g. ID = 23, SystemProcessorStatistics, and ID = 24,
674
SystemDpcInformation) incorrectly return a length of zero, so we
675
manually adjust the length to the correct value. */
679
ulSize = 6 * sizeof (ULONG);
680
else if (dwType == 24)
681
ulSize = 5 * sizeof (ULONG);
684
/* If we got some data back, add it to the entropy pool. */
685
if (ulSize > 0 && ulSize <= PERFORMANCE_BUFFER_SIZE - 2048)
688
log_debug ("rndw32#slow_gatherer: %lu bytes from sysinfo %ld\n",
690
(*add) (buffer, ulSize, requester);
695
/* Now we would do the same for the process information. This
696
call would rather ugly in that it requires an exact length
697
match for the data returned, failing with a
698
STATUS_INFO_LENGTH_MISMATCH error code (0xC0000004) if the
699
length isn't an exact match. It requires a compiler to handle
700
complex nested structs, alignment issues, and so on, and
701
without the headers in which the entries are declared it's
702
almost impossible to do. Thus we don't. */
705
/* Finally, do the same for the system power status information. There
706
are only a limited number of useful information types available so we
707
restrict ourselves to the useful types. In addition since this
708
function doesn't return length information, we have to hardcode in
710
if (pNtPowerInformation)
712
static const struct { int type; int size; } powerInfo[] = {
713
{ 0, 128 }, /* SystemPowerPolicyAc */
714
{ 1, 128 }, /* SystemPowerPolicyDc */
715
{ 4, 64 }, /* SystemPowerCapabilities */
716
{ 5, 48 }, /* SystemBatteryState */
717
{ 11, 48 }, /* ProcessorInformation */
718
{ 12, 24 }, /* SystemPowerInformation */
723
/* The 100 is a failsafe limit. */
724
for (i = 0; powerInfo[i].type != -1 && i < 100; i++ )
726
/* Query the info for this ID */
727
dwResult = pNtPowerInformation (powerInfo[i].type, NULL, 0, buffer,
728
PERFORMANCE_BUFFER_SIZE - 2048);
729
if (dwResult != ERROR_SUCCESS)
732
log_debug ("rndw32#slow_gatherer: %u bytes from powerinfo %d\n",
733
powerInfo[i].size, i);
734
(*add) (buffer, powerInfo[i].size, requester);
737
gcry_assert (i < 100);
741
/* We couldn't get enough results from the kernel, fall back to the
742
somewhat troublesome registry poll. */
744
registry_poll (add, requester);
749
_gcry_rndw32_gather_random (void (*add)(const void*, size_t,
750
enum random_origins),
751
enum random_origins origin,
752
size_t length, int level )
754
static int is_initialized;
759
/* We don't differentiate between level 1 and 2 here because there
760
is no internal entropy pool as a scary resource. It may all work
761
slower, but because our entropy source will never block but
762
deliver some not easy to measure entropy, we assume level 2. */
766
OSVERSIONINFO osvi = { sizeof( osvi ) };
768
GetVersionEx( &osvi );
769
if ( osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
770
log_fatal ("can only run on a Windows NT platform\n" );
776
log_debug ("rndw32#gather_random: ori=%d len=%u lvl=%d\n",
777
origin, (unsigned int)length, level );
779
slow_gatherer (add, origin);
787
_gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
788
enum random_origins),
789
enum random_origins origin)
791
static int addedFixedItems = 0;
794
log_debug ("rndw32#gather_random_fast: ori=%d\n", origin );
796
/* Get various basic pieces of system information: Handle of active
797
window, handle of window with mouse capture, handle of clipboard
798
owner handle of start of clpboard viewer list, pseudohandle of
799
current process, current process ID, pseudohandle of current
800
thread, current thread ID, handle of desktop window, handle of
801
window with keyboard focus, whether system queue has any events,
802
cursor position for last message, 1 ms time for last message,
803
handle of window with clipboard open, handle of process heap,
804
handle of procs window station, types of events in input queue,
805
and milliseconds since Windows was started. */
808
byte buffer[20*sizeof(ulong)], *bufptr;
811
#define ADD(f) do { ulong along = (ulong)(f); \
812
memcpy (bufptr, &along, sizeof (along) ); \
813
bufptr += sizeof (along); \
816
ADD ( GetActiveWindow ());
817
ADD ( GetCapture ());
818
ADD ( GetClipboardOwner ());
819
ADD ( GetClipboardViewer ());
820
ADD ( GetCurrentProcess ());
821
ADD ( GetCurrentProcessId ());
822
ADD ( GetCurrentThread ());
823
ADD ( GetCurrentThreadId ());
824
ADD ( GetDesktopWindow ());
826
ADD ( GetInputState ());
827
ADD ( GetMessagePos ());
828
ADD ( GetMessageTime ());
829
ADD ( GetOpenClipboardWindow ());
830
ADD ( GetProcessHeap ());
831
ADD ( GetProcessWindowStation ());
832
ADD ( GetQueueStatus (QS_ALLEVENTS));
833
ADD ( GetTickCount ());
835
gcry_assert ( bufptr-buffer < sizeof (buffer) );
836
(*add) ( buffer, bufptr-buffer, origin );
840
/* Get multiword system information: Current caret position, current
841
mouse cursor position. */
845
GetCaretPos (&point);
846
(*add) ( &point, sizeof (point), origin );
847
GetCursorPos (&point);
848
(*add) ( &point, sizeof (point), origin );
851
/* Get percent of memory in use, bytes of physical memory, bytes of
852
free physical memory, bytes in paging file, free bytes in paging
853
file, user bytes of address space, and free user bytes. */
855
MEMORYSTATUS memoryStatus;
857
memoryStatus.dwLength = sizeof (MEMORYSTATUS);
858
GlobalMemoryStatus (&memoryStatus);
859
(*add) ( &memoryStatus, sizeof (memoryStatus), origin );
862
/* Get thread and process creation time, exit time, time in kernel
863
mode, and time in user mode in 100ns intervals. */
866
FILETIME creationTime, exitTime, kernelTime, userTime;
867
DWORD minimumWorkingSetSize, maximumWorkingSetSize;
869
handle = GetCurrentThread ();
870
GetThreadTimes (handle, &creationTime, &exitTime,
871
&kernelTime, &userTime);
872
(*add) ( &creationTime, sizeof (creationTime), origin );
873
(*add) ( &exitTime, sizeof (exitTime), origin );
874
(*add) ( &kernelTime, sizeof (kernelTime), origin );
875
(*add) ( &userTime, sizeof (userTime), origin );
877
handle = GetCurrentProcess ();
878
GetProcessTimes (handle, &creationTime, &exitTime,
879
&kernelTime, &userTime);
880
(*add) ( &creationTime, sizeof (creationTime), origin );
881
(*add) ( &exitTime, sizeof (exitTime), origin );
882
(*add) ( &kernelTime, sizeof (kernelTime), origin );
883
(*add) ( &userTime, sizeof (userTime), origin );
885
/* Get the minimum and maximum working set size for the current
887
GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
888
&maximumWorkingSetSize);
889
(*add) ( &minimumWorkingSetSize,
890
sizeof (minimumWorkingSetSize), origin );
891
(*add) ( &maximumWorkingSetSize,
892
sizeof (maximumWorkingSetSize), origin );
896
/* The following are fixed for the lifetime of the process so we only
898
if (!addedFixedItems)
900
STARTUPINFO startupInfo;
902
/* Get name of desktop, console window title, new window
903
position and size, window flags, and handles for stdin,
904
stdout, and stderr. */
905
startupInfo.cb = sizeof (STARTUPINFO);
906
GetStartupInfo (&startupInfo);
907
(*add) ( &startupInfo, sizeof (STARTUPINFO), origin );
911
/* The performance of QPC varies depending on the architecture it's
912
running on and on the OS, the MS documentation is vague about the
913
details because it varies so much. Under Win9x/ME it reads the
914
1.193180 MHz PIC timer. Under NT/Win2K/XP it may or may not read the
915
64-bit TSC depending on the HAL and assorted other circumstances,
916
generally on machines with a uniprocessor HAL
917
KeQueryPerformanceCounter() uses a 3.579545MHz timer and on machines
918
with a multiprocessor or APIC HAL it uses the TSC (the exact time
919
source is controlled by the HalpUse8254 flag in the kernel). That
920
choice of time sources is somewhat peculiar because on a
921
multiprocessor machine it's theoretically possible to get completely
922
different TSC readings depending on which CPU you're currently
923
running on, while for uniprocessor machines it's not a problem.
924
However, the kernel appears to synchronise the TSCs across CPUs at
925
boot time (it resets the TSC as part of its system init), so this
926
shouldn't really be a problem. Under WinCE it's completely platform-
927
dependant, if there's no hardware performance counter available, it
928
uses the 1ms system timer.
930
Another feature of the TSC (although it doesn't really affect us here)
931
is that mobile CPUs will turn off the TSC when they idle, Pentiums
932
will change the rate of the counter when they clock-throttle (to
933
match the current CPU speed), and hyperthreading Pentiums will turn
934
it off when both threads are idle (this more or less makes sense,
935
since the CPU will be in the halted state and not executing any
936
instructions to count).
938
To make things unambiguous, we detect a CPU new enough to call RDTSC
939
directly by checking for CPUID capabilities, and fall back to QPC if
940
this isn't present. */
942
/* FIXME: We would need to implement the CPU feature tests first. */
943
/* if (cpu_has_feature_rdtsc) */
945
/* uint32_t lo, hi; */
946
/* We cannot use "=A", since this would use %rax on x86_64. */
947
/* __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); */
948
/* Ignore high 32 bits, hwich are >1s res. */
949
/* (*add) (&lo, 4, origin ); */
954
LARGE_INTEGER performanceCount;
956
if (QueryPerformanceCounter (&performanceCount))
959
log_debug ("rndw32#gather_random_fast: perf data\n");
960
(*add) (&performanceCount, sizeof (performanceCount), origin);
964
/* Millisecond accuracy at best... */
965
DWORD aword = GetTickCount ();
966
(*add) (&aword, sizeof (aword), origin );