From: Alan T. DeKok Date: Tue, 2 May 2017 16:22:43 +0000 (-0400) Subject: move randomness functions to rand.c X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dbbbd7c681781b2570243e58a8671eb7d0ea48e2;p=thirdparty%2Ffreeradius-server.git move randomness functions to rand.c --- diff --git a/src/lib/util/all.mk b/src/lib/util/all.mk index 7d0269a3c83..aba18c1325a 100644 --- a/src/lib/util/all.mk +++ b/src/lib/util/all.mk @@ -35,6 +35,7 @@ SOURCES := base64.c \ radius_packet.c \ radius_encode.c \ radius_decode.c \ + rand.c \ rbtree.c \ regex.c \ sha1.c \ diff --git a/src/lib/util/radius.c b/src/lib/util/radius.c index 675c112627e..8bb2af9b773 100644 --- a/src/lib/util/radius.c +++ b/src/lib/util/radius.c @@ -79,9 +79,6 @@ static void print_hex_data(uint8_t const *ptr, int attrlen, int depth) if ((i & 0x0f) != 0) fprintf(fr_log_fp, "\n"); } -static _Thread_local fr_randctx fr_rand_pool; //!< A pool of pre-generated random integers -static _Thread_local bool fr_rand_initialized = false; - char const *fr_packet_codes[FR_MAX_PACKET_CODE] = { "", //!< 0 "Access-Request", @@ -984,79 +981,3 @@ int fr_radius_packet_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original, char return 0; } - -/** Seed the random number generator - * - * May be called any number of times. - */ -void fr_rand_seed(void const *data, size_t size) -{ - uint32_t hash; - - /* - * Ensure that the pool is initialized. - */ - if (!fr_rand_initialized) { - int fd; - - memset(&fr_rand_pool, 0, sizeof(fr_rand_pool)); - - fd = open("/dev/urandom", O_RDONLY); - if (fd >= 0) { - size_t total; - ssize_t this; - - total = 0; - while (total < sizeof(fr_rand_pool.randrsl)) { - this = read(fd, fr_rand_pool.randrsl, - sizeof(fr_rand_pool.randrsl) - total); - if ((this < 0) && (errno != EINTR)) break; - if (this > 0) total += this; - } - close(fd); - } else { - fr_rand_pool.randrsl[0] = fd; - fr_rand_pool.randrsl[1] = time(NULL); - fr_rand_pool.randrsl[2] = errno; - } - - fr_randinit(&fr_rand_pool, 1); - fr_rand_pool.randcnt = 0; - fr_rand_initialized = 1; - } - - if (!data) return; - - /* - * Hash the user data - */ - hash = fr_rand(); - if (!hash) hash = fr_rand(); - hash = fr_hash_update(data, size, hash); - - fr_rand_pool.randmem[fr_rand_pool.randcnt] ^= hash; -} - - -/** Return a 32-bit random number - * - */ -uint32_t fr_rand(void) -{ - uint32_t num; - - /* - * Ensure that the pool is initialized. - */ - if (!fr_rand_initialized) { - fr_rand_seed(NULL, 0); - } - - num = fr_rand_pool.randrsl[fr_rand_pool.randcnt++]; - if (fr_rand_pool.randcnt >= 256) { - fr_rand_pool.randcnt = 0; - fr_isaac(&fr_rand_pool); - } - - return num; -} diff --git a/src/lib/util/rand.c b/src/lib/util/rand.c new file mode 100644 index 00000000000..5ac904d1934 --- /dev/null +++ b/src/lib/util/rand.c @@ -0,0 +1,110 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * $Id$ + * + * @file rand.c + * @brief Functions to get randomness + * + * @copyright 1999-2017 The FreeRADIUS server project + */ + +RCSID("$Id$") + +#include + +#include + +static _Thread_local fr_randctx fr_rand_pool; //!< A pool of pre-generated random integers +static _Thread_local bool fr_rand_initialized = false; + + +/** Seed the random number generator + * + * May be called any number of times. + */ +void fr_rand_seed(void const *data, size_t size) +{ + uint32_t hash; + + /* + * Ensure that the pool is initialized. + */ + if (!fr_rand_initialized) { + int fd; + + memset(&fr_rand_pool, 0, sizeof(fr_rand_pool)); + + fd = open("/dev/urandom", O_RDONLY); + if (fd >= 0) { + size_t total; + ssize_t this; + + total = 0; + while (total < sizeof(fr_rand_pool.randrsl)) { + this = read(fd, fr_rand_pool.randrsl, + sizeof(fr_rand_pool.randrsl) - total); + if ((this < 0) && (errno != EINTR)) break; + if (this > 0) total += this; + } + close(fd); + } else { + fr_rand_pool.randrsl[0] = fd; + fr_rand_pool.randrsl[1] = time(NULL); + fr_rand_pool.randrsl[2] = errno; + } + + fr_randinit(&fr_rand_pool, 1); + fr_rand_pool.randcnt = 0; + fr_rand_initialized = 1; + } + + if (!data) return; + + /* + * Hash the user data + */ + hash = fr_rand(); + if (!hash) hash = fr_rand(); + hash = fr_hash_update(data, size, hash); + + fr_rand_pool.randmem[fr_rand_pool.randcnt] ^= hash; +} + + +/** Return a 32-bit random number + * + */ +uint32_t fr_rand(void) +{ + uint32_t num; + + /* + * Ensure that the pool is initialized. + */ + if (!fr_rand_initialized) { + fr_rand_seed(NULL, 0); + } + + num = fr_rand_pool.randrsl[fr_rand_pool.randcnt++]; + if (fr_rand_pool.randcnt >= 256) { + fr_rand_pool.randcnt = 0; + fr_isaac(&fr_rand_pool); + } + + return num; +}