|
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 #define INCL_DOS |
|
6 #define INCL_DOSERRORS |
|
7 #include <os2.h> |
|
8 #include "secrng.h" |
|
9 #include "prerror.h" |
|
10 #include <stdlib.h> |
|
11 #include <time.h> |
|
12 #include <stdio.h> |
|
13 #include <sys/stat.h> |
|
14 |
|
15 static BOOL clockTickTime(unsigned long *phigh, unsigned long *plow) |
|
16 { |
|
17 APIRET rc = NO_ERROR; |
|
18 QWORD qword = {0,0}; |
|
19 |
|
20 rc = DosTmrQueryTime(&qword); |
|
21 if (rc != NO_ERROR) |
|
22 return FALSE; |
|
23 |
|
24 *phigh = qword.ulHi; |
|
25 *plow = qword.ulLo; |
|
26 |
|
27 return TRUE; |
|
28 } |
|
29 |
|
30 size_t RNG_GetNoise(void *buf, size_t maxbuf) |
|
31 { |
|
32 unsigned long high = 0; |
|
33 unsigned long low = 0; |
|
34 clock_t val = 0; |
|
35 int n = 0; |
|
36 int nBytes = 0; |
|
37 time_t sTime; |
|
38 |
|
39 if (maxbuf <= 0) |
|
40 return 0; |
|
41 |
|
42 clockTickTime(&high, &low); |
|
43 |
|
44 /* get the maximally changing bits first */ |
|
45 nBytes = sizeof(low) > maxbuf ? maxbuf : sizeof(low); |
|
46 memcpy(buf, &low, nBytes); |
|
47 n += nBytes; |
|
48 maxbuf -= nBytes; |
|
49 |
|
50 if (maxbuf <= 0) |
|
51 return n; |
|
52 |
|
53 nBytes = sizeof(high) > maxbuf ? maxbuf : sizeof(high); |
|
54 memcpy(((char *)buf) + n, &high, nBytes); |
|
55 n += nBytes; |
|
56 maxbuf -= nBytes; |
|
57 |
|
58 if (maxbuf <= 0) |
|
59 return n; |
|
60 |
|
61 /* get the number of milliseconds that have elapsed since application started */ |
|
62 val = clock(); |
|
63 |
|
64 nBytes = sizeof(val) > maxbuf ? maxbuf : sizeof(val); |
|
65 memcpy(((char *)buf) + n, &val, nBytes); |
|
66 n += nBytes; |
|
67 maxbuf -= nBytes; |
|
68 |
|
69 if (maxbuf <= 0) |
|
70 return n; |
|
71 |
|
72 /* get the time in seconds since midnight Jan 1, 1970 */ |
|
73 time(&sTime); |
|
74 nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime); |
|
75 memcpy(((char *)buf) + n, &sTime, nBytes); |
|
76 n += nBytes; |
|
77 |
|
78 return n; |
|
79 } |
|
80 |
|
81 static BOOL |
|
82 EnumSystemFiles(void (*func)(const char *)) |
|
83 { |
|
84 APIRET rc; |
|
85 ULONG sysInfo = 0; |
|
86 char bootLetter[2]; |
|
87 char sysDir[_MAX_PATH] = ""; |
|
88 char filename[_MAX_PATH]; |
|
89 HDIR hdir = HDIR_CREATE; |
|
90 ULONG numFiles = 1; |
|
91 FILEFINDBUF3 fileBuf = {0}; |
|
92 ULONG buflen = sizeof(FILEFINDBUF3); |
|
93 |
|
94 if (DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&sysInfo, |
|
95 sizeof(ULONG)) == NO_ERROR) |
|
96 { |
|
97 bootLetter[0] = sysInfo + 'A' -1; |
|
98 bootLetter[1] = '\0'; |
|
99 strcpy(sysDir, bootLetter); |
|
100 strcpy(sysDir+1, ":\\OS2\\"); |
|
101 |
|
102 strcpy( filename, sysDir ); |
|
103 strcat( filename, "*.*" ); |
|
104 } |
|
105 |
|
106 rc =DosFindFirst( filename, &hdir, FILE_NORMAL, &fileBuf, buflen, |
|
107 &numFiles, FIL_STANDARD ); |
|
108 if( rc == NO_ERROR ) |
|
109 { |
|
110 do { |
|
111 // pass the full pathname to the callback |
|
112 sprintf( filename, "%s%s", sysDir, fileBuf.achName ); |
|
113 (*func)(filename); |
|
114 |
|
115 numFiles = 1; |
|
116 rc = DosFindNext( hdir, &fileBuf, buflen, &numFiles ); |
|
117 if( rc != NO_ERROR && rc != ERROR_NO_MORE_FILES ) |
|
118 printf( "DosFindNext errod code = %d\n", rc ); |
|
119 } while ( rc == NO_ERROR ); |
|
120 |
|
121 rc = DosFindClose(hdir); |
|
122 if( rc != NO_ERROR ) |
|
123 printf( "DosFindClose error code = %d", rc ); |
|
124 } |
|
125 else |
|
126 printf( "DosFindFirst error code = %d", rc ); |
|
127 |
|
128 return TRUE; |
|
129 } |
|
130 |
|
131 static int dwNumFiles, dwReadEvery, dwFileToRead=0; |
|
132 |
|
133 static void |
|
134 CountFiles(const char *file) |
|
135 { |
|
136 dwNumFiles++; |
|
137 } |
|
138 |
|
139 static void |
|
140 ReadFiles(const char *file) |
|
141 { |
|
142 if ((dwNumFiles % dwReadEvery) == 0) |
|
143 RNG_FileForRNG(file); |
|
144 |
|
145 dwNumFiles++; |
|
146 } |
|
147 |
|
148 static void |
|
149 ReadSingleFile(const char *filename) |
|
150 { |
|
151 unsigned char buffer[1024]; |
|
152 FILE *file; |
|
153 |
|
154 file = fopen((char *)filename, "rb"); |
|
155 if (file != NULL) { |
|
156 while (fread(buffer, 1, sizeof(buffer), file) > 0) |
|
157 ; |
|
158 fclose(file); |
|
159 } |
|
160 } |
|
161 |
|
162 static void |
|
163 ReadOneFile(const char *file) |
|
164 { |
|
165 if (dwNumFiles == dwFileToRead) { |
|
166 ReadSingleFile(file); |
|
167 } |
|
168 |
|
169 dwNumFiles++; |
|
170 } |
|
171 |
|
172 static void |
|
173 ReadSystemFiles(void) |
|
174 { |
|
175 // first count the number of files |
|
176 dwNumFiles = 0; |
|
177 if (!EnumSystemFiles(CountFiles)) |
|
178 return; |
|
179 |
|
180 RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles)); |
|
181 |
|
182 // now read 10 files |
|
183 if (dwNumFiles == 0) |
|
184 return; |
|
185 |
|
186 dwReadEvery = dwNumFiles / 10; |
|
187 if (dwReadEvery == 0) |
|
188 dwReadEvery = 1; // less than 10 files |
|
189 |
|
190 dwNumFiles = 0; |
|
191 EnumSystemFiles(ReadFiles); |
|
192 } |
|
193 |
|
194 void RNG_SystemInfoForRNG(void) |
|
195 { |
|
196 unsigned long *plong = 0; |
|
197 PTIB ptib; |
|
198 PPIB ppib; |
|
199 APIRET rc = NO_ERROR; |
|
200 DATETIME dt; |
|
201 COUNTRYCODE cc = {0}; |
|
202 COUNTRYINFO ci = {0}; |
|
203 unsigned long actual = 0; |
|
204 char path[_MAX_PATH]=""; |
|
205 char fullpath[_MAX_PATH]=""; |
|
206 unsigned long pathlength = sizeof(path); |
|
207 FSALLOCATE fsallocate; |
|
208 FILESTATUS3 fstatus; |
|
209 unsigned long defaultdrive = 0; |
|
210 unsigned long logicaldrives = 0; |
|
211 unsigned long sysInfo[QSV_MAX] = {0}; |
|
212 char buffer[20]; |
|
213 int nBytes = 0; |
|
214 |
|
215 nBytes = RNG_GetNoise(buffer, sizeof(buffer)); |
|
216 RNG_RandomUpdate(buffer, nBytes); |
|
217 |
|
218 /* allocate memory and use address and memory */ |
|
219 plong = (unsigned long *)malloc(sizeof(*plong)); |
|
220 RNG_RandomUpdate(&plong, sizeof(plong)); |
|
221 RNG_RandomUpdate(plong, sizeof(*plong)); |
|
222 free(plong); |
|
223 |
|
224 /* process info */ |
|
225 rc = DosGetInfoBlocks(&ptib, &ppib); |
|
226 if (rc == NO_ERROR) |
|
227 { |
|
228 RNG_RandomUpdate(ptib, sizeof(*ptib)); |
|
229 RNG_RandomUpdate(ppib, sizeof(*ppib)); |
|
230 } |
|
231 |
|
232 /* time */ |
|
233 rc = DosGetDateTime(&dt); |
|
234 if (rc == NO_ERROR) |
|
235 { |
|
236 RNG_RandomUpdate(&dt, sizeof(dt)); |
|
237 } |
|
238 |
|
239 /* country */ |
|
240 rc = DosQueryCtryInfo(sizeof(ci), &cc, &ci, &actual); |
|
241 if (rc == NO_ERROR) |
|
242 { |
|
243 RNG_RandomUpdate(&cc, sizeof(cc)); |
|
244 RNG_RandomUpdate(&ci, sizeof(ci)); |
|
245 RNG_RandomUpdate(&actual, sizeof(actual)); |
|
246 } |
|
247 |
|
248 /* current directory */ |
|
249 rc = DosQueryCurrentDir(0, path, &pathlength); |
|
250 strcat(fullpath, "\\"); |
|
251 strcat(fullpath, path); |
|
252 if (rc == NO_ERROR) |
|
253 { |
|
254 RNG_RandomUpdate(fullpath, strlen(fullpath)); |
|
255 // path info |
|
256 rc = DosQueryPathInfo(fullpath, FIL_STANDARD, &fstatus, sizeof(fstatus)); |
|
257 if (rc == NO_ERROR) |
|
258 { |
|
259 RNG_RandomUpdate(&fstatus, sizeof(fstatus)); |
|
260 } |
|
261 } |
|
262 |
|
263 /* file system info */ |
|
264 rc = DosQueryFSInfo(0, FSIL_ALLOC, &fsallocate, sizeof(fsallocate)); |
|
265 if (rc == NO_ERROR) |
|
266 { |
|
267 RNG_RandomUpdate(&fsallocate, sizeof(fsallocate)); |
|
268 } |
|
269 |
|
270 /* drive info */ |
|
271 rc = DosQueryCurrentDisk(&defaultdrive, &logicaldrives); |
|
272 if (rc == NO_ERROR) |
|
273 { |
|
274 RNG_RandomUpdate(&defaultdrive, sizeof(defaultdrive)); |
|
275 RNG_RandomUpdate(&logicaldrives, sizeof(logicaldrives)); |
|
276 } |
|
277 |
|
278 /* system info */ |
|
279 rc = DosQuerySysInfo(1L, QSV_MAX, (PVOID)&sysInfo, sizeof(ULONG)*QSV_MAX); |
|
280 if (rc == NO_ERROR) |
|
281 { |
|
282 RNG_RandomUpdate(&sysInfo, sizeof(sysInfo)); |
|
283 } |
|
284 |
|
285 // now let's do some files |
|
286 ReadSystemFiles(); |
|
287 |
|
288 /* more noise */ |
|
289 nBytes = RNG_GetNoise(buffer, sizeof(buffer)); |
|
290 RNG_RandomUpdate(buffer, nBytes); |
|
291 } |
|
292 |
|
293 void RNG_FileForRNG(const char *filename) |
|
294 { |
|
295 struct stat stat_buf; |
|
296 unsigned char buffer[1024]; |
|
297 FILE *file = 0; |
|
298 int nBytes = 0; |
|
299 static int totalFileBytes = 0; |
|
300 |
|
301 if (stat((char *)filename, &stat_buf) < 0) |
|
302 return; |
|
303 |
|
304 RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf)); |
|
305 |
|
306 file = fopen((char *)filename, "r"); |
|
307 if (file != NULL) |
|
308 { |
|
309 for (;;) |
|
310 { |
|
311 size_t bytes = fread(buffer, 1, sizeof(buffer), file); |
|
312 |
|
313 if (bytes == 0) |
|
314 break; |
|
315 |
|
316 RNG_RandomUpdate(buffer, bytes); |
|
317 totalFileBytes += bytes; |
|
318 if (totalFileBytes > 250000) |
|
319 break; |
|
320 } |
|
321 fclose(file); |
|
322 } |
|
323 |
|
324 nBytes = RNG_GetNoise(buffer, 20); |
|
325 RNG_RandomUpdate(buffer, nBytes); |
|
326 } |
|
327 |
|
328 static void rng_systemJitter(void) |
|
329 { |
|
330 dwNumFiles = 0; |
|
331 EnumSystemFiles(ReadOneFile); |
|
332 dwFileToRead++; |
|
333 if (dwFileToRead >= dwNumFiles) { |
|
334 dwFileToRead = 0; |
|
335 } |
|
336 } |
|
337 |
|
338 size_t RNG_SystemRNG(void *dest, size_t maxLen) |
|
339 { |
|
340 return rng_systemFromNoise(dest,maxLen); |
|
341 } |