Blame nss/lib/freebl/os2_rand.c

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