/* 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"
#ifdef XP_WIN
#include <windows.h>
#include <time.h>
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;
}
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));
}
nBytes = RNG_GetNoise(buffer, 20);
// get up to 20 bytes
RNG_RandomUpdate(buffer, nBytes);
}
/*
* The RtlGenRandom function is declared in <ntsecapi.h>, but the
* declaration is missing a calling convention specifier. So we
* declare it manually here.
*/
#define RtlGenRandom SystemFunction036
DECLSPEC_IMPORT BOOLEAN WINAPI RtlGenRandom(
PVOID RandomBuffer,
ULONG RandomBufferLength);
size_t
RNG_SystemRNG(
void *dest, size_t maxLen)
{
size_t bytes = 0;
if (RtlGenRandom(dest, maxLen)) {
bytes = maxLen;
}
return bytes;
}
#endif /* is XP_WIN */