tests: Add tests for mpi_cmp.
[libgcrypt.git] / random / rndw32.c
index d250c06..5c5d6c6 100644 (file)
@@ -1,5 +1,6 @@
 /* rndw32.c  -  W32 entropy gatherer
- * Copyright (C) 1999, 2000, 2002, 2003, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 1999, 2000, 2002, 2003, 2007,
+ *               2010 Free Software Foundation, Inc.
  * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2006
  *
  * This file is part of Libgcrypt.
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
-#ifdef __GNUC__  
+#ifdef __GNUC__
 #include <stdint.h>
 #endif
 
+#include <winsock2.h>
 #include <windows.h>
 
 
@@ -140,22 +142,22 @@ typedef DWORD (WINAPI *NTPOWERINFORMATION)
 /* Type definitions for function pointers to call CryptoAPI functions. */
 typedef BOOL (WINAPI *CRYPTACQUIRECONTEXT)(HCRYPTPROV *phProv,
                                            LPCTSTR pszContainer,
-                                           LPCTSTR pszProvider, 
+                                           LPCTSTR pszProvider,
                                            DWORD dwProvType,
                                            DWORD dwFlags);
 typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,
                                       BYTE *pbBuffer);
 typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags);
 
-/* Somewhat alternative functionality available as a direct call, for 
+/* Somewhat alternative functionality available as a direct call, for
    Windows XP and newer.  This is the CryptoAPI RNG, which isn't anywhere
    near as good as the HW RNG, but we use it if it's present on the basis
-   that at least it can't make things any worse.  This direct access version 
+   that at least it can't make things any worse.  This direct access version
    is only available under Windows XP, we don't go out of our way to access
-   the more general CryptoAPI one since the main purpose of using it is to 
-   take advantage of any possible future hardware RNGs that may be added, 
+   the more general CryptoAPI one since the main purpose of using it is to
+   take advantage of any possible future hardware RNGs that may be added,
    for example via TCPA devices.  */
-typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer, 
+typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer,
                                     ULONG RandomBufferLength);
 
 
@@ -166,13 +168,13 @@ typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer,
 #define SMBType         char
 #define SensorType      char
 
-typedef struct 
+typedef struct
 {
   SensorType iType;               /* Type of sensor.  */
   int Count;                      /* Number of sensor for that type.  */
 } SharedIndex;
 
-typedef struct 
+typedef struct
 {
   SensorType ssType;              /* Type of sensor */
   unsigned char ssName[12];       /* Name of sensor */
@@ -251,7 +253,7 @@ static int system_is_w2000;     /* True if running on W2000.  */
 
 \f
 /* Try and connect to the system RNG if there's one present. */
-static void 
+static void
 init_system_rng (void)
 {
   system_rng_available = 0;
@@ -267,17 +269,17 @@ init_system_rng (void)
     GetProcAddress (hAdvAPI32, "CryptGenRandom");
   pCryptReleaseContext = (CRYPTRELEASECONTEXT)
     GetProcAddress (hAdvAPI32, "CryptReleaseContext");
-  
-  /* Get a pointer to the native randomness function if it's available.  
+
+  /* Get a pointer to the native randomness function if it's available.
      This isn't exported by name, so we have to get it by ordinal.  */
   pRtlGenRandom = (RTLGENRANDOM)
     GetProcAddress (hAdvAPI32, "SystemFunction036");
 
-  /* Try and connect to the PIII RNG CSP.  The AMD 768 southbridge (from 
-     the 760 MP chipset) also has a hardware RNG, but there doesn't appear 
-     to be any driver support for this as there is for the Intel RNG so we 
-     can't do much with it.  OTOH the Intel RNG is also effectively dead 
-     as well, mostly due to virtually nonexistant support/marketing by 
+  /* Try and connect to the PIII RNG CSP.  The AMD 768 southbridge (from
+     the 760 MP chipset) also has a hardware RNG, but there doesn't appear
+     to be any driver support for this as there is for the Intel RNG so we
+     can't do much with it.  OTOH the Intel RNG is also effectively dead
+     as well, mostly due to virtually nonexistent support/marketing by
      Intel, it's included here mostly for form's sake.  */
   if ( (!pCryptAcquireContext || !pCryptGenRandom || !pCryptReleaseContext
         || !pCryptAcquireContext (&hRNGProv, NULL, INTEL_DEF_PROV,
@@ -292,7 +294,7 @@ init_system_rng (void)
 
 
 /* Read data from the system RNG if availavle.  */
-static void 
+static void
 read_system_rng (void (*add)(const void*, size_t, enum random_origins),
                  enum random_origins requester)
 {
@@ -329,7 +331,7 @@ read_system_rng (void (*add)(const void*, size_t, enum random_origins),
 /* Read data from MBM.  This communicates via shared memory, so all we
    need to do is map a file and read the data out.  */
 static void
-read_mbm_data (void (*add)(const void*, size_t, enum random_origins), 
+read_mbm_data (void (*add)(const void*, size_t, enum random_origins),
                enum random_origins requester)
 {
   HANDLE hMBMData;
@@ -354,7 +356,7 @@ read_mbm_data (void (*add)(const void*, size_t, enum random_origins),
 
 /* Fallback method using the registry to poll the statistics.  */
 static void
-registry_poll (void (*add)(const void*, size_t, enum random_origins), 
+registry_poll (void (*add)(const void*, size_t, enum random_origins),
                enum random_origins requester)
 {
   static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
@@ -417,45 +419,58 @@ registry_poll (void (*add)(const void*, size_t, enum random_origins),
      this can consume tens of MB of memory and huge amounts of CPU time
      while it gathers its data, and even running once can still consume
      about 1/2MB of memory */
-  pPerfData = gcry_xmalloc (cbPerfData);
-  for (iterations=0; iterations < 10; iterations++)
+  if (getenv ("GNUPG_RNDW32_NOPERF"))
     {
-      dwSize = cbPerfData;
-      if ( debug_me )
-        log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
+      static int shown;
 
-      status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
-                                NULL, (LPBYTE) pPerfData, &dwSize);
-      if (status == ERROR_SUCCESS)
+      if (!shown)
         {
-          if (!memcmp (pPerfData->Signature, L"PERF", 8))
-            (*add) ( pPerfData, dwSize, requester );
-          else
-            log_debug ("rndw32: no PERF signature\n");
-          break;
+          shown = 1;
+          log_info ("note: get performance data has been disabled\n");
         }
-      else if (status == ERROR_MORE_DATA)
-        {
-          cbPerfData += PERFORMANCE_BUFFER_STEP;
-          pPerfData = gcry_xrealloc (pPerfData, cbPerfData);
-        }
-      else
+    }
+  else
+    {
+      pPerfData = gcry_xmalloc (cbPerfData);
+      for (iterations=0; iterations < 10; iterations++)
         {
-          static int been_here;
+          dwSize = cbPerfData;
+          if ( debug_me )
+            log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
 
-          /* Silence the error message.  In particular under Wine (as
-             of 2008) we would get swamped with such diagnotiscs.  One
-             such diagnotiscs should be enough.  */
-          if (been_here != status)
+          status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
+                                    NULL, (LPBYTE) pPerfData, &dwSize);
+          if (status == ERROR_SUCCESS)
             {
-              been_here = status;
-              log_debug ("rndw32: get performance data problem: ec=%ld\n",
-                         status);
+              if (!memcmp (pPerfData->Signature, L"PERF", 8))
+                (*add) ( pPerfData, dwSize, requester );
+              else
+                log_debug ("rndw32: no PERF signature\n");
+              break;
+            }
+          else if (status == ERROR_MORE_DATA)
+            {
+              cbPerfData += PERFORMANCE_BUFFER_STEP;
+              pPerfData = gcry_xrealloc (pPerfData, cbPerfData);
+            }
+          else
+            {
+              static int been_here;
+
+              /* Silence the error message.  In particular under Wine (as
+                 of 2008) we would get swamped with such diagnotiscs.  One
+                 such diagnotiscs should be enough.  */
+              if (been_here != status)
+                {
+                  been_here = status;
+                  log_debug ("rndw32: get performance data problem: ec=%ld\n",
+                             status);
+                }
+              break;
             }
-          break;
         }
+      gcry_free (pPerfData);
     }
-  gcry_free (pPerfData);
 
   /* Although this isn't documented in the Win32 API docs, it's necessary
      to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
@@ -467,7 +482,7 @@ registry_poll (void (*add)(const void*, size_t, enum random_origins),
 
 
 static void
-slow_gatherer ( void (*add)(const void*, size_t, enum random_origins), 
+slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
                 enum random_origins requester )
 {
   static int is_initialized = 0;
@@ -554,10 +569,10 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
 
       is_initialized = 1;
     }
-  
+
   read_system_rng ( add, requester );
   read_mbm_data ( add, requester );
-  
+
   /* Get network statistics.    Note: Both NT Workstation and NT Server by
      default will be running both the workstation and server services.  The
      heuristic below is probably useful though on the assumption that the
@@ -565,7 +580,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
      In any case the network statistics return almost no randomness.  */
   {
     LPBYTE lpBuffer;
-    
+
     if (hNetAPI32
         && !pNetStatisticsGet (NULL,
                                is_workstation ? L"LanmanWorkstation" :
@@ -585,7 +600,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
     {
       char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT + 8];
       char szDevice[50];
-      
+
       /* Check whether we can access this device.  */
       snprintf (szDevice, sizeof szDevice, "\\\\.\\PhysicalDrive%d",
                 drive_no);
@@ -593,7 +608,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
                             NULL, OPEN_EXISTING, 0, NULL);
       if (hDevice == INVALID_HANDLE_VALUE)
         break; /* No more drives.  */
-        
+
       /* Note: This only works if you have turned on the disk performance
          counters with 'diskperf -y'.  These counters are off by default. */
       dwSize = sizeof diskPerformance;
@@ -774,7 +789,7 @@ _gcry_rndw32_gather_random (void (*add)(const void*, size_t,
       OSVERSIONINFO osvi = { sizeof( osvi ) };
 
       GetVersionEx( &osvi );
-      if ( osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
+      if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
         log_fatal ("can only run on a Windows NT platform\n" );
       system_is_w2000 = (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0);
       init_system_rng ();
@@ -935,7 +950,7 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
      shouldn't really be a problem.  Under WinCE it's completely platform-
      dependant, if there's no hardware performance counter available, it
      uses the 1ms system timer.
-     
+
      Another feature of the TSC (although it doesn't really affect us here)
      is that mobile CPUs will turn off the TSC when they idle, Pentiums
      will change the rate of the counter when they clock-throttle (to
@@ -943,11 +958,11 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
      it off when both threads are idle (this more or less makes sense,
      since the CPU will be in the halted state and not executing any
      instructions to count).
-     
+
      To make things unambiguous, we detect a CPU new enough to call RDTSC
      directly by checking for CPUID capabilities, and fall back to QPC if
      this isn't present.  */
-#ifdef __GNUC__  
+#ifdef __GNUC__
 /*   FIXME: We would need to implement the CPU feature tests first.  */
 /*   if (cpu_has_feature_rdtsc) */
 /*     { */
@@ -961,7 +976,7 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
 #endif /*!__GNUC__*/
     {
       LARGE_INTEGER performanceCount;
-      
+
       if (QueryPerformanceCounter (&performanceCount))
         {
           if ( debug_me )