Bug 466745: random number generator fails on windows ce
patch by Brad Lassey <bugmail@lassey.us>, r=nelson git-svn-id: svn://10.0.0.236/trunk@256030 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
@@ -85,6 +84,10 @@ SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_
|
||||
RES = $(OBJDIR)/$(LIBRARY_NAME).res
|
||||
RESNAME = freebl.rc
|
||||
|
||||
ifndef WINCE
|
||||
OS_LIBS += shell32.lib
|
||||
endif
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(DIST)/lib \
|
||||
|
||||
@@ -36,8 +36,10 @@
|
||||
|
||||
#include "secrng.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
#include "shlobj.h" /* for CSIDL constants */
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
#include <stdlib.h> /* Win CE puts lots of stuff here. */
|
||||
@@ -49,13 +51,6 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#define VTD_Device_ID 5
|
||||
#define OP_OVERRIDE _asm _emit 0x66
|
||||
#include <dos.h>
|
||||
#endif
|
||||
|
||||
#include "prio.h"
|
||||
#include "prerror.h"
|
||||
|
||||
@@ -67,7 +62,6 @@ static DWORD dwNumFiles, dwReadEvery;
|
||||
static BOOL
|
||||
CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER liCount;
|
||||
|
||||
if (!QueryPerformanceCounter(&liCount))
|
||||
@@ -76,57 +70,6 @@ CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow)
|
||||
*lpdwHigh = liCount.u.HighPart;
|
||||
*lpdwLow = liCount.u.LowPart;
|
||||
return TRUE;
|
||||
|
||||
#else /* is WIN16 */
|
||||
BOOL bRetVal;
|
||||
FARPROC lpAPI;
|
||||
WORD w1, w2, w3, w4;
|
||||
|
||||
// Get direct access to the VTD and query the current clock tick time
|
||||
_asm {
|
||||
xor di, di
|
||||
mov es, di
|
||||
mov ax, 1684h
|
||||
mov bx, VTD_Device_ID
|
||||
int 2fh
|
||||
mov ax, es
|
||||
or ax, di
|
||||
jz EnumerateFailed
|
||||
|
||||
; VTD API is available. First store the API address (the address actually
|
||||
; contains an instruction that causes a fault, the fault handler then
|
||||
; makes the ring transition and calls the API in the VxD)
|
||||
mov word ptr lpAPI, di
|
||||
mov word ptr lpAPI+2, es
|
||||
mov ax, 100h ; API function to VTD_Get_Real_Time
|
||||
; call dword ptr [lpAPI]
|
||||
call [lpAPI]
|
||||
|
||||
; Result is in EDX:EAX which we will get 16-bits at a time
|
||||
mov w2, dx
|
||||
OP_OVERRIDE
|
||||
shr dx,10h ; really "shr edx, 16"
|
||||
mov w1, dx
|
||||
|
||||
mov w4, ax
|
||||
OP_OVERRIDE
|
||||
shr ax,10h ; really "shr eax, 16"
|
||||
mov w3, ax
|
||||
|
||||
mov bRetVal, 1 ; return TRUE
|
||||
jmp EnumerateExit
|
||||
|
||||
EnumerateFailed:
|
||||
mov bRetVal, 0 ; return FALSE
|
||||
|
||||
EnumerateExit:
|
||||
}
|
||||
|
||||
*lpdwHigh = MAKELONG(w2, w1);
|
||||
*lpdwLow = MAKELONG(w4, w3);
|
||||
|
||||
return bRetVal;
|
||||
#endif /* is WIN16 */
|
||||
}
|
||||
|
||||
size_t RNG_GetNoise(void *buf, size_t maxbuf)
|
||||
@@ -168,125 +111,78 @@ size_t RNG_GetNoise(void *buf, size_t maxbuf)
|
||||
if (maxbuf <= 0)
|
||||
return n;
|
||||
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
{
|
||||
// get the number of milliseconds elapsed since Windows CE was started.
|
||||
DWORD tickCount = GetTickCount();
|
||||
nBytes = (sizeof tickCount) > maxbuf ? maxbuf : (sizeof tickCount);
|
||||
memcpy(((char *)buf) + n, &tickCount, nBytes);
|
||||
n += nBytes;
|
||||
}
|
||||
FILETIME sTime;
|
||||
SYSTEMTIME st;
|
||||
GetSystemTime(&st);
|
||||
SystemTimeToFileTime(&st,&sTime);
|
||||
#else
|
||||
{
|
||||
time_t sTime;
|
||||
// get the time in seconds since midnight Jan 1, 1970
|
||||
time(&sTime);
|
||||
#endif
|
||||
nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
|
||||
memcpy(((char *)buf) + n, &sTime, nBytes);
|
||||
n += nBytes;
|
||||
}
|
||||
#endif
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
static BOOL
|
||||
EnumSystemFilesWithNSPR(const char * dirName,
|
||||
BOOL recursive,
|
||||
PRInt32 (*func)(const char *))
|
||||
{
|
||||
PRDir * pDir;
|
||||
PRDirEntry * pEntry;
|
||||
BOOL rv = FALSE;
|
||||
|
||||
pDir = PR_OpenDir(dirName);
|
||||
if (!pDir)
|
||||
return rv;
|
||||
while ((pEntry = PR_ReadDir(pDir, PR_SKIP_BOTH|PR_SKIP_HIDDEN)) != NULL) {
|
||||
PRStatus status;
|
||||
PRInt32 count;
|
||||
PRInt32 stop;
|
||||
PRFileInfo fileInfo;
|
||||
char szFileName[_MAX_PATH];
|
||||
|
||||
count = (PRInt32)PR_snprintf(szFileName, sizeof szFileName, "%s\\%s",
|
||||
dirName, PR_DirName(pEntry));
|
||||
if (count < 1)
|
||||
continue;
|
||||
status = PR_GetFileInfo(szFileName, &fileInfo);
|
||||
if (status != PR_SUCCESS)
|
||||
continue;
|
||||
if (fileInfo.type == PR_FILE_FILE) {
|
||||
stop = (*func)(szFileName);
|
||||
rv = TRUE;
|
||||
if (stop)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (recursive && fileInfo.type == PR_FILE_DIRECTORY) {
|
||||
rv |= EnumSystemFilesWithNSPR(szFileName, recursive, func);
|
||||
}
|
||||
}
|
||||
PR_CloseDir(pDir);
|
||||
return rv;
|
||||
static void
|
||||
EnumSystemFilesInFolder(PRInt32 (*func)(const char *), PRUnichar* szSysDir) {
|
||||
int iStatus;
|
||||
PRUnichar szFileName[_MAX_PATH];
|
||||
char narrowFileName[_MAX_PATH];
|
||||
WIN32_FIND_DATAW fdData;
|
||||
HANDLE lFindHandle;
|
||||
// tack *.* on the end so we actually look for files. this will
|
||||
// not overflow
|
||||
wcscpy(szFileName, szSysDir);
|
||||
wcscat(szFileName, L"\\*.*");
|
||||
|
||||
lFindHandle = FindFirstFileW(szFileName, &fdData);
|
||||
if (lFindHandle == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
do {
|
||||
// pass the full pathname to the callback
|
||||
_snwprintf(szFileName,_MAX_PATH, L"%s\\%s", szSysDir, fdData.cFileName);
|
||||
WideCharToMultiByte(CP_ACP, 0, szFileName, -1,
|
||||
narrowFileName,_MAX_PATH,0,0);
|
||||
(*func)(narrowFileName);
|
||||
iStatus = FindNextFileW(lFindHandle, &fdData);
|
||||
} while (iStatus != 0);
|
||||
FindClose(lFindHandle);
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL
|
||||
EnumSystemFiles(PRInt32 (*func)(const char *))
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
BOOL rv = FALSE;
|
||||
rv |= EnumSystemFilesWithNSPR("\\Windows\\Temporary Internet Files", TRUE, func);
|
||||
rv |= EnumSystemFilesWithNSPR("\\Temp", FALSE, func);
|
||||
rv |= EnumSystemFilesWithNSPR("\\Windows", FALSE, func);
|
||||
return rv;
|
||||
#else
|
||||
int iStatus;
|
||||
char szSysDir[_MAX_PATH];
|
||||
char szFileName[_MAX_PATH];
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATA fdData;
|
||||
HANDLE lFindHandle;
|
||||
#else
|
||||
struct _find_t fdData;
|
||||
#endif
|
||||
|
||||
if (!GetSystemDirectory(szSysDir, sizeof(szSysDir)))
|
||||
return FALSE;
|
||||
|
||||
// tack *.* on the end so we actually look for files. this will
|
||||
// not overflow
|
||||
strcpy(szFileName, szSysDir);
|
||||
strcat(szFileName, "\\*.*");
|
||||
|
||||
#ifdef _WIN32
|
||||
lFindHandle = FindFirstFile(szFileName, &fdData);
|
||||
if (lFindHandle == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
do {
|
||||
// pass the full pathname to the callback
|
||||
sprintf(szFileName, "%s\\%s", szSysDir, fdData.cFileName);
|
||||
(*func)(szFileName);
|
||||
iStatus = FindNextFile(lFindHandle, &fdData);
|
||||
} while (iStatus != 0);
|
||||
FindClose(lFindHandle);
|
||||
#else
|
||||
if (_dos_findfirst(szFileName,
|
||||
_A_NORMAL | _A_RDONLY | _A_ARCH | _A_SUBDIR, &fdData) != 0)
|
||||
return FALSE;
|
||||
do {
|
||||
// pass the full pathname to the callback
|
||||
sprintf(szFileName, "%s\\%s", szSysDir, fdData.name);
|
||||
(*func)(szFileName);
|
||||
iStatus = _dos_findnext(&fdData);
|
||||
} while (iStatus == 0);
|
||||
_dos_findclose(&fdData);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
PRUnichar szSysDir[_MAX_PATH];
|
||||
static const int folders[] = {
|
||||
CSIDL_BITBUCKET,
|
||||
CSIDL_RECENT
|
||||
#ifndef WINCE
|
||||
, CSIDL_INTERNET_CACHE,
|
||||
CSIDL_COMPUTERSNEARME,
|
||||
CSIDL_HISTORY
|
||||
#endif
|
||||
};
|
||||
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);
|
||||
}
|
||||
for(i = 0; i < (sizeof(folders)/ sizeof(folders[0])) ; i++) {
|
||||
DWORD rv = SHGetSpecialFolderPathW(NULL,szSysDir,folders[i],0);
|
||||
if (szSysDir[0])
|
||||
EnumSystemFilesInFolder(func, szSysDir);
|
||||
szSysDir[0] = L'\0';
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRInt32
|
||||
@@ -342,7 +238,6 @@ void RNG_SystemInfoForRNG(void)
|
||||
DWORD dwVal;
|
||||
char buffer[256];
|
||||
int nBytes;
|
||||
#ifdef _WIN32
|
||||
MEMORYSTATUS sMem;
|
||||
HANDLE hVal;
|
||||
#if !defined(_WIN32_WCE)
|
||||
@@ -352,17 +247,10 @@ void RNG_SystemInfoForRNG(void)
|
||||
char volName[128];
|
||||
DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters;
|
||||
#endif
|
||||
#else
|
||||
int iVal;
|
||||
HTASK hTask;
|
||||
WORD wDS, wCS;
|
||||
LPSTR lpszEnv;
|
||||
#endif
|
||||
|
||||
nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
|
||||
RNG_RandomUpdate(buffer, nBytes);
|
||||
|
||||
#ifdef _WIN32
|
||||
sMem.dwLength = sizeof(sMem);
|
||||
GlobalMemoryStatus(&sMem); // assorted memory stats
|
||||
RNG_RandomUpdate(&sMem, sizeof(sMem));
|
||||
@@ -370,47 +258,12 @@ void RNG_SystemInfoForRNG(void)
|
||||
dwVal = GetLogicalDrives();
|
||||
RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25
|
||||
#endif
|
||||
#else
|
||||
dwVal = GetFreeSpace(0);
|
||||
RNG_RandomUpdate(&dwVal, sizeof(dwVal));
|
||||
|
||||
_asm mov wDS, ds;
|
||||
_asm mov wCS, cs;
|
||||
RNG_RandomUpdate(&wDS, sizeof(wDS));
|
||||
RNG_RandomUpdate(&wCS, sizeof(wCS));
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if !defined(_WIN32_WCE)
|
||||
dwVal = sizeof(buffer);
|
||||
if (GetComputerName(buffer, &dwVal))
|
||||
RNG_RandomUpdate(buffer, dwVal);
|
||||
#endif
|
||||
/* XXX This is code that got yanked because of NSPR20. We should put it
|
||||
* back someday.
|
||||
*/
|
||||
#ifdef notdef
|
||||
{
|
||||
POINT ptVal;
|
||||
GetCursorPos(&ptVal);
|
||||
RNG_RandomUpdate(&ptVal, sizeof(ptVal));
|
||||
}
|
||||
|
||||
dwVal = GetQueueStatus(QS_ALLINPUT); // high and low significant
|
||||
RNG_RandomUpdate(&dwVal, sizeof(dwVal));
|
||||
|
||||
{
|
||||
HWND hWnd;
|
||||
hWnd = GetClipboardOwner(); // 2 or 4 bytes
|
||||
RNG_RandomUpdate((void *)&hWnd, sizeof(hWnd));
|
||||
}
|
||||
|
||||
{
|
||||
UUID sUuid;
|
||||
UuidCreate(&sUuid); // this will fail on machines with no ethernet
|
||||
RNG_RandomUpdate(&sUuid, sizeof(sUuid)); // boards. shove the bits in regardless
|
||||
}
|
||||
#endif
|
||||
|
||||
hVal = GetCurrentProcess(); // 4 or 8 byte pseudo handle (a
|
||||
// constant!) of current process
|
||||
@@ -440,27 +293,14 @@ void RNG_SystemInfoForRNG(void)
|
||||
RNG_RandomUpdate(&dwSysFlags, sizeof(dwSysFlags));
|
||||
RNG_RandomUpdate(buffer, strlen(buffer));
|
||||
|
||||
if (GetDiskFreeSpace(NULL, &dwSectors, &dwBytes, &dwFreeClusters, &dwNumClusters)) {
|
||||
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));
|
||||
}
|
||||
#endif
|
||||
#else /* is WIN16 */
|
||||
hTask = GetCurrentTask();
|
||||
RNG_RandomUpdate((void *)&hTask, sizeof(hTask));
|
||||
|
||||
iVal = GetNumTasks();
|
||||
RNG_RandomUpdate(&iVal, sizeof(iVal)); // number of running tasks
|
||||
|
||||
lpszEnv = GetDOSEnvironment();
|
||||
while (*lpszEnv != '\0') {
|
||||
RNG_RandomUpdate(lpszEnv, strlen(lpszEnv));
|
||||
|
||||
lpszEnv += strlen(lpszEnv) + 1;
|
||||
}
|
||||
#endif /* is WIN16 */
|
||||
|
||||
// now let's do some files
|
||||
ReadSystemFiles();
|
||||
@@ -508,6 +348,19 @@ void RNG_FileForRNG(const char *filename)
|
||||
RNG_RandomUpdate(buffer, nBytes);
|
||||
}
|
||||
|
||||
size_t RNG_SystemRNG(void *dest, size_t maxLen)
|
||||
{
|
||||
size_t bytes = 0;
|
||||
if (CeGenRandom(maxLen, dest)) {
|
||||
bytes = maxLen;
|
||||
}
|
||||
if (bytes == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM); /* system RNG failed */
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
#else /* not WinCE */
|
||||
|
||||
void RNG_FileForRNG(const char *filename)
|
||||
@@ -550,8 +403,6 @@ void RNG_FileForRNG(const char *filename)
|
||||
RNG_RandomUpdate(buffer, nBytes);
|
||||
}
|
||||
|
||||
#endif /* not WinCE */
|
||||
|
||||
/*
|
||||
* CryptoAPI requires Windows NT 4.0 or Windows 95 OSR2 and later.
|
||||
* Until we drop support for Windows 95, we need to emulate some
|
||||
@@ -644,5 +495,6 @@ done:
|
||||
FreeLibrary(hModule);
|
||||
return bytes;
|
||||
}
|
||||
#endif /* not WinCE */
|
||||
|
||||
#endif /* is XP_WIN */
|
||||
|
||||
Reference in New Issue
Block a user