diff options
Diffstat (limited to 'security/nss/lib/freebl/win_rand.c')
-rw-r--r-- | security/nss/lib/freebl/win_rand.c | 463 |
1 files changed, 0 insertions, 463 deletions
diff --git a/security/nss/lib/freebl/win_rand.c b/security/nss/lib/freebl/win_rand.c deleted file mode 100644 index 0100ac446..000000000 --- a/security/nss/lib/freebl/win_rand.c +++ /dev/null @@ -1,463 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "secrng.h" -#include "secerr.h" - -#ifdef XP_WIN -#include <windows.h> -#include <shlobj.h> /* for CSIDL constants */ -#include <time.h> -#include <io.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <stdio.h> -#include "prio.h" -#include "prerror.h" - -static PRInt32 filesToRead; -static DWORD totalFileBytes; -static DWORD maxFileBytes = 250000; /* 250 thousand */ -static DWORD dwNumFiles, dwReadEvery, dwFileToRead; -static PRBool usedWindowsPRNG; - -static BOOL -CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow) -{ - LARGE_INTEGER liCount; - - if (!QueryPerformanceCounter(&liCount)) - return FALSE; - - *lpdwHigh = liCount.u.HighPart; - *lpdwLow = liCount.u.LowPart; - return TRUE; -} - -size_t RNG_GetNoise(void *buf, size_t maxbuf) -{ - DWORD dwHigh, dwLow, dwVal; - int n = 0; - int nBytes; - time_t sTime; - - if (maxbuf <= 0) - return 0; - - CurrentClockTickTime(&dwHigh, &dwLow); - - // get the maximally changing bits first - nBytes = sizeof(dwLow) > maxbuf ? maxbuf : sizeof(dwLow); - memcpy((char *)buf, &dwLow, nBytes); - n += nBytes; - maxbuf -= nBytes; - - if (maxbuf <= 0) - return n; - - nBytes = sizeof(dwHigh) > maxbuf ? maxbuf : sizeof(dwHigh); - memcpy(((char *)buf) + n, &dwHigh, nBytes); - n += nBytes; - maxbuf -= nBytes; - - if (maxbuf <= 0) - return n; - - // get the number of milliseconds that have elapsed since Windows started - dwVal = GetTickCount(); - - nBytes = sizeof(dwVal) > maxbuf ? maxbuf : sizeof(dwVal); - memcpy(((char *)buf) + n, &dwVal, nBytes); - n += nBytes; - maxbuf -= nBytes; - - if (maxbuf <= 0) - return n; - - // get the time in seconds since midnight Jan 1, 1970 - time(&sTime); - nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime); - memcpy(((char *)buf) + n, &sTime, nBytes); - n += nBytes; - - return n; -} - -typedef PRInt32 (* Handler)(const PRUnichar *); -#define MAX_DEPTH 2 -#define MAX_FOLDERS 4 -#define MAX_FILES 1024 - -static void -EnumSystemFilesInFolder(Handler func, PRUnichar* szSysDir, int maxDepth) -{ - int iContinue; - unsigned int uFolders = 0; - unsigned int uFiles = 0; - HANDLE lFindHandle; - WIN32_FIND_DATAW fdData; - PRUnichar szFileName[_MAX_PATH]; - - if (maxDepth < 0) - return; - // append *.* so we actually look for files. - _snwprintf(szFileName, _MAX_PATH, L"%s\\*.*", szSysDir); - szFileName[_MAX_PATH - 1] = L'\0'; - - lFindHandle = FindFirstFileW(szFileName, &fdData); - if (lFindHandle == INVALID_HANDLE_VALUE) - return; - do { - iContinue = 1; - if (wcscmp(fdData.cFileName, L".") == 0 || - wcscmp(fdData.cFileName, L"..") == 0) { - // skip "." and ".." - } else { - // pass the full pathname to the callback - _snwprintf(szFileName, _MAX_PATH, L"%s\\%s", szSysDir, - fdData.cFileName); - szFileName[_MAX_PATH - 1] = L'\0'; - if (fdData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (++uFolders <= MAX_FOLDERS) - EnumSystemFilesInFolder(func, szFileName, maxDepth - 1); - } else { - iContinue = (++uFiles <= MAX_FILES) && !(*func)(szFileName); - } - } - if (iContinue) - iContinue = FindNextFileW(lFindHandle, &fdData); - } while (iContinue); - FindClose(lFindHandle); -} - -static BOOL -EnumSystemFiles(Handler func) -{ - PRUnichar szSysDir[_MAX_PATH]; - static const int folders[] = { - CSIDL_BITBUCKET, - CSIDL_RECENT, - CSIDL_INTERNET_CACHE, - CSIDL_HISTORY, - 0 - }; - int i = 0; - if (_MAX_PATH > (i = GetTempPathW(_MAX_PATH, szSysDir))) { - if (i > 0 && szSysDir[i-1] == L'\\') - szSysDir[i-1] = L'\0'; // we need to lop off the trailing slash - EnumSystemFilesInFolder(func, szSysDir, MAX_DEPTH); - } - for(i = 0; folders[i]; i++) { - DWORD rv = SHGetSpecialFolderPathW(NULL, szSysDir, folders[i], 0); - if (szSysDir[0]) - EnumSystemFilesInFolder(func, szSysDir, MAX_DEPTH); - szSysDir[0] = L'\0'; - } - return PR_TRUE; -} - -static PRInt32 -CountFiles(const PRUnichar *file) -{ - dwNumFiles++; - return 0; -} - -static int -ReadSingleFile(const char *filename) -{ - PRFileDesc * file; - unsigned char buffer[1024]; - - file = PR_Open(filename, PR_RDONLY, 0); - if (file != NULL) { - while (PR_Read(file, buffer, sizeof buffer) > 0) - ; - PR_Close(file); - } - return (file != NULL); -} - -static PRInt32 -ReadOneFile(const PRUnichar *szFileName) -{ - char narrowFileName[_MAX_PATH]; - - if (dwNumFiles == dwFileToRead) { - int success = WideCharToMultiByte(CP_ACP, 0, szFileName, -1, - narrowFileName, _MAX_PATH, - NULL, NULL); - if (success) - success = ReadSingleFile(narrowFileName); - if (!success) - dwFileToRead++; /* couldn't read this one, read the next one. */ - } - dwNumFiles++; - return dwNumFiles > dwFileToRead; -} - -static PRInt32 -ReadFiles(const PRUnichar *szFileName) -{ - char narrowFileName[_MAX_PATH]; - - if ((dwNumFiles % dwReadEvery) == 0) { - ++filesToRead; - } - if (filesToRead) { - DWORD prevFileBytes = totalFileBytes; - int iContinue = WideCharToMultiByte(CP_ACP, 0, szFileName, -1, - narrowFileName, _MAX_PATH, - NULL, NULL); - if (iContinue) { - RNG_FileForRNG(narrowFileName); - } - if (prevFileBytes < totalFileBytes) { - --filesToRead; - } - } - dwNumFiles++; - return (totalFileBytes >= maxFileBytes); -} - -static void -ReadSystemFiles(void) -{ - // first count the number of files - dwNumFiles = 0; - if (!EnumSystemFiles(CountFiles)) - return; - - RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles)); - - // now read the first 10 readable files, then 10 or 11 files - // spread throughout the system directory - filesToRead = 10; - if (dwNumFiles == 0) - return; - - dwReadEvery = dwNumFiles / 10; - if (dwReadEvery == 0) - dwReadEvery = 1; // less than 10 files - - dwNumFiles = 0; - totalFileBytes = 0; - EnumSystemFiles(ReadFiles); -} - -void RNG_SystemInfoForRNG(void) -{ - DWORD dwVal; - char buffer[256]; - int nBytes; - MEMORYSTATUS sMem; - HANDLE hVal; - DWORD dwSerialNum; - DWORD dwComponentLen; - DWORD dwSysFlags; - char volName[128]; - DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters; - - nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes - RNG_RandomUpdate(buffer, nBytes); - - sMem.dwLength = sizeof(sMem); - GlobalMemoryStatus(&sMem); // assorted memory stats - RNG_RandomUpdate(&sMem, sizeof(sMem)); - - dwVal = GetLogicalDrives(); - RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25 - - dwVal = sizeof(buffer); - if (GetComputerName(buffer, &dwVal)) - RNG_RandomUpdate(buffer, dwVal); - - hVal = GetCurrentProcess(); // 4 or 8 byte pseudo handle (a - // constant!) of current process - RNG_RandomUpdate(&hVal, sizeof(hVal)); - - dwVal = GetCurrentProcessId(); // process ID (4 bytes) - RNG_RandomUpdate(&dwVal, sizeof(dwVal)); - - dwVal = GetCurrentThreadId(); // thread ID (4 bytes) - RNG_RandomUpdate(&dwVal, sizeof(dwVal)); - - volName[0] = '\0'; - buffer[0] = '\0'; - GetVolumeInformation(NULL, - volName, - sizeof(volName), - &dwSerialNum, - &dwComponentLen, - &dwSysFlags, - buffer, - sizeof(buffer)); - - RNG_RandomUpdate(volName, strlen(volName)); - RNG_RandomUpdate(&dwSerialNum, sizeof(dwSerialNum)); - RNG_RandomUpdate(&dwComponentLen, sizeof(dwComponentLen)); - RNG_RandomUpdate(&dwSysFlags, sizeof(dwSysFlags)); - RNG_RandomUpdate(buffer, strlen(buffer)); - - if (GetDiskFreeSpace(NULL, &dwSectors, &dwBytes, &dwFreeClusters, - &dwNumClusters)) { - RNG_RandomUpdate(&dwSectors, sizeof(dwSectors)); - RNG_RandomUpdate(&dwBytes, sizeof(dwBytes)); - RNG_RandomUpdate(&dwFreeClusters, sizeof(dwFreeClusters)); - RNG_RandomUpdate(&dwNumClusters, sizeof(dwNumClusters)); - } - - // Skip the potentially slow file scanning if the OS's PRNG worked. - if (!usedWindowsPRNG) - ReadSystemFiles(); - - nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes - RNG_RandomUpdate(buffer, nBytes); -} - -static void rng_systemJitter(void) -{ - dwNumFiles = 0; - EnumSystemFiles(ReadOneFile); - dwFileToRead++; - if (dwFileToRead >= dwNumFiles) { - dwFileToRead = 0; - } -} - - -void RNG_FileForRNG(const char *filename) -{ - FILE* file; - int nBytes; - struct stat stat_buf; - unsigned char buffer[1024]; - - /* windows doesn't initialize all the bytes in the stat buf, - * so initialize them all here to avoid UMRs. - */ - memset(&stat_buf, 0, sizeof stat_buf); - - if (stat((char *)filename, &stat_buf) < 0) - return; - - RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf)); - - file = fopen((char *)filename, "r"); - if (file != NULL) { - for (;;) { - size_t bytes = fread(buffer, 1, sizeof(buffer), file); - - if (bytes == 0) - break; - - RNG_RandomUpdate(buffer, bytes); - totalFileBytes += bytes; - if (totalFileBytes > maxFileBytes) - break; - } - - fclose(file); - } - - nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes - RNG_RandomUpdate(buffer, nBytes); -} - - -/* - * CryptoAPI requires Windows NT 4.0 or Windows 95 OSR2 and later. - * Until we drop support for Windows 95, we need to emulate some - * definitions and declarations in <wincrypt.h> and look up the - * functions in advapi32.dll at run time. - */ - -#ifndef WIN64 -typedef unsigned long HCRYPTPROV; -#endif - -#define CRYPT_VERIFYCONTEXT 0xF0000000 - -#define PROV_RSA_FULL 1 - -typedef BOOL -(WINAPI *CryptAcquireContextAFn)( - HCRYPTPROV *phProv, - LPCSTR pszContainer, - LPCSTR pszProvider, - DWORD dwProvType, - DWORD dwFlags); - -typedef BOOL -(WINAPI *CryptReleaseContextFn)( - HCRYPTPROV hProv, - DWORD dwFlags); - -typedef BOOL -(WINAPI *CryptGenRandomFn)( - HCRYPTPROV hProv, - DWORD dwLen, - BYTE *pbBuffer); - -/* - * Windows XP and Windows Server 2003 and later have RtlGenRandom, - * which must be looked up by the name SystemFunction036. - */ -typedef BOOLEAN -(APIENTRY *RtlGenRandomFn)( - PVOID RandomBuffer, - ULONG RandomBufferLength); - -size_t RNG_SystemRNG(void *dest, size_t maxLen) -{ - HMODULE hModule; - RtlGenRandomFn pRtlGenRandom; - CryptAcquireContextAFn pCryptAcquireContextA; - CryptReleaseContextFn pCryptReleaseContext; - CryptGenRandomFn pCryptGenRandom; - HCRYPTPROV hCryptProv; - size_t bytes = 0; - - usedWindowsPRNG = PR_FALSE; - hModule = LoadLibrary("advapi32.dll"); - if (hModule == NULL) { - return rng_systemFromNoise(dest,maxLen); - } - pRtlGenRandom = (RtlGenRandomFn) - GetProcAddress(hModule, "SystemFunction036"); - if (pRtlGenRandom) { - if (pRtlGenRandom(dest, maxLen)) { - bytes = maxLen; - usedWindowsPRNG = PR_TRUE; - } else { - bytes = rng_systemFromNoise(dest,maxLen); - } - goto done; - } - pCryptAcquireContextA = (CryptAcquireContextAFn) - GetProcAddress(hModule, "CryptAcquireContextA"); - pCryptReleaseContext = (CryptReleaseContextFn) - GetProcAddress(hModule, "CryptReleaseContext"); - pCryptGenRandom = (CryptGenRandomFn) - GetProcAddress(hModule, "CryptGenRandom"); - if (!pCryptAcquireContextA || !pCryptReleaseContext || !pCryptGenRandom) { - bytes = rng_systemFromNoise(dest,maxLen); - goto done; - } - if (pCryptAcquireContextA(&hCryptProv, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - if (pCryptGenRandom(hCryptProv, maxLen, dest)) { - bytes = maxLen; - usedWindowsPRNG = PR_TRUE; - } - pCryptReleaseContext(hCryptProv, 0); - } - if (bytes == 0) { - bytes = rng_systemFromNoise(dest,maxLen); - } -done: - FreeLibrary(hModule); - return bytes; -} -#endif /* is XP_WIN */ |