From df906d2e75d6822c88999b8cc537166371f2da6e Mon Sep 17 00:00:00 2001 From: "Paul R. Eggert" Date: Fri, 23 Jul 2010 15:07:27 -0700 Subject: randread: run 2x faster on 64-bit hosts, don't assume no padding bits * gl/lib/rand-isaac.c: Remove the I/O; this belongs elsewhere. Add support for ISAAC64. Port to hosts with padding bits. Add self to author list. Include , for CHAR_BIT. Don't include string.h, sys/time.h, unistd.h. (min, just): New functions. (IF32): New macros. (ind, ISAAC_STEP, isaac_refill, mix, isaac_init, isaac_seed): Add support for ISAAC64. Port to hosts with padding bits. (ind): Now an inline function rather than a macro; no need for it to be a macro with modern compilers. (ISAAC_STEP): Renamed from isaac_step, since it's not function-like. Don't bother to pass args that are always the same. All uses changed. (ISAAC_STEP, ISAAC_SEED): Move to inside the only function body that can use it. (ISAAC_MIX): Renamed from isaac_mix, since it's now a macro and is no longer function-like. Don't bother saving and restoring state; no longer needed now that we're not a function. All uses changed. (isaac_seed_start, isaac_seed_data, isaac_seed_finish): Remove. (isaac_seed): Take just the one arg; the caller now sets s->m. * gl/lib/rand-isaac.h: Use _GL_RAND_ISAAC_H to protect, instead of RAND_ISAAC_H. Try out " #" rather than "# " for indenting. (ISAAC_BITS_LOG, ISAAC_BITS): New macros. (ISAAC_WORDS_LOG): Renamed from ISAAC_LOG. (isaac_word): New type. All uses of uint32_t changed to isaac_word, to support ISAAC64. (struct isaac_state): Rename member MM to M, and make it public. (isaac_seed, isaac_refill): Adjust to new API. * gl/lib/randread.c: Include sys/time.h. (get_nonce): New function, containing the nonce stuff that used to be in rand-isaac.c but better belongs here. (randread_new): Use it. * gl/modules/randread (Depends-on): Add inline. * gl/modules/randread-tests: New file. * gl/tests/test-rand-isaac.c: New file. --- gl/lib/rand-isaac.c | 373 ++++++++++++++++++++++------------------------------ gl/lib/rand-isaac.h | 53 +++++--- gl/lib/randread.c | 60 ++++++++- 3 files changed, 247 insertions(+), 239 deletions(-) (limited to 'gl/lib') diff --git a/gl/lib/rand-isaac.c b/gl/lib/rand-isaac.c index f73144afe..efa9ba2dc 100644 --- a/gl/lib/rand-isaac.c +++ b/gl/lib/rand-isaac.c @@ -1,4 +1,4 @@ -/* Bob Jenkins's cryptographic random number generator, ISAAC. +/* Bob Jenkins's cryptographic random number generators, ISAAC and ISAAC64. Copyright (C) 1999-2006, 2009-2010 Free Software Foundation, Inc. Copyright (C) 1997, 1998, 1999 Colin Plumb. @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . - Written by Colin Plumb. */ + Written by Colin Plumb and Paul Eggert. */ /* * -------------------------------------------------------------------- @@ -34,59 +34,90 @@ #include "rand-isaac.h" -#include -#include -#include +#include +/* The minimum of two sizes A and B. */ +static inline size_t +min (size_t a, size_t b) +{ + return (a < b ? a : b); +} -/* This index operation is more efficient on many processors */ -#define ind(mm, x) \ - (* (uint32_t *) ((char *) (mm) \ - + ((x) & (ISAAC_WORDS - 1) * sizeof (uint32_t)))) +/* A if 32-bit ISAAC, B if 64-bit. This is a macro, not an inline + function, to prevent undefined behavior if the unused argument + shifts by more than a word width. */ +#define IF32(a, b) (ISAAC_BITS == 32 ? (a) : (b)) -/* - * The central step. This uses two temporaries, x and y. mm is the - * whole state array, while m is a pointer to the current word. off is - * the offset from m to the word ISAAC_WORDS/2 words away in the mm array, - * i.e. +/- ISAAC_WORDS/2. - */ -#define isaac_step(mix, a, b, mm, m, off, r) \ -( \ - a = ((a) ^ (mix)) + (m)[off], \ - x = *(m), \ - *(m) = y = ind (mm, x) + (a) + (b), \ - *(r) = b = ind (mm, (y) >> ISAAC_LOG) + x \ -) +/* Discard bits outside the desired range. On typical machines, any + decent compiler should optimize this function call away to nothing. + But machines with pad bits in integers may need to do more work. */ +static inline isaac_word +just (isaac_word a) +{ + isaac_word desired_bits = ((isaac_word) 1 << 1 << (ISAAC_BITS - 1)) - 1; + return a & desired_bits; +} -/* Use and update *S to generate random data to fill R. */ -void -isaac_refill (struct isaac_state *s, uint32_t r[ISAAC_WORDS]) +/* The index operation. On typical machines whose words are exactly + the right size, this is optimized to a mask, an addition, and an + indirect load. Atypical machines need more work. */ +static inline isaac_word +ind (isaac_word const *m, isaac_word x) { - uint32_t a, b; /* Caches of a and b */ - uint32_t x, y; /* Temps needed by isaac_step macro */ - uint32_t *m = s->mm; /* Pointer into state array */ + return (sizeof *m * CHAR_BIT == ISAAC_BITS + ? (* (isaac_word *) ((char *) m + + (x & ((ISAAC_WORDS - 1) * sizeof *m)))) + : m[(x / (ISAAC_BITS / CHAR_BIT)) & (ISAAC_WORDS - 1)]); +} - a = s->a; - b = s->b + (++s->c); +/* Use and update *S to generate random data to fill RESULT. */ +void +isaac_refill (struct isaac_state *s, isaac_word result[ISAAC_WORDS]) +{ + /* Caches of S->a and S->b. */ + isaac_word a = s->a; + isaac_word b = s->b + (++s->c); + + /* Pointers into state array and into result. */ + isaac_word *m = s->m; + isaac_word *r = result; + + enum { HALF = ISAAC_WORDS / 2 }; + + /* The central step. S->m is the whole state array, while M is a + pointer to the current word. OFF is the offset from M to the + word ISAAC_WORDS/2 words away in the SM array, i.e. +/- + ISAAC_WORDS/2. A and B are state variables, and R the result. + This updates A, B, M[I], and R[I]. */ + #define ISAAC_STEP(i, off, mix) \ + { \ + isaac_word x, y; \ + a = (IF32 (a, 0) ^ (mix)) + m[off + (i)]; \ + x = m[i]; \ + m[i] = y = ind (s->m, x) + a + b; \ + r[i] = b = just (ind (s->m, y >> ISAAC_WORDS_LOG) + x); \ + } do { - isaac_step (a << 13, a, b, s->mm, m, ISAAC_WORDS / 2, r); - isaac_step (a >> 6, a, b, s->mm, m + 1, ISAAC_WORDS / 2, r + 1); - isaac_step (a << 2, a, b, s->mm, m + 2, ISAAC_WORDS / 2, r + 2); - isaac_step (a >> 16, a, b, s->mm, m + 3, ISAAC_WORDS / 2, r + 3); + ISAAC_STEP (0, HALF, IF32 ( a << 13, ~ (a ^ (a << 21)))); + ISAAC_STEP (1, HALF, IF32 (just (a) >> 6, a ^ (just (a) >> 5))); + ISAAC_STEP (2, HALF, IF32 ( a << 2, a ^ ( a << 12))); + ISAAC_STEP (3, HALF, IF32 (just (a) >> 16, a ^ (just (a) >> 33))); r += 4; } - while ((m += 4) < s->mm + ISAAC_WORDS / 2); + while ((m += 4) < s->m + HALF); + do { - isaac_step (a << 13, a, b, s->mm, m, -ISAAC_WORDS / 2, r); - isaac_step (a >> 6, a, b, s->mm, m + 1, -ISAAC_WORDS / 2, r + 1); - isaac_step (a << 2, a, b, s->mm, m + 2, -ISAAC_WORDS / 2, r + 2); - isaac_step (a >> 16, a, b, s->mm, m + 3, -ISAAC_WORDS / 2, r + 3); + ISAAC_STEP (0, -HALF, IF32 ( a << 13, ~ (a ^ (a << 21)))); + ISAAC_STEP (1, -HALF, IF32 (just (a) >> 6, a ^ (just (a) >> 5))); + ISAAC_STEP (2, -HALF, IF32 ( a << 2, a ^ ( a << 12))); + ISAAC_STEP (3, -HALF, IF32 (just (a) >> 16, a ^ (just (a) >> 33))); r += 4; } - while ((m += 4) < s->mm + ISAAC_WORDS); + while ((m += 4) < s->m + ISAAC_WORDS); + s->a = a; s->b = b; } @@ -95,223 +126,133 @@ isaac_refill (struct isaac_state *s, uint32_t r[ISAAC_WORDS]) * The basic seed-scrambling step for initialization, based on Bob * Jenkins' 256-bit hash. */ -#define mix(a,b,c,d,e,f,g,h) \ - ( a ^= b << 11, d += a, \ - b += c, b ^= c >> 2, e += b, \ - c += d, c ^= d << 8, f += c, \ - d += e, d ^= e >> 16, g += d, \ - e += f, e ^= f << 10, h += e, \ - f += g, f ^= g >> 4, a += f, \ - g += h, g ^= h << 8, b += g, \ - h += a, h ^= a >> 9, c += h, \ - a += b ) - -/* The basic ISAAC initialization pass. */ -static void -isaac_mix (struct isaac_state *s, uint32_t const seed[/* ISAAC_WORDS */]) -{ - int i; - uint32_t a = s->iv[0]; - uint32_t b = s->iv[1]; - uint32_t c = s->iv[2]; - uint32_t d = s->iv[3]; - uint32_t e = s->iv[4]; - uint32_t f = s->iv[5]; - uint32_t g = s->iv[6]; - uint32_t h = s->iv[7]; - - for (i = 0; i < ISAAC_WORDS; i += 8) - { - a += seed[i]; - b += seed[i + 1]; - c += seed[i + 2]; - d += seed[i + 3]; - e += seed[i + 4]; - f += seed[i + 5]; - g += seed[i + 6]; - h += seed[i + 7]; - - mix (a, b, c, d, e, f, g, h); - - s->mm[i] = a; - s->mm[i + 1] = b; - s->mm[i + 2] = c; - s->mm[i + 3] = d; - s->mm[i + 4] = e; - s->mm[i + 5] = f; - s->mm[i + 6] = g; - s->mm[i + 7] = h; +#if ISAAC_BITS == 32 + #define mix(a, b, c, d, e, f, g, h) \ + { \ + a ^= b << 11; d += a; \ + b += c; b ^= just (c) >> 2; e += b; \ + c += d; c ^= d << 8; f += c; \ + d += e; d ^= just (e) >> 16; g += d; \ + e += f; e ^= f << 10; h += e; \ + f += g; f ^= just (g) >> 4; a += f; \ + g += h; g ^= h << 8; b += g; \ + h += a; h ^= just (a) >> 9; c += h; \ + a += b; \ + } +#else + #define mix(a, b, c, d, e, f, g, h) \ + { \ + a -= e; f ^= just (h) >> 9; h += a; \ + b -= f; g ^= a << 9; a += b; \ + c -= g; h ^= just (b) >> 23; b += c; \ + d -= h; a ^= c << 15; c += d; \ + e -= a; b ^= just (d) >> 14; d += e; \ + f -= b; c ^= e << 20; e += f; \ + g -= c; d ^= just (f) >> 17; f += g; \ + h -= d; e ^= g << 14; g += h; \ } +#endif - s->iv[0] = a; - s->iv[1] = b; - s->iv[2] = c; - s->iv[3] = d; - s->iv[4] = e; - s->iv[5] = f; - s->iv[6] = g; - s->iv[7] = h; -} + +/* The basic ISAAC initialization pass. */ +#define ISAAC_MIX(s, a, b, c, d, e, f, g, h, seed) \ + { \ + int i; \ + \ + for (i = 0; i < ISAAC_WORDS; i += 8) \ + { \ + a += seed[i]; \ + b += seed[i + 1]; \ + c += seed[i + 2]; \ + d += seed[i + 3]; \ + e += seed[i + 4]; \ + f += seed[i + 5]; \ + g += seed[i + 6]; \ + h += seed[i + 7]; \ + mix (a, b, c, d, e, f, g, h); \ + s->m[i] = a; \ + s->m[i + 1] = b; \ + s->m[i + 2] = c; \ + s->m[i + 3] = d; \ + s->m[i + 4] = e; \ + s->m[i + 5] = f; \ + s->m[i + 6] = g; \ + s->m[i + 7] = h; \ + } \ + } #if 0 /* Provided for reference only; not used in this code */ /* * Initialize the ISAAC RNG with the given seed material. * Its size MUST be a multiple of ISAAC_BYTES, and may be - * stored in the s->mm array. + * stored in the s->m array. * * This is a generalization of the original ISAAC initialization code * to support larger seed sizes. For seed sizes of 0 and ISAAC_BYTES, * it is identical. */ static void -isaac_init (struct isaac_state *s, uint32_t const *seed, size_t seedsize) +isaac_init (struct isaac_state *s, isaac_word const *seed, size_t seedsize) { - static uint32_t const iv[8] = - { - 0x1367df5a, 0x95d90059, 0xc3163e4b, 0x0f421ad8, - 0xd92a4a78, 0xa51a3c49, 0xc4efea1b, 0x30609119}; - int i; + isaac_word a, b, c, d, e, f, g, h; -# if 0 - /* The initialization of iv is a precomputed form of: */ - for (i = 0; i < 7; i++) - iv[i] = 0x9e3779b9; /* the golden ratio */ - for (i = 0; i < 4; ++i) /* scramble it */ - mix (iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]); -# endif + a = b = c = d = e = f = g = h = /* the golden ratio */ + IF32 (UINT32_C (0x9e3779b9), UINT64_C (0x9e3779b97f4a7c13)); + for (int i = 0; i < 4; i++) /* scramble it */ + mix (a, b, c, d, e, f, g, h); s->a = s->b = s->c = 0; - for (i = 0; i < 8; i++) - s->iv[i] = iv[i]; - if (seedsize) { /* First pass (as in reference ISAAC code) */ - isaac_mix (s, seed); + ISAAC_MIX (s, a, b, c, d, e, f, g, h, seed); /* Second and subsequent passes (extension to ISAAC) */ while (seedsize -= ISAAC_BYTES) { seed += ISAAC_WORDS; for (i = 0; i < ISAAC_WORDS; i++) - s->mm[i] += seed[i]; - isaac_mix (s, s->mm); + s->m[i] += seed[i]; + ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m); } } else { /* The no seed case (as in reference ISAAC code) */ for (i = 0; i < ISAAC_WORDS; i++) - s->mm[i] = 0; + s->m[i] = 0; } /* Final pass */ - isaac_mix (s, s->mm); + ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m); } #endif -/* Initialize *S to a somewhat-random value. The first SEEDED bytes - in S->mm are already seeded with random data. */ -static void -isaac_seed_start (struct isaac_state *s, size_t seeded) +/* Initialize *S to a somewhat-random value, derived from a seed + stored in S->m. */ +void +isaac_seed (struct isaac_state *s) { - static uint32_t const iv[8] = - { - 0x1367df5a, 0x95d90059, 0xc3163e4b, 0x0f421ad8, - 0xd92a4a78, 0xa51a3c49, 0xc4efea1b, 0x30609119 - }; + isaac_word a = IF32 (UINT32_C (0x1367df5a), UINT64_C (0x647c4677a2884b7c)); + isaac_word b = IF32 (UINT32_C (0x95d90059), UINT64_C (0xb9f8b322c73ac862)); + isaac_word c = IF32 (UINT32_C (0xc3163e4b), UINT64_C (0x8c0ea5053d4712a0)); + isaac_word d = IF32 (UINT32_C (0x0f421ad8), UINT64_C (0xb29b2e824a595524)); + isaac_word e = IF32 (UINT32_C (0xd92a4a78), UINT64_C (0x82f053db8355e0ce)); + isaac_word f = IF32 (UINT32_C (0xa51a3c49), UINT64_C (0x48fe4a0fa5a09315)); + isaac_word g = IF32 (UINT32_C (0xc4efea1b), UINT64_C (0xae985bf2cbfc89ed)); + isaac_word h = IF32 (UINT32_C (0x30609119), UINT64_C (0x98f5704f6c44c0ab)); #if 0 - /* The initialization of iv is a precomputed form of: */ - int i; - for (i = 0; i < 7; i++) - iv[i] = 0x9e3779b9; /* the golden ratio */ - for (i = 0; i < 4; ++i) /* scramble it */ - mix (iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]); + /* The initialization of a through h is a precomputed form of: */ + a = b = c = d = e = f = g = h = /* the golden ratio */ + IF32 (UINT32_C (0x9e3779b9), UINT64_C (0x9e3779b97f4a7c13)); + for (int i = 0; i < 4; i++) /* scramble it */ + mix (a, b, c, d, e, f, g, h); #endif - memset ((char *) s->mm + seeded, 0, sizeof s->mm - seeded); - memcpy (s->iv, iv, sizeof s->iv); - - /* s->c gets used for a data pointer during the seeding phase */ - s->a = s->b = 0; - s->c = seeded; -} - -/* Add a buffer of seed material. */ -static void -isaac_seed_data (struct isaac_state *s, void const *buffer, size_t size) -{ - unsigned char const *buf = buffer; - unsigned char *p; - size_t avail; - size_t i; - - avail = sizeof s->mm - s->c; /* s->c is used as a write pointer */ - - /* Do any full buffers that are necessary */ - while (size > avail) - { - p = (unsigned char *) s->mm + s->c; - for (i = 0; i < avail; i++) - p[i] ^= buf[i]; - buf += avail; - size -= avail; - isaac_mix (s, s->mm); - s->c = 0; - avail = sizeof s->mm; - } - - /* And the final partial block */ - p = (unsigned char *) s->mm + s->c; - for (i = 0; i < size; i++) - p[i] ^= buf[i]; - s->c = size; -} - - -/* End of seeding phase; get everything ready to produce output. */ -static void -isaac_seed_finish (struct isaac_state *s) -{ - isaac_mix (s, s->mm); - isaac_mix (s, s->mm); - /* Now reinitialize c to start things off right */ - s->c = 0; -} -#define ISAAC_SEED(s,x) isaac_seed_data (s, &(x), sizeof (x)) - -/* Initialize *S to a somewhat-random value; this starts seeding, - seeds with somewhat-random data, and finishes seeding. If FD is - nonnegative, seed by reading at most BYTES_BOUNDS bytes from it. */ -void -isaac_seed (struct isaac_state *s, int fd, size_t bytes_bound) -{ - /* Get some data from FD if available. */ - ssize_t seeded = 0; - if (0 <= fd) - { - if (sizeof s->mm < bytes_bound) - bytes_bound = sizeof s->mm; - seeded = read (fd, s->mm, bytes_bound); - if (seeded < 0) - seeded = 0; - } - - isaac_seed_start (s, seeded); - - if (seeded < sizeof s->mm) - { - { pid_t t = getpid (); ISAAC_SEED (s, t); } - { pid_t t = getppid (); ISAAC_SEED (s, t); } - { uid_t t = getuid (); ISAAC_SEED (s, t); } - { gid_t t = getgid (); ISAAC_SEED (s, t); } + /* Mix S->m so that every part of the seed affects every part of the + state. */ + ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m); + ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m); - { - struct timeval t; - gettimeofday (&t, NULL); - ISAAC_SEED (s, t); - } - } - - isaac_seed_finish (s); + s->a = s->b = s->c = 0; } diff --git a/gl/lib/rand-isaac.h b/gl/lib/rand-isaac.h index 052dc9f3a..6e5af0676 100644 --- a/gl/lib/rand-isaac.h +++ b/gl/lib/rand-isaac.h @@ -1,4 +1,4 @@ -/* Bob Jenkins's cryptographic random number generator, ISAAC. +/* Bob Jenkins's cryptographic random number generators, ISAAC and ISAAC64. Copyright (C) 1999-2005, 2009-2010 Free Software Foundation, Inc. Copyright (C) 1997, 1998, 1999 Colin Plumb. @@ -16,29 +16,50 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . - Written by Colin Plumb. */ + Written by Colin Plumb and Paul Eggert. */ -#ifndef RAND_ISAAC_H -# define RAND_ISAAC_H +#ifndef _GL_RAND_ISAAC_H +#define _GL_RAND_ISAAC_H -# include -# include +#include +#include -/* Size of the state tables to use. ISAAC_LOG should be at least 3, +/* Log base 2 of the number of useful bits in an ISAAC word. It must + be either 5 or 6. By default, this uses a value that should be + faster for this architecture. */ +#ifndef ISAAC_BITS_LOG + #if SIZE_MAX >> 31 >> 31 < 3 /* SIZE_MAX < 2**64 - 1 */ + #define ISAAC_BITS_LOG 5 + #else + #define ISAAC_BITS_LOG 6 + #endif +#endif + +/* The number of bits in an ISAAC word. */ +#define ISAAC_BITS (1 << ISAAC_BITS_LOG) + +#if ISAAC_BITS == 32 + typedef uint_least32_t isaac_word; +#else + typedef uint_least64_t isaac_word; +#endif + +/* Size of the state tables to use. ISAAC_WORDS_LOG should be at least 3, and smaller values give less security. */ -# define ISAAC_LOG 8 -# define ISAAC_WORDS (1 << ISAAC_LOG) -# define ISAAC_BYTES (ISAAC_WORDS * sizeof (uint32_t)) +#define ISAAC_WORDS_LOG 8 +#define ISAAC_WORDS (1 << ISAAC_WORDS_LOG) +#define ISAAC_BYTES (ISAAC_WORDS * sizeof (isaac_word)) -/* RNG state variables. The members of this structure are private. */ +/* State variables for the random number generator. The M member + should be seeded with nonce data before calling isaac_seed. The + other members are private. */ struct isaac_state { - uint32_t mm[ISAAC_WORDS]; /* Main state array */ - uint32_t iv[8]; /* Seeding initial vector */ - uint32_t a, b, c; /* Extra index variables */ + isaac_word m[ISAAC_WORDS]; /* Main state array */ + isaac_word a, b, c; /* Extra variables */ }; -void isaac_seed (struct isaac_state *, int, size_t); -void isaac_refill (struct isaac_state *, uint32_t[ISAAC_WORDS]); +void isaac_seed (struct isaac_state *); +void isaac_refill (struct isaac_state *, isaac_word[ISAAC_WORDS]); #endif diff --git a/gl/lib/randread.c b/gl/lib/randread.c index a681c8dae..dcaeee460 100644 --- a/gl/lib/randread.c +++ b/gl/lib/randread.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "gettext.h" @@ -106,7 +107,7 @@ struct randread_source /* Up to a buffer's worth of pseudorandom data. */ union { - uint32_t w[ISAAC_WORDS]; + isaac_word w[ISAAC_WORDS]; unsigned char b[ISAAC_BYTES]; } data; } isaac; @@ -139,6 +140,52 @@ simple_new (FILE *source, void const *handler_arg) return s; } +/* Put a nonce value into BUFFER, with size BUFSIZE, but do not get + more than BYTES_BOUND bytes' worth of random information from any + nonce device. */ + +static void +get_nonce (void *buffer, size_t bufsize, size_t bytes_bound) +{ + char *buf = buffer; + ssize_t seeded = 0; + + /* Get some data from FD if available. */ + int fd = open (NAME_OF_NONCE_DEVICE, O_RDONLY | O_BINARY); + if (0 <= fd) + { + seeded = read (fd, buf, MIN (bufsize, bytes_bound)); + if (seeded < 0) + seeded = 0; + close (fd); + } + + /* If there's no nonce device, use a poor approximation + by getting the time of day, etc. */ +# define ISAAC_SEED(type, initialize_v) \ + if (seeded < bufsize) \ + { \ + type v; \ + size_t nbytes = MIN (sizeof v, bufsize - seeded); \ + initialize_v; \ + memcpy (buf + seeded, &v, nbytes); \ + seeded += nbytes; \ + } + ISAAC_SEED (struct timeval, gettimeofday (&v, NULL)); + ISAAC_SEED (pid_t, v = getpid ()); + ISAAC_SEED (pid_t, v = getppid ()); + ISAAC_SEED (uid_t, v = getuid ()); + ISAAC_SEED (uid_t, v = getgid ()); + +#ifdef lint + /* Normally we like having the extra randomness from uninitialized + parts of BUFFER. However, omit this randomness if we want to + avoid false-positives from memory-checking debugging tools. */ + memset (buf + seeded, 0, bufsize - seeded); +#endif +} + + /* Create and initialize a random data source from NAME, or use a reasonable default source if NAME is null. BYTES_BOUND is an upper bound on the number of bytes that will be needed. If zero, it is a @@ -170,11 +217,10 @@ randread_new (char const *name, size_t bytes_bound) setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound)); else { - int nonce_device = open (NAME_OF_NONCE_DEVICE, O_RDONLY | O_BINARY); s->buf.isaac.buffered = 0; - isaac_seed (&s->buf.isaac.state, nonce_device, bytes_bound); - if (0 <= nonce_device) - close (nonce_device); + get_nonce (s->buf.isaac.state.m, sizeof s->buf.isaac.state.m, + bytes_bound); + isaac_seed (&s->buf.isaac.state); } return s; @@ -245,9 +291,9 @@ readisaac (struct isaac *isaac, unsigned char *p, size_t size) /* If P is aligned, write to *P directly to avoid the overhead of copying from the buffer. */ - if (ALIGNED_POINTER (p, uint32_t)) + if (ALIGNED_POINTER (p, isaac_word)) { - uint32_t *wp = (uint32_t *) p; + isaac_word *wp = (isaac_word *) p; while (ISAAC_BYTES <= size) { isaac_refill (&isaac->state, wp); -- cgit v1.2.3-70-g09d2