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