summaryrefslogtreecommitdiffstats
path: root/contrib/libottery/ottery_entropy.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libottery/ottery_entropy.c')
-rw-r--r--contrib/libottery/ottery_entropy.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/contrib/libottery/ottery_entropy.c b/contrib/libottery/ottery_entropy.c
new file mode 100644
index 0000000..819a380
--- /dev/null
+++ b/contrib/libottery/ottery_entropy.c
@@ -0,0 +1,112 @@
+/* Libottery by Nick Mathewson.
+
+ This software has been dedicated to the public domain under the CC0
+ public domain dedication.
+
+ To the extent possible under law, the person who associated CC0 with
+ libottery has waived all copyright and related or neighboring rights
+ to libottery.
+
+ You should have received a copy of the CC0 legalcode along with this
+ work in doc/cc0.txt. If not, see
+ <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+#define OTTERY_INTERNAL
+#include "ottery-internal.h"
+#include "ottery.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#define SRC(x) OTTERY_ENTROPY_SRC_ ## x
+#define DOM(x) OTTERY_ENTROPY_DOM_ ## x
+#define FL(x) OTTERY_ENTROPY_FL_ ## x
+
+#include "ottery_entropy_cryptgenrandom.c"
+#include "ottery_entropy_urandom.c"
+#include "ottery_entropy_rdrand.c"
+#include "ottery_entropy_egd.c"
+
+/** Table of RNG functions and their properties. */
+static struct ottery_randbytes_source {
+ int (*fn)(const struct ottery_entropy_config *,
+ struct ottery_entropy_state *,
+ uint8_t *, size_t);
+ uint32_t flags;
+} RAND_SOURCES[] = {
+#ifdef ENTROPY_SOURCE_CRYPTGENRANDOM
+ ENTROPY_SOURCE_CRYPTGENRANDOM,
+#endif
+#ifdef ENTROPY_SOURCE_URANDOM
+ ENTROPY_SOURCE_URANDOM,
+#endif
+#ifdef ENTROPY_SOURCE_EGD
+ ENTROPY_SOURCE_EGD,
+#endif
+#ifdef ENTROPY_SOURCE_RDRAND
+ ENTROPY_SOURCE_RDRAND,
+#endif
+ { NULL, 0 }
+};
+
+size_t
+ottery_get_entropy_bufsize_(size_t n)
+{
+ return n * (sizeof(RAND_SOURCES)/sizeof(RAND_SOURCES[0]) - 1);
+}
+
+int
+ottery_get_entropy_(const struct ottery_entropy_config *config,
+ struct ottery_entropy_state *state,
+ uint32_t select_sources,
+ uint8_t *bytes, size_t n, size_t *buflen,
+ uint32_t *flags_out)
+{
+ ssize_t err = OTTERY_ERR_INIT_STRONG_RNG, last_err = 0;
+ int i;
+ uint32_t got = 0;
+ uint8_t *next;
+ const uint32_t disabled_sources = config ? config->disabled_sources : 0;
+
+ memset(bytes, 0, *buflen);
+ next = bytes;
+
+ *flags_out = 0;
+
+ for (i=0; RAND_SOURCES[i].fn; ++i) {
+ uint32_t flags = RAND_SOURCES[i].flags;
+ /* Don't use a disabled source. */
+ if (0 != (flags & disabled_sources))
+ continue;
+ /* If some flags must be set, only use those. */
+ if ((flags & select_sources) != select_sources)
+ continue;
+ /* If we already have input from a certain domain, we don't need more */
+ if ((flags & (got & OTTERY_ENTROPY_DOM_MASK)) != 0)
+ continue;
+ /* If we can't write these bytes, don't try. */
+ if (next + n > bytes + *buflen)
+ break;
+ err = RAND_SOURCES[i].fn(config, state, next, n);
+ if (err == 0) {
+ uint32_t flags = RAND_SOURCES[i].flags;
+ if (config && (flags & config->weak_sources))
+ flags &= ~OTTERY_ENTROPY_FL_STRONG;
+
+ got |= flags;
+ next += n;
+ } else {
+ last_err = err;
+ }
+ }
+
+ /* Do not report success unless at least one source was strong. */
+ if (0 == (got & OTTERY_ENTROPY_FL_STRONG))
+ return last_err ? last_err : OTTERY_ERR_INIT_STRONG_RNG;
+
+ *flags_out = got;
+ *buflen = next - bytes;
+
+ return 0;
+}