summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Unbound/src/src/util/random.c')
-rw-r--r--3rdParty/Unbound/src/src/util/random.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/3rdParty/Unbound/src/src/util/random.c b/3rdParty/Unbound/src/src/util/random.c
new file mode 100644
index 0000000..1458104
--- /dev/null
+++ b/3rdParty/Unbound/src/src/util/random.c
@@ -0,0 +1,198 @@
+/*
+ * util/random.c - thread safe random generator, which is reasonably secure.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ * Thread safe random functions. Similar to arc4random() with an explicit
+ * initialisation routine.
+ *
+ * The code in this file is based on arc4random from
+ * openssh-4.0p1/openbsd-compat/bsd-arc4random.c
+ * That code is also BSD licensed. Here is their statement:
+ *
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "config.h"
+#include "util/random.h"
+#include "util/log.h"
+#include <openssl/rand.h>
+#include <openssl/rc4.h>
+#include <openssl/err.h>
+
+/**
+ * Struct with per-thread random state.
+ * Keeps SSL types away from the header file.
+ */
+struct ub_randstate {
+ /** key used for arc4random generation */
+ RC4_KEY rc4;
+ /** keeps track of key usage */
+ int rc4_ready;
+};
+
+/** Size of key to use */
+#define SEED_SIZE 20
+
+/**
+ * Max random value. Similar to RAND_MAX, but more portable
+ * (mingw uses only 15 bits random).
+ */
+#define MAX_VALUE 0x7fffffff
+
+/** Number of bytes to reseed after */
+#define REKEY_BYTES (1 << 24)
+
+/* (re)setup system seed */
+void
+ub_systemseed(unsigned int seed)
+{
+ /* RAND_ is threadsafe, by the way */
+ if(!RAND_status()) {
+ /* try to seed it */
+ unsigned char buf[256];
+ unsigned int v = seed;
+ size_t i;
+ for(i=0; i<256/sizeof(seed); i++) {
+ memmove(buf+i*sizeof(seed), &v, sizeof(seed));
+ v = v*seed + (unsigned int)i;
+ }
+ RAND_seed(buf, 256);
+ if(!RAND_status()) {
+ log_err("Random generator has no entropy "
+ "(error %ld)", ERR_get_error());
+ } else {
+ verbose(VERB_OPS, "openssl has no entropy, "
+ "seeding with time and pid");
+ }
+ }
+}
+
+/** reseed random generator */
+static void
+ub_arc4random_stir(struct ub_randstate* s, struct ub_randstate* from)
+{
+ unsigned char rand_buf[SEED_SIZE];
+ int i;
+
+ memset(&s->rc4, 0, sizeof(s->rc4));
+ memset(rand_buf, 0xc, sizeof(rand_buf));
+ if (from) {
+ for(i=0; i<SEED_SIZE; i++)
+ rand_buf[i] = (unsigned char)ub_random(from);
+ } else {
+ if(!RAND_status())
+ ub_systemseed((unsigned)getpid()^(unsigned)time(NULL));
+ if (RAND_bytes(rand_buf, (int)sizeof(rand_buf)) <= 0) {
+ /* very unlikely that this happens, since we seeded
+ * above, if it does; complain and keep going */
+ log_err("Couldn't obtain random bytes (error %ld)",
+ ERR_get_error());
+ s->rc4_ready = 256;
+ return;
+ }
+ }
+ RC4_set_key(&s->rc4, SEED_SIZE, rand_buf);
+
+ /*
+ * Discard early keystream, as per recommendations in:
+ * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
+ */
+ for(i = 0; i <= 256; i += sizeof(rand_buf))
+ RC4(&s->rc4, sizeof(rand_buf), rand_buf, rand_buf);
+
+ memset(rand_buf, 0, sizeof(rand_buf));
+
+ s->rc4_ready = REKEY_BYTES;
+}
+
+struct ub_randstate*
+ub_initstate(unsigned int seed, struct ub_randstate* from)
+{
+ struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s));
+ if(!s) {
+ log_err("malloc failure in random init");
+ return NULL;
+ }
+ ub_systemseed(seed);
+ ub_arc4random_stir(s, from);
+ return s;
+}
+
+long int
+ub_random(struct ub_randstate* s)
+{
+ unsigned int r = 0;
+ if (s->rc4_ready <= 0) {
+ ub_arc4random_stir(s, NULL);
+ }
+
+ RC4(&s->rc4, sizeof(r),
+ (unsigned char *)&r, (unsigned char *)&r);
+ s->rc4_ready -= sizeof(r);
+ return (long int)((r) % (((unsigned)MAX_VALUE + 1)));
+}
+
+long int
+ub_random_max(struct ub_randstate* state, long int x)
+{
+ /* make sure we fetch in a range that is divisible by x. ignore
+ * values from d .. MAX_VALUE, instead draw a new number */
+ long int d = MAX_VALUE - (MAX_VALUE % x); /* d is divisible by x */
+ long int v = ub_random(state);
+ while(d <= v)
+ v = ub_random(state);
+ return (v % x);
+}
+
+void
+ub_randfree(struct ub_randstate* s)
+{
+ if(s)
+ free(s);
+ /* user app must do RAND_cleanup(); */
+}