Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(296)

Side by Side Diff: mozilla/security/nss/lib/freebl/win_rand.c

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "secerr.h"
7
8 #ifdef XP_WIN
9 #include <windows.h>
10 #include <shlobj.h> /* for CSIDL constants */
11 #include <time.h>
12 #include <io.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <stdio.h>
16 #include "prio.h"
17 #include "prerror.h"
18
19 static PRInt32 filesToRead;
20 static DWORD totalFileBytes;
21 static DWORD maxFileBytes = 250000; /* 250 thousand */
22 static DWORD dwNumFiles, dwReadEvery, dwFileToRead;
23 static PRBool usedWindowsPRNG;
24
25 static BOOL
26 CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow)
27 {
28 LARGE_INTEGER liCount;
29
30 if (!QueryPerformanceCounter(&liCount))
31 return FALSE;
32
33 *lpdwHigh = liCount.u.HighPart;
34 *lpdwLow = liCount.u.LowPart;
35 return TRUE;
36 }
37
38 size_t RNG_GetNoise(void *buf, size_t maxbuf)
39 {
40 DWORD dwHigh, dwLow, dwVal;
41 int n = 0;
42 int nBytes;
43 time_t sTime;
44
45 if (maxbuf <= 0)
46 return 0;
47
48 CurrentClockTickTime(&dwHigh, &dwLow);
49
50 // get the maximally changing bits first
51 nBytes = sizeof(dwLow) > maxbuf ? maxbuf : sizeof(dwLow);
52 memcpy((char *)buf, &dwLow, nBytes);
53 n += nBytes;
54 maxbuf -= nBytes;
55
56 if (maxbuf <= 0)
57 return n;
58
59 nBytes = sizeof(dwHigh) > maxbuf ? maxbuf : sizeof(dwHigh);
60 memcpy(((char *)buf) + n, &dwHigh, nBytes);
61 n += nBytes;
62 maxbuf -= nBytes;
63
64 if (maxbuf <= 0)
65 return n;
66
67 // get the number of milliseconds that have elapsed since Windows started
68 dwVal = GetTickCount();
69
70 nBytes = sizeof(dwVal) > maxbuf ? maxbuf : sizeof(dwVal);
71 memcpy(((char *)buf) + n, &dwVal, nBytes);
72 n += nBytes;
73 maxbuf -= nBytes;
74
75 if (maxbuf <= 0)
76 return n;
77
78 // get the time in seconds since midnight Jan 1, 1970
79 time(&sTime);
80 nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
81 memcpy(((char *)buf) + n, &sTime, nBytes);
82 n += nBytes;
83
84 return n;
85 }
86
87 typedef PRInt32 (* Handler)(const PRUnichar *);
88 #define MAX_DEPTH 2
89 #define MAX_FOLDERS 4
90 #define MAX_FILES 1024
91
92 static void
93 EnumSystemFilesInFolder(Handler func, PRUnichar* szSysDir, int maxDepth)
94 {
95 int iContinue;
96 unsigned int uFolders = 0;
97 unsigned int uFiles = 0;
98 HANDLE lFindHandle;
99 WIN32_FIND_DATAW fdData;
100 PRUnichar szFileName[_MAX_PATH];
101
102 if (maxDepth < 0)
103 return;
104 // append *.* so we actually look for files.
105 _snwprintf(szFileName, _MAX_PATH, L"%s\\*.*", szSysDir);
106 szFileName[_MAX_PATH - 1] = L'\0';
107
108 lFindHandle = FindFirstFileW(szFileName, &fdData);
109 if (lFindHandle == INVALID_HANDLE_VALUE)
110 return;
111 do {
112 iContinue = 1;
113 if (wcscmp(fdData.cFileName, L".") == 0 ||
114 wcscmp(fdData.cFileName, L"..") == 0) {
115 // skip "." and ".."
116 } else {
117 // pass the full pathname to the callback
118 _snwprintf(szFileName, _MAX_PATH, L"%s\\%s", szSysDir,
119 fdData.cFileName);
120 szFileName[_MAX_PATH - 1] = L'\0';
121 if (fdData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
122 if (++uFolders <= MAX_FOLDERS)
123 EnumSystemFilesInFolder(func, szFileName, maxDepth - 1);
124 } else {
125 iContinue = (++uFiles <= MAX_FILES) && !(*func)(szFileName);
126 }
127 }
128 if (iContinue)
129 iContinue = FindNextFileW(lFindHandle, &fdData);
130 } while (iContinue);
131 FindClose(lFindHandle);
132 }
133
134 static BOOL
135 EnumSystemFiles(Handler func)
136 {
137 PRUnichar szSysDir[_MAX_PATH];
138 static const int folders[] = {
139 CSIDL_BITBUCKET,
140 CSIDL_RECENT,
141 CSIDL_INTERNET_CACHE,
142 CSIDL_HISTORY,
143 0
144 };
145 int i = 0;
146 if (_MAX_PATH > (i = GetTempPathW(_MAX_PATH, szSysDir))) {
147 if (i > 0 && szSysDir[i-1] == L'\\')
148 szSysDir[i-1] = L'\0'; // we need to lop off the trailing slash
149 EnumSystemFilesInFolder(func, szSysDir, MAX_DEPTH);
150 }
151 for(i = 0; folders[i]; i++) {
152 DWORD rv = SHGetSpecialFolderPathW(NULL, szSysDir, folders[i], 0);
153 if (szSysDir[0])
154 EnumSystemFilesInFolder(func, szSysDir, MAX_DEPTH);
155 szSysDir[0] = L'\0';
156 }
157 return PR_TRUE;
158 }
159
160 static PRInt32
161 CountFiles(const PRUnichar *file)
162 {
163 dwNumFiles++;
164 return 0;
165 }
166
167 static int
168 ReadSingleFile(const char *filename)
169 {
170 PRFileDesc * file;
171 unsigned char buffer[1024];
172
173 file = PR_Open(filename, PR_RDONLY, 0);
174 if (file != NULL) {
175 while (PR_Read(file, buffer, sizeof buffer) > 0)
176 ;
177 PR_Close(file);
178 }
179 return (file != NULL);
180 }
181
182 static PRInt32
183 ReadOneFile(const PRUnichar *szFileName)
184 {
185 char narrowFileName[_MAX_PATH];
186
187 if (dwNumFiles == dwFileToRead) {
188 int success = WideCharToMultiByte(CP_ACP, 0, szFileName, -1,
189 narrowFileName, _MAX_PATH,
190 NULL, NULL);
191 if (success)
192 success = ReadSingleFile(narrowFileName);
193 if (!success)
194 dwFileToRead++; /* couldn't read this one, read the next one. */
195 }
196 dwNumFiles++;
197 return dwNumFiles > dwFileToRead;
198 }
199
200 static PRInt32
201 ReadFiles(const PRUnichar *szFileName)
202 {
203 char narrowFileName[_MAX_PATH];
204
205 if ((dwNumFiles % dwReadEvery) == 0) {
206 ++filesToRead;
207 }
208 if (filesToRead) {
209 DWORD prevFileBytes = totalFileBytes;
210 int iContinue = WideCharToMultiByte(CP_ACP, 0, szFileName, -1,
211 narrowFileName, _MAX_PATH,
212 NULL, NULL);
213 if (iContinue) {
214 RNG_FileForRNG(narrowFileName);
215 }
216 if (prevFileBytes < totalFileBytes) {
217 --filesToRead;
218 }
219 }
220 dwNumFiles++;
221 return (totalFileBytes >= maxFileBytes);
222 }
223
224 static void
225 ReadSystemFiles(void)
226 {
227 // first count the number of files
228 dwNumFiles = 0;
229 if (!EnumSystemFiles(CountFiles))
230 return;
231
232 RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles));
233
234 // now read the first 10 readable files, then 10 or 11 files
235 // spread throughout the system directory
236 filesToRead = 10;
237 if (dwNumFiles == 0)
238 return;
239
240 dwReadEvery = dwNumFiles / 10;
241 if (dwReadEvery == 0)
242 dwReadEvery = 1; // less than 10 files
243
244 dwNumFiles = 0;
245 totalFileBytes = 0;
246 EnumSystemFiles(ReadFiles);
247 }
248
249 void RNG_SystemInfoForRNG(void)
250 {
251 DWORD dwVal;
252 char buffer[256];
253 int nBytes;
254 MEMORYSTATUS sMem;
255 HANDLE hVal;
256 DWORD dwSerialNum;
257 DWORD dwComponentLen;
258 DWORD dwSysFlags;
259 char volName[128];
260 DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters;
261
262 nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
263 RNG_RandomUpdate(buffer, nBytes);
264
265 sMem.dwLength = sizeof(sMem);
266 GlobalMemoryStatus(&sMem); // assorted memory stats
267 RNG_RandomUpdate(&sMem, sizeof(sMem));
268
269 dwVal = GetLogicalDrives();
270 RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25
271
272 dwVal = sizeof(buffer);
273 if (GetComputerName(buffer, &dwVal))
274 RNG_RandomUpdate(buffer, dwVal);
275
276 hVal = GetCurrentProcess(); // 4 or 8 byte pseudo handle (a
277 // constant!) of current process
278 RNG_RandomUpdate(&hVal, sizeof(hVal));
279
280 dwVal = GetCurrentProcessId(); // process ID (4 bytes)
281 RNG_RandomUpdate(&dwVal, sizeof(dwVal));
282
283 dwVal = GetCurrentThreadId(); // thread ID (4 bytes)
284 RNG_RandomUpdate(&dwVal, sizeof(dwVal));
285
286 volName[0] = '\0';
287 buffer[0] = '\0';
288 GetVolumeInformation(NULL,
289 volName,
290 sizeof(volName),
291 &dwSerialNum,
292 &dwComponentLen,
293 &dwSysFlags,
294 buffer,
295 sizeof(buffer));
296
297 RNG_RandomUpdate(volName, strlen(volName));
298 RNG_RandomUpdate(&dwSerialNum, sizeof(dwSerialNum));
299 RNG_RandomUpdate(&dwComponentLen, sizeof(dwComponentLen));
300 RNG_RandomUpdate(&dwSysFlags, sizeof(dwSysFlags));
301 RNG_RandomUpdate(buffer, strlen(buffer));
302
303 if (GetDiskFreeSpace(NULL, &dwSectors, &dwBytes, &dwFreeClusters,
304 &dwNumClusters)) {
305 RNG_RandomUpdate(&dwSectors, sizeof(dwSectors));
306 RNG_RandomUpdate(&dwBytes, sizeof(dwBytes));
307 RNG_RandomUpdate(&dwFreeClusters, sizeof(dwFreeClusters));
308 RNG_RandomUpdate(&dwNumClusters, sizeof(dwNumClusters));
309 }
310
311 // Skip the potentially slow file scanning if the OS's PRNG worked.
312 if (!usedWindowsPRNG)
313 ReadSystemFiles();
314
315 nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
316 RNG_RandomUpdate(buffer, nBytes);
317 }
318
319 static void rng_systemJitter(void)
320 {
321 dwNumFiles = 0;
322 EnumSystemFiles(ReadOneFile);
323 dwFileToRead++;
324 if (dwFileToRead >= dwNumFiles) {
325 dwFileToRead = 0;
326 }
327 }
328
329
330 void RNG_FileForRNG(const char *filename)
331 {
332 FILE* file;
333 int nBytes;
334 struct stat stat_buf;
335 unsigned char buffer[1024];
336
337 /* windows doesn't initialize all the bytes in the stat buf,
338 * so initialize them all here to avoid UMRs.
339 */
340 memset(&stat_buf, 0, sizeof stat_buf);
341
342 if (stat((char *)filename, &stat_buf) < 0)
343 return;
344
345 RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf));
346
347 file = fopen((char *)filename, "r");
348 if (file != NULL) {
349 for (;;) {
350 size_t bytes = fread(buffer, 1, sizeof(buffer), file);
351
352 if (bytes == 0)
353 break;
354
355 RNG_RandomUpdate(buffer, bytes);
356 totalFileBytes += bytes;
357 if (totalFileBytes > maxFileBytes)
358 break;
359 }
360
361 fclose(file);
362 }
363
364 nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
365 RNG_RandomUpdate(buffer, nBytes);
366 }
367
368
369 /*
370 * CryptoAPI requires Windows NT 4.0 or Windows 95 OSR2 and later.
371 * Until we drop support for Windows 95, we need to emulate some
372 * definitions and declarations in <wincrypt.h> and look up the
373 * functions in advapi32.dll at run time.
374 */
375
376 #ifndef WIN64
377 typedef unsigned long HCRYPTPROV;
378 #endif
379
380 #define CRYPT_VERIFYCONTEXT 0xF0000000
381
382 #define PROV_RSA_FULL 1
383
384 typedef BOOL
385 (WINAPI *CryptAcquireContextAFn)(
386 HCRYPTPROV *phProv,
387 LPCSTR pszContainer,
388 LPCSTR pszProvider,
389 DWORD dwProvType,
390 DWORD dwFlags);
391
392 typedef BOOL
393 (WINAPI *CryptReleaseContextFn)(
394 HCRYPTPROV hProv,
395 DWORD dwFlags);
396
397 typedef BOOL
398 (WINAPI *CryptGenRandomFn)(
399 HCRYPTPROV hProv,
400 DWORD dwLen,
401 BYTE *pbBuffer);
402
403 /*
404 * Windows XP and Windows Server 2003 and later have RtlGenRandom,
405 * which must be looked up by the name SystemFunction036.
406 */
407 typedef BOOLEAN
408 (APIENTRY *RtlGenRandomFn)(
409 PVOID RandomBuffer,
410 ULONG RandomBufferLength);
411
412 size_t RNG_SystemRNG(void *dest, size_t maxLen)
413 {
414 HMODULE hModule;
415 RtlGenRandomFn pRtlGenRandom;
416 CryptAcquireContextAFn pCryptAcquireContextA;
417 CryptReleaseContextFn pCryptReleaseContext;
418 CryptGenRandomFn pCryptGenRandom;
419 HCRYPTPROV hCryptProv;
420 size_t bytes = 0;
421
422 usedWindowsPRNG = PR_FALSE;
423 hModule = LoadLibrary("advapi32.dll");
424 if (hModule == NULL) {
425 return rng_systemFromNoise(dest,maxLen);
426 }
427 pRtlGenRandom = (RtlGenRandomFn)
428 GetProcAddress(hModule, "SystemFunction036");
429 if (pRtlGenRandom) {
430 if (pRtlGenRandom(dest, maxLen)) {
431 bytes = maxLen;
432 usedWindowsPRNG = PR_TRUE;
433 } else {
434 bytes = rng_systemFromNoise(dest,maxLen);
435 }
436 goto done;
437 }
438 pCryptAcquireContextA = (CryptAcquireContextAFn)
439 GetProcAddress(hModule, "CryptAcquireContextA");
440 pCryptReleaseContext = (CryptReleaseContextFn)
441 GetProcAddress(hModule, "CryptReleaseContext");
442 pCryptGenRandom = (CryptGenRandomFn)
443 GetProcAddress(hModule, "CryptGenRandom");
444 if (!pCryptAcquireContextA || !pCryptReleaseContext || !pCryptGenRandom) {
445 bytes = rng_systemFromNoise(dest,maxLen);
446 goto done;
447 }
448 if (pCryptAcquireContextA(&hCryptProv, NULL, NULL,
449 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
450 if (pCryptGenRandom(hCryptProv, maxLen, dest)) {
451 bytes = maxLen;
452 usedWindowsPRNG = PR_TRUE;
453 }
454 pCryptReleaseContext(hCryptProv, 0);
455 }
456 if (bytes == 0) {
457 bytes = rng_systemFromNoise(dest,maxLen);
458 }
459 done:
460 FreeLibrary(hModule);
461 return bytes;
462 }
463 #endif /* is XP_WIN */
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/freebl/unix_rand.c ('k') | mozilla/security/nss/lib/libpkix/include/pkix.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698