diff options
Diffstat (limited to 'src/lib/libcrypto/rand/rand_unix.c')
| -rw-r--r-- | src/lib/libcrypto/rand/rand_unix.c | 308 |
1 files changed, 2 insertions, 306 deletions
diff --git a/src/lib/libcrypto/rand/rand_unix.c b/src/lib/libcrypto/rand/rand_unix.c index 3316388443..a5b9b2a529 100644 --- a/src/lib/libcrypto/rand/rand_unix.c +++ b/src/lib/libcrypto/rand/rand_unix.c | |||
| @@ -108,318 +108,14 @@ | |||
| 108 | * Hudson (tjh@cryptsoft.com). | 108 | * Hudson (tjh@cryptsoft.com). |
| 109 | * | 109 | * |
| 110 | */ | 110 | */ |
| 111 | #include <stdio.h> | ||
| 112 | |||
| 113 | #define USE_SOCKETS | ||
| 114 | #include "e_os.h" | 111 | #include "e_os.h" |
| 115 | #include "cryptlib.h" | 112 | #include "cryptlib.h" |
| 116 | #include <openssl/rand.h> | 113 | #include <openssl/rand.h> |
| 117 | #include "rand_lcl.h" | ||
| 118 | |||
| 119 | #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE)) | ||
| 120 | |||
| 121 | #include <sys/types.h> | ||
| 122 | #include <sys/time.h> | ||
| 123 | #include <sys/times.h> | ||
| 124 | #include <sys/stat.h> | ||
| 125 | #include <fcntl.h> | ||
| 126 | #include <unistd.h> | ||
| 127 | #include <time.h> | ||
| 128 | #if defined(OPENSSL_SYS_LINUX) /* should actually be available virtually everywhere */ | ||
| 129 | # include <poll.h> | ||
| 130 | #endif | ||
| 131 | #include <limits.h> | ||
| 132 | #ifndef FD_SETSIZE | ||
| 133 | # define FD_SETSIZE (8*sizeof(fd_set)) | ||
| 134 | #endif | ||
| 135 | |||
| 136 | #if defined(OPENSSL_SYS_VOS) | ||
| 137 | |||
| 138 | /* The following algorithm repeatedly samples the real-time clock | ||
| 139 | (RTC) to generate a sequence of unpredictable data. The algorithm | ||
| 140 | relies upon the uneven execution speed of the code (due to factors | ||
| 141 | such as cache misses, interrupts, bus activity, and scheduling) and | ||
| 142 | upon the rather large relative difference between the speed of the | ||
| 143 | clock and the rate at which it can be read. | ||
| 144 | |||
| 145 | If this code is ported to an environment where execution speed is | ||
| 146 | more constant or where the RTC ticks at a much slower rate, or the | ||
| 147 | clock can be read with fewer instructions, it is likely that the | ||
| 148 | results would be far more predictable. | ||
| 149 | |||
| 150 | As a precaution, we generate 4 times the minimum required amount of | ||
| 151 | seed data. */ | ||
| 152 | |||
| 153 | int RAND_poll(void) | ||
| 154 | { | ||
| 155 | short int code; | ||
| 156 | gid_t curr_gid; | ||
| 157 | pid_t curr_pid; | ||
| 158 | uid_t curr_uid; | ||
| 159 | int i, k; | ||
| 160 | struct timespec ts; | ||
| 161 | unsigned char v; | ||
| 162 | |||
| 163 | #ifdef OPENSSL_SYS_VOS_HPPA | ||
| 164 | long duration; | ||
| 165 | extern void s$sleep (long *_duration, short int *_code); | ||
| 166 | #else | ||
| 167 | #ifdef OPENSSL_SYS_VOS_IA32 | ||
| 168 | long long duration; | ||
| 169 | extern void s$sleep2 (long long *_duration, short int *_code); | ||
| 170 | #else | ||
| 171 | #error "Unsupported Platform." | ||
| 172 | #endif /* OPENSSL_SYS_VOS_IA32 */ | ||
| 173 | #endif /* OPENSSL_SYS_VOS_HPPA */ | ||
| 174 | |||
| 175 | /* Seed with the gid, pid, and uid, to ensure *some* | ||
| 176 | variation between different processes. */ | ||
| 177 | 114 | ||
| 178 | curr_gid = getgid(); | 115 | #include <stdlib.h> |
| 179 | RAND_add (&curr_gid, sizeof curr_gid, 1); | 116 | #include <string.h> |
| 180 | curr_gid = 0; | ||
| 181 | 117 | ||
| 182 | curr_pid = getpid(); | ||
| 183 | RAND_add (&curr_pid, sizeof curr_pid, 1); | ||
| 184 | curr_pid = 0; | ||
| 185 | |||
| 186 | curr_uid = getuid(); | ||
| 187 | RAND_add (&curr_uid, sizeof curr_uid, 1); | ||
| 188 | curr_uid = 0; | ||
| 189 | |||
| 190 | for (i=0; i<(ENTROPY_NEEDED*4); i++) | ||
| 191 | { | ||
| 192 | /* burn some cpu; hope for interrupts, cache | ||
| 193 | collisions, bus interference, etc. */ | ||
| 194 | for (k=0; k<99; k++) | ||
| 195 | ts.tv_nsec = random (); | ||
| 196 | |||
| 197 | #ifdef OPENSSL_SYS_VOS_HPPA | ||
| 198 | /* sleep for 1/1024 of a second (976 us). */ | ||
| 199 | duration = 1; | ||
| 200 | s$sleep (&duration, &code); | ||
| 201 | #else | ||
| 202 | #ifdef OPENSSL_SYS_VOS_IA32 | ||
| 203 | /* sleep for 1/65536 of a second (15 us). */ | ||
| 204 | duration = 1; | ||
| 205 | s$sleep2 (&duration, &code); | ||
| 206 | #endif /* OPENSSL_SYS_VOS_IA32 */ | ||
| 207 | #endif /* OPENSSL_SYS_VOS_HPPA */ | ||
| 208 | |||
| 209 | /* get wall clock time. */ | ||
| 210 | clock_gettime (CLOCK_REALTIME, &ts); | ||
| 211 | |||
| 212 | /* take 8 bits */ | ||
| 213 | v = (unsigned char) (ts.tv_nsec % 256); | ||
| 214 | RAND_add (&v, sizeof v, 1); | ||
| 215 | v = 0; | ||
| 216 | } | ||
| 217 | return 1; | ||
| 218 | } | ||
| 219 | #elif defined __OpenBSD__ | ||
| 220 | int RAND_poll(void) | 118 | int RAND_poll(void) |
| 221 | { | 119 | { |
| 222 | unsigned char buf[ENTROPY_NEEDED]; | ||
| 223 | |||
| 224 | arc4random_buf(buf, sizeof(buf)); | ||
| 225 | RAND_add(buf, sizeof(buf), sizeof(buf)); | ||
| 226 | memset(buf, 0, sizeof(buf)); | ||
| 227 | |||
| 228 | return 1; | 120 | return 1; |
| 229 | } | 121 | } |
| 230 | #else /* !defined(__OpenBSD__) */ | ||
| 231 | int RAND_poll(void) | ||
| 232 | { | ||
| 233 | unsigned long l; | ||
| 234 | pid_t curr_pid = getpid(); | ||
| 235 | #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) | ||
| 236 | unsigned char tmpbuf[ENTROPY_NEEDED]; | ||
| 237 | int n = 0; | ||
| 238 | #endif | ||
| 239 | #ifdef DEVRANDOM | ||
| 240 | static const char *randomfiles[] = { DEVRANDOM }; | ||
| 241 | struct stat randomstats[sizeof(randomfiles)/sizeof(randomfiles[0])]; | ||
| 242 | int fd; | ||
| 243 | unsigned int i; | ||
| 244 | #endif | ||
| 245 | #ifdef DEVRANDOM_EGD | ||
| 246 | static const char *egdsockets[] = { DEVRANDOM_EGD, NULL }; | ||
| 247 | const char **egdsocket = NULL; | ||
| 248 | #endif | ||
| 249 | |||
| 250 | #ifdef DEVRANDOM | ||
| 251 | memset(randomstats,0,sizeof(randomstats)); | ||
| 252 | /* Use a random entropy pool device. Linux, FreeBSD and OpenBSD | ||
| 253 | * have this. Use /dev/urandom if you can as /dev/random may block | ||
| 254 | * if it runs out of random entries. */ | ||
| 255 | |||
| 256 | for (i = 0; (i < sizeof(randomfiles)/sizeof(randomfiles[0])) && | ||
| 257 | (n < ENTROPY_NEEDED); i++) | ||
| 258 | { | ||
| 259 | if ((fd = open(randomfiles[i], O_RDONLY | ||
| 260 | #ifdef O_NONBLOCK | ||
| 261 | |O_NONBLOCK | ||
| 262 | #endif | ||
| 263 | #ifdef O_BINARY | ||
| 264 | |O_BINARY | ||
| 265 | #endif | ||
| 266 | #ifdef O_NOCTTY /* If it happens to be a TTY (god forbid), do not make it | ||
| 267 | our controlling tty */ | ||
| 268 | |O_NOCTTY | ||
| 269 | #endif | ||
| 270 | )) >= 0) | ||
| 271 | { | ||
| 272 | int usec = 10*1000; /* spend 10ms on each file */ | ||
| 273 | int r; | ||
| 274 | unsigned int j; | ||
| 275 | struct stat *st=&randomstats[i]; | ||
| 276 | |||
| 277 | /* Avoid using same input... Used to be O_NOFOLLOW | ||
| 278 | * above, but it's not universally appropriate... */ | ||
| 279 | if (fstat(fd,st) != 0) { close(fd); continue; } | ||
| 280 | for (j=0;j<i;j++) | ||
| 281 | { | ||
| 282 | if (randomstats[j].st_ino==st->st_ino && | ||
| 283 | randomstats[j].st_dev==st->st_dev) | ||
| 284 | break; | ||
| 285 | } | ||
| 286 | if (j<i) { close(fd); continue; } | ||
| 287 | |||
| 288 | do | ||
| 289 | { | ||
| 290 | int try_read = 0; | ||
| 291 | |||
| 292 | #if defined(OPENSSL_SYS_BEOS_R5) | ||
| 293 | /* select() is broken in BeOS R5, so we simply | ||
| 294 | * try to read something and snooze if we couldn't */ | ||
| 295 | try_read = 1; | ||
| 296 | |||
| 297 | #elif defined(OPENSSL_SYS_LINUX) | ||
| 298 | /* use poll() */ | ||
| 299 | struct pollfd pset; | ||
| 300 | |||
| 301 | pset.fd = fd; | ||
| 302 | pset.events = POLLIN; | ||
| 303 | pset.revents = 0; | ||
| 304 | |||
| 305 | if (poll(&pset, 1, usec / 1000) < 0) | ||
| 306 | usec = 0; | ||
| 307 | else | ||
| 308 | try_read = (pset.revents & POLLIN) != 0; | ||
| 309 | |||
| 310 | #else | ||
| 311 | /* use select() */ | ||
| 312 | fd_set fset; | ||
| 313 | struct timeval t; | ||
| 314 | |||
| 315 | t.tv_sec = 0; | ||
| 316 | t.tv_usec = usec; | ||
| 317 | |||
| 318 | if (FD_SETSIZE > 0 && (unsigned)fd >= FD_SETSIZE) | ||
| 319 | { | ||
| 320 | /* can't use select, so just try to read once anyway */ | ||
| 321 | try_read = 1; | ||
| 322 | } | ||
| 323 | else | ||
| 324 | { | ||
| 325 | FD_ZERO(&fset); | ||
| 326 | FD_SET(fd, &fset); | ||
| 327 | |||
| 328 | if (select(fd+1,&fset,NULL,NULL,&t) >= 0) | ||
| 329 | { | ||
| 330 | usec = t.tv_usec; | ||
| 331 | if (FD_ISSET(fd, &fset)) | ||
| 332 | try_read = 1; | ||
| 333 | } | ||
| 334 | else | ||
| 335 | usec = 0; | ||
| 336 | } | ||
| 337 | #endif | ||
| 338 | |||
| 339 | if (try_read) | ||
| 340 | { | ||
| 341 | r = read(fd,(unsigned char *)tmpbuf+n, ENTROPY_NEEDED-n); | ||
| 342 | if (r > 0) | ||
| 343 | n += r; | ||
| 344 | #if defined(OPENSSL_SYS_BEOS_R5) | ||
| 345 | if (r == 0) | ||
| 346 | snooze(t.tv_usec); | ||
| 347 | #endif | ||
| 348 | } | ||
| 349 | else | ||
| 350 | r = -1; | ||
| 351 | |||
| 352 | /* Some Unixen will update t in select(), some | ||
| 353 | won't. For those who won't, or if we | ||
| 354 | didn't use select() in the first place, | ||
| 355 | give up here, otherwise, we will do | ||
| 356 | this once again for the remaining | ||
| 357 | time. */ | ||
| 358 | if (usec == 10*1000) | ||
| 359 | usec = 0; | ||
| 360 | } | ||
| 361 | while ((r > 0 || | ||
| 362 | (errno == EINTR || errno == EAGAIN)) && usec != 0 && n < ENTROPY_NEEDED); | ||
| 363 | |||
| 364 | close(fd); | ||
| 365 | } | ||
| 366 | } | ||
| 367 | #endif /* defined(DEVRANDOM) */ | ||
| 368 | |||
| 369 | #ifdef DEVRANDOM_EGD | ||
| 370 | /* Use an EGD socket to read entropy from an EGD or PRNGD entropy | ||
| 371 | * collecting daemon. */ | ||
| 372 | |||
| 373 | for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED; egdsocket++) | ||
| 374 | { | ||
| 375 | int r; | ||
| 376 | |||
| 377 | r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf+n, | ||
| 378 | ENTROPY_NEEDED-n); | ||
| 379 | if (r > 0) | ||
| 380 | n += r; | ||
| 381 | } | ||
| 382 | #endif /* defined(DEVRANDOM_EGD) */ | ||
| 383 | |||
| 384 | #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) | ||
| 385 | if (n > 0) | ||
| 386 | { | ||
| 387 | RAND_add(tmpbuf,sizeof tmpbuf,(double)n); | ||
| 388 | OPENSSL_cleanse(tmpbuf,n); | ||
| 389 | } | ||
| 390 | #endif | ||
| 391 | |||
| 392 | /* put in some default random data, we need more than just this */ | ||
| 393 | l=curr_pid; | ||
| 394 | RAND_add(&l,sizeof(l),0.0); | ||
| 395 | l=getuid(); | ||
| 396 | RAND_add(&l,sizeof(l),0.0); | ||
| 397 | |||
| 398 | l=time(NULL); | ||
| 399 | RAND_add(&l,sizeof(l),0.0); | ||
| 400 | |||
| 401 | #if defined(OPENSSL_SYS_BEOS) | ||
| 402 | { | ||
| 403 | system_info sysInfo; | ||
| 404 | get_system_info(&sysInfo); | ||
| 405 | RAND_add(&sysInfo,sizeof(sysInfo),0); | ||
| 406 | } | ||
| 407 | #endif | ||
| 408 | |||
| 409 | #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) | ||
| 410 | return 1; | ||
| 411 | #else | ||
| 412 | return 0; | ||
| 413 | #endif | ||
| 414 | } | ||
| 415 | |||
| 416 | #endif /* defined(__OpenBSD__) */ | ||
| 417 | #endif /* !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE)) */ | ||
| 418 | |||
| 419 | |||
| 420 | #if defined(OPENSSL_SYS_VXWORKS) | ||
| 421 | int RAND_poll(void) | ||
| 422 | { | ||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | #endif | ||
