michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "secrng.h" michael@0: michael@0: #ifdef XP_WIN michael@0: #include michael@0: #include michael@0: michael@0: static BOOL michael@0: CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow) michael@0: { michael@0: LARGE_INTEGER liCount; michael@0: michael@0: if (!QueryPerformanceCounter(&liCount)) michael@0: return FALSE; michael@0: michael@0: *lpdwHigh = liCount.u.HighPart; michael@0: *lpdwLow = liCount.u.LowPart; michael@0: return TRUE; michael@0: } michael@0: michael@0: size_t RNG_GetNoise(void *buf, size_t maxbuf) michael@0: { michael@0: DWORD dwHigh, dwLow, dwVal; michael@0: int n = 0; michael@0: int nBytes; michael@0: time_t sTime; michael@0: michael@0: if (maxbuf <= 0) michael@0: return 0; michael@0: michael@0: CurrentClockTickTime(&dwHigh, &dwLow); michael@0: michael@0: // get the maximally changing bits first michael@0: nBytes = sizeof(dwLow) > maxbuf ? maxbuf : sizeof(dwLow); michael@0: memcpy((char *)buf, &dwLow, nBytes); michael@0: n += nBytes; michael@0: maxbuf -= nBytes; michael@0: michael@0: if (maxbuf <= 0) michael@0: return n; michael@0: michael@0: nBytes = sizeof(dwHigh) > maxbuf ? maxbuf : sizeof(dwHigh); michael@0: memcpy(((char *)buf) + n, &dwHigh, nBytes); michael@0: n += nBytes; michael@0: maxbuf -= nBytes; michael@0: michael@0: if (maxbuf <= 0) michael@0: return n; michael@0: michael@0: // get the number of milliseconds that have elapsed since Windows started michael@0: dwVal = GetTickCount(); michael@0: michael@0: nBytes = sizeof(dwVal) > maxbuf ? maxbuf : sizeof(dwVal); michael@0: memcpy(((char *)buf) + n, &dwVal, nBytes); michael@0: n += nBytes; michael@0: maxbuf -= nBytes; michael@0: michael@0: if (maxbuf <= 0) michael@0: return n; michael@0: michael@0: // get the time in seconds since midnight Jan 1, 1970 michael@0: time(&sTime); michael@0: nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime); michael@0: memcpy(((char *)buf) + n, &sTime, nBytes); michael@0: n += nBytes; michael@0: michael@0: return n; michael@0: } michael@0: michael@0: void RNG_SystemInfoForRNG(void) michael@0: { michael@0: DWORD dwVal; michael@0: char buffer[256]; michael@0: int nBytes; michael@0: MEMORYSTATUS sMem; michael@0: HANDLE hVal; michael@0: DWORD dwSerialNum; michael@0: DWORD dwComponentLen; michael@0: DWORD dwSysFlags; michael@0: char volName[128]; michael@0: DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters; michael@0: michael@0: nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes michael@0: RNG_RandomUpdate(buffer, nBytes); michael@0: michael@0: sMem.dwLength = sizeof(sMem); michael@0: GlobalMemoryStatus(&sMem); // assorted memory stats michael@0: RNG_RandomUpdate(&sMem, sizeof(sMem)); michael@0: michael@0: dwVal = GetLogicalDrives(); michael@0: RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25 michael@0: michael@0: dwVal = sizeof(buffer); michael@0: if (GetComputerName(buffer, &dwVal)) michael@0: RNG_RandomUpdate(buffer, dwVal); michael@0: michael@0: hVal = GetCurrentProcess(); // 4 or 8 byte pseudo handle (a michael@0: // constant!) of current process michael@0: RNG_RandomUpdate(&hVal, sizeof(hVal)); michael@0: michael@0: dwVal = GetCurrentProcessId(); // process ID (4 bytes) michael@0: RNG_RandomUpdate(&dwVal, sizeof(dwVal)); michael@0: michael@0: dwVal = GetCurrentThreadId(); // thread ID (4 bytes) michael@0: RNG_RandomUpdate(&dwVal, sizeof(dwVal)); michael@0: michael@0: volName[0] = '\0'; michael@0: buffer[0] = '\0'; michael@0: GetVolumeInformation(NULL, michael@0: volName, michael@0: sizeof(volName), michael@0: &dwSerialNum, michael@0: &dwComponentLen, michael@0: &dwSysFlags, michael@0: buffer, michael@0: sizeof(buffer)); michael@0: michael@0: RNG_RandomUpdate(volName, strlen(volName)); michael@0: RNG_RandomUpdate(&dwSerialNum, sizeof(dwSerialNum)); michael@0: RNG_RandomUpdate(&dwComponentLen, sizeof(dwComponentLen)); michael@0: RNG_RandomUpdate(&dwSysFlags, sizeof(dwSysFlags)); michael@0: RNG_RandomUpdate(buffer, strlen(buffer)); michael@0: michael@0: if (GetDiskFreeSpace(NULL, &dwSectors, &dwBytes, &dwFreeClusters, michael@0: &dwNumClusters)) { michael@0: RNG_RandomUpdate(&dwSectors, sizeof(dwSectors)); michael@0: RNG_RandomUpdate(&dwBytes, sizeof(dwBytes)); michael@0: RNG_RandomUpdate(&dwFreeClusters, sizeof(dwFreeClusters)); michael@0: RNG_RandomUpdate(&dwNumClusters, sizeof(dwNumClusters)); michael@0: } michael@0: michael@0: nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes michael@0: RNG_RandomUpdate(buffer, nBytes); michael@0: } michael@0: michael@0: michael@0: /* michael@0: * The RtlGenRandom function is declared in , but the michael@0: * declaration is missing a calling convention specifier. So we michael@0: * declare it manually here. michael@0: */ michael@0: #define RtlGenRandom SystemFunction036 michael@0: DECLSPEC_IMPORT BOOLEAN WINAPI RtlGenRandom( michael@0: PVOID RandomBuffer, michael@0: ULONG RandomBufferLength); michael@0: michael@0: size_t RNG_SystemRNG(void *dest, size_t maxLen) michael@0: { michael@0: size_t bytes = 0; michael@0: michael@0: if (RtlGenRandom(dest, maxLen)) { michael@0: bytes = maxLen; michael@0: } michael@0: return bytes; michael@0: } michael@0: #endif /* is XP_WIN */