winnoise.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Noise generation for PuTTY's cryptographic random number
  3. * generator.
  4. */
  5. #include <stdio.h>
  6. #include "putty.h"
  7. #include "ssh.h"
  8. #include "storage.h"
  9. #include <wincrypt.h>
  10. DECL_WINDOWS_FUNCTION(static, BOOL, CryptAcquireContextA,
  11. (HCRYPTPROV *, LPCTSTR, LPCTSTR, DWORD, DWORD));
  12. DECL_WINDOWS_FUNCTION(static, BOOL, CryptGenRandom,
  13. (HCRYPTPROV, DWORD, BYTE *));
  14. DECL_WINDOWS_FUNCTION(static, BOOL, CryptReleaseContext,
  15. (HCRYPTPROV, DWORD));
  16. static HMODULE wincrypt_module = NULL;
  17. /*
  18. * This function is called once, at PuTTY startup.
  19. */
  20. void noise_get_heavy(void (*func) (void *, int))
  21. {
  22. HANDLE srch;
  23. WIN32_FIND_DATA finddata;
  24. DWORD pid;
  25. HCRYPTPROV crypt_provider;
  26. char winpath[MAX_PATH + 3];
  27. GetWindowsDirectory(winpath, sizeof(winpath));
  28. strcat(winpath, "\\*");
  29. srch = FindFirstFile(winpath, &finddata);
  30. if (srch != INVALID_HANDLE_VALUE) {
  31. do {
  32. func(&finddata, sizeof(finddata));
  33. } while (FindNextFile(srch, &finddata));
  34. FindClose(srch);
  35. }
  36. pid = GetCurrentProcessId();
  37. func(&pid, sizeof(pid));
  38. if (!wincrypt_module) {
  39. wincrypt_module = load_system32_dll("advapi32.dll");
  40. GET_WINDOWS_FUNCTION(wincrypt_module, CryptAcquireContextA);
  41. GET_WINDOWS_FUNCTION(wincrypt_module, CryptGenRandom);
  42. GET_WINDOWS_FUNCTION(wincrypt_module, CryptReleaseContext);
  43. }
  44. if (wincrypt_module && p_CryptAcquireContextA &&
  45. p_CryptGenRandom && p_CryptReleaseContext &&
  46. p_CryptAcquireContextA(&crypt_provider, NULL, NULL, PROV_RSA_FULL,
  47. CRYPT_VERIFYCONTEXT)) {
  48. BYTE buf[32];
  49. if (p_CryptGenRandom(crypt_provider, 32, buf)) {
  50. func(buf, sizeof(buf));
  51. }
  52. p_CryptReleaseContext(crypt_provider, 0);
  53. }
  54. read_random_seed(func);
  55. /* Update the seed immediately, in case another instance uses it. */
  56. random_save_seed();
  57. }
  58. void random_save_seed(void)
  59. {
  60. int len;
  61. void *data;
  62. if (random_active) {
  63. random_get_savedata(&data, &len);
  64. write_random_seed(data, len);
  65. sfree(data);
  66. }
  67. }
  68. /*
  69. * This function is called every time the random pool needs
  70. * stirring, and will acquire the system time in all available
  71. * forms.
  72. */
  73. void noise_get_light(void (*func) (void *, int))
  74. {
  75. SYSTEMTIME systime;
  76. DWORD adjust[2];
  77. BOOL rubbish;
  78. GetSystemTime(&systime);
  79. func(&systime, sizeof(systime));
  80. GetSystemTimeAdjustment(&adjust[0], &adjust[1], &rubbish);
  81. func(&adjust, sizeof(adjust));
  82. }
  83. /*
  84. * This function is called on a timer, and it will monitor
  85. * frequently changing quantities such as the state of physical and
  86. * virtual memory, the state of the process's message queue, which
  87. * window is in the foreground, which owns the clipboard, etc.
  88. */
  89. void noise_regular(void)
  90. {
  91. HWND w;
  92. DWORD z;
  93. POINT pt;
  94. MEMORYSTATUS memstat;
  95. FILETIME times[4];
  96. MPEXT_PUTTY_SECTION_ENTER;
  97. w = GetForegroundWindow();
  98. random_add_noise(&w, sizeof(w));
  99. w = GetCapture();
  100. random_add_noise(&w, sizeof(w));
  101. w = GetClipboardOwner();
  102. random_add_noise(&w, sizeof(w));
  103. z = GetQueueStatus(QS_ALLEVENTS);
  104. random_add_noise(&z, sizeof(z));
  105. GetCursorPos(&pt);
  106. random_add_noise(&pt, sizeof(pt));
  107. GlobalMemoryStatus(&memstat);
  108. random_add_noise(&memstat, sizeof(memstat));
  109. GetThreadTimes(GetCurrentThread(), times, times + 1, times + 2,
  110. times + 3);
  111. random_add_noise(&times, sizeof(times));
  112. GetProcessTimes(GetCurrentProcess(), times, times + 1, times + 2,
  113. times + 3);
  114. random_add_noise(&times, sizeof(times));
  115. MPEXT_PUTTY_SECTION_LEAVE;
  116. }
  117. /*
  118. * This function is called on every keypress or mouse move, and
  119. * will add the current Windows time and performance monitor
  120. * counter to the noise pool. It gets the scan code or mouse
  121. * position passed in.
  122. */
  123. void noise_ultralight(unsigned long data)
  124. {
  125. DWORD wintime;
  126. LARGE_INTEGER perftime;
  127. MPEXT_PUTTY_SECTION_ENTER;
  128. random_add_noise(&data, sizeof(DWORD));
  129. wintime = GetTickCount();
  130. random_add_noise(&wintime, sizeof(DWORD));
  131. if (QueryPerformanceCounter(&perftime))
  132. random_add_noise(&perftime, sizeof(perftime));
  133. MPEXT_PUTTY_SECTION_LEAVE;
  134. }