From: Aki Tuomi Date: Wed, 23 Aug 2017 09:49:03 +0000 (+0300) Subject: lib: Use best available random number generator X-Git-Tag: 2.3.0.rc1~1081 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8045f6e30e98b009b85fcd6cc8d1bdc90524a556;p=thirdparty%2Fdovecot%2Fcore.git lib: Use best available random number generator The best available method is used from short list of getrandom, arc4random or reading /dev/urandom --- diff --git a/src/lib/randgen.c b/src/lib/randgen.c index 332fc84597..2b0410bf9a 100644 --- a/src/lib/randgen.c +++ b/src/lib/randgen.c @@ -6,28 +6,56 @@ #include #include +/* get randomness from either getrandom, arc4random or /dev/urandom */ + +#if defined(HAVE_GETRANDOM) && HAVE_DECL_GETRANDOM != 0 +# include +# define USE_GETRANDOM +#elif defined(HAVE_ARC4RANDOM) +# if defined(HAVE_LIBBSD) +# include +# endif +# define USE_ARC4RANDOM +#else +# define USE_RANDOM_DEV +#endif + static int init_refcount = 0; +#if defined(USE_RANDOM_DEV) static int urandom_fd; +#endif void random_fill(void *buf, size_t size) { - size_t pos; - ssize_t ret; - i_assert(init_refcount > 0); i_assert(size < SSIZE_T_MAX); +#if defined(USE_ARC4RANDOM) + arc4random_buf(buf, size); +#else + size_t pos; + ssize_t ret; + for (pos = 0; pos < size; ) { +# if defined(USE_GETRANDOM) + ret = getrandom(buf, size - pos, 0); +# else ret = read(urandom_fd, (char *) buf + pos, size - pos); +# endif if (unlikely(ret <= 0)) { if (ret == 0) - i_fatal("EOF when reading from "DEV_URANDOM_PATH); + i_fatal("read("DEV_URANDOM_PATH") failed: EOF"); else if (errno != EINTR) +# if defined(USE_RANDOM_DEV) i_fatal("read("DEV_URANDOM_PATH") failed: %m"); +# elif defined(USE_GETRANDOM) + i_fatal("getrandom() failed: %m"); +# endif } else { pos += ret; } } +#endif /* defined(USE_ARC4RANDOM) */ } void random_init(void) @@ -36,49 +64,27 @@ void random_init(void) if (init_refcount++ > 0) return; - +#if defined(USE_RANDOM_DEV) urandom_fd = open(DEV_URANDOM_PATH, O_RDONLY); if (urandom_fd == -1) { if (errno == ENOENT) { - i_fatal(DEV_URANDOM_PATH" doesn't exist, " + i_fatal("open("DEV_URANDOM_PATH") failed: doesn't exist," "currently we require it"); } else { - i_fatal("Can't open "DEV_URANDOM_PATH": %m"); + i_fatal("open("DEV_URANDOM_PATH") failed: %m"); } } - + fd_close_on_exec(urandom_fd, TRUE); +#endif random_fill(&seed, sizeof(seed)); srand(seed); - - fd_close_on_exec(urandom_fd, TRUE); } void random_deinit(void) { if (--init_refcount > 0) return; - +#if defined(USE_RANDOM_DEV) i_close_fd(&urandom_fd); -} - -#ifdef HAVE_ARC4RANDOM -#ifdef HAVE_LIBBSD -#include #endif - -void random_fill_weak(void *buf, size_t size) -{ - arc4random_buf(buf, size); } - -#else - -void random_fill_weak(void *buf, size_t size) -{ - unsigned char *cbuf = buf; - - for (; size > 0; size--) - *cbuf++ = (unsigned char)rand(); -} - -#endif diff --git a/src/lib/randgen.h b/src/lib/randgen.h index dc0a79863a..c3b4dedcc8 100644 --- a/src/lib/randgen.h +++ b/src/lib/randgen.h @@ -1,14 +1,12 @@ #ifndef RANDGEN_H #define RANDGEN_H -/* Fill given buffer with semi-strong randomness, usually from /dev/urandom. */ +/* Fill given buffer with semi-strong randomness */ void random_fill(void *buf, size_t size); -/* Fill given buffer with weak randomness, ie. with rand(). This is better if - no real randomness is required, as reading from /dev/urandom usually also - consumes /dev/random entropy, which may disturb other processes. */ -void random_fill_weak(void *buf, size_t size); +#define random_fill_weak(buf,size) random_fill((buf), (size)) -/* may be called multiple times */ +/* may be called multiple times, + and are called by default in lib_init */ void random_init(void); void random_deinit(void);