|
| 1 | +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT |
| 2 | +// file at the top-level directory of this distribution and at |
| 3 | +// http://rust-lang.org/COPYRIGHT. |
| 4 | +// |
| 5 | +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 6 | +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 7 | +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| 8 | +// option. This file may not be copied, modified, or distributed |
| 9 | +// except according to those terms. |
| 10 | + |
| 11 | +#include "rust_globals.h" |
| 12 | +#include "rust_rng.h" |
| 13 | +#include "rust_util.h" |
| 14 | + |
| 15 | +// Initialization helpers for ISAAC RNG |
| 16 | + |
| 17 | +void |
| 18 | +isaac_seed(rust_kernel* kernel, uint8_t* dest, size_t size) { |
| 19 | +#ifdef __WIN32__ |
| 20 | + HCRYPTPROV hProv; |
| 21 | + kernel->win32_require |
| 22 | + (_T("CryptAcquireContext"), |
| 23 | + CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, |
| 24 | + CRYPT_VERIFYCONTEXT|CRYPT_SILENT)); |
| 25 | + kernel->win32_require |
| 26 | + (_T("CryptGenRandom"), CryptGenRandom(hProv, size, (BYTE*) dest)); |
| 27 | + kernel->win32_require |
| 28 | + (_T("CryptReleaseContext"), CryptReleaseContext(hProv, 0)); |
| 29 | +#else |
| 30 | + int fd = open("/dev/urandom", O_RDONLY); |
| 31 | + if (fd == -1) |
| 32 | + kernel->fatal("error opening /dev/urandom: %s", strerror(errno)); |
| 33 | + size_t amount = 0; |
| 34 | + do { |
| 35 | + ssize_t ret = read(fd, dest+amount, size-amount); |
| 36 | + if (ret < 0) |
| 37 | + kernel->fatal("error reading /dev/urandom: %s", strerror(errno)); |
| 38 | + else if (ret == 0) |
| 39 | + kernel->fatal("somehow hit eof reading from /dev/urandom"); |
| 40 | + amount += (size_t)ret; |
| 41 | + } while (amount < size); |
| 42 | + int ret = close(fd); |
| 43 | + // FIXME #3697: Why does this fail sometimes? |
| 44 | + if (ret != 0) |
| 45 | + kernel->log(log_warn, "error closing /dev/urandom: %s", |
| 46 | + strerror(errno)); |
| 47 | +#endif |
| 48 | +} |
| 49 | + |
| 50 | +void |
| 51 | +isaac_init(rust_kernel *kernel, randctx *rctx, rust_vec_box* user_seed) { |
| 52 | + memset(rctx, 0, sizeof(randctx)); |
| 53 | + |
| 54 | + char *env_seed = kernel->env->rust_seed; |
| 55 | + if (user_seed != NULL) { |
| 56 | + // ignore bytes after the required length |
| 57 | + size_t seed_len = user_seed->body.fill < sizeof(rctx->randrsl) |
| 58 | + ? user_seed->body.fill : sizeof(rctx->randrsl); |
| 59 | + memcpy(&rctx->randrsl, user_seed->body.data, seed_len); |
| 60 | + } else if (env_seed != NULL) { |
| 61 | + ub4 seed = (ub4) atoi(env_seed); |
| 62 | + for (size_t i = 0; i < RANDSIZ; i ++) { |
| 63 | + memcpy(&rctx->randrsl[i], &seed, sizeof(ub4)); |
| 64 | + seed = (seed + 0x7ed55d16) + (seed << 12); |
| 65 | + } |
| 66 | + } else { |
| 67 | + isaac_seed(kernel, (uint8_t*) &rctx->randrsl, sizeof(rctx->randrsl)); |
| 68 | + } |
| 69 | + |
| 70 | + randinit(rctx, 1); |
| 71 | +} |
| 72 | + |
| 73 | +// |
| 74 | +// Local Variables: |
| 75 | +// mode: C++ |
| 76 | +// fill-column: 78; |
| 77 | +// indent-tabs-mode: nil |
| 78 | +// c-basic-offset: 4 |
| 79 | +// buffer-file-coding-system: utf-8-unix |
| 80 | +// End: |
| 81 | +// |
0 commit comments