Back to index

lightning-sunbird  0.9+nobinonly
os2_rand.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #define INCL_DOS
00038 #define INCL_DOSERRORS
00039 #include <os2.h>
00040 #include "secrng.h"
00041 #include "prerror.h"
00042 #include <stdlib.h>
00043 #include <time.h>
00044 #include <stdio.h>
00045 #include <sys/stat.h>
00046 
00047 static BOOL clockTickTime(unsigned long *phigh, unsigned long *plow)
00048 {
00049     APIRET rc = NO_ERROR;
00050     QWORD qword = {0,0};
00051 
00052     rc = DosTmrQueryTime(&qword);
00053     if (rc != NO_ERROR)
00054        return FALSE;
00055 
00056     *phigh = qword.ulHi;
00057     *plow  = qword.ulLo;
00058 
00059     return TRUE;
00060 }
00061 
00062 size_t RNG_GetNoise(void *buf, size_t maxbuf)
00063 {
00064     unsigned long high = 0;
00065     unsigned long low  = 0;
00066     clock_t val = 0;
00067     int n = 0;
00068     int nBytes = 0;
00069     time_t sTime;
00070 
00071     if (maxbuf <= 0)
00072        return 0;
00073 
00074     clockTickTime(&high, &low);
00075 
00076     /* get the maximally changing bits first */
00077     nBytes = sizeof(low) > maxbuf ? maxbuf : sizeof(low);
00078     memcpy(buf, &low, nBytes);
00079     n += nBytes;
00080     maxbuf -= nBytes;
00081 
00082     if (maxbuf <= 0)
00083        return n;
00084 
00085     nBytes = sizeof(high) > maxbuf ? maxbuf : sizeof(high);
00086     memcpy(((char *)buf) + n, &high, nBytes);
00087     n += nBytes;
00088     maxbuf -= nBytes;
00089 
00090     if (maxbuf <= 0)
00091        return n;
00092 
00093     /* get the number of milliseconds that have elapsed since application started */
00094     val = clock();
00095 
00096     nBytes = sizeof(val) > maxbuf ? maxbuf : sizeof(val);
00097     memcpy(((char *)buf) + n, &val, nBytes);
00098     n += nBytes;
00099     maxbuf -= nBytes;
00100 
00101     if (maxbuf <= 0)
00102        return n;
00103 
00104     /* get the time in seconds since midnight Jan 1, 1970 */
00105     time(&sTime);
00106     nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
00107     memcpy(((char *)buf) + n, &sTime, nBytes);
00108     n += nBytes;
00109 
00110     return n;
00111 }
00112 
00113 static BOOL
00114 EnumSystemFiles(void (*func)(const char *))
00115 {
00116     APIRET              rc;
00117     ULONG               sysInfo = 0;
00118     char                bootLetter[2];
00119     char                sysDir[_MAX_PATH] = "";
00120     char                filename[_MAX_PATH];
00121     HDIR                hdir = HDIR_CREATE;
00122     ULONG               numFiles = 1;
00123     FILEFINDBUF3        fileBuf = {0};
00124     ULONG               buflen = sizeof(FILEFINDBUF3);
00125 
00126     if (DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&sysInfo,
00127                         sizeof(ULONG)) == NO_ERROR)
00128     {
00129       bootLetter[0] = sysInfo + 'A' -1;
00130       bootLetter[1] = '\0';
00131       strcpy(sysDir, bootLetter);
00132       strcpy(sysDir+1, ":\\OS2\\");
00133 
00134       strcpy( filename, sysDir );
00135       strcat( filename, "*.*" );
00136     }
00137 
00138     rc =DosFindFirst( filename, &hdir, FILE_NORMAL, &fileBuf, buflen,
00139                       &numFiles, FIL_STANDARD );
00140     if( rc == NO_ERROR )
00141     {
00142       do {
00143         // pass the full pathname to the callback
00144         sprintf( filename, "%s\\%s", sysDir, fileBuf.achName );
00145         (*func)(filename);
00146 
00147         numFiles = 1;
00148         rc = DosFindNext( hdir, &fileBuf, buflen, &numFiles );
00149         if( rc != NO_ERROR && rc != ERROR_NO_MORE_FILES )
00150           printf( "DosFindNext errod code = %d\n", rc );
00151       } while ( rc == NO_ERROR );
00152 
00153       rc = DosFindClose(hdir);
00154       if( rc != NO_ERROR )
00155         printf( "DosFindClose error code = %d", rc );
00156     }
00157     else
00158       printf( "DosFindFirst error code = %d", rc );
00159 
00160     return TRUE;
00161 }
00162 
00163 static int    dwNumFiles, dwReadEvery;
00164 
00165 static void
00166 CountFiles(const char *file)
00167 {
00168     dwNumFiles++;
00169 }
00170 
00171 static void
00172 ReadFiles(const char *file)
00173 {
00174     if ((dwNumFiles % dwReadEvery) == 0)
00175         RNG_FileForRNG(file);
00176 
00177     dwNumFiles++;
00178 }
00179 
00180 static void
00181 ReadSystemFiles(void)
00182 {
00183     // first count the number of files
00184     dwNumFiles = 0;
00185     if (!EnumSystemFiles(CountFiles))
00186         return;
00187 
00188     RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles));
00189 
00190     // now read 10 files
00191     if (dwNumFiles == 0)
00192         return;
00193 
00194     dwReadEvery = dwNumFiles / 10;
00195     if (dwReadEvery == 0)
00196         dwReadEvery = 1;  // less than 10 files
00197 
00198     dwNumFiles = 0;
00199     EnumSystemFiles(ReadFiles);
00200 }
00201 
00202 void RNG_SystemInfoForRNG(void)
00203 {
00204    unsigned long *plong = 0;
00205    PTIB ptib;
00206    PPIB ppib;
00207    APIRET rc = NO_ERROR;
00208    DATETIME dt;
00209    COUNTRYCODE cc = {0};
00210    COUNTRYINFO ci = {0};
00211    unsigned long actual = 0;
00212    char path[_MAX_PATH]="";
00213    char fullpath[_MAX_PATH]="";
00214    unsigned long pathlength = sizeof(path);
00215    FSALLOCATE fsallocate;
00216    FILESTATUS3 fstatus;
00217    unsigned long defaultdrive = 0;
00218    unsigned long logicaldrives = 0;
00219    unsigned long sysInfo[QSV_MAX] = {0};
00220    char buffer[20];
00221    int nBytes = 0;
00222 
00223    nBytes = RNG_GetNoise(buffer, sizeof(buffer));
00224    RNG_RandomUpdate(buffer, nBytes);
00225    
00226    /* allocate memory and use address and memory */
00227    plong = (unsigned long *)malloc(sizeof(*plong));
00228    RNG_RandomUpdate(&plong, sizeof(plong));
00229    RNG_RandomUpdate(plong, sizeof(*plong));
00230    free(plong);
00231 
00232    /* process info */
00233    rc = DosGetInfoBlocks(&ptib, &ppib);
00234    if (rc == NO_ERROR)
00235    {
00236       RNG_RandomUpdate(ptib, sizeof(*ptib));
00237       RNG_RandomUpdate(ppib, sizeof(*ppib));
00238    }
00239 
00240    /* time */
00241    rc = DosGetDateTime(&dt);
00242    if (rc == NO_ERROR)
00243    {
00244       RNG_RandomUpdate(&dt, sizeof(dt));
00245    }
00246 
00247    /* country */
00248    rc = DosQueryCtryInfo(sizeof(ci), &cc, &ci, &actual);
00249    if (rc == NO_ERROR)
00250    {
00251       RNG_RandomUpdate(&cc, sizeof(cc));
00252       RNG_RandomUpdate(&ci, sizeof(ci));
00253       RNG_RandomUpdate(&actual, sizeof(actual));
00254    }
00255 
00256    /* current directory */
00257    rc = DosQueryCurrentDir(0, path, &pathlength);
00258    strcat(fullpath, "\\");
00259    strcat(fullpath, path);
00260    if (rc == NO_ERROR)
00261    {
00262       RNG_RandomUpdate(fullpath, strlen(fullpath));
00263       // path info
00264       rc = DosQueryPathInfo(fullpath, FIL_STANDARD, &fstatus, sizeof(fstatus));
00265       if (rc == NO_ERROR)
00266       {
00267          RNG_RandomUpdate(&fstatus, sizeof(fstatus));
00268       }
00269    }
00270 
00271    /* file system info */
00272    rc = DosQueryFSInfo(0, FSIL_ALLOC, &fsallocate, sizeof(fsallocate));
00273    if (rc == NO_ERROR)
00274    {
00275       RNG_RandomUpdate(&fsallocate, sizeof(fsallocate));
00276    }
00277 
00278    /* drive info */
00279    rc = DosQueryCurrentDisk(&defaultdrive, &logicaldrives);
00280    if (rc == NO_ERROR)
00281    {
00282       RNG_RandomUpdate(&defaultdrive, sizeof(defaultdrive));
00283       RNG_RandomUpdate(&logicaldrives, sizeof(logicaldrives));
00284    }
00285 
00286    /* system info */
00287    rc = DosQuerySysInfo(1L, QSV_MAX, (PVOID)&sysInfo, sizeof(ULONG)*QSV_MAX);
00288    if (rc == NO_ERROR)
00289    {
00290       RNG_RandomUpdate(&sysInfo, sizeof(sysInfo));
00291    }
00292 
00293    // now let's do some files
00294    ReadSystemFiles();
00295 
00296    /* more noise */
00297    nBytes = RNG_GetNoise(buffer, sizeof(buffer));
00298    RNG_RandomUpdate(buffer, nBytes);
00299 }
00300 
00301 void RNG_FileForRNG(const char *filename)
00302 {
00303     struct stat stat_buf;
00304     unsigned char buffer[1024];
00305     FILE *file = 0;
00306     int nBytes = 0;
00307     static int totalFileBytes = 0;
00308     
00309     if (stat((char *)filename, &stat_buf) < 0)
00310        return;
00311 
00312     RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf));
00313     
00314     file = fopen((char *)filename, "r");
00315     if (file != NULL)
00316     {
00317        for (;;)
00318        {
00319            size_t bytes = fread(buffer, 1, sizeof(buffer), file);
00320 
00321            if (bytes == 0)
00322               break;
00323 
00324            RNG_RandomUpdate(buffer, bytes);
00325            totalFileBytes += bytes;
00326            if (totalFileBytes > 250000)
00327               break;
00328        }
00329        fclose(file);
00330     }
00331 
00332     nBytes = RNG_GetNoise(buffer, 20); 
00333     RNG_RandomUpdate(buffer, nBytes);
00334 }
00335 
00336 size_t RNG_SystemRNG(void *dest, size_t maxLen)
00337 {
00338     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
00339     return 0;
00340 }