security/nss/lib/freebl/os2_rand.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #define INCL_DOS
michael@0 6 #define INCL_DOSERRORS
michael@0 7 #include <os2.h>
michael@0 8 #include "secrng.h"
michael@0 9 #include "prerror.h"
michael@0 10 #include <stdlib.h>
michael@0 11 #include <time.h>
michael@0 12 #include <stdio.h>
michael@0 13 #include <sys/stat.h>
michael@0 14
michael@0 15 static BOOL clockTickTime(unsigned long *phigh, unsigned long *plow)
michael@0 16 {
michael@0 17 APIRET rc = NO_ERROR;
michael@0 18 QWORD qword = {0,0};
michael@0 19
michael@0 20 rc = DosTmrQueryTime(&qword);
michael@0 21 if (rc != NO_ERROR)
michael@0 22 return FALSE;
michael@0 23
michael@0 24 *phigh = qword.ulHi;
michael@0 25 *plow = qword.ulLo;
michael@0 26
michael@0 27 return TRUE;
michael@0 28 }
michael@0 29
michael@0 30 size_t RNG_GetNoise(void *buf, size_t maxbuf)
michael@0 31 {
michael@0 32 unsigned long high = 0;
michael@0 33 unsigned long low = 0;
michael@0 34 clock_t val = 0;
michael@0 35 int n = 0;
michael@0 36 int nBytes = 0;
michael@0 37 time_t sTime;
michael@0 38
michael@0 39 if (maxbuf <= 0)
michael@0 40 return 0;
michael@0 41
michael@0 42 clockTickTime(&high, &low);
michael@0 43
michael@0 44 /* get the maximally changing bits first */
michael@0 45 nBytes = sizeof(low) > maxbuf ? maxbuf : sizeof(low);
michael@0 46 memcpy(buf, &low, nBytes);
michael@0 47 n += nBytes;
michael@0 48 maxbuf -= nBytes;
michael@0 49
michael@0 50 if (maxbuf <= 0)
michael@0 51 return n;
michael@0 52
michael@0 53 nBytes = sizeof(high) > maxbuf ? maxbuf : sizeof(high);
michael@0 54 memcpy(((char *)buf) + n, &high, nBytes);
michael@0 55 n += nBytes;
michael@0 56 maxbuf -= nBytes;
michael@0 57
michael@0 58 if (maxbuf <= 0)
michael@0 59 return n;
michael@0 60
michael@0 61 /* get the number of milliseconds that have elapsed since application started */
michael@0 62 val = clock();
michael@0 63
michael@0 64 nBytes = sizeof(val) > maxbuf ? maxbuf : sizeof(val);
michael@0 65 memcpy(((char *)buf) + n, &val, nBytes);
michael@0 66 n += nBytes;
michael@0 67 maxbuf -= nBytes;
michael@0 68
michael@0 69 if (maxbuf <= 0)
michael@0 70 return n;
michael@0 71
michael@0 72 /* get the time in seconds since midnight Jan 1, 1970 */
michael@0 73 time(&sTime);
michael@0 74 nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
michael@0 75 memcpy(((char *)buf) + n, &sTime, nBytes);
michael@0 76 n += nBytes;
michael@0 77
michael@0 78 return n;
michael@0 79 }
michael@0 80
michael@0 81 static BOOL
michael@0 82 EnumSystemFiles(void (*func)(const char *))
michael@0 83 {
michael@0 84 APIRET rc;
michael@0 85 ULONG sysInfo = 0;
michael@0 86 char bootLetter[2];
michael@0 87 char sysDir[_MAX_PATH] = "";
michael@0 88 char filename[_MAX_PATH];
michael@0 89 HDIR hdir = HDIR_CREATE;
michael@0 90 ULONG numFiles = 1;
michael@0 91 FILEFINDBUF3 fileBuf = {0};
michael@0 92 ULONG buflen = sizeof(FILEFINDBUF3);
michael@0 93
michael@0 94 if (DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&sysInfo,
michael@0 95 sizeof(ULONG)) == NO_ERROR)
michael@0 96 {
michael@0 97 bootLetter[0] = sysInfo + 'A' -1;
michael@0 98 bootLetter[1] = '\0';
michael@0 99 strcpy(sysDir, bootLetter);
michael@0 100 strcpy(sysDir+1, ":\\OS2\\");
michael@0 101
michael@0 102 strcpy( filename, sysDir );
michael@0 103 strcat( filename, "*.*" );
michael@0 104 }
michael@0 105
michael@0 106 rc =DosFindFirst( filename, &hdir, FILE_NORMAL, &fileBuf, buflen,
michael@0 107 &numFiles, FIL_STANDARD );
michael@0 108 if( rc == NO_ERROR )
michael@0 109 {
michael@0 110 do {
michael@0 111 // pass the full pathname to the callback
michael@0 112 sprintf( filename, "%s%s", sysDir, fileBuf.achName );
michael@0 113 (*func)(filename);
michael@0 114
michael@0 115 numFiles = 1;
michael@0 116 rc = DosFindNext( hdir, &fileBuf, buflen, &numFiles );
michael@0 117 if( rc != NO_ERROR && rc != ERROR_NO_MORE_FILES )
michael@0 118 printf( "DosFindNext errod code = %d\n", rc );
michael@0 119 } while ( rc == NO_ERROR );
michael@0 120
michael@0 121 rc = DosFindClose(hdir);
michael@0 122 if( rc != NO_ERROR )
michael@0 123 printf( "DosFindClose error code = %d", rc );
michael@0 124 }
michael@0 125 else
michael@0 126 printf( "DosFindFirst error code = %d", rc );
michael@0 127
michael@0 128 return TRUE;
michael@0 129 }
michael@0 130
michael@0 131 static int dwNumFiles, dwReadEvery, dwFileToRead=0;
michael@0 132
michael@0 133 static void
michael@0 134 CountFiles(const char *file)
michael@0 135 {
michael@0 136 dwNumFiles++;
michael@0 137 }
michael@0 138
michael@0 139 static void
michael@0 140 ReadFiles(const char *file)
michael@0 141 {
michael@0 142 if ((dwNumFiles % dwReadEvery) == 0)
michael@0 143 RNG_FileForRNG(file);
michael@0 144
michael@0 145 dwNumFiles++;
michael@0 146 }
michael@0 147
michael@0 148 static void
michael@0 149 ReadSingleFile(const char *filename)
michael@0 150 {
michael@0 151 unsigned char buffer[1024];
michael@0 152 FILE *file;
michael@0 153
michael@0 154 file = fopen((char *)filename, "rb");
michael@0 155 if (file != NULL) {
michael@0 156 while (fread(buffer, 1, sizeof(buffer), file) > 0)
michael@0 157 ;
michael@0 158 fclose(file);
michael@0 159 }
michael@0 160 }
michael@0 161
michael@0 162 static void
michael@0 163 ReadOneFile(const char *file)
michael@0 164 {
michael@0 165 if (dwNumFiles == dwFileToRead) {
michael@0 166 ReadSingleFile(file);
michael@0 167 }
michael@0 168
michael@0 169 dwNumFiles++;
michael@0 170 }
michael@0 171
michael@0 172 static void
michael@0 173 ReadSystemFiles(void)
michael@0 174 {
michael@0 175 // first count the number of files
michael@0 176 dwNumFiles = 0;
michael@0 177 if (!EnumSystemFiles(CountFiles))
michael@0 178 return;
michael@0 179
michael@0 180 RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles));
michael@0 181
michael@0 182 // now read 10 files
michael@0 183 if (dwNumFiles == 0)
michael@0 184 return;
michael@0 185
michael@0 186 dwReadEvery = dwNumFiles / 10;
michael@0 187 if (dwReadEvery == 0)
michael@0 188 dwReadEvery = 1; // less than 10 files
michael@0 189
michael@0 190 dwNumFiles = 0;
michael@0 191 EnumSystemFiles(ReadFiles);
michael@0 192 }
michael@0 193
michael@0 194 void RNG_SystemInfoForRNG(void)
michael@0 195 {
michael@0 196 unsigned long *plong = 0;
michael@0 197 PTIB ptib;
michael@0 198 PPIB ppib;
michael@0 199 APIRET rc = NO_ERROR;
michael@0 200 DATETIME dt;
michael@0 201 COUNTRYCODE cc = {0};
michael@0 202 COUNTRYINFO ci = {0};
michael@0 203 unsigned long actual = 0;
michael@0 204 char path[_MAX_PATH]="";
michael@0 205 char fullpath[_MAX_PATH]="";
michael@0 206 unsigned long pathlength = sizeof(path);
michael@0 207 FSALLOCATE fsallocate;
michael@0 208 FILESTATUS3 fstatus;
michael@0 209 unsigned long defaultdrive = 0;
michael@0 210 unsigned long logicaldrives = 0;
michael@0 211 unsigned long sysInfo[QSV_MAX] = {0};
michael@0 212 char buffer[20];
michael@0 213 int nBytes = 0;
michael@0 214
michael@0 215 nBytes = RNG_GetNoise(buffer, sizeof(buffer));
michael@0 216 RNG_RandomUpdate(buffer, nBytes);
michael@0 217
michael@0 218 /* allocate memory and use address and memory */
michael@0 219 plong = (unsigned long *)malloc(sizeof(*plong));
michael@0 220 RNG_RandomUpdate(&plong, sizeof(plong));
michael@0 221 RNG_RandomUpdate(plong, sizeof(*plong));
michael@0 222 free(plong);
michael@0 223
michael@0 224 /* process info */
michael@0 225 rc = DosGetInfoBlocks(&ptib, &ppib);
michael@0 226 if (rc == NO_ERROR)
michael@0 227 {
michael@0 228 RNG_RandomUpdate(ptib, sizeof(*ptib));
michael@0 229 RNG_RandomUpdate(ppib, sizeof(*ppib));
michael@0 230 }
michael@0 231
michael@0 232 /* time */
michael@0 233 rc = DosGetDateTime(&dt);
michael@0 234 if (rc == NO_ERROR)
michael@0 235 {
michael@0 236 RNG_RandomUpdate(&dt, sizeof(dt));
michael@0 237 }
michael@0 238
michael@0 239 /* country */
michael@0 240 rc = DosQueryCtryInfo(sizeof(ci), &cc, &ci, &actual);
michael@0 241 if (rc == NO_ERROR)
michael@0 242 {
michael@0 243 RNG_RandomUpdate(&cc, sizeof(cc));
michael@0 244 RNG_RandomUpdate(&ci, sizeof(ci));
michael@0 245 RNG_RandomUpdate(&actual, sizeof(actual));
michael@0 246 }
michael@0 247
michael@0 248 /* current directory */
michael@0 249 rc = DosQueryCurrentDir(0, path, &pathlength);
michael@0 250 strcat(fullpath, "\\");
michael@0 251 strcat(fullpath, path);
michael@0 252 if (rc == NO_ERROR)
michael@0 253 {
michael@0 254 RNG_RandomUpdate(fullpath, strlen(fullpath));
michael@0 255 // path info
michael@0 256 rc = DosQueryPathInfo(fullpath, FIL_STANDARD, &fstatus, sizeof(fstatus));
michael@0 257 if (rc == NO_ERROR)
michael@0 258 {
michael@0 259 RNG_RandomUpdate(&fstatus, sizeof(fstatus));
michael@0 260 }
michael@0 261 }
michael@0 262
michael@0 263 /* file system info */
michael@0 264 rc = DosQueryFSInfo(0, FSIL_ALLOC, &fsallocate, sizeof(fsallocate));
michael@0 265 if (rc == NO_ERROR)
michael@0 266 {
michael@0 267 RNG_RandomUpdate(&fsallocate, sizeof(fsallocate));
michael@0 268 }
michael@0 269
michael@0 270 /* drive info */
michael@0 271 rc = DosQueryCurrentDisk(&defaultdrive, &logicaldrives);
michael@0 272 if (rc == NO_ERROR)
michael@0 273 {
michael@0 274 RNG_RandomUpdate(&defaultdrive, sizeof(defaultdrive));
michael@0 275 RNG_RandomUpdate(&logicaldrives, sizeof(logicaldrives));
michael@0 276 }
michael@0 277
michael@0 278 /* system info */
michael@0 279 rc = DosQuerySysInfo(1L, QSV_MAX, (PVOID)&sysInfo, sizeof(ULONG)*QSV_MAX);
michael@0 280 if (rc == NO_ERROR)
michael@0 281 {
michael@0 282 RNG_RandomUpdate(&sysInfo, sizeof(sysInfo));
michael@0 283 }
michael@0 284
michael@0 285 // now let's do some files
michael@0 286 ReadSystemFiles();
michael@0 287
michael@0 288 /* more noise */
michael@0 289 nBytes = RNG_GetNoise(buffer, sizeof(buffer));
michael@0 290 RNG_RandomUpdate(buffer, nBytes);
michael@0 291 }
michael@0 292
michael@0 293 void RNG_FileForRNG(const char *filename)
michael@0 294 {
michael@0 295 struct stat stat_buf;
michael@0 296 unsigned char buffer[1024];
michael@0 297 FILE *file = 0;
michael@0 298 int nBytes = 0;
michael@0 299 static int totalFileBytes = 0;
michael@0 300
michael@0 301 if (stat((char *)filename, &stat_buf) < 0)
michael@0 302 return;
michael@0 303
michael@0 304 RNG_RandomUpdate((unsigned char*)&stat_buf, sizeof(stat_buf));
michael@0 305
michael@0 306 file = fopen((char *)filename, "r");
michael@0 307 if (file != NULL)
michael@0 308 {
michael@0 309 for (;;)
michael@0 310 {
michael@0 311 size_t bytes = fread(buffer, 1, sizeof(buffer), file);
michael@0 312
michael@0 313 if (bytes == 0)
michael@0 314 break;
michael@0 315
michael@0 316 RNG_RandomUpdate(buffer, bytes);
michael@0 317 totalFileBytes += bytes;
michael@0 318 if (totalFileBytes > 250000)
michael@0 319 break;
michael@0 320 }
michael@0 321 fclose(file);
michael@0 322 }
michael@0 323
michael@0 324 nBytes = RNG_GetNoise(buffer, 20);
michael@0 325 RNG_RandomUpdate(buffer, nBytes);
michael@0 326 }
michael@0 327
michael@0 328 static void rng_systemJitter(void)
michael@0 329 {
michael@0 330 dwNumFiles = 0;
michael@0 331 EnumSystemFiles(ReadOneFile);
michael@0 332 dwFileToRead++;
michael@0 333 if (dwFileToRead >= dwNumFiles) {
michael@0 334 dwFileToRead = 0;
michael@0 335 }
michael@0 336 }
michael@0 337
michael@0 338 size_t RNG_SystemRNG(void *dest, size_t maxLen)
michael@0 339 {
michael@0 340 return rng_systemFromNoise(dest,maxLen);
michael@0 341 }

mercurial