Been meaning to get round to this for a while: use CryptGenRandom to
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 20 Jul 2013 08:34:54 +0000 (08:34 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 20 Jul 2013 08:34:54 +0000 (08:34 +0000)
gather extra entropy at Windows PuTTY startup time. (It's only used as
one of the inputs to PuTTY's internal entropy pool, so nobody is
required to trust it.)

git-svn-id: svn://svn.tartarus.org/sgt/putty@9941 cda61777-01e9-0310-a592-d414129be87e

windows/winnoise.c

index affb1a5..3136454 100644 (file)
@@ -9,10 +9,18 @@
 #include "ssh.h"
 #include "storage.h"
 
+#include <wincrypt.h>
+
+DECL_WINDOWS_FUNCTION(static, BOOL, CryptAcquireContextA,
+                      (HCRYPTPROV *, LPCTSTR, LPCTSTR, DWORD, DWORD));
+DECL_WINDOWS_FUNCTION(static, BOOL, CryptGenRandom,
+                      (HCRYPTPROV, DWORD, BYTE *));
+DECL_WINDOWS_FUNCTION(static, BOOL, CryptReleaseContext,
+                      (HCRYPTPROV, DWORD));
+static HMODULE wincrypt_module = NULL;
+
 /*
- * This function is called once, at PuTTY startup, and will do some
- * seriously silly things like listing directories and getting disk
- * free space and a process snapshot.
+ * This function is called once, at PuTTY startup.
  */
 
 void noise_get_heavy(void (*func) (void *, int))
@@ -20,6 +28,7 @@ void noise_get_heavy(void (*func) (void *, int))
     HANDLE srch;
     WIN32_FIND_DATA finddata;
     DWORD pid;
+    HCRYPTPROV crypt_provider;
     char winpath[MAX_PATH + 3];
 
     GetWindowsDirectory(winpath, sizeof(winpath));
@@ -35,6 +44,24 @@ void noise_get_heavy(void (*func) (void *, int))
     pid = GetCurrentProcessId();
     func(&pid, sizeof(pid));
 
+    if (!wincrypt_module) {
+        wincrypt_module = load_system32_dll("advapi32.dll");
+        GET_WINDOWS_FUNCTION(wincrypt_module, CryptAcquireContextA);
+        GET_WINDOWS_FUNCTION(wincrypt_module, CryptGenRandom);
+        GET_WINDOWS_FUNCTION(wincrypt_module, CryptReleaseContext);
+    }
+
+    if (wincrypt_module && p_CryptAcquireContextA &&
+        p_CryptGenRandom && p_CryptReleaseContext &&
+        p_CryptAcquireContextA(&crypt_provider, NULL, NULL, PROV_RSA_FULL,
+                               CRYPT_VERIFYCONTEXT)) {
+        BYTE buf[32];
+        if (p_CryptGenRandom(crypt_provider, 32, buf)) {
+            func(buf, sizeof(buf));
+        }
+        p_CryptReleaseContext(crypt_provider, 0);
+    }
+
     read_random_seed(func);
     /* Update the seed immediately, in case another instance uses it. */
     random_save_seed();