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