1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the MPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the MPL, the GPL or the LGPL.
35
* ***** END LICENSE BLOCK ***** */
42
#if defined(_WIN32_WCE)
43
#include <stdlib.h> /* Win CE puts lots of stuff here. */
44
#include "prprf.h" /* for PR_snprintf */
48
#include <sys/types.h>
54
#define VTD_Device_ID 5
55
#define OP_OVERRIDE _asm _emit 0x66
62
static PRInt32 filesToRead;
63
static DWORD totalFileBytes;
64
static DWORD maxFileBytes = 250000; /* 250 thousand */
65
static DWORD dwNumFiles, dwReadEvery;
68
CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow)
71
LARGE_INTEGER liCount;
73
if (!QueryPerformanceCounter(&liCount))
76
*lpdwHigh = liCount.u.HighPart;
77
*lpdwLow = liCount.u.LowPart;
85
// Get direct access to the VTD and query the current clock tick time
96
; VTD API is available. First store the API address (the address actually
97
; contains an instruction that causes a fault, the fault handler then
98
; makes the ring transition and calls the API in the VxD)
99
mov word ptr lpAPI, di
100
mov word ptr lpAPI+2, es
101
mov ax, 100h ; API function to VTD_Get_Real_Time
102
; call dword ptr [lpAPI]
105
; Result is in EDX:EAX which we will get 16-bits at a time
108
shr dx,10h ; really "shr edx, 16"
113
shr ax,10h ; really "shr eax, 16"
116
mov bRetVal, 1 ; return TRUE
120
mov bRetVal, 0 ; return FALSE
125
*lpdwHigh = MAKELONG(w2, w1);
126
*lpdwLow = MAKELONG(w4, w3);
129
#endif /* is WIN16 */
132
size_t RNG_GetNoise(void *buf, size_t maxbuf)
134
DWORD dwHigh, dwLow, dwVal;
141
CurrentClockTickTime(&dwHigh, &dwLow);
143
// get the maximally changing bits first
144
nBytes = sizeof(dwLow) > maxbuf ? maxbuf : sizeof(dwLow);
145
memcpy((char *)buf, &dwLow, nBytes);
152
nBytes = sizeof(dwHigh) > maxbuf ? maxbuf : sizeof(dwHigh);
153
memcpy(((char *)buf) + n, &dwHigh, nBytes);
160
// get the number of milliseconds that have elapsed since Windows started
161
dwVal = GetTickCount();
163
nBytes = sizeof(dwVal) > maxbuf ? maxbuf : sizeof(dwVal);
164
memcpy(((char *)buf) + n, &dwVal, nBytes);
171
#if defined(_WIN32_WCE)
173
// get the number of milliseconds elapsed since Windows CE was started.
174
DWORD tickCount = GetTickCount();
175
nBytes = (sizeof tickCount) > maxbuf ? maxbuf : (sizeof tickCount);
176
memcpy(((char *)buf) + n, &tickCount, nBytes);
182
// get the time in seconds since midnight Jan 1, 1970
184
nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
185
memcpy(((char *)buf) + n, &sTime, nBytes);
193
#if defined(_WIN32_WCE)
195
EnumSystemFilesWithNSPR(const char * dirName,
197
PRInt32 (*func)(const char *))
203
pDir = PR_OpenDir(dirName);
206
while ((pEntry = PR_ReadDir(pDir, PR_SKIP_BOTH|PR_SKIP_HIDDEN)) != NULL) {
211
char szFileName[_MAX_PATH];
213
count = (PRInt32)PR_snprintf(szFileName, sizeof szFileName, "%s\\%s",
214
dirName, PR_DirName(pEntry));
217
status = PR_GetFileInfo(szFileName, &fileInfo);
218
if (status != PR_SUCCESS)
220
if (fileInfo.type == PR_FILE_FILE) {
221
stop = (*func)(szFileName);
227
if (recursive && fileInfo.type == PR_FILE_DIRECTORY) {
228
rv |= EnumSystemFilesWithNSPR(szFileName, recursive, func);
237
EnumSystemFiles(PRInt32 (*func)(const char *))
239
#if defined(_WIN32_WCE)
241
rv |= EnumSystemFilesWithNSPR("\\Windows\\Temporary Internet Files", TRUE, func);
242
rv |= EnumSystemFilesWithNSPR("\\Temp", FALSE, func);
243
rv |= EnumSystemFilesWithNSPR("\\Windows", FALSE, func);
247
char szSysDir[_MAX_PATH];
248
char szFileName[_MAX_PATH];
250
struct _finddata_t fdData;
253
struct _find_t fdData;
256
if (!GetSystemDirectory(szSysDir, sizeof(szSysDir)))
259
// tack *.* on the end so we actually look for files. this will
261
strcpy(szFileName, szSysDir);
262
strcat(szFileName, "\\*.*");
265
lFindHandle = _findfirst(szFileName, &fdData);
266
if (lFindHandle == -1)
269
if (_dos_findfirst(szFileName, _A_NORMAL | _A_RDONLY | _A_ARCH | _A_SUBDIR, &fdData) != 0)
274
// pass the full pathname to the callback
275
sprintf(szFileName, "%s\\%s", szSysDir, fdData.name);
279
iStatus = _findnext(lFindHandle, &fdData);
281
iStatus = _dos_findnext(&fdData);
283
} while (iStatus == 0);
286
_findclose(lFindHandle);
294
CountFiles(const char *file)
301
ReadFiles(const char *file)
303
if ((dwNumFiles % dwReadEvery) == 0) {
307
DWORD prevFileBytes = totalFileBytes;
308
RNG_FileForRNG(file);
309
if (prevFileBytes < totalFileBytes) {
314
return (totalFileBytes >= maxFileBytes);
320
// first count the number of files
322
if (!EnumSystemFiles(CountFiles))
325
RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles));
332
dwReadEvery = dwNumFiles / 10;
333
if (dwReadEvery == 0)
334
dwReadEvery = 1; // less than 10 files
337
EnumSystemFiles(ReadFiles);
340
void RNG_SystemInfoForRNG(void)
348
#if !defined(_WIN32_WCE)
350
DWORD dwComponentLen;
353
DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters;
362
nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
363
RNG_RandomUpdate(buffer, nBytes);
366
sMem.dwLength = sizeof(sMem);
367
GlobalMemoryStatus(&sMem); // assorted memory stats
368
RNG_RandomUpdate(&sMem, sizeof(sMem));
369
#if !defined(_WIN32_WCE)
370
dwVal = GetLogicalDrives();
371
RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25
374
dwVal = GetFreeSpace(0);
375
RNG_RandomUpdate(&dwVal, sizeof(dwVal));
379
RNG_RandomUpdate(&wDS, sizeof(wDS));
380
RNG_RandomUpdate(&wCS, sizeof(wCS));
384
#if !defined(_WIN32_WCE)
385
dwVal = sizeof(buffer);
386
if (GetComputerName(buffer, &dwVal))
387
RNG_RandomUpdate(buffer, dwVal);
389
/* XXX This is code that got yanked because of NSPR20. We should put it
395
GetCursorPos(&ptVal);
396
RNG_RandomUpdate(&ptVal, sizeof(ptVal));
399
dwVal = GetQueueStatus(QS_ALLINPUT); // high and low significant
400
RNG_RandomUpdate(&dwVal, sizeof(dwVal));
404
hWnd = GetClipboardOwner(); // 2 or 4 bytes
405
RNG_RandomUpdate((void *)&hWnd, sizeof(hWnd));
410
UuidCreate(&sUuid); // this will fail on machines with no ethernet
411
RNG_RandomUpdate(&sUuid, sizeof(sUuid)); // boards. shove the bits in regardless
415
hVal = GetCurrentProcess(); // 4 byte handle of current task
416
RNG_RandomUpdate(&hVal, sizeof(hVal));
418
dwVal = GetCurrentProcessId(); // process ID (4 bytes)
419
RNG_RandomUpdate(&dwVal, sizeof(dwVal));
421
#if !defined(_WIN32_WCE)
424
GetVolumeInformation(NULL,
433
RNG_RandomUpdate(volName, strlen(volName));
434
RNG_RandomUpdate(&dwSerialNum, sizeof(dwSerialNum));
435
RNG_RandomUpdate(&dwComponentLen, sizeof(dwComponentLen));
436
RNG_RandomUpdate(&dwSysFlags, sizeof(dwSysFlags));
437
RNG_RandomUpdate(buffer, strlen(buffer));
439
if (GetDiskFreeSpace(NULL, &dwSectors, &dwBytes, &dwFreeClusters, &dwNumClusters)) {
440
RNG_RandomUpdate(&dwSectors, sizeof(dwSectors));
441
RNG_RandomUpdate(&dwBytes, sizeof(dwBytes));
442
RNG_RandomUpdate(&dwFreeClusters, sizeof(dwFreeClusters));
443
RNG_RandomUpdate(&dwNumClusters, sizeof(dwNumClusters));
447
hTask = GetCurrentTask();
448
RNG_RandomUpdate((void *)&hTask, sizeof(hTask));
450
iVal = GetNumTasks();
451
RNG_RandomUpdate(&iVal, sizeof(iVal)); // number of running tasks
453
lpszEnv = GetDOSEnvironment();
454
while (*lpszEnv != '\0') {
455
RNG_RandomUpdate(lpszEnv, strlen(lpszEnv));
457
lpszEnv += strlen(lpszEnv) + 1;
459
#endif /* is WIN16 */
461
// now let's do some files
464
nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
465
RNG_RandomUpdate(buffer, nBytes);
468
#if defined(_WIN32_WCE)
469
void RNG_FileForRNG(const char *filename)
474
unsigned char buffer[1024];
476
/* windows doesn't initialize all the bytes in the stat buf,
477
* so initialize them all here to avoid UMRs.
479
memset(&infoBuf, 0, sizeof infoBuf);
481
if (PR_GetFileInfo(filename, &infoBuf) < 0)
484
RNG_RandomUpdate((unsigned char*)&infoBuf, sizeof(infoBuf));
486
file = PR_Open(filename, PR_RDONLY, 0);
489
PRInt32 bytes = PR_Read(file, buffer, sizeof buffer);
494
RNG_RandomUpdate(buffer, bytes);
495
totalFileBytes += bytes;
496
if (totalFileBytes > maxFileBytes)
503
nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
504
RNG_RandomUpdate(buffer, nBytes);
507
#else /* not WinCE */
509
void RNG_FileForRNG(const char *filename)
513
struct stat stat_buf;
514
unsigned char buffer[1024];
516
/* static DWORD totalFileBytes = 0; */
518
/* windows doesn't initialize all the bytes in the stat buf,
519
* so initialize them all here to avoid UMRs.
521
memset(&stat_buf, 0, sizeof stat_buf);
523
if (stat((char *)filename, &stat_buf) < 0)
526
RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf));
528
file = fopen((char *)filename, "r");
531
size_t bytes = fread(buffer, 1, sizeof(buffer), file);
536
RNG_RandomUpdate(buffer, bytes);
537
totalFileBytes += bytes;
538
if (totalFileBytes > maxFileBytes)
545
nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
546
RNG_RandomUpdate(buffer, nBytes);
549
#endif /* not WinCE */
552
* CryptoAPI requires Windows NT 4.0 or Windows 95 OSR2 and later.
553
* Until we drop support for Windows 95, we need to emulate some
554
* definitions and declarations in <wincrypt.h> and look up the
555
* functions in advapi32.dll at run time.
558
typedef unsigned long HCRYPTPROV;
560
#define CRYPT_VERIFYCONTEXT 0xF0000000
562
#define PROV_RSA_FULL 1
565
(WINAPI *CryptAcquireContextAFn)(
573
(WINAPI *CryptReleaseContextFn)(
578
(WINAPI *CryptGenRandomFn)(
584
* Windows XP and Windows Server 2003 and later have RtlGenRandom,
585
* which must be looked up by the name SystemFunction036.
588
(APIENTRY *RtlGenRandomFn)(
590
ULONG RandomBufferLength);
592
size_t RNG_SystemRNG(void *dest, size_t maxLen)
595
RtlGenRandomFn pRtlGenRandom;
596
CryptAcquireContextAFn pCryptAcquireContextA;
597
CryptReleaseContextFn pCryptReleaseContext;
598
CryptGenRandomFn pCryptGenRandom;
599
HCRYPTPROV hCryptProv;
602
hModule = LoadLibrary("advapi32.dll");
603
if (hModule == NULL) {
604
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
607
pRtlGenRandom = (RtlGenRandomFn)
608
GetProcAddress(hModule, "SystemFunction036");
610
if (pRtlGenRandom(dest, maxLen)) {
613
PORT_SetError(SEC_ERROR_NEED_RANDOM); /* system RNG failed */
617
pCryptAcquireContextA = (CryptAcquireContextAFn)
618
GetProcAddress(hModule, "CryptAcquireContextA");
619
pCryptReleaseContext = (CryptReleaseContextFn)
620
GetProcAddress(hModule, "CryptReleaseContext");
621
pCryptGenRandom = (CryptGenRandomFn)
622
GetProcAddress(hModule, "CryptGenRandom");
623
if (!pCryptAcquireContextA || !pCryptReleaseContext || !pCryptGenRandom) {
624
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
627
if (pCryptAcquireContextA(&hCryptProv, NULL, NULL,
628
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
629
if (pCryptGenRandom(hCryptProv, maxLen, dest)) {
632
pCryptReleaseContext(hCryptProv, 0);
635
PORT_SetError(SEC_ERROR_NEED_RANDOM); /* system RNG failed */
638
FreeLibrary(hModule);
642
#endif /* is XP_WIN */