michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #define INCL_DOS michael@0: #define INCL_DOSERRORS michael@0: #include michael@0: #include "secrng.h" michael@0: #include "prerror.h" michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: static BOOL clockTickTime(unsigned long *phigh, unsigned long *plow) michael@0: { michael@0: APIRET rc = NO_ERROR; michael@0: QWORD qword = {0,0}; michael@0: michael@0: rc = DosTmrQueryTime(&qword); michael@0: if (rc != NO_ERROR) michael@0: return FALSE; michael@0: michael@0: *phigh = qword.ulHi; michael@0: *plow = qword.ulLo; michael@0: michael@0: return TRUE; michael@0: } michael@0: michael@0: size_t RNG_GetNoise(void *buf, size_t maxbuf) michael@0: { michael@0: unsigned long high = 0; michael@0: unsigned long low = 0; michael@0: clock_t val = 0; michael@0: int n = 0; michael@0: int nBytes = 0; michael@0: time_t sTime; michael@0: michael@0: if (maxbuf <= 0) michael@0: return 0; michael@0: michael@0: clockTickTime(&high, &low); michael@0: michael@0: /* get the maximally changing bits first */ michael@0: nBytes = sizeof(low) > maxbuf ? maxbuf : sizeof(low); michael@0: memcpy(buf, &low, nBytes); michael@0: n += nBytes; michael@0: maxbuf -= nBytes; michael@0: michael@0: if (maxbuf <= 0) michael@0: return n; michael@0: michael@0: nBytes = sizeof(high) > maxbuf ? maxbuf : sizeof(high); michael@0: memcpy(((char *)buf) + n, &high, nBytes); michael@0: n += nBytes; michael@0: maxbuf -= nBytes; michael@0: michael@0: if (maxbuf <= 0) michael@0: return n; michael@0: michael@0: /* get the number of milliseconds that have elapsed since application started */ michael@0: val = clock(); michael@0: michael@0: nBytes = sizeof(val) > maxbuf ? maxbuf : sizeof(val); michael@0: memcpy(((char *)buf) + n, &val, nBytes); michael@0: n += nBytes; michael@0: maxbuf -= nBytes; michael@0: michael@0: if (maxbuf <= 0) michael@0: return n; michael@0: michael@0: /* get the time in seconds since midnight Jan 1, 1970 */ michael@0: time(&sTime); michael@0: nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime); michael@0: memcpy(((char *)buf) + n, &sTime, nBytes); michael@0: n += nBytes; michael@0: michael@0: return n; michael@0: } michael@0: michael@0: static BOOL michael@0: EnumSystemFiles(void (*func)(const char *)) michael@0: { michael@0: APIRET rc; michael@0: ULONG sysInfo = 0; michael@0: char bootLetter[2]; michael@0: char sysDir[_MAX_PATH] = ""; michael@0: char filename[_MAX_PATH]; michael@0: HDIR hdir = HDIR_CREATE; michael@0: ULONG numFiles = 1; michael@0: FILEFINDBUF3 fileBuf = {0}; michael@0: ULONG buflen = sizeof(FILEFINDBUF3); michael@0: michael@0: if (DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&sysInfo, michael@0: sizeof(ULONG)) == NO_ERROR) michael@0: { michael@0: bootLetter[0] = sysInfo + 'A' -1; michael@0: bootLetter[1] = '\0'; michael@0: strcpy(sysDir, bootLetter); michael@0: strcpy(sysDir+1, ":\\OS2\\"); michael@0: michael@0: strcpy( filename, sysDir ); michael@0: strcat( filename, "*.*" ); michael@0: } michael@0: michael@0: rc =DosFindFirst( filename, &hdir, FILE_NORMAL, &fileBuf, buflen, michael@0: &numFiles, FIL_STANDARD ); michael@0: if( rc == NO_ERROR ) michael@0: { michael@0: do { michael@0: // pass the full pathname to the callback michael@0: sprintf( filename, "%s%s", sysDir, fileBuf.achName ); michael@0: (*func)(filename); michael@0: michael@0: numFiles = 1; michael@0: rc = DosFindNext( hdir, &fileBuf, buflen, &numFiles ); michael@0: if( rc != NO_ERROR && rc != ERROR_NO_MORE_FILES ) michael@0: printf( "DosFindNext errod code = %d\n", rc ); michael@0: } while ( rc == NO_ERROR ); michael@0: michael@0: rc = DosFindClose(hdir); michael@0: if( rc != NO_ERROR ) michael@0: printf( "DosFindClose error code = %d", rc ); michael@0: } michael@0: else michael@0: printf( "DosFindFirst error code = %d", rc ); michael@0: michael@0: return TRUE; michael@0: } michael@0: michael@0: static int dwNumFiles, dwReadEvery, dwFileToRead=0; michael@0: michael@0: static void michael@0: CountFiles(const char *file) michael@0: { michael@0: dwNumFiles++; michael@0: } michael@0: michael@0: static void michael@0: ReadFiles(const char *file) michael@0: { michael@0: if ((dwNumFiles % dwReadEvery) == 0) michael@0: RNG_FileForRNG(file); michael@0: michael@0: dwNumFiles++; michael@0: } michael@0: michael@0: static void michael@0: ReadSingleFile(const char *filename) michael@0: { michael@0: unsigned char buffer[1024]; michael@0: FILE *file; michael@0: michael@0: file = fopen((char *)filename, "rb"); michael@0: if (file != NULL) { michael@0: while (fread(buffer, 1, sizeof(buffer), file) > 0) michael@0: ; michael@0: fclose(file); michael@0: } michael@0: } michael@0: michael@0: static void michael@0: ReadOneFile(const char *file) michael@0: { michael@0: if (dwNumFiles == dwFileToRead) { michael@0: ReadSingleFile(file); michael@0: } michael@0: michael@0: dwNumFiles++; michael@0: } michael@0: michael@0: static void michael@0: ReadSystemFiles(void) michael@0: { michael@0: // first count the number of files michael@0: dwNumFiles = 0; michael@0: if (!EnumSystemFiles(CountFiles)) michael@0: return; michael@0: michael@0: RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles)); michael@0: michael@0: // now read 10 files michael@0: if (dwNumFiles == 0) michael@0: return; michael@0: michael@0: dwReadEvery = dwNumFiles / 10; michael@0: if (dwReadEvery == 0) michael@0: dwReadEvery = 1; // less than 10 files michael@0: michael@0: dwNumFiles = 0; michael@0: EnumSystemFiles(ReadFiles); michael@0: } michael@0: michael@0: void RNG_SystemInfoForRNG(void) michael@0: { michael@0: unsigned long *plong = 0; michael@0: PTIB ptib; michael@0: PPIB ppib; michael@0: APIRET rc = NO_ERROR; michael@0: DATETIME dt; michael@0: COUNTRYCODE cc = {0}; michael@0: COUNTRYINFO ci = {0}; michael@0: unsigned long actual = 0; michael@0: char path[_MAX_PATH]=""; michael@0: char fullpath[_MAX_PATH]=""; michael@0: unsigned long pathlength = sizeof(path); michael@0: FSALLOCATE fsallocate; michael@0: FILESTATUS3 fstatus; michael@0: unsigned long defaultdrive = 0; michael@0: unsigned long logicaldrives = 0; michael@0: unsigned long sysInfo[QSV_MAX] = {0}; michael@0: char buffer[20]; michael@0: int nBytes = 0; michael@0: michael@0: nBytes = RNG_GetNoise(buffer, sizeof(buffer)); michael@0: RNG_RandomUpdate(buffer, nBytes); michael@0: michael@0: /* allocate memory and use address and memory */ michael@0: plong = (unsigned long *)malloc(sizeof(*plong)); michael@0: RNG_RandomUpdate(&plong, sizeof(plong)); michael@0: RNG_RandomUpdate(plong, sizeof(*plong)); michael@0: free(plong); michael@0: michael@0: /* process info */ michael@0: rc = DosGetInfoBlocks(&ptib, &ppib); michael@0: if (rc == NO_ERROR) michael@0: { michael@0: RNG_RandomUpdate(ptib, sizeof(*ptib)); michael@0: RNG_RandomUpdate(ppib, sizeof(*ppib)); michael@0: } michael@0: michael@0: /* time */ michael@0: rc = DosGetDateTime(&dt); michael@0: if (rc == NO_ERROR) michael@0: { michael@0: RNG_RandomUpdate(&dt, sizeof(dt)); michael@0: } michael@0: michael@0: /* country */ michael@0: rc = DosQueryCtryInfo(sizeof(ci), &cc, &ci, &actual); michael@0: if (rc == NO_ERROR) michael@0: { michael@0: RNG_RandomUpdate(&cc, sizeof(cc)); michael@0: RNG_RandomUpdate(&ci, sizeof(ci)); michael@0: RNG_RandomUpdate(&actual, sizeof(actual)); michael@0: } michael@0: michael@0: /* current directory */ michael@0: rc = DosQueryCurrentDir(0, path, &pathlength); michael@0: strcat(fullpath, "\\"); michael@0: strcat(fullpath, path); michael@0: if (rc == NO_ERROR) michael@0: { michael@0: RNG_RandomUpdate(fullpath, strlen(fullpath)); michael@0: // path info michael@0: rc = DosQueryPathInfo(fullpath, FIL_STANDARD, &fstatus, sizeof(fstatus)); michael@0: if (rc == NO_ERROR) michael@0: { michael@0: RNG_RandomUpdate(&fstatus, sizeof(fstatus)); michael@0: } michael@0: } michael@0: michael@0: /* file system info */ michael@0: rc = DosQueryFSInfo(0, FSIL_ALLOC, &fsallocate, sizeof(fsallocate)); michael@0: if (rc == NO_ERROR) michael@0: { michael@0: RNG_RandomUpdate(&fsallocate, sizeof(fsallocate)); michael@0: } michael@0: michael@0: /* drive info */ michael@0: rc = DosQueryCurrentDisk(&defaultdrive, &logicaldrives); michael@0: if (rc == NO_ERROR) michael@0: { michael@0: RNG_RandomUpdate(&defaultdrive, sizeof(defaultdrive)); michael@0: RNG_RandomUpdate(&logicaldrives, sizeof(logicaldrives)); michael@0: } michael@0: michael@0: /* system info */ michael@0: rc = DosQuerySysInfo(1L, QSV_MAX, (PVOID)&sysInfo, sizeof(ULONG)*QSV_MAX); michael@0: if (rc == NO_ERROR) michael@0: { michael@0: RNG_RandomUpdate(&sysInfo, sizeof(sysInfo)); michael@0: } michael@0: michael@0: // now let's do some files michael@0: ReadSystemFiles(); michael@0: michael@0: /* more noise */ michael@0: nBytes = RNG_GetNoise(buffer, sizeof(buffer)); michael@0: RNG_RandomUpdate(buffer, nBytes); michael@0: } michael@0: michael@0: void RNG_FileForRNG(const char *filename) michael@0: { michael@0: struct stat stat_buf; michael@0: unsigned char buffer[1024]; michael@0: FILE *file = 0; michael@0: int nBytes = 0; michael@0: static int totalFileBytes = 0; michael@0: michael@0: if (stat((char *)filename, &stat_buf) < 0) michael@0: return; michael@0: michael@0: RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf)); michael@0: michael@0: file = fopen((char *)filename, "r"); michael@0: if (file != NULL) michael@0: { michael@0: for (;;) michael@0: { michael@0: size_t bytes = fread(buffer, 1, sizeof(buffer), file); michael@0: michael@0: if (bytes == 0) michael@0: break; michael@0: michael@0: RNG_RandomUpdate(buffer, bytes); michael@0: totalFileBytes += bytes; michael@0: if (totalFileBytes > 250000) michael@0: break; michael@0: } michael@0: fclose(file); michael@0: } michael@0: michael@0: nBytes = RNG_GetNoise(buffer, 20); michael@0: RNG_RandomUpdate(buffer, nBytes); michael@0: } michael@0: michael@0: static void rng_systemJitter(void) michael@0: { michael@0: dwNumFiles = 0; michael@0: EnumSystemFiles(ReadOneFile); michael@0: dwFileToRead++; michael@0: if (dwFileToRead >= dwNumFiles) { michael@0: dwFileToRead = 0; michael@0: } michael@0: } michael@0: michael@0: size_t RNG_SystemRNG(void *dest, size_t maxLen) michael@0: { michael@0: return rng_systemFromNoise(dest,maxLen); michael@0: }