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
CurrentClockTickTime(LPDWORD lpdwHigh,LPDWORD lpdwLow)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
RNG_GetNoise(void * buf,size_t maxbuf)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
RNG_SystemInfoForRNG(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
RNG_SystemRNG(void * dest,size_t maxLen)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 */
162