Been meaning to get round to this for a while: use CryptGenRandom to
[u/mdw/putty] / windows / winnoise.c
index 1b1d1f5..3136454 100644 (file)
@@ -9,16 +9,26 @@
 #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))
 {
     HANDLE srch;
     WIN32_FIND_DATA finddata;
+    DWORD pid;
+    HCRYPTPROV crypt_provider;
     char winpath[MAX_PATH + 3];
 
     GetWindowsDirectory(winpath, sizeof(winpath));
@@ -31,6 +41,27 @@ void noise_get_heavy(void (*func) (void *, int))
        FindClose(srch);
     }
 
+    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();
@@ -51,7 +82,7 @@ void random_save_seed(void)
 /*
  * This function is called every time the random pool needs
  * stirring, and will acquire the system time in all available
- * forms and the battery status.
+ * forms.
  */
 void noise_get_light(void (*func) (void *, int))
 {