| Index: nss/lib/freebl/win_rand.c
|
| ===================================================================
|
| --- nss/lib/freebl/win_rand.c (revision 256695)
|
| +++ nss/lib/freebl/win_rand.c (working copy)
|
| @@ -3,25 +3,11 @@
|
| * 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)
|
| {
|
| @@ -84,168 +70,6 @@
|
| 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;
|
| @@ -308,91 +132,28 @@
|
| 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);
|
| -}
|
| -
|
| -
|
| /*
|
| - * Windows XP and Windows Server 2003 and later have RtlGenRandom,
|
| - * which must be looked up by the name SystemFunction036.
|
| + * The RtlGenRandom function is declared in <ntsecapi.h>, but the
|
| + * declaration is missing a calling convention specifier. So we
|
| + * declare it manually here.
|
| */
|
| -typedef BOOLEAN
|
| -(APIENTRY *RtlGenRandomFn)(
|
| +#define RtlGenRandom SystemFunction036
|
| +DECLSPEC_IMPORT BOOLEAN WINAPI RtlGenRandom(
|
| PVOID RandomBuffer,
|
| ULONG RandomBufferLength);
|
|
|
| size_t RNG_SystemRNG(void *dest, size_t maxLen)
|
| {
|
| - HMODULE hModule;
|
| - RtlGenRandomFn pRtlGenRandom;
|
| size_t bytes = 0;
|
|
|
| - usedWindowsPRNG = PR_FALSE;
|
| - hModule = LoadLibrary("advapi32.dll");
|
| - if (hModule == NULL) {
|
| - return bytes;
|
| - }
|
| - pRtlGenRandom = (RtlGenRandomFn)
|
| - GetProcAddress(hModule, "SystemFunction036");
|
| - if (pRtlGenRandom && pRtlGenRandom(dest, maxLen)) {
|
| + if (RtlGenRandom(dest, maxLen)) {
|
| bytes = maxLen;
|
| - usedWindowsPRNG = PR_TRUE;
|
| }
|
| - FreeLibrary(hModule);
|
| return bytes;
|
| }
|
| #endif /* is XP_WIN */
|
|
|