Added an entropy gatherer for W32CE.
authorWerner Koch <wk@gnupg.org>
Wed, 24 Mar 2010 15:51:37 +0000 (15:51 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 24 Mar 2010 15:51:37 +0000 (15:51 +0000)
ChangeLog
configure.ac
random/ChangeLog
random/Makefile.am
random/rand-internal.h
random/random-csprng.c
random/rndw32.c
random/rndw32ce.c [new file with mode: 0644]

index d774a4c..b24a6f9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2010-03-24  Werner Koch  <wk@g10code.com>
+
+       * configure.ac (USE_RNDW32CE): New.
+
 2010-03-15  Werner Koch  <wk@g10code.com>
 
        * configure.ac (emacs_local_vars_begin)
index da41225..5a44b31 100644 (file)
@@ -179,10 +179,17 @@ have_w32ce_system=no
 # Setup some stuff depending on host.
 case "${host}" in
     *-*-mingw32*)
-      available_random_modules="w32"
       ac_cv_have_dev_random=no
       have_w32_system=yes
-      case "${host}" in *-mingw32ce*) have_w32ce_system=yes ;; esac
+      case "${host}" in 
+        *-mingw32ce*)
+            have_w32ce_system=yes
+            available_random_modules="w32ce"
+            ;;
+        *)
+            available_random_modules="w32"
+            ;;
+      esac
       AC_DEFINE(USE_ONLY_8DOT3,1,
                 [set this to limit filenames to the 8.3 format])
       AC_DEFINE(HAVE_DRIVE_LETTERS,1,
@@ -245,11 +252,11 @@ AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes)
 # A printable OS Name is sometimes useful.
 case "${host}" in
     *-*-mingw32ce*)
-        PRINTABLE_OS_NAME="MingW32CE"
+        PRINTABLE_OS_NAME="W32CE"
         ;;
 
     *-*-mingw32*)
-        PRINTABLE_OS_NAME="MingW32"
+        PRINTABLE_OS_NAME="W32"
         ;;
 
     i?86-emx-os2 | i?86-*-os2*emx )
@@ -807,6 +814,10 @@ if test "$random" = "default"; then
         random_modules="linux"
     else
         case "${host}" in
+        *-*-mingw32ce*)
+          # WindowsCE random device.
+          random_modules="w32ce"
+          ;;
         *-*-mingw32*|*-*-cygwin*)
           # Windows random device.
           random_modules="w32"
@@ -1105,6 +1116,13 @@ if test "$found" = "1" ; then
              [Defined if the Windows specific RNG should be used.])
 fi
 
+LIST_MEMBER(w32ce, $random_modules)
+if test "$found" = "1" ; then
+   GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32ce.lo"
+   AC_DEFINE(USE_RNDW32CE, 1, 
+             [Defined if the WindowsCE specific RNG should be used.])
+fi
+
 AC_SUBST([GCRYPT_CIPHERS])
 AC_SUBST([GCRYPT_PUBKEY_CIPHERS])
 AC_SUBST([GCRYPT_DIGESTS])
index 76fa5ec..2fa2b81 100644 (file)
@@ -1,3 +1,12 @@
+2010-03-24  Werner Koch  <wk@g10code.com>
+
+       * rndw32.c: Revert all changes from 2010-01-21.
+
+       * rndw32ce.c: New.
+       * Makefile.am (EXTRA_librandom_la_SOURCES): Add it.
+       * random-csprng.c (getfnc_gather_random)
+       (getfnc_fast_random_poll) [USE_RNDW32CE]: Use rndw32ce.
+
 2010-01-21  Werner Koch  <wk@g10code.com>
 
        * rndw32.c (read_mbm_data) [W32CE]: Do not build.
index 336109a..2058d56 100644 (file)
@@ -46,4 +46,5 @@ EXTRA_librandom_la_SOURCES = \
 rndlinux.c \
 rndegd.c \
 rndunix.c \
-rndw32.c 
+rndw32.c  \
+rndw32ce.c
index 534d828..2cce906 100644 (file)
@@ -123,6 +123,15 @@ void _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
                                                   enum random_origins),
                                       enum random_origins origin );
 
+/*-- rndw32ce.c --*/
+int _gcry_rndw32ce_gather_random (void (*add) (const void *, size_t,
+                                               enum random_origins),
+                                  enum random_origins origin,
+                                  size_t length, int level);
+void _gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t, 
+                                                    enum random_origins),
+                                        enum random_origins origin );
+
 /*-- rndhw.c --*/
 int _gcry_rndhw_failed_p (void);
 void _gcry_rndhw_poll_fast (void (*add)(const void*, size_t,
index fbc4230..9ad3951 100644 (file)
@@ -1,6 +1,6 @@
 /* random-csprng.c - CSPRNG style random number generator (libgcrypt classic)
  * Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- *               2007, 2008  Free Software Foundation, Inc.
+ *               2007, 2008, 2010  Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -1144,6 +1144,11 @@ getfnc_gather_random (void))(void (*)(const void*, size_t,
   return fnc;
 #endif
 
+#if USE_RNDW32CE
+  fnc = _gcry_rndw32ce_gather_random;
+  return fnc;
+#endif
+
   log_fatal (_("no entropy gathering module detected\n"));
 
   return NULL; /*NOTREACHED*/
@@ -1159,6 +1164,9 @@ getfnc_fast_random_poll (void))( void (*)(const void*, size_t,
 #if USE_RNDW32
   return _gcry_rndw32_gather_random_fast;
 #endif
+#if USE_RNDW32CE
+  return _gcry_rndw32ce_gather_random_fast;
+#endif
   return NULL;
 }
 
index 4511cee..49dff3c 100644 (file)
@@ -329,7 +329,6 @@ 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.  */
-#ifndef HAVE_W32CE_SYSTEM
 static void
 read_mbm_data (void (*add)(const void*, size_t, enum random_origins), 
                enum random_origins requester)
@@ -352,7 +351,6 @@ read_mbm_data (void (*add)(const void*, size_t, enum random_origins),
       CloseHandle (hMBMData);
     }
 }
-#endif /*!HAVE_W32CE_SYSTEM*/
 
 
 /* Fallback method using the registry to poll the statistics.  */
@@ -559,9 +557,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
     }
   
   read_system_rng ( add, requester );
-#ifndef HAVE_W32CE_SYSTEM
   read_mbm_data ( add, requester );
-#endif  
 
   /* Get network statistics.    Note: Both NT Workstation and NT Server by
      default will be running both the workstation and server services.  The
@@ -779,13 +775,8 @@ _gcry_rndw32_gather_random (void (*add)(const void*, size_t,
       OSVERSIONINFO osvi = { sizeof( osvi ) };
 
       GetVersionEx( &osvi );
-#ifdef HAVE_W32CE_SYSTEM
-      if (osvi.dwPlatformId != VER_PLATFORM_WIN32_CE)
-        log_fatal ("can only run on a Windows CE platform\n" );
-#else
       if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
         log_fatal ("can only run on a Windows NT platform\n" );
-#endif
       system_is_w2000 = (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0);
       init_system_rng ();
       is_initialized = 1;
@@ -831,28 +822,23 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
                      memcpy (bufptr, &along, sizeof (along) );  \
                      bufptr += sizeof (along);                  \
                    } while (0)
-#ifdef HAVE_W32CE_SYSTEM
-# define ADD_NO_CE(f)
-#else
-# define ADD_NO_CE(f)  ADD(f)
-#endif
 
     ADD ( GetActiveWindow ());
     ADD ( GetCapture ());
     ADD ( GetClipboardOwner ());
-    ADD_NO_CE ( GetClipboardViewer ());
+    ADD ( GetClipboardViewer ());
     ADD ( GetCurrentProcess ());
     ADD ( GetCurrentProcessId ());
     ADD ( GetCurrentThread ());
     ADD ( GetCurrentThreadId ());
     ADD ( GetDesktopWindow ());
     ADD ( GetFocus ());
-    ADD_NO_CE ( GetInputState ());
+    ADD ( GetInputState ());
     ADD ( GetMessagePos ());
-    ADD_NO_CE ( GetMessageTime ());
+    ADD ( GetMessageTime ());
     ADD ( GetOpenClipboardWindow ());
     ADD ( GetProcessHeap ());
-    ADD_NO_CE ( GetProcessWindowStation ());
+    ADD ( GetProcessWindowStation ());
     ADD ( GetQueueStatus (QS_ALLEVENTS));
     ADD ( GetTickCount ());
 
@@ -898,15 +884,9 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
     (*add) ( &kernelTime, sizeof (kernelTime), origin );
     (*add) ( &userTime, sizeof (userTime), origin );
 
-#ifdef HAVE_W32CE_SYSTEM
-    handle = GetCurrentThread ();
-    GetThreadTimes (handle, &creationTime, &exitTime,
-                     &kernelTime, &userTime);
-#else
     handle = GetCurrentProcess ();
     GetProcessTimes (handle, &creationTime, &exitTime,
                      &kernelTime, &userTime);
-#endif
     (*add) ( &creationTime, sizeof (creationTime), origin );
     (*add) ( &exitTime, sizeof (exitTime), origin );
     (*add) ( &kernelTime, sizeof (kernelTime), origin );
@@ -914,20 +894,17 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
 
     /* Get the minimum and maximum working set size for the current
        process.  */
-#ifndef HAVE_W32CE_SYSTEM
     GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
                               &maximumWorkingSetSize);
     (*add) ( &minimumWorkingSetSize,
              sizeof (minimumWorkingSetSize), origin );
     (*add) ( &maximumWorkingSetSize,
              sizeof (maximumWorkingSetSize), origin );
-#endif /*!HAVE_W32CE_SYSTEM*/
   }
 
 
   /* The following are fixed for the lifetime of the process so we only
    * add them once */
-#ifndef HAVE_W32CE_SYSTEM
   if (!addedFixedItems)
     {
       STARTUPINFO startupInfo;
@@ -940,7 +917,6 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
       (*add) ( &startupInfo, sizeof (STARTUPINFO), origin );
       addedFixedItems = 1;
     }
-#endif /*!HAVE_W32CE_SYSTEM*/
 
   /* The performance of QPC varies depending on the architecture it's
      running on and on the OS, the MS documentation is vague about the
diff --git a/random/rndw32ce.c b/random/rndw32ce.c
new file mode 100644 (file)
index 0000000..1223960
--- /dev/null
@@ -0,0 +1,193 @@
+/* rndw32ce.c  -  W32CE entropy gatherer
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include "types.h"
+#include "g10lib.h"
+#include "rand-internal.h"
+
+
+/* The Microsoft docs say that it is suggested to see the buffer with
+   some extra random.  We do this, despite that it is a questionable
+   suggestion as the OS as better means of collecting entropy than an
+   application.  */
+static void
+fillup_buffer (unsigned char *buffer, size_t length)
+{
+  size_t used = 0;
+
+  /* This code uses gcc anyway, thus we can use a nested function.  */
+  void filler (const void *data, size_t datalen, enum random_origins dummy)
+  {
+    (void)dummy;
+    if (used + datalen > length)
+      datalen = length - used;
+    memcpy (buffer+used, data, datalen);
+    used += datalen;
+  }
+
+  while (used < length)
+    _gcry_rndw32ce_gather_random_fast (filler, 0);
+}
+
+
+
+int
+_gcry_rndw32ce_gather_random (void (*add)(const void*, size_t,
+                                          enum random_origins),
+                              enum random_origins origin,
+                              size_t length, int level )
+{
+  HCRYPTPROV prov;
+  unsigned char buffer [256];
+  DWORD buflen;
+
+  if (!level)
+    return 0;
+
+  /* Note that LENGTH is not really important because the caller
+     checks the returned lengths and calls this function until it
+     feels that enough entropy has been gathered.  */
+
+  buflen = sizeof buffer;
+  if (length+8 < buflen)
+    buflen = length+8;  /* Return a bit more than requested.  */
+
+  if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL, 
+                           (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
+    log_debug ("CryptAcquireContext failed: rc=%d\n", (int)GetLastError ());
+  else
+    {
+      fillup_buffer (buffer, buflen);
+      if (!CryptGenRandom (prov, buflen, buffer))
+        log_debug ("CryptGenRandom(%d) failed: rc=%d\n",
+                   (int)buflen, (int)GetLastError ());
+      else
+        (*add) (buffer, buflen, origin);
+      CryptReleaseContext (prov, 0);
+      wipememory (buffer, sizeof buffer);
+    }
+
+  return 0;
+}
+
+
+
+void
+_gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
+                                             enum random_origins),
+                                   enum random_origins origin)
+{
+
+  /* Add word sized values.  */
+  {
+#   define ADD(t,f)  do {                                          \
+      t along = (f);                                               \
+      memcpy (bufptr, &along, sizeof (along));                     \
+      bufptr += sizeof (along);                                    \
+    } while (0)
+    unsigned char buffer[20*sizeof(ulong)], *bufptr;
+
+    bufptr = buffer;
+    ADD (HWND,   GetActiveWindow ());
+    ADD (HWND,   GetCapture ());
+    ADD (HWND,   GetClipboardOwner ());
+    ADD (HANDLE, GetCurrentProcess ());
+    ADD (DWORD,  GetCurrentProcessId ());
+    ADD (HANDLE, GetCurrentThread ());
+    ADD (DWORD,  GetCurrentThreadId ());
+    ADD (HWND,   GetDesktopWindow ());
+    ADD (HWND,   GetFocus ());
+    ADD (DWORD,  GetMessagePos ());
+    ADD (HWND,   GetOpenClipboardWindow ());
+    ADD (HWND,   GetProcessHeap ());
+    ADD (DWORD,  GetQueueStatus (QS_ALLEVENTS));
+    ADD (DWORD,  GetTickCount ());
+
+    gcry_assert ( bufptr-buffer < sizeof (buffer) );
+    (*add) ( buffer, bufptr-buffer, origin );
+#   undef ADD
+  }
+
+  /* Get multiword system information: Current caret position, current
+     mouse cursor position.  */
+  {
+    POINT point;
+
+    GetCaretPos (&point);
+    (*add) ( &point, sizeof (point), origin );
+    GetCursorPos (&point);
+    (*add) ( &point, sizeof (point), origin );
+  }
+
+  /* Get percent of memory in use, bytes of physical memory, bytes of
+     free physical memory, bytes in paging file, free bytes in paging
+     file, user bytes of address space, and free user bytes.  */
+  {
+    MEMORYSTATUS memoryStatus;
+
+    memoryStatus.dwLength = sizeof (MEMORYSTATUS);
+    GlobalMemoryStatus (&memoryStatus);
+    (*add) ( &memoryStatus, sizeof (memoryStatus), origin );
+  }
+
+
+  /* Get thread and process creation time, exit time, time in kernel
+     mode, and time in user mode in 100ns intervals.  */
+  {
+    HANDLE handle;
+    FILETIME creationTime, exitTime, kernelTime, userTime;
+
+    handle = GetCurrentThread ();
+    GetThreadTimes (handle, &creationTime, &exitTime,
+                    &kernelTime, &userTime);
+    (*add) ( &creationTime, sizeof (creationTime), origin );
+    (*add) ( &exitTime, sizeof (exitTime), origin );
+    (*add) ( &kernelTime, sizeof (kernelTime), origin );
+    (*add) ( &userTime, sizeof (userTime), origin );
+
+    handle = GetCurrentThread ();
+    GetThreadTimes (handle, &creationTime, &exitTime,
+                     &kernelTime, &userTime);
+    (*add) ( &creationTime, sizeof (creationTime), origin );
+    (*add) ( &exitTime, sizeof (exitTime), origin );
+    (*add) ( &kernelTime, sizeof (kernelTime), origin );
+    (*add) ( &userTime, sizeof (userTime), origin );
+
+  }
+  
+
+  /* In case the OEM provides a high precision timer get this.  If
+     none is available the default implementation returns the
+     GetTickCount.  */
+  {
+    LARGE_INTEGER performanceCount;
+    
+    if (QueryPerformanceCounter (&performanceCount))
+      (*add) (&performanceCount, sizeof (performanceCount), origin);
+  }
+  
+}