winnoise.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. bool win_read_random(void *buf, unsigned wanted)
  18. {
  19. bool toret = false;
  20. HCRYPTPROV crypt_provider;
  21. if (!wincrypt_module) {
  22. wincrypt_module = load_system32_dll("advapi32.dll");
  23. GET_WINDOWS_FUNCTION(wincrypt_module, CryptAcquireContextA);
  24. GET_WINDOWS_FUNCTION(wincrypt_module, CryptGenRandom);
  25. GET_WINDOWS_FUNCTION(wincrypt_module, CryptReleaseContext);
  26. }
  27. if (wincrypt_module && p_CryptAcquireContextA &&
  28. p_CryptGenRandom && p_CryptReleaseContext &&
  29. p_CryptAcquireContextA(&crypt_provider, NULL, NULL, PROV_RSA_FULL,
  30. CRYPT_VERIFYCONTEXT)) {
  31. toret = p_CryptGenRandom(crypt_provider, wanted, buf);
  32. p_CryptReleaseContext(crypt_provider, 0);
  33. }
  34. return toret;
  35. }
  36. /*
  37. * This function is called once, at PuTTY startup.
  38. */
  39. void noise_get_heavy(void (*func) (void *, int))
  40. {
  41. HANDLE srch;
  42. WIN32_FIND_DATA finddata;
  43. DWORD pid;
  44. char winpath[MAX_PATH + 3];
  45. BYTE buf[32];
  46. GetWindowsDirectory(winpath, sizeof(winpath));
  47. strcat(winpath, "\\*");
  48. srch = FindFirstFile(winpath, &finddata);
  49. if (srch != INVALID_HANDLE_VALUE) {
  50. do {
  51. func(&finddata, sizeof(finddata));
  52. } while (FindNextFile(srch, &finddata));
  53. FindClose(srch);
  54. }
  55. pid = GetCurrentProcessId();
  56. func(&pid, sizeof(pid));
  57. if (win_read_random(buf, sizeof(buf))) {
  58. func(buf, sizeof(buf));
  59. smemclr(buf, sizeof(buf));
  60. }
  61. read_random_seed(func);
  62. }
  63. void random_save_seed(void)
  64. {
  65. int len;
  66. void *data;
  67. if (random_active) {
  68. random_get_savedata(&data, &len);
  69. write_random_seed(data, len);
  70. sfree(data);
  71. }
  72. }
  73. /*
  74. * This function is called on a timer, and it will monitor
  75. * frequently changing quantities such as the state of physical and
  76. * virtual memory, the state of the process's message queue, which
  77. * window is in the foreground, which owns the clipboard, etc.
  78. */
  79. void noise_regular(void)
  80. {
  81. HWND w;
  82. DWORD z;
  83. POINT pt;
  84. MEMORYSTATUS memstat;
  85. FILETIME times[4];
  86. w = GetForegroundWindow();
  87. random_add_noise(NOISE_SOURCE_FGWINDOW, &w, sizeof(w));
  88. w = GetCapture();
  89. random_add_noise(NOISE_SOURCE_CAPTURE, &w, sizeof(w));
  90. w = GetClipboardOwner();
  91. random_add_noise(NOISE_SOURCE_CLIPBOARD, &w, sizeof(w));
  92. z = GetQueueStatus(QS_ALLEVENTS);
  93. random_add_noise(NOISE_SOURCE_QUEUE, &z, sizeof(z));
  94. GetCursorPos(&pt);
  95. random_add_noise(NOISE_SOURCE_CURSORPOS, &pt, sizeof(pt));
  96. GlobalMemoryStatus(&memstat);
  97. random_add_noise(NOISE_SOURCE_MEMINFO, &memstat, sizeof(memstat));
  98. GetThreadTimes(GetCurrentThread(), times, times + 1, times + 2,
  99. times + 3);
  100. random_add_noise(NOISE_SOURCE_THREADTIME, &times, sizeof(times));
  101. GetProcessTimes(GetCurrentProcess(), times, times + 1, times + 2,
  102. times + 3);
  103. random_add_noise(NOISE_SOURCE_PROCTIME, &times, sizeof(times));
  104. }
  105. /*
  106. * This function is called on every keypress or mouse move, and
  107. * will add the current Windows time and performance monitor
  108. * counter to the noise pool. It gets the scan code or mouse
  109. * position passed in.
  110. */
  111. void noise_ultralight(NoiseSourceId id, unsigned long data)
  112. {
  113. DWORD wintime;
  114. LARGE_INTEGER perftime;
  115. random_add_noise(id, &data, sizeof(DWORD));
  116. wintime = GetTickCount();
  117. random_add_noise(NOISE_SOURCE_TIME, &wintime, sizeof(DWORD));
  118. if (QueryPerformanceCounter(&perftime))
  119. random_add_noise(NOISE_SOURCE_PERFCOUNT, &perftime, sizeof(perftime));
  120. }
  121. uint64_t prng_reseed_time_ms(void)
  122. {
  123. FILETIME ft;
  124. GetSystemTimeAsFileTime(&ft);
  125. { // WINSCP
  126. uint64_t value = ft.dwHighDateTime;
  127. value = (value << 32) + ft.dwLowDateTime;
  128. return value / 10000; /* 1 millisecond / 100ns */
  129. } // WINSCP
  130. }