win_rand.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 416 行
C
416 行
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "secrng.h"#ifdef XP_WIN#include <windows.h>#include <time.h>#include <io.h>#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#ifndef _WIN32#define VTD_Device_ID 5#define OP_OVERRIDE _asm _emit 0x66#include <dos.h>#endifstatic BOOLCurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow){#ifdef _WIN32 LARGE_INTEGER liCount; if (!QueryPerformanceCounter(&liCount)) return FALSE; *lpdwHigh = liCount.u.HighPart; *lpdwLow = liCount.u.LowPart; return TRUE;#else /* is WIN16 */ BOOL bRetVal; FARPROC lpAPI; WORD w1, w2, w3, w4; // Get direct access to the VTD and query the current clock tick time _asm { xor di, di mov es, di mov ax, 1684h mov bx, VTD_Device_ID int 2fh mov ax, es or ax, di jz EnumerateFailed ; VTD API is available. First store the API address (the address actually ; contains an instruction that causes a fault, the fault handler then ; makes the ring transition and calls the API in the VxD) mov word ptr lpAPI, di mov word ptr lpAPI+2, es mov ax, 100h ; API function to VTD_Get_Real_Time; call dword ptr [lpAPI] call [lpAPI] ; Result is in EDX:EAX which we will get 16-bits at a time mov w2, dx OP_OVERRIDE shr dx,10h ; really "shr edx, 16" mov w1, dx mov w4, ax OP_OVERRIDE shr ax,10h ; really "shr eax, 16" mov w3, ax mov bRetVal, 1 ; return TRUE jmp EnumerateExit EnumerateFailed: mov bRetVal, 0 ; return FALSE EnumerateExit: } *lpdwHigh = MAKELONG(w2, w1); *lpdwLow = MAKELONG(w4, w3); return bRetVal;#endif /* is WIN16 */}size_t RNG_GetNoise(void *buf, size_t maxbuf){ DWORD dwHigh, dwLow, dwVal; int n = 0; int nBytes; time_t sTime; if (maxbuf <= 0) return 0; CurrentClockTickTime(&dwHigh, &dwLow); // get the maximally changing bits first nBytes = sizeof(dwLow) > maxbuf ? maxbuf : sizeof(dwLow); memcpy((char *)buf, &dwLow, nBytes); n += nBytes; maxbuf -= nBytes; if (maxbuf <= 0) return n; nBytes = sizeof(dwHigh) > maxbuf ? maxbuf : sizeof(dwHigh); memcpy(((char *)buf) + n, &dwHigh, nBytes); n += nBytes; maxbuf -= nBytes; if (maxbuf <= 0) return n; // get the number of milliseconds that have elapsed since Windows started dwVal = GetTickCount(); nBytes = sizeof(dwVal) > maxbuf ? maxbuf : sizeof(dwVal); memcpy(((char *)buf) + n, &dwVal, nBytes); n += nBytes; maxbuf -= nBytes; if (maxbuf <= 0) return n; // get the time in seconds since midnight Jan 1, 1970 time(&sTime); nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime); memcpy(((char *)buf) + n, &sTime, nBytes); n += nBytes; return n;}static BOOLEnumSystemFiles(void (*func)(char *)){ int iStatus; char szSysDir[_MAX_PATH]; char szFileName[_MAX_PATH];#ifdef _WIN32 struct _finddata_t fdData; long lFindHandle;#else struct _find_t fdData;#endif if (!GetSystemDirectory(szSysDir, sizeof(szSysDir))) return FALSE; // tack *.* on the end so we actually look for files. this will // not overflow strcpy(szFileName, szSysDir); strcat(szFileName, "\\*.*");#ifdef _WIN32 lFindHandle = _findfirst(szFileName, &fdData); if (lFindHandle == -1) return FALSE;#else if (_dos_findfirst(szFileName, _A_NORMAL | _A_RDONLY | _A_ARCH | _A_SUBDIR, &fdData) != 0) return FALSE;#endif do { // pass the full pathname to the callback sprintf(szFileName, "%s\\%s", szSysDir, fdData.name); (*func)(szFileName);#ifdef _WIN32 iStatus = _findnext(lFindHandle, &fdData);#else iStatus = _dos_findnext(&fdData);#endif } while (iStatus == 0);#ifdef _WIN32 _findclose(lFindHandle);#endif return TRUE;}static DWORD dwNumFiles, dwReadEvery;static voidCountFiles(char *file){ dwNumFiles++;}static voidReadFiles(char *file){ if ((dwNumFiles % dwReadEvery) == 0) RNG_FileForRNG(file); dwNumFiles++;}static voidReadSystemFiles(){ // first count the number of files dwNumFiles = 0; if (!EnumSystemFiles(CountFiles)) return; RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles)); // now read 10 files if (dwNumFiles == 0) return; dwReadEvery = dwNumFiles / 10; if (dwReadEvery == 0) dwReadEvery = 1; // less than 10 files dwNumFiles = 0; EnumSystemFiles(ReadFiles);}void RNG_SystemInfoForRNG(void){ DWORD dwVal; char buffer[256]; int nBytes;#ifdef _WIN32 MEMORYSTATUS sMem; DWORD dwSerialNum; DWORD dwComponentLen; DWORD dwSysFlags; char volName[128]; DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters; HANDLE hVal;#else int iVal; HTASK hTask; WORD wDS, wCS; LPSTR lpszEnv;#endif nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes RNG_RandomUpdate(buffer, nBytes);#ifdef _WIN32 sMem.dwLength = sizeof(sMem); GlobalMemoryStatus(&sMem); // assorted memory stats RNG_RandomUpdate(&sMem, sizeof(sMem)); dwVal = GetLogicalDrives(); RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25#else dwVal = GetFreeSpace(0); RNG_RandomUpdate(&dwVal, sizeof(dwVal)); _asm mov wDS, ds; _asm mov wCS, cs; RNG_RandomUpdate(&wDS, sizeof(wDS)); RNG_RandomUpdate(&wCS, sizeof(wCS));#endif#ifdef _WIN32 dwVal = sizeof(buffer); if (GetComputerName(buffer, &dwVal)) RNG_RandomUpdate(buffer, dwVal);/* XXX This is code that got yanked because of NSPR20. We should put it * back someday. */#ifdef notdef { POINT ptVal; GetCursorPos(&ptVal); RNG_RandomUpdate(&ptVal, sizeof(ptVal)); } dwVal = GetQueueStatus(QS_ALLINPUT); // high and low significant RNG_RandomUpdate(&dwVal, sizeof(dwVal)); { HWND hWnd; hWnd = GetClipboardOwner(); // 2 or 4 bytes RNG_RandomUpdate((void *)&hWnd, sizeof(hWnd)); } { UUID sUuid; UuidCreate(&sUuid); // this will fail on machines with no ethernet RNG_RandomUpdate(&sUuid, sizeof(sUuid)); // boards. shove the bits in regardless }#endif hVal = GetCurrentProcess(); // 4 byte handle of current task RNG_RandomUpdate(&hVal, sizeof(hVal)); dwVal = GetCurrentProcessId(); // process ID (4 bytes) RNG_RandomUpdate(&dwVal, sizeof(dwVal)); volName[0] = '\0'; buffer[0] = '\0'; GetVolumeInformation(NULL, volName, sizeof(volName), &dwSerialNum, &dwComponentLen, &dwSysFlags, buffer, sizeof(buffer)); RNG_RandomUpdate(volName, strlen(volName)); RNG_RandomUpdate(&dwSerialNum, sizeof(dwSerialNum)); RNG_RandomUpdate(&dwComponentLen, sizeof(dwComponentLen)); RNG_RandomUpdate(&dwSysFlags, sizeof(dwSysFlags)); RNG_RandomUpdate(buffer, strlen(buffer)); if (GetDiskFreeSpace(NULL, &dwSectors, &dwBytes, &dwFreeClusters, &dwNumClusters)) { RNG_RandomUpdate(&dwSectors, sizeof(dwSectors)); RNG_RandomUpdate(&dwBytes, sizeof(dwBytes)); RNG_RandomUpdate(&dwFreeClusters, sizeof(dwFreeClusters)); RNG_RandomUpdate(&dwNumClusters, sizeof(dwNumClusters)); }#else /* is WIN16 */ hTask = GetCurrentTask(); RNG_RandomUpdate((void *)&hTask, sizeof(hTask)); iVal = GetNumTasks(); RNG_RandomUpdate(&iVal, sizeof(iVal)); // number of running tasks lpszEnv = GetDOSEnvironment(); while (*lpszEnv != '\0') { RNG_RandomUpdate(lpszEnv, strlen(lpszEnv)); lpszEnv += strlen(lpszEnv) + 1; }#endif /* is WIN16 */ // now let's do some files ReadSystemFiles(); nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes RNG_RandomUpdate(buffer, nBytes);}void RNG_FileForRNG(char *filename){ FILE* file; int nBytes; struct stat stat_buf; unsigned char buffer[1024]; static DWORD totalFileBytes = 0; /* windows doesn't initialize all the bytes in the stat buf, * so initialize them all here to avoid UMRs. */ memset(&stat_buf, 0, sizeof stat_buf); if (stat((char *)filename, &stat_buf) < 0) return; RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf)); file = fopen((char *)filename, "r"); if (file != NULL) { for (;;) { size_t bytes = fread(buffer, 1, sizeof(buffer), file); if (bytes == 0) break; RNG_RandomUpdate(buffer, bytes); totalFileBytes += bytes; if (totalFileBytes > 250000) break; } fclose(file); } nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes RNG_RandomUpdate(buffer, nBytes);}#endif /* is XP_WIN */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?