diff options
Diffstat (limited to 'security/nss/lib/freebl/os2_rand.c')
-rw-r--r-- | security/nss/lib/freebl/os2_rand.c | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/security/nss/lib/freebl/os2_rand.c b/security/nss/lib/freebl/os2_rand.c new file mode 100644 index 000000000..407b08014 --- /dev/null +++ b/security/nss/lib/freebl/os2_rand.c @@ -0,0 +1,334 @@ +/* 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 <os2.h> +#include "secrng.h" +#include "prerror.h" +#include <stdlib.h> +#include <time.h> +#include <stdio.h> +#include <sys/stat.h> + +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); +} |