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 +}