security/nss/lib/freebl/os2_rand.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/freebl/os2_rand.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,341 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#define INCL_DOS
     1.9 +#define INCL_DOSERRORS
    1.10 +#include <os2.h>
    1.11 +#include "secrng.h"
    1.12 +#include "prerror.h"
    1.13 +#include <stdlib.h>
    1.14 +#include <time.h>
    1.15 +#include <stdio.h>
    1.16 +#include <sys/stat.h>
    1.17 +
    1.18 +static BOOL clockTickTime(unsigned long *phigh, unsigned long *plow)
    1.19 +{
    1.20 +    APIRET rc = NO_ERROR;
    1.21 +    QWORD qword = {0,0};
    1.22 +
    1.23 +    rc = DosTmrQueryTime(&qword);
    1.24 +    if (rc != NO_ERROR)
    1.25 +       return FALSE;
    1.26 +
    1.27 +    *phigh = qword.ulHi;
    1.28 +    *plow  = qword.ulLo;
    1.29 +
    1.30 +    return TRUE;
    1.31 +}
    1.32 +
    1.33 +size_t RNG_GetNoise(void *buf, size_t maxbuf)
    1.34 +{
    1.35 +    unsigned long high = 0;
    1.36 +    unsigned long low  = 0;
    1.37 +    clock_t val = 0;
    1.38 +    int n = 0;
    1.39 +    int nBytes = 0;
    1.40 +    time_t sTime;
    1.41 +
    1.42 +    if (maxbuf <= 0)
    1.43 +       return 0;
    1.44 +
    1.45 +    clockTickTime(&high, &low);
    1.46 +
    1.47 +    /* get the maximally changing bits first */
    1.48 +    nBytes = sizeof(low) > maxbuf ? maxbuf : sizeof(low);
    1.49 +    memcpy(buf, &low, nBytes);
    1.50 +    n += nBytes;
    1.51 +    maxbuf -= nBytes;
    1.52 +
    1.53 +    if (maxbuf <= 0)
    1.54 +       return n;
    1.55 +
    1.56 +    nBytes = sizeof(high) > maxbuf ? maxbuf : sizeof(high);
    1.57 +    memcpy(((char *)buf) + n, &high, nBytes);
    1.58 +    n += nBytes;
    1.59 +    maxbuf -= nBytes;
    1.60 +
    1.61 +    if (maxbuf <= 0)
    1.62 +       return n;
    1.63 +
    1.64 +    /* get the number of milliseconds that have elapsed since application started */
    1.65 +    val = clock();
    1.66 +
    1.67 +    nBytes = sizeof(val) > maxbuf ? maxbuf : sizeof(val);
    1.68 +    memcpy(((char *)buf) + n, &val, nBytes);
    1.69 +    n += nBytes;
    1.70 +    maxbuf -= nBytes;
    1.71 +
    1.72 +    if (maxbuf <= 0)
    1.73 +       return n;
    1.74 +
    1.75 +    /* get the time in seconds since midnight Jan 1, 1970 */
    1.76 +    time(&sTime);
    1.77 +    nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
    1.78 +    memcpy(((char *)buf) + n, &sTime, nBytes);
    1.79 +    n += nBytes;
    1.80 +
    1.81 +    return n;
    1.82 +}
    1.83 +
    1.84 +static BOOL
    1.85 +EnumSystemFiles(void (*func)(const char *))
    1.86 +{
    1.87 +    APIRET              rc;
    1.88 +    ULONG               sysInfo = 0;
    1.89 +    char                bootLetter[2];
    1.90 +    char                sysDir[_MAX_PATH] = "";
    1.91 +    char                filename[_MAX_PATH];
    1.92 +    HDIR                hdir = HDIR_CREATE;
    1.93 +    ULONG               numFiles = 1;
    1.94 +    FILEFINDBUF3        fileBuf = {0};
    1.95 +    ULONG               buflen = sizeof(FILEFINDBUF3);
    1.96 +
    1.97 +    if (DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&sysInfo,
    1.98 +                        sizeof(ULONG)) == NO_ERROR)
    1.99 +    {
   1.100 +      bootLetter[0] = sysInfo + 'A' -1;
   1.101 +      bootLetter[1] = '\0';
   1.102 +      strcpy(sysDir, bootLetter);
   1.103 +      strcpy(sysDir+1, ":\\OS2\\");
   1.104 +
   1.105 +      strcpy( filename, sysDir );
   1.106 +      strcat( filename, "*.*" );
   1.107 +    }
   1.108 +
   1.109 +    rc =DosFindFirst( filename, &hdir, FILE_NORMAL, &fileBuf, buflen,
   1.110 +                      &numFiles, FIL_STANDARD );
   1.111 +    if( rc == NO_ERROR )
   1.112 +    {
   1.113 +      do {
   1.114 +        // pass the full pathname to the callback
   1.115 +        sprintf( filename, "%s%s", sysDir, fileBuf.achName );
   1.116 +        (*func)(filename);
   1.117 +
   1.118 +        numFiles = 1;
   1.119 +        rc = DosFindNext( hdir, &fileBuf, buflen, &numFiles );
   1.120 +        if( rc != NO_ERROR && rc != ERROR_NO_MORE_FILES )
   1.121 +          printf( "DosFindNext errod code = %d\n", rc );
   1.122 +      } while ( rc == NO_ERROR );
   1.123 +
   1.124 +      rc = DosFindClose(hdir);
   1.125 +      if( rc != NO_ERROR )
   1.126 +        printf( "DosFindClose error code = %d", rc );
   1.127 +    }
   1.128 +    else
   1.129 +      printf( "DosFindFirst error code = %d", rc );
   1.130 +
   1.131 +    return TRUE;
   1.132 +}
   1.133 +
   1.134 +static int    dwNumFiles, dwReadEvery, dwFileToRead=0;
   1.135 +
   1.136 +static void
   1.137 +CountFiles(const char *file)
   1.138 +{
   1.139 +    dwNumFiles++;
   1.140 +}
   1.141 +
   1.142 +static void
   1.143 +ReadFiles(const char *file)
   1.144 +{
   1.145 +    if ((dwNumFiles % dwReadEvery) == 0)
   1.146 +        RNG_FileForRNG(file);
   1.147 +
   1.148 +    dwNumFiles++;
   1.149 +}
   1.150 +
   1.151 +static void 
   1.152 +ReadSingleFile(const char *filename)
   1.153 +{
   1.154 +    unsigned char buffer[1024];
   1.155 +    FILE *file; 
   1.156 +    
   1.157 +    file = fopen((char *)filename, "rb");
   1.158 +    if (file != NULL) {
   1.159 +	while (fread(buffer, 1, sizeof(buffer), file) > 0) 
   1.160 +	    ;
   1.161 +	fclose(file);
   1.162 +    }
   1.163 +}
   1.164 +
   1.165 +static void
   1.166 +ReadOneFile(const char *file)
   1.167 +{
   1.168 +    if (dwNumFiles == dwFileToRead) {
   1.169 +        ReadSingleFile(file);
   1.170 +    }
   1.171 +
   1.172 +    dwNumFiles++;
   1.173 +}
   1.174 +
   1.175 +static void
   1.176 +ReadSystemFiles(void)
   1.177 +{
   1.178 +    // first count the number of files
   1.179 +    dwNumFiles = 0;
   1.180 +    if (!EnumSystemFiles(CountFiles))
   1.181 +        return;
   1.182 +
   1.183 +    RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles));
   1.184 +
   1.185 +    // now read 10 files
   1.186 +    if (dwNumFiles == 0)
   1.187 +        return;
   1.188 +
   1.189 +    dwReadEvery = dwNumFiles / 10;
   1.190 +    if (dwReadEvery == 0)
   1.191 +        dwReadEvery = 1;  // less than 10 files
   1.192 +
   1.193 +    dwNumFiles = 0;
   1.194 +    EnumSystemFiles(ReadFiles);
   1.195 +}
   1.196 +
   1.197 +void RNG_SystemInfoForRNG(void)
   1.198 +{
   1.199 +   unsigned long *plong = 0;
   1.200 +   PTIB ptib;
   1.201 +   PPIB ppib;
   1.202 +   APIRET rc = NO_ERROR;
   1.203 +   DATETIME dt;
   1.204 +   COUNTRYCODE cc = {0};
   1.205 +   COUNTRYINFO ci = {0};
   1.206 +   unsigned long actual = 0;
   1.207 +   char path[_MAX_PATH]="";
   1.208 +   char fullpath[_MAX_PATH]="";
   1.209 +   unsigned long pathlength = sizeof(path);
   1.210 +   FSALLOCATE fsallocate;
   1.211 +   FILESTATUS3 fstatus;
   1.212 +   unsigned long defaultdrive = 0;
   1.213 +   unsigned long logicaldrives = 0;
   1.214 +   unsigned long sysInfo[QSV_MAX] = {0};
   1.215 +   char buffer[20];
   1.216 +   int nBytes = 0;
   1.217 +
   1.218 +   nBytes = RNG_GetNoise(buffer, sizeof(buffer));
   1.219 +   RNG_RandomUpdate(buffer, nBytes);
   1.220 +   
   1.221 +   /* allocate memory and use address and memory */
   1.222 +   plong = (unsigned long *)malloc(sizeof(*plong));
   1.223 +   RNG_RandomUpdate(&plong, sizeof(plong));
   1.224 +   RNG_RandomUpdate(plong, sizeof(*plong));
   1.225 +   free(plong);
   1.226 +
   1.227 +   /* process info */
   1.228 +   rc = DosGetInfoBlocks(&ptib, &ppib);
   1.229 +   if (rc == NO_ERROR)
   1.230 +   {
   1.231 +      RNG_RandomUpdate(ptib, sizeof(*ptib));
   1.232 +      RNG_RandomUpdate(ppib, sizeof(*ppib));
   1.233 +   }
   1.234 +
   1.235 +   /* time */
   1.236 +   rc = DosGetDateTime(&dt);
   1.237 +   if (rc == NO_ERROR)
   1.238 +   {
   1.239 +      RNG_RandomUpdate(&dt, sizeof(dt));
   1.240 +   }
   1.241 +
   1.242 +   /* country */
   1.243 +   rc = DosQueryCtryInfo(sizeof(ci), &cc, &ci, &actual);
   1.244 +   if (rc == NO_ERROR)
   1.245 +   {
   1.246 +      RNG_RandomUpdate(&cc, sizeof(cc));
   1.247 +      RNG_RandomUpdate(&ci, sizeof(ci));
   1.248 +      RNG_RandomUpdate(&actual, sizeof(actual));
   1.249 +   }
   1.250 +
   1.251 +   /* current directory */
   1.252 +   rc = DosQueryCurrentDir(0, path, &pathlength);
   1.253 +   strcat(fullpath, "\\");
   1.254 +   strcat(fullpath, path);
   1.255 +   if (rc == NO_ERROR)
   1.256 +   {
   1.257 +      RNG_RandomUpdate(fullpath, strlen(fullpath));
   1.258 +      // path info
   1.259 +      rc = DosQueryPathInfo(fullpath, FIL_STANDARD, &fstatus, sizeof(fstatus));
   1.260 +      if (rc == NO_ERROR)
   1.261 +      {
   1.262 +         RNG_RandomUpdate(&fstatus, sizeof(fstatus));
   1.263 +      }
   1.264 +   }
   1.265 +
   1.266 +   /* file system info */
   1.267 +   rc = DosQueryFSInfo(0, FSIL_ALLOC, &fsallocate, sizeof(fsallocate));
   1.268 +   if (rc == NO_ERROR)
   1.269 +   {
   1.270 +      RNG_RandomUpdate(&fsallocate, sizeof(fsallocate));
   1.271 +   }
   1.272 +
   1.273 +   /* drive info */
   1.274 +   rc = DosQueryCurrentDisk(&defaultdrive, &logicaldrives);
   1.275 +   if (rc == NO_ERROR)
   1.276 +   {
   1.277 +      RNG_RandomUpdate(&defaultdrive, sizeof(defaultdrive));
   1.278 +      RNG_RandomUpdate(&logicaldrives, sizeof(logicaldrives));
   1.279 +   }
   1.280 +
   1.281 +   /* system info */
   1.282 +   rc = DosQuerySysInfo(1L, QSV_MAX, (PVOID)&sysInfo, sizeof(ULONG)*QSV_MAX);
   1.283 +   if (rc == NO_ERROR)
   1.284 +   {
   1.285 +      RNG_RandomUpdate(&sysInfo, sizeof(sysInfo));
   1.286 +   }
   1.287 +
   1.288 +   // now let's do some files
   1.289 +   ReadSystemFiles();
   1.290 +
   1.291 +   /* more noise */
   1.292 +   nBytes = RNG_GetNoise(buffer, sizeof(buffer));
   1.293 +   RNG_RandomUpdate(buffer, nBytes);
   1.294 +}
   1.295 +
   1.296 +void RNG_FileForRNG(const char *filename)
   1.297 +{
   1.298 +    struct stat stat_buf;
   1.299 +    unsigned char buffer[1024];
   1.300 +    FILE *file = 0;
   1.301 +    int nBytes = 0;
   1.302 +    static int totalFileBytes = 0;
   1.303 +    
   1.304 +    if (stat((char *)filename, &stat_buf) < 0)
   1.305 +       return;
   1.306 +
   1.307 +    RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf));
   1.308 +    
   1.309 +    file = fopen((char *)filename, "r");
   1.310 +    if (file != NULL)
   1.311 +    {
   1.312 +       for (;;)
   1.313 +       {
   1.314 +           size_t bytes = fread(buffer, 1, sizeof(buffer), file);
   1.315 +
   1.316 +           if (bytes == 0)
   1.317 +              break;
   1.318 +
   1.319 +           RNG_RandomUpdate(buffer, bytes);
   1.320 +           totalFileBytes += bytes;
   1.321 +           if (totalFileBytes > 250000)
   1.322 +              break;
   1.323 +       }
   1.324 +       fclose(file);
   1.325 +    }
   1.326 +
   1.327 +    nBytes = RNG_GetNoise(buffer, 20); 
   1.328 +    RNG_RandomUpdate(buffer, nBytes);
   1.329 +}
   1.330 +
   1.331 +static void rng_systemJitter(void)
   1.332 +{
   1.333 +    dwNumFiles = 0;
   1.334 +    EnumSystemFiles(ReadOneFile);
   1.335 +    dwFileToRead++;
   1.336 +    if (dwFileToRead >= dwNumFiles) {
   1.337 +	dwFileToRead = 0;
   1.338 +    }
   1.339 +}
   1.340 +
   1.341 +size_t RNG_SystemRNG(void *dest, size_t maxLen)
   1.342 +{
   1.343 +    return rng_systemFromNoise(dest,maxLen);
   1.344 +}

mercurial