gnutls-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnutls-dev] [PATCH] Fix slow startup under Windows


From: Gerald Combs
Subject: [gnutls-dev] [PATCH] Fix slow startup under Windows
Date: Wed, 31 Jan 2007 10:18:33 -0800
User-agent: Thunderbird 1.5.0.9 (Macintosh/20061207)

Attached is a modified version of the patch at
http://www.securitypunk.com/libgcrypt/ which addresses the slow startup
problems with libgcrypt under Windows.  The patch includes following
changes:

  - Additional flags are passed to CryptAcquireContext to increase its
    likelihood of success
  - If CryptAcquireContext fails, fall back to slower methods instead of
    aborting
  - Add Doxygen-compatible comments, including links to MSDN
    documentation (we'll see how long the links stay valid)
  - Add debug logging

A version of GNUTLS with the patch applied has been included with recent
Wireshark builds, and will be in the 0.99.5 release.  The response from
testers has been positive so far.

diff -ur libgcrypt-1.2.3.old/acinclude.m4 libgcrypt-1.2.3/acinclude.m4
--- libgcrypt-1.2.3.old/acinclude.m4    2005-07-29 06:45:48.000000000 -0700
+++ libgcrypt-1.2.3/acinclude.m4        2006-12-21 15:55:16.522866500 -0800
@@ -96,7 +96,7 @@
 AC_DEFUN([GNUPG_SYS_SYMBOL_UNDERSCORE],
 [tmp_do_check="no"
 case "${target}" in
-    i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp)
+    i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp | 
i[3456]86-pc-mingw32)
         ac_cv_sys_symbol_underscore=yes
         ;;
     *)
diff -ur libgcrypt-1.2.3.old/cipher/rndw32.c libgcrypt-1.2.3/cipher/rndw32.c
--- libgcrypt-1.2.3.old/cipher/rndw32.c 2005-07-29 06:45:48.000000000 -0700
+++ libgcrypt-1.2.3/cipher/rndw32.c     2006-12-22 09:46:59.205533000 -0800
@@ -53,12 +53,14 @@
 #include <string.h>
 
 #include <windows.h>
-
+#include <wincrypt.h>
 
 #include "types.h"
 #include "g10lib.h"
 #include "rand-internal.h"
 
+/* A handle to a crypto provider.  All CryptoAPI functions need this. */
+static HCRYPTPROV hCryptProvider = 0;
 
 static int debug_me;
 
@@ -171,7 +173,6 @@
 #define PERFORMANCE_BUFFER_SIZE        65536   /* Start at 64K */
 #define PERFORMANCE_BUFFER_STEP        16384   /* Step by 16K */
 
-
 static void
 slow_gatherer_windows95( void (*add)(const void*, size_t, int), int requester )
 {
@@ -495,6 +496,39 @@
     RegCloseKey (HKEY_PERFORMANCE_DATA);
 }
 
+/**
+ * Create a block of random bytes using a Windows cryptography provider.
+ *
+ * @param add Callback used to hand off random data.
+ * @param requester Requester ID passed to callback.
+ * @return 0 on failure, nonzero on success.
+ */
+static int
+wincrypt_gatherer( void (*add)(const void*, size_t, int), int requester )
+{
+
+  /* The buffer to store the random bytes in.  For extra safety, this is
+   * memset()'ed to NULL after each use. */
+  static unsigned char rand_bytes[ 32 ];
+
+  if (!hCryptProvider)
+    return 0;
+
+  /* Now that we have a crypto context, we request a block of
+   * cryptographically random bytes, and call the add function with it. */
+  if( CryptGenRandom( hCryptProvider, sizeof( rand_bytes ), rand_bytes ) ) {
+    (*add) ( rand_bytes, sizeof( rand_bytes ), requester );
+  } else {
+    if ( debug_me )
+      log_debug( "CryptGenRandom failed: %d", GetLastError() );
+    return 0;
+  }
+
+  /* These random bytes might be used as key material, so we want to clear
+   * them now. */
+  memset(rand_bytes, 0, sizeof(rand_bytes));
+  return 1;
+}
 
 int
 _gcry_rndw32_gather_random( void (*add)(const void*, size_t, int),
@@ -537,6 +571,13 @@
        log_debug ("rndw32#gather_random: req=%d len=%u lvl=%d\n",
                           requester, (unsigned int)length, level );
 
+    if (wincrypt_gatherer( add, requester ) ) {
+      return 0;
+    }
+
+    if ( debug_me )
+       log_debug ("rndw32#gather_random: wincrypt_gatherer failed\n");
+
     if ( has_toolhelp ) {
         slow_gatherer_windows95 ( add, requester );
     }
@@ -681,3 +722,46 @@
     return 0;
 }
 
+/**
+ * Windows DLL entry/exit routine used to acquire and release a crypto
+ * provider context.
+ * References:
+ * CryptGenRandom:
+ *   
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/cryptgenrandom.asp
+ * CryptAcquireContext:
+ *   
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/cryptacquirecontext.asp
+ * CryptAcquireContext troubleshooting:
+ *   http://support.microsoft.com/default.aspx?scid=238187
+ *
+ * @param hinstDLL Handle/base address for the DLL.
+ * @param fdwReason Why the entry is being called.
+ * @param lpReserved Unused in this function.
+ */
+BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved ) {
+    switch( fdwReason ) {
+        case DLL_PROCESS_ATTACH:
+         if ( hCryptProvider == 0 ) {
+           /* Try to acquire an existing context. */
+           if( !CryptAcquireContext( &hCryptProvider, NULL, NULL,
+                                     PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | 
CRYPT_SILENT ) ) {
+             if ( debug_me )
+                log_debug( "CryptAcquireContext first try failed: %d", 
GetLastError() );
+             /* An existing context does not exist, so make one. */
+             if( !CryptAcquireContext( &hCryptProvider, NULL, NULL,
+                                       PROV_RSA_FULL, CRYPT_NEWKEYSET | 
CRYPT_VERIFYCONTEXT | CRYPT_SILENT ) ) {
+                if ( debug_me )
+                  log_debug( "CryptAcquireContext second try failed: %d", 
GetLastError() );
+             }
+           }
+         }
+         break;
+
+
+        case DLL_PROCESS_DETACH:
+         CryptReleaseContext( hCryptProvider, 0 );
+         hCryptProvider = 0;
+         break;
+    }
+
+    return TRUE;
+}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]