win_rand.c (4373B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "secrng.h" 6 7 #ifdef XP_WIN 8 #include <windows.h> 9 #include <time.h> 10 11 static BOOL 12 CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow) 13 { 14 LARGE_INTEGER liCount; 15 16 if (!QueryPerformanceCounter(&liCount)) 17 return FALSE; 18 19 *lpdwHigh = liCount.u.HighPart; 20 *lpdwLow = liCount.u.LowPart; 21 return TRUE; 22 } 23 24 size_t 25 RNG_GetNoise(void *buf, size_t maxbuf) 26 { 27 DWORD dwHigh, dwLow, dwVal; 28 int n = 0; 29 int nBytes; 30 time_t sTime; 31 32 if (maxbuf <= 0) 33 return 0; 34 35 CurrentClockTickTime(&dwHigh, &dwLow); 36 37 // get the maximally changing bits first 38 nBytes = sizeof(dwLow) > maxbuf ? maxbuf : sizeof(dwLow); 39 memcpy((char *)buf, &dwLow, nBytes); 40 n += nBytes; 41 maxbuf -= nBytes; 42 43 if (maxbuf <= 0) 44 return n; 45 46 nBytes = sizeof(dwHigh) > maxbuf ? maxbuf : sizeof(dwHigh); 47 memcpy(((char *)buf) + n, &dwHigh, nBytes); 48 n += nBytes; 49 maxbuf -= nBytes; 50 51 if (maxbuf <= 0) 52 return n; 53 54 // get the number of milliseconds that have elapsed since Windows started 55 dwVal = GetTickCount(); 56 57 nBytes = sizeof(dwVal) > maxbuf ? maxbuf : sizeof(dwVal); 58 memcpy(((char *)buf) + n, &dwVal, nBytes); 59 n += nBytes; 60 maxbuf -= nBytes; 61 62 if (maxbuf <= 0) 63 return n; 64 65 // get the time in seconds since midnight Jan 1, 1970 66 time(&sTime); 67 nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime); 68 memcpy(((char *)buf) + n, &sTime, nBytes); 69 n += nBytes; 70 71 return n; 72 } 73 74 void 75 RNG_SystemInfoForRNG(void) 76 { 77 DWORD dwVal; 78 char buffer[256]; 79 int nBytes; 80 MEMORYSTATUS sMem; 81 HANDLE hVal; 82 DWORD dwSerialNum; 83 DWORD dwComponentLen; 84 DWORD dwSysFlags; 85 char volName[128]; 86 DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters; 87 88 nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes 89 RNG_RandomUpdate(buffer, nBytes); 90 91 sMem.dwLength = sizeof(sMem); 92 GlobalMemoryStatus(&sMem); // assorted memory stats 93 RNG_RandomUpdate(&sMem, sizeof(sMem)); 94 95 dwVal = GetLogicalDrives(); 96 RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25 97 98 dwVal = sizeof(buffer); 99 if (GetComputerName(buffer, &dwVal)) 100 RNG_RandomUpdate(buffer, dwVal); 101 102 hVal = GetCurrentProcess(); // 4 or 8 byte pseudo handle (a 103 // constant!) of current process 104 RNG_RandomUpdate(&hVal, sizeof(hVal)); 105 106 dwVal = GetCurrentProcessId(); // process ID (4 bytes) 107 RNG_RandomUpdate(&dwVal, sizeof(dwVal)); 108 109 dwVal = GetCurrentThreadId(); // thread ID (4 bytes) 110 RNG_RandomUpdate(&dwVal, sizeof(dwVal)); 111 112 volName[0] = '\0'; 113 buffer[0] = '\0'; 114 GetVolumeInformation(NULL, 115 volName, 116 sizeof(volName), 117 &dwSerialNum, 118 &dwComponentLen, 119 &dwSysFlags, 120 buffer, 121 sizeof(buffer)); 122 123 RNG_RandomUpdate(volName, strlen(volName)); 124 RNG_RandomUpdate(&dwSerialNum, sizeof(dwSerialNum)); 125 RNG_RandomUpdate(&dwComponentLen, sizeof(dwComponentLen)); 126 RNG_RandomUpdate(&dwSysFlags, sizeof(dwSysFlags)); 127 RNG_RandomUpdate(buffer, strlen(buffer)); 128 129 if (GetDiskFreeSpace(NULL, &dwSectors, &dwBytes, &dwFreeClusters, 130 &dwNumClusters)) { 131 RNG_RandomUpdate(&dwSectors, sizeof(dwSectors)); 132 RNG_RandomUpdate(&dwBytes, sizeof(dwBytes)); 133 RNG_RandomUpdate(&dwFreeClusters, sizeof(dwFreeClusters)); 134 RNG_RandomUpdate(&dwNumClusters, sizeof(dwNumClusters)); 135 } 136 137 nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes 138 RNG_RandomUpdate(buffer, nBytes); 139 } 140 141 /* 142 * The RtlGenRandom function is declared in <ntsecapi.h>, but the 143 * declaration is missing a calling convention specifier. So we 144 * declare it manually here. 145 */ 146 #define RtlGenRandom SystemFunction036 147 DECLSPEC_IMPORT BOOLEAN WINAPI RtlGenRandom( 148 PVOID RandomBuffer, 149 ULONG RandomBufferLength); 150 151 size_t 152 RNG_SystemRNG(void *dest, size_t maxLen) 153 { 154 size_t bytes = 0; 155 156 if (RtlGenRandom(dest, maxLen)) { 157 bytes = maxLen; 158 } 159 return bytes; 160 } 161 #endif /* is XP_WIN */