diff options
Diffstat (limited to 'lib/randread.c')
-rw-r--r-- | lib/randread.c | 297 |
1 files changed, 0 insertions, 297 deletions
diff --git a/lib/randread.c b/lib/randread.c deleted file mode 100644 index 9f65db676..000000000 --- a/lib/randread.c +++ /dev/null @@ -1,297 +0,0 @@ -/* Generate buffers of random data. - - Copyright (C) 2006 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -/* Written by Paul Eggert. */ - -#include <config.h> - -#include "randread.h" - -#include <errno.h> -#include <error.h> -#include <exitfail.h> -#include <quotearg.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "gettext.h" -#define _(msgid) gettext (msgid) - -#include "rand-isaac.h" -#include "stdio-safer.h" -#include "unlocked-io.h" -#include "xalloc.h" - -#ifndef MIN -# define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef __attribute__ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ -# define __attribute__(x) -# endif -#endif - -#ifndef ATTRIBUTE_UNUSED -# define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -#endif - -#if _STRING_ARCH_unaligned -# define ALIGNED_POINTER(ptr, type) true -#else -# define alignof(type) offsetof (struct { char c; type x; }, x) -# define ALIGNED_POINTER(ptr, type) ((size_t) (ptr) % alignof (type) == 0) -#endif - -#ifndef DEFAULT_RANDOM_FILE -# define DEFAULT_RANDOM_FILE "/dev/urandom" -#endif - -/* The maximum buffer size used for reads of random data. Using the - value 2 * ISAAC_BYTES makes this the largest power of two that - would not otherwise cause struct randread_source to grow. */ -#define RANDREAD_BUFFER_SIZE (2 * ISAAC_BYTES) - -/* A source of random data for generating random buffers. */ -struct randread_source -{ - /* Stream to read random bytes from. If null, the behavior is - undefined; the current implementation uses ISAAC in this case, - but this is for old-fashioned implementations that lack - /dev/urandom and callers should not rely on this. */ - FILE *source; - - /* Function to call, and its argument, if there is an input error or - end of file when reading from the stream; errno is nonzero if - there was an error. If this function returns, it should fix the - problem before returning. The default handler assumes that - handler_arg is the file name of the source. */ - void (*handler) (void const *); - void const *handler_arg; - - /* The buffer for SOURCE. It's kept here to simplify storage - allocation and to make it easier to clear out buffered random - data. */ - union - { - /* The stream buffer, if SOURCE is not null. */ - char c[RANDREAD_BUFFER_SIZE]; - - /* The buffered ISAAC pseudorandom buffer, if SOURCE is null. */ - struct isaac - { - /* The number of bytes that are buffered at the end of data.b. */ - size_t buffered; - - /* State of the ISAAC generator. */ - struct isaac_state state; - - /* Up to a buffer's worth of pseudorandom data. */ - union - { - uint32_t w[ISAAC_WORDS]; - unsigned char b[ISAAC_BYTES]; - } data; - } isaac; - } buf; -}; - - -/* The default error handler. */ - -static void -randread_error (void const *file_name) -{ - if (file_name) - error (exit_failure, errno, - _(errno == 0 ? "%s: end of file" : "%s: read error"), - quotearg_colon (file_name)); - abort (); -} - -/* Simply return a new randread_source object with the default error - handler. */ - -static struct randread_source * -simple_new (FILE *source, void const *handler_arg) -{ - struct randread_source *s = xmalloc (sizeof *s); - s->source = source; - s->handler = randread_error; - s->handler_arg = handler_arg; - return s; -} - -/* 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 - hard bound; otherwise it is just an estimate. - - If NAME is not null, NAME is saved for use as the argument of the - default handler. Unless a non-default handler is used, NAME's - lifetime should be at least that of the returned value. - - Return NULL (setting errno) on failure. */ - -struct randread_source * -randread_new (char const *name, size_t bytes_bound) -{ - if (bytes_bound == 0) - return simple_new (NULL, NULL); - else - { - char const *file_name = (name ? name : DEFAULT_RANDOM_FILE); - FILE *source = fopen_safer (file_name, "rb"); - struct randread_source *s; - - if (! source) - { - if (name) - return NULL; - file_name = NULL; - } - - s = simple_new (source, file_name); - - if (source) - setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound)); - else - { - s->buf.isaac.buffered = 0; - isaac_seed (&s->buf.isaac.state); - } - - return s; - } -} - - -/* Set S's handler and its argument. HANDLER (HANDLER_ARG) is called - when there is a read error or end of file from the random data - source; errno is nonzero if there was an error. If HANDLER - returns, it should fix the problem before returning. The default - handler assumes that handler_arg is the file name of the source; it - does not return. */ - -void -randread_set_handler (struct randread_source *s, void (*handler) (void const *)) -{ - s->handler = handler; -} - -void -randread_set_handler_arg (struct randread_source *s, void const *handler_arg) -{ - s->handler_arg = handler_arg; -} - - -/* Place SIZE random bytes into the buffer beginning at P, using - the stream in S. */ - -static void -readsource (struct randread_source *s, unsigned char *p, size_t size) -{ - for (;;) - { - size_t inbytes = fread (p, sizeof *p, size, s->source); - int fread_errno = errno; - p += inbytes; - size -= inbytes; - if (size == 0) - break; - errno = (ferror (s->source) ? fread_errno : 0); - s->handler (s->handler_arg); - } -} - - -/* Place SIZE pseudorandom bytes into the buffer beginning at P, using - the buffered ISAAC generator in ISAAC. */ - -static void -readisaac (struct isaac *isaac, unsigned char *p, size_t size) -{ - size_t inbytes = isaac->buffered; - - for (;;) - { - if (size <= inbytes) - { - memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, size); - isaac->buffered = inbytes - size; - return; - } - - memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, inbytes); - p += inbytes; - size -= inbytes; - - /* If P is aligned, write to *P directly to avoid the overhead - of copying from the buffer. */ - if (ALIGNED_POINTER (p, uint32_t)) - { - uint32_t *wp = (uint32_t *) p; - while (ISAAC_BYTES <= size) - { - isaac_refill (&isaac->state, wp); - wp += ISAAC_WORDS; - size -= ISAAC_BYTES; - if (size == 0) - { - isaac->buffered = 0; - return; - } - } - p = (unsigned char *) wp; - } - - isaac_refill (&isaac->state, isaac->data.w); - inbytes = ISAAC_BYTES; - } -} - - -/* Consume random data from *S to generate a random buffer BUF of size - SIZE. */ - -void -randread (struct randread_source *s, void *buf, size_t size) -{ - if (s->source) - readsource (s, buf, size); - else - readisaac (&s->buf.isaac, buf, size); -} - - -/* Clear *S so that it no longer contains undelivered random data, and - deallocate any system resources associated with *S. Return 0 if - successful, a negative number (setting errno) if not (this is rare, - but can occur in theory if there is an input error). */ - -int -randread_free (struct randread_source *s) -{ - FILE *source = s->source; - memset (s, 0, sizeof *s); - free (s); - return (source ? fclose (source) : 0); -} |