/* * Noise generation for PuTTY's cryptographic random number * generator. */ #include <stdio.h> #include "putty.h" #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. */ 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)); strcat(winpath, "\\*"); srch = FindFirstFile(winpath, &finddata); if (srch != INVALID_HANDLE_VALUE) { do { func(&finddata, sizeof(finddata)); } while (FindNextFile(srch, &finddata)); 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(); } void random_save_seed(void) { int len; void *data; if (random_active) { random_get_savedata(&data, &len); write_random_seed(data, len); sfree(data); } } /* * This function is called every time the random pool needs * stirring, and will acquire the system time in all available * forms. */ void noise_get_light(void (*func) (void *, int)) { SYSTEMTIME systime; DWORD adjust[2]; BOOL rubbish; GetSystemTime(&systime); func(&systime, sizeof(systime)); GetSystemTimeAdjustment(&adjust[0], &adjust[1], &rubbish); func(&adjust, sizeof(adjust)); } /* * This function is called on a timer, and it will monitor * frequently changing quantities such as the state of physical and * virtual memory, the state of the process's message queue, which * window is in the foreground, which owns the clipboard, etc. */ void noise_regular(void) { HWND w; DWORD z; POINT pt; MEMORYSTATUS memstat; FILETIME times[4]; w = GetForegroundWindow(); random_add_noise(&w, sizeof(w)); w = GetCapture(); random_add_noise(&w, sizeof(w)); w = GetClipboardOwner(); random_add_noise(&w, sizeof(w)); z = GetQueueStatus(QS_ALLEVENTS); random_add_noise(&z, sizeof(z)); GetCursorPos(&pt); random_add_noise(&pt, sizeof(pt)); GlobalMemoryStatus(&memstat); random_add_noise(&memstat, sizeof(memstat)); GetThreadTimes(GetCurrentThread(), times, times + 1, times + 2, times + 3); random_add_noise(×, sizeof(times)); GetProcessTimes(GetCurrentProcess(), times, times + 1, times + 2, times + 3); random_add_noise(×, sizeof(times)); } /* * This function is called on every keypress or mouse move, and * will add the current Windows time and performance monitor * counter to the noise pool. It gets the scan code or mouse * position passed in. */ void noise_ultralight(unsigned long data) { DWORD wintime; LARGE_INTEGER perftime; random_add_noise(&data, sizeof(DWORD)); wintime = GetTickCount(); random_add_noise(&wintime, sizeof(DWORD)); if (QueryPerformanceCounter(&perftime)) random_add_noise(&perftime, sizeof(perftime)); }