| Index: mozilla/security/nss/lib/freebl/win_rand.c
|
| ===================================================================
|
| --- mozilla/security/nss/lib/freebl/win_rand.c (revision 191424)
|
| +++ mozilla/security/nss/lib/freebl/win_rand.c (working copy)
|
| @@ -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 */
|
|
|