summaryrefslogtreecommitdiffstats
path: root/contrib/libottery
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 21:30:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 21:30:40 +0000
commit133a45c109da5310add55824db21af5239951f93 (patch)
treeba6ac4c0a950a0dda56451944315d66409923918 /contrib/libottery
parentInitial commit. (diff)
downloadrspamd-133a45c109da5310add55824db21af5239951f93.tar.xz
rspamd-133a45c109da5310add55824db21af5239951f93.zip
Adding upstream version 3.8.1.upstream/3.8.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'contrib/libottery')
-rw-r--r--contrib/libottery/CMakeLists.txt11
-rw-r--r--contrib/libottery/aes_cryptobox.c181
-rw-r--r--contrib/libottery/chacha_cryptobox.c64
-rw-r--r--contrib/libottery/chacha_merged.c218
-rw-r--r--contrib/libottery/chacha_merged_ecrypt.h133
-rw-r--r--contrib/libottery/ottery-internal.h335
-rw-r--r--contrib/libottery/ottery-threading.h96
-rw-r--r--contrib/libottery/ottery.c847
-rw-r--r--contrib/libottery/ottery.h143
-rw-r--r--contrib/libottery/ottery_common.h351
-rw-r--r--contrib/libottery/ottery_cpuinfo.c88
-rw-r--r--contrib/libottery/ottery_entropy.c112
-rw-r--r--contrib/libottery/ottery_entropy_cryptgenrandom.c51
-rw-r--r--contrib/libottery/ottery_entropy_egd.c75
-rw-r--r--contrib/libottery/ottery_entropy_rdrand.c58
-rw-r--r--contrib/libottery/ottery_entropy_urandom.c117
-rw-r--r--contrib/libottery/ottery_global.c116
-rw-r--r--contrib/libottery/ottery_nolock.h190
-rw-r--r--contrib/libottery/ottery_st.h184
-rw-r--r--contrib/libottery/ottery_version.h.in28
20 files changed, 3398 insertions, 0 deletions
diff --git a/contrib/libottery/CMakeLists.txt b/contrib/libottery/CMakeLists.txt
new file mode 100644
index 0000000..b8536f2
--- /dev/null
+++ b/contrib/libottery/CMakeLists.txt
@@ -0,0 +1,11 @@
+SET(OTTERYSRC chacha_merged.c
+ ottery.c
+ ottery_cpuinfo.c
+ ottery_entropy.c
+ ottery_global.c
+ chacha_cryptobox.c
+ aes_cryptobox.c)
+ADD_LIBRARY(ottery STATIC ${OTTERYSRC})
+
+SET(OTTERY_CFLAGS "-DBUILD_RSPAMD -DOTTERY_NO_PID_CHECK -DOTTERY_NO_INIT_CHECK -DOTTERY_NO_WIPE_STACK")
+set_target_properties(ottery PROPERTIES COMPILE_FLAGS "${OTTERY_CFLAGS}") \ No newline at end of file
diff --git a/contrib/libottery/aes_cryptobox.c b/contrib/libottery/aes_cryptobox.c
new file mode 100644
index 0000000..ea86dc7
--- /dev/null
+++ b/contrib/libottery/aes_cryptobox.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2017, Vsevolod Stakhov
+ * Copyright (c) 2017, Frank Denis
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR ''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 AUTHOR 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.
+ */
+
+#include "config.h"
+#include "ottery-internal.h"
+#include "cryptobox.h"
+
+#if defined(__x86_64__) && defined(RSPAMD_HAS_TARGET_ATTR)
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC push_options
+#pragma GCC target("aes")
+#endif
+#ifndef __SSE2__
+#define __SSE2__
+#endif
+#ifndef __SSE__
+#define __SSE__
+#endif
+#ifndef __AES__
+#define __AES__
+#endif
+#include <immintrin.h>
+#define ROUNDS 10
+
+typedef struct RSPAMD_ALIGNED(16) aes_rng_state {
+ __m128i round_keys[ROUNDS + 1];
+ __m128i counter;
+} aes_stream_state;
+
+
+#define STATE_LEN sizeof(aes_stream_state)
+#define STATE_BYTES 16
+
+#define OUTPUT_LEN 1024
+
+static void
+aes_key_expand (__m128i round_keys[ROUNDS + 1], __m128i t) __attribute__((target("aes")));
+
+static void
+aes_key_expand (__m128i round_keys[ROUNDS + 1], __m128i t)
+{
+ __m128i t1;
+
+#define DO_ROUND_KEY(ROUND, RC) \
+ do { \
+ t1 = _mm_aeskeygenassist_si128(t, (RC)); \
+ round_keys[ROUND] = t; \
+ t = _mm_xor_si128(t, _mm_slli_si128(t, 4)); \
+ t = _mm_xor_si128(t, _mm_slli_si128(t, 8)); \
+ t = _mm_xor_si128(t, _mm_shuffle_epi32(t1, 0xff)); \
+ } while (0)
+
+ DO_ROUND_KEY(0, 1);
+ DO_ROUND_KEY(1, 2);
+ DO_ROUND_KEY(2, 4);
+ DO_ROUND_KEY(3, 8);
+ DO_ROUND_KEY(4, 16);
+ DO_ROUND_KEY(5, 32);
+ DO_ROUND_KEY(6, 64);
+ DO_ROUND_KEY(7, 128);
+ DO_ROUND_KEY(8, 27);
+ DO_ROUND_KEY(9, 54);
+ round_keys[10] = t;
+}
+
+/*
+ * Computes one 128 bytes block and refresh keys
+ */
+static void
+aes_round(unsigned char *buf, struct aes_rng_state *st) __attribute__((target("aes")));
+static void
+aes_round(unsigned char *buf, struct aes_rng_state *st)
+{
+ const __m128i one = _mm_set_epi64x(0, 1);
+ __m128i *round_keys = st->round_keys;
+ __m128i c0, c1, c2, c3, c4, c5, c6, c7;
+ __m128i r0, r1, r2, r3, r4, r5, r6, r7;
+ __m128i s0, s1, s2, s3, s4, s5, s6, s7;
+ size_t i;
+
+#define COMPUTE_ROUNDS(N) \
+ do { \
+ r##N = _mm_aesenc_si128( _mm_xor_si128(c##N, round_keys[0]), round_keys[1]); \
+ r##N = _mm_aesenc_si128(_mm_aesenc_si128(r##N, round_keys[2]), round_keys[3]); \
+ r##N = _mm_aesenc_si128(_mm_aesenc_si128(r##N, round_keys[4]), round_keys[5]); \
+ s##N = r##N; \
+ r##N = _mm_aesenc_si128(_mm_aesenc_si128(r##N, round_keys[6]), round_keys[7]); \
+ r##N = _mm_aesenc_si128(_mm_aesenc_si128(r##N, round_keys[8]), round_keys[9]); \
+ r##N = _mm_xor_si128(s##N, _mm_aesenclast_si128(r##N, round_keys[10])); \
+ } while (0)
+
+ c0 = st->counter;
+
+ for (i = 0; i < OUTPUT_LEN / 128; i ++) {
+ c1 = _mm_add_epi64 (c0, one);
+ c2 = _mm_add_epi64 (c1, one);
+ c3 = _mm_add_epi64 (c2, one);
+ c4 = _mm_add_epi64 (c3, one);
+ c5 = _mm_add_epi64 (c4, one);
+ c6 = _mm_add_epi64 (c5, one);
+ c7 = _mm_add_epi64 (c6, one);
+ COMPUTE_ROUNDS(0);
+ COMPUTE_ROUNDS(1);
+ COMPUTE_ROUNDS(2);
+ COMPUTE_ROUNDS(3);
+ COMPUTE_ROUNDS(4);
+ COMPUTE_ROUNDS(5);
+ COMPUTE_ROUNDS(6);
+ COMPUTE_ROUNDS(7);
+ c0 = _mm_add_epi64 (c7, one);
+ _mm_storeu_si128 ((__m128i *) (void *) (buf + 0), r0);
+ _mm_storeu_si128 ((__m128i *) (void *) (buf + 16), r1);
+ _mm_storeu_si128 ((__m128i *) (void *) (buf + 32), r2);
+ _mm_storeu_si128 ((__m128i *) (void *) (buf + 48), r3);
+ _mm_storeu_si128 ((__m128i *) (void *) (buf + 64), r4);
+ _mm_storeu_si128 ((__m128i *) (void *) (buf + 80), r5);
+ _mm_storeu_si128 ((__m128i *) (void *) (buf + 96), r6);
+ _mm_storeu_si128 ((__m128i *) (void *) (buf + 112), r7);
+ buf += 128;
+ }
+
+ st->counter = c0;
+ c0 = _mm_setzero_si128();
+ COMPUTE_ROUNDS(0);
+ aes_key_expand(round_keys, r0);
+}
+
+
+static void
+aes_cryptobox_state_setup (void *state_, const uint8_t *bytes)
+{
+ struct aes_rng_state *x = state_;
+
+ aes_key_expand (x->round_keys,
+ _mm_loadu_si128((const __m128i *) (const void *)bytes));
+}
+
+static void
+aes_cryptobox_generate (void *state_, uint8_t *output, uint32_t idx)
+{
+ struct aes_rng_state *x = state_;
+
+ aes_round(output, x);
+}
+
+#define PRF_AES(r) { \
+ "AES-" #r, \
+ "AES-" #r "-NOSIMD", \
+ "AES-" #r "-NOSIMD-DEFAULT", \
+ STATE_LEN, \
+ STATE_BYTES, \
+ OUTPUT_LEN, \
+ OTTERY_CPUCAP_AES, \
+ aes_cryptobox_state_setup, \
+ aes_cryptobox_generate \
+}
+
+const struct ottery_prf ottery_prf_aes_cryptobox_ = PRF_AES(128);
+#endif /* x86_64 */
diff --git a/contrib/libottery/chacha_cryptobox.c b/contrib/libottery/chacha_cryptobox.c
new file mode 100644
index 0000000..4e9cdae
--- /dev/null
+++ b/contrib/libottery/chacha_cryptobox.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR ''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 AUTHOR 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.
+ */
+
+#include "config.h"
+#include "ottery-internal.h"
+#include "libcryptobox/chacha20/chacha.h"
+
+#define STATE_LEN (sizeof(chacha_state))
+#define STATE_BYTES 40
+
+#define IDX_STEP 16
+#define OUTPUT_LEN (IDX_STEP * 64)
+
+static void
+chacha20_cryptobox_state_setup (void *state_, const uint8_t *bytes)
+{
+ chacha_state *x = state_;
+ chacha_init (x, (chacha_key *)bytes, (chacha_iv *)(bytes + 32), 20);
+}
+
+static void
+chacha20_cryptobox_generate (void *state_, uint8_t *output, uint32_t idx)
+{
+ chacha_state *x = state_;
+
+ memset (output, 0, OUTPUT_LEN);
+ memcpy (output, &idx, sizeof (idx));
+ chacha_update (x, output, output, OUTPUT_LEN);
+}
+
+#define PRF_CHACHA(r) { \
+ "CHACHA" #r "-CRYPTOBOX", \
+ "CHACHA" #r "-CRYPTOBOX", \
+ "CHACHA" #r "-CRYPTOBOX", \
+ STATE_LEN, \
+ STATE_BYTES, \
+ OUTPUT_LEN, \
+ 0, \
+ chacha ## r ## _cryptobox_state_setup, \
+ chacha ## r ## _cryptobox_generate \
+}
+
+const struct ottery_prf ottery_prf_chacha20_cryptobox_ = PRF_CHACHA(20);
diff --git a/contrib/libottery/chacha_merged.c b/contrib/libottery/chacha_merged.c
new file mode 100644
index 0000000..c31a8bb
--- /dev/null
+++ b/contrib/libottery/chacha_merged.c
@@ -0,0 +1,218 @@
+/*
+ * This code is based on Dan Bernstein's pure C "merged" ChaCha
+ * implementation; details below.
+ *
+ * Note that I've ripped out all of the code that wasn't suitable for doing
+ * block-oriented operation, all (residual) support for 128-bit ChaCha keys,
+ * all support for counter values over 32 bits, the ability to xor the stream
+ * with a plaintext, and so on.
+ *
+ * Future versions of this might remove bigendian conversions too. DO NOT use
+ * this code for your stream cipher: go back to the original source. (I got
+ * this copy from SUPERCOP).
+ */
+
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+*/
+#include <string.h>
+#include "ottery-internal.h"
+#define u8 uint8_t
+#define u32 uint32_t
+#include "chacha_merged_ecrypt.h"
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+#define QUARTERROUND(a,b,c,d) \
+ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
+
+static const char sigma[16] = "expand 32-byte k";
+
+static void ECRYPT_keysetup(ECRYPT_ctx *x,const u8 *k,u32 ivbits)
+{
+ const char *constants;
+ (void)ivbits;
+
+ x->input[4] = U8TO32_LITTLE(k + 0);
+ x->input[5] = U8TO32_LITTLE(k + 4);
+ x->input[6] = U8TO32_LITTLE(k + 8);
+ x->input[7] = U8TO32_LITTLE(k + 12);
+ k += 16;
+ constants = sigma;
+ x->input[8] = U8TO32_LITTLE(k + 0);
+ x->input[9] = U8TO32_LITTLE(k + 4);
+ x->input[10] = U8TO32_LITTLE(k + 8);
+ x->input[11] = U8TO32_LITTLE(k + 12);
+ x->input[0] = U8TO32_LITTLE(constants + 0);
+ x->input[1] = U8TO32_LITTLE(constants + 4);
+ x->input[2] = U8TO32_LITTLE(constants + 8);
+ x->input[3] = U8TO32_LITTLE(constants + 12);
+}
+
+static void ECRYPT_ivsetup(ECRYPT_ctx *x,const u8 *iv)
+{
+ x->input[12] = 0;
+ x->input[13] = 0;
+ x->input[14] = U8TO32_LITTLE(iv + 0);
+ x->input[15] = U8TO32_LITTLE(iv + 4);
+}
+
+#define IDX_STEP 16
+#define OUTPUT_LEN (IDX_STEP * 64)
+
+static inline void chacha_merged_getblocks(const int chacha_rounds, ECRYPT_ctx *x,u8 *c) __attribute__((always_inline));
+
+/** Generate OUTPUT_LEN bytes of output using the key, nonce, and counter in x,
+ * and store them in c.
+ */
+static void chacha_merged_getblocks(const int chacha_rounds, ECRYPT_ctx *x,u8 *c)
+{
+ u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
+ u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
+ unsigned i, block;
+
+ j0 = x->input[0];
+ j1 = x->input[1];
+ j2 = x->input[2];
+ j3 = x->input[3];
+ j4 = x->input[4];
+ j5 = x->input[5];
+ j6 = x->input[6];
+ j7 = x->input[7];
+ j8 = x->input[8];
+ j9 = x->input[9];
+ j10 = x->input[10];
+ j11 = x->input[11];
+ j12 = x->input[12];
+ j13 = x->input[13];
+ j14 = x->input[14];
+ j15 = x->input[15];
+
+ for (block = 0; block < IDX_STEP; ++block) {
+ x0 = j0;
+ x1 = j1;
+ x2 = j2;
+ x3 = j3;
+ x4 = j4;
+ x5 = j5;
+ x6 = j6;
+ x7 = j7;
+ x8 = j8;
+ x9 = j9;
+ x10 = j10;
+ x11 = j11;
+ x12 = j12;
+ x13 = j13;
+ x14 = j14;
+ x15 = j15;
+ for (i = chacha_rounds;i > 0;i -= 2) {
+ QUARTERROUND( x0, x4, x8,x12)
+ QUARTERROUND( x1, x5, x9,x13)
+ QUARTERROUND( x2, x6,x10,x14)
+ QUARTERROUND( x3, x7,x11,x15)
+ QUARTERROUND( x0, x5,x10,x15)
+ QUARTERROUND( x1, x6,x11,x12)
+ QUARTERROUND( x2, x7, x8,x13)
+ QUARTERROUND( x3, x4, x9,x14)
+ }
+ x0 = PLUS(x0,j0);
+ x1 = PLUS(x1,j1);
+ x2 = PLUS(x2,j2);
+ x3 = PLUS(x3,j3);
+ x4 = PLUS(x4,j4);
+ x5 = PLUS(x5,j5);
+ x6 = PLUS(x6,j6);
+ x7 = PLUS(x7,j7);
+ x8 = PLUS(x8,j8);
+ x9 = PLUS(x9,j9);
+ x10 = PLUS(x10,j10);
+ x11 = PLUS(x11,j11);
+ x12 = PLUS(x12,j12);
+ x13 = PLUS(x13,j13);
+ x14 = PLUS(x14,j14);
+ x15 = PLUS(x15,j15);
+
+ j12 = PLUSONE(j12);
+ /* Ottery: j13 can never need to be incremented. */
+
+ U32TO8_LITTLE(c + 0,x0);
+ U32TO8_LITTLE(c + 4,x1);
+ U32TO8_LITTLE(c + 8,x2);
+ U32TO8_LITTLE(c + 12,x3);
+ U32TO8_LITTLE(c + 16,x4);
+ U32TO8_LITTLE(c + 20,x5);
+ U32TO8_LITTLE(c + 24,x6);
+
+ U32TO8_LITTLE(c + 28,x7);
+ U32TO8_LITTLE(c + 32,x8);
+ U32TO8_LITTLE(c + 36,x9);
+ U32TO8_LITTLE(c + 40,x10);
+ U32TO8_LITTLE(c + 44,x11);
+ U32TO8_LITTLE(c + 48,x12);
+ U32TO8_LITTLE(c + 52,x13);
+ U32TO8_LITTLE(c + 56,x14);
+ U32TO8_LITTLE(c + 60,x15);
+
+ c += 64;
+ }
+}
+
+#define STATE_LEN (sizeof(ECRYPT_ctx))
+#define STATE_BYTES 40
+
+static void
+chacha_merged_state_setup(void *state_, const uint8_t *bytes)
+{
+ ECRYPT_ctx *x = state_;
+ ECRYPT_keysetup(x, bytes, 0);
+ ECRYPT_ivsetup(x, bytes+32);
+}
+
+static void
+chacha8_merged_generate(void *state_, uint8_t *output, uint32_t idx)
+{
+ ECRYPT_ctx *x = state_;
+ x->input[12] = idx * IDX_STEP;
+ chacha_merged_getblocks(8, x, output);
+}
+
+static void
+chacha12_merged_generate(void *state_, uint8_t *output, uint32_t idx)
+{
+ ECRYPT_ctx *x = state_;
+ x->input[12] = idx * IDX_STEP;
+ chacha_merged_getblocks(12, x, output);
+}
+
+static void
+chacha20_merged_generate(void *state_, uint8_t *output, uint32_t idx)
+{
+ ECRYPT_ctx *x = state_;
+ x->input[12] = idx * IDX_STEP;
+ chacha_merged_getblocks(20, x, output);
+}
+
+#define PRF_CHACHA(r) { \
+ "CHACHA" #r, \
+ "CHACHA" #r "-NOSIMD", \
+ "CHACHA" #r "-NOSIMD-DEFAULT", \
+ STATE_LEN, \
+ STATE_BYTES, \
+ OUTPUT_LEN, \
+ 0, \
+ chacha_merged_state_setup, \
+ chacha ## r ## _merged_generate \
+}
+
+const struct ottery_prf ottery_prf_chacha8_merged_ = PRF_CHACHA(8);
+const struct ottery_prf ottery_prf_chacha12_merged_ = PRF_CHACHA(12);
+const struct ottery_prf ottery_prf_chacha20_merged_ = PRF_CHACHA(20);
+
diff --git a/contrib/libottery/chacha_merged_ecrypt.h b/contrib/libottery/chacha_merged_ecrypt.h
new file mode 100644
index 0000000..5cc94a9
--- /dev/null
+++ b/contrib/libottery/chacha_merged_ecrypt.h
@@ -0,0 +1,133 @@
+/* Definitions for types and macros used in chacha_merged.c. Taken from
+ * supercop.
+ */
+
+#include <limits.h>
+
+typedef struct
+{
+ u32 input[16]; /* could be compressed */
+ /*
+ * [edit]
+ *
+ * Put here all state variable needed during the encryption process.
+ */
+} ECRYPT_ctx;
+#if (UCHAR_MAX / 0xFFFFU > 0xFFFFU)
+#ifndef I32T
+#define I32T char
+#define U32C(v) (v##U)
+#endif
+#endif
+
+#if (USHRT_MAX / 0xFFFFU > 0xFFFFU)
+#ifndef I32T
+#define I32T short
+#define U32C(v) (v##U)
+#endif
+#endif
+
+#if (UINT_MAX / 0xFFFFU > 0xFFFFU)
+#ifndef I32T
+#define I32T int
+#define U32C(v) (v##U)
+#endif
+#endif
+
+#if (ULONG_MAX / 0xFFFFUL > 0xFFFFUL)
+#ifndef I32T
+#define I32T long
+#define U32C(v) (v##UL)
+#endif
+#endif
+
+#define U8C(v) (v ## U)
+#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
+#define U8V(v) ((u8)(v) & U8C(0xFF))
+
+#if (defined(WIN32) && defined(_MSC_VER))
+#include <stdlib.h>
+#pragma intrinsic(_lrotl) /* compile rotations "inline" */
+#define ROTL32(v, n) _lrotl(v, n)
+#else
+#define ROTL32(v, n) \
+ (U32V((v) << (n)) | ((v) >> (32 - (n))))
+#endif
+
+
+
+#if ECRYPT_LITTLE_ENDIAN
+#define U32TO32_LITTLE(v) (v)
+#endif
+#ifdef ECRYPT_BIG_ENDIAN
+#define SWAP32(v) \
+ ((ROTL32(v, 8) & U32C(0x00FF00FF)) | \
+ (ROTL32(v, 24) & U32C(0xFF00FF00)))
+
+#define U32TO32_LITTLE(v) SWAP32(v)
+#endif
+
+#ifdef U32TO32_LITTLE
+#define U8TO32_LITTLE(p) U32TO32_LITTLE(((u32*)(p))[0])
+#define U32TO8_LITTLE(p, v) (((u32*)(p))[0] = U32TO32_LITTLE(v))
+#else
+#define U8TO32_LITTLE(p) \
+ (((u32)((p)[0]) ) | \
+ ((u32)((p)[1]) << 8) | \
+ ((u32)((p)[2]) << 16) | \
+ ((u32)((p)[3]) << 24))
+#define U32TO8_LITTLE(p, v) \
+ do { \
+ (p)[0] = U8V((v) ); \
+ (p)[1] = U8V((v) >> 8); \
+ (p)[2] = U8V((v) >> 16); \
+ (p)[3] = U8V((v) >> 24); \
+ } while (0)
+#endif
+
+/*
+ * The LITTLE endian machines:
+ */
+#if defined(__ultrix) /* Older MIPS */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(__alpha) /* Alpha */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(i386) /* x86 (gcc) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(__i386) /* x86 (gcc) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(__x86_64) /* x86_64 (gcc) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(_M_IX86) /* x86 (MSC, Borland) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(_MSC_VER) /* x86 (surely MSC) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(__INTEL_COMPILER) /* x86 (surely Intel compiler icl.exe) */
+#define ECRYPT_LITTLE_ENDIAN
+
+/*
+ * The BIG endian machines:
+ */
+#elif defined(__sparc) /* Newer Sparc's */
+#define ECRYPT_BIG_ENDIAN
+#elif defined(__powerpc__) /* PowerPC */
+#define ECRYPT_BIG_ENDIAN
+#elif defined(__ppc__) /* PowerPC */
+#define ECRYPT_BIG_ENDIAN
+#elif defined(__hppa) /* HP-PA */
+#define ECRYPT_BIG_ENDIAN
+
+/*
+ * Finally machines with UNKNOWN endianness:
+ */
+#elif defined (_AIX) /* RS6000 */
+#define ECRYPT_UNKNOWN
+#elif defined(__aux) /* 68K */
+#define ECRYPT_UNKNOWN
+#elif defined(__dgux) /* 88K (but P6 in latest boxes) */
+#define ECRYPT_UNKNOWN
+#elif defined(__sgi) /* Newer MIPS */
+#define ECRYPT_UNKNOWN
+#else /* Any other processor */
+#define ECRYPT_UNKNOWN
+#endif
diff --git a/contrib/libottery/ottery-internal.h b/contrib/libottery/ottery-internal.h
new file mode 100644
index 0000000..cc047f8
--- /dev/null
+++ b/contrib/libottery/ottery-internal.h
@@ -0,0 +1,335 @@
+/* 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/>.
+ */
+#ifndef OTTERY_INTERNAL_H_HEADER_INCLUDED_
+#define OTTERY_INTERNAL_H_HEADER_INCLUDED_
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef BUILD_RSPAMD
+#include "config.h"
+#endif
+
+#include "ottery-threading.h"
+
+
+/**
+ * Version number for Libottery. The first three bytes are the major number,
+ * minor number, and patch-level respectively. The final byte is 0 for a
+ * released version, and nonzero otherwise.
+ */
+#define OTTERY_VERSION 0x00000001
+/**
+ * Human-readable string representing the Libottery version.
+ */
+#define OTTERY_VERSION_STRING "0.0.0"
+
+/** Largest possible state_bytes value. */
+#define MAX_STATE_BYTES 64
+/** Largest possible state_len value. */
+#define MAX_STATE_LEN 256
+/** Largest possible output_len value. */
+#define MAX_OUTPUT_LEN 1024
+
+/**
+ * @brief Flags for external entropy sources.
+ *
+ * @{ */
+/** An RNG that probably provides strong entropy. */
+#define OTTERY_ENTROPY_FL_STRONG 0x000001
+/** An RNG that runs very quickly. */
+#define OTTERY_ENTROPY_FL_FAST 0x000002
+/** @} */
+
+/**
+ * @brief Identifying external entropy domains.
+ */
+/** An RNG provided by the operating system. */
+#define OTTERY_ENTROPY_DOM_OS 0x000100
+/** An RNG provided by the CPU. */
+#define OTTERY_ENTROPY_DOM_CPU 0x000200
+/** An EGD-style entropy source */
+#define OTTERY_ENTROPY_DOM_EGD 0x000400
+/** @} */
+
+#define OTTERY_ENTROPY_FLAG_MASK 0x000000ff
+#define OTTERY_ENTROPY_DOM_MASK 0x0000ff00
+#define OTTERY_ENTROPY_ALL_SOURCES 0x0fff0000
+
+struct sockaddr;
+
+/** Configuration for the strong RNG the we use for entropy. */
+struct ottery_entropy_config {
+ /** The filename to use as /dev/urandom. Ignored if this
+ * is not a unix-like operating system. If this is NULL, we use
+ * the default value. */
+ const char *urandom_fname;
+ /** An fd to use to access /dev/urandom. -1 if not set. Overrides
+ * urandom_fname. */
+ int urandom_fd;
+ /** True if urandom_fd has been set. */
+ unsigned urandom_fd_is_set;
+ /** Socket for egd */
+ const struct sockaddr *egd_sockaddr;
+ /** Socklen for egd_sockaddr. */
+ int egd_socklen;
+ /** Bitmask of sources to disable. */
+ uint32_t disabled_sources;
+ /** Bitmask of sources to consider weak. */
+ uint32_t weak_sources;
+
+ /** If true, we don't enforce that urandom_fname must be a device file.
+ * This is for testing, and is not exposed to user code.
+ */
+ unsigned allow_nondev_urandom;
+};
+
+struct ottery_entropy_state {
+ /* Cached value for the inode of the urandom device. If this value changes,
+ * we assume that somebody messed with the fd by accident. */
+ uint64_t urandom_fd_inode;
+};
+
+/**
+ * Return the buffer size to allocate when getting at least n bytes from each
+ * entropy source. We might not actually need so many. */
+size_t ottery_get_entropy_bufsize_(size_t n);
+
+/**
+ * Interface to underlying strong RNGs. If this were fast, we'd just use it
+ * for everything, and forget about having a userspace PRNG. Unfortunately,
+ * it typically isn't.
+ *
+ * @param config A correctly set-up ottery_entropy_config.
+ * @param state A correctly set-up ottery_entropy_state.
+ * @param require_flags Only run entropy sources with *all* of these
+ * OTTERY_ENTROPY_* flags set. Set this to 0 to use all the sources
+ * that work.
+ * @param bytes A buffer to receive random bytes.
+ * @param n The number of bytes to try to get from each entropy source.
+ * @param bufsize The number of bytes available in the buffer; modified
+ * to hold the number of bytes actually written.
+ * @param flags_out Set to a bitwise OR of all of the OTTERY_ENTROPY_* flags
+ * for sources in the result.
+ * @return Zero on success, or an error code on failure. On failure, it is not
+ * safe to treat the contents of the buffer as random at all.
+ */
+int ottery_get_entropy_(const struct ottery_entropy_config *config,
+ struct ottery_entropy_state *state,
+ uint32_t require_flags,
+ uint8_t *bytes, size_t n, size_t *bufsize,
+ uint32_t *flags_out);
+
+/**
+ * Clear all bytes stored in a structure. Unlike memset, the compiler is not
+ * going to optimize this out of existence because the target is about to go
+ * out of scope.
+ *
+ * @param mem Pointer to the memory to erase.
+ * @param len The number of bytes to erase.
+ */
+void ottery_memclear_(void *mem, size_t len);
+
+/**
+ * Information on a single pseudorandom function that we can use to generate
+ * a bytestream which (we hope) an observer can't distinguish from random
+ * bytes.
+ *
+ * Broadly speaking, every ottery_prf has an underlying function from an
+ * (state_bytes)-byte state and a 4 byte counter to an output_len-byte
+ * output block.
+ **/
+struct ottery_prf {
+ /** The name of this algorithm. */
+ const char *name;
+ /** The name of the implementation of this algorithm*/
+ const char *impl;
+ /** The name of the flavor of the implementation of this algorithm*/
+ const char *flav;
+ /** The length of the object that's used to hold the state (keys, nonces,
+ * subkeys as needed, etc) for this PRF. This can be longer than
+ * state_bytes because of key expansion or structure padding. It must be
+ * no greater than MAX_STATE_LEN. */
+ unsigned state_len;
+ /** The number of bytes used to generate a state object. It must be no
+ * greater than MAX_STATE_BYTES. It must be no grater than output_len. */
+ unsigned state_bytes;
+ /** The number of bytes generated by a single call to the generate
+ * function. It must be no larger than MAX_OUTPUT_LEN.
+ */
+ unsigned output_len;
+ /** Bitmask of CPU flags required to run this PRF. */
+ uint32_t required_cpucap;
+ /** Pointer to a function to initialize a state structure for the PRF.
+ *
+ * @param state An object of size at least (state_len) that will
+ * hold the state and any derived values. It must be aligned to
+ * a 16-byte boundary.
+ * @param bytes An array of (state_bytes) random bytes.
+ */
+ void (*setup)(void *state, const uint8_t *bytes);
+ /** Pointer to a function that calculates the PRF.
+ *
+ * @param state A state object previously initialized by the setup
+ * function.
+ * @param output An array of (output_len) bytes in which to store the
+ * result of the function
+ * @param idx A counter value for the function.
+ */
+ void (*generate)(void *state, uint8_t *output, uint32_t idx);
+};
+
+/**
+ * Evaluate the condition 'x', while hinting to the compiler that it is
+ * likely to be false.
+ */
+#ifdef __GNUC__
+#define UNLIKELY(x) __builtin_expect((x), 0)
+#else
+#define UNLIKELY(x) (x)
+#endif
+
+#ifdef OTTERY_INTERNAL
+struct ottery_config {
+ /** The PRF that we should use. If NULL, we use the default. */
+ const struct ottery_prf *impl;
+
+ /** Configuration for how we will set up our entropy sources. */
+ struct ottery_entropy_config entropy_config;
+};
+
+#define ottery_state_nolock ottery_state
+
+struct RSPAMD_ALIGNED(16) ottery_state {
+ /**
+ * Holds up to prf.output_len bytes that have been generated by the
+ * pseudorandom function. */
+ uint8_t buffer[MAX_OUTPUT_LEN] RSPAMD_ALIGNED(16);
+ /**
+ * Holds the state information (typically nonces and keys) used by the
+ * pseudorandom function. */
+
+ uint8_t state[MAX_STATE_LEN] RSPAMD_ALIGNED(16);
+ /**
+ * Parameters and function pointers for the cryptographic pseudorandom
+ * function that we're using. */
+ struct ottery_prf prf;
+ /**
+ * Index of the *next* block counter to use when generating random bytes
+ * with prf. When this equals or exceeds prf.stir_after, we should stir
+ * the PRNG. */
+ uint32_t block_counter;
+ /**
+ * Magic number; used to tell whether this state is initialized.
+ */
+ uint32_t magic;
+ /**
+ * Index of the next byte in (buffer) to yield to the user.
+ *
+ * Invariant: this is less than prf.output_len. */
+ uint16_t pos;
+ /**
+ * The pid of the process in which this PRF was most recently seeded
+ * from the OS. We use this to avoid use-after-fork problems; see
+ * ottery_st_rand_lock_and_check(). */
+ pid_t pid;
+ /**
+ * Combined flags_out results from all calls to the entropy source that
+ * have influenced our current state.
+ */
+ uint32_t entropy_src_flags;
+ /**
+ * flags_out result from our last call to the entropy source.
+ */
+ uint32_t last_entropy_flags;
+ /**
+ * Configuration for the entropy source.
+ */
+ struct ottery_entropy_config entropy_config;
+ /** State for the entropy source.
+ */
+ struct ottery_entropy_state entropy_state;
+ /**
+ * @brief Locks for this structure.
+ *
+ * This lock will not necessarily be recursive. It's probably a
+ * spinlock.
+ *
+ * @{
+ */
+DECL_LOCK(mutex)
+ /**@}*/
+};
+#endif
+
+struct ottery_config;
+/**
+ * For testing: manually supply a PRF.
+ */
+void ottery_config_set_manual_prf_(struct ottery_config *cfg,
+ const struct ottery_prf *prf);
+
+
+/** Called when a fatal error has occurred: Die horribly, or invoke
+ * ottery_fatal_handler. */
+void ottery_fatal_error_(int error);
+
+#define OTTERY_CPUCAP_SIMD (1<<0)
+#define OTTERY_CPUCAP_SSSE3 (1<<1)
+#define OTTERY_CPUCAP_AES (1<<2)
+#define OTTERY_CPUCAP_RAND (1<<3)
+
+/** Return a mask of OTTERY_CPUCAP_* for what the CPU will offer us. */
+uint32_t ottery_get_cpu_capabilities_(void);
+
+/** Tell ottery_get_cpu_capabilities to never report certain capabilities as
+ * present. */
+void ottery_disable_cpu_capabilities_(uint32_t disable);
+
+/**
+ * @brief pure-C portable ChaCha implementations.
+ *
+ * @{
+ */
+extern const struct ottery_prf ottery_prf_chacha8_merged_;
+extern const struct ottery_prf ottery_prf_chacha12_merged_;
+extern const struct ottery_prf ottery_prf_chacha20_merged_;
+
+#ifdef BUILD_RSPAMD
+#ifdef __x86_64__
+extern const struct ottery_prf ottery_prf_aes_cryptobox_;
+#endif
+extern const struct ottery_prf ottery_prf_chacha20_cryptobox_;
+#endif
+/**@}*/
+
+/**
+ * @brief SIMD-basd ChaCha implementations.
+ *
+ * These are much, much faster.
+ *
+ * @{ */
+#ifdef HAVE_SIMD_CHACHA
+extern const struct ottery_prf ottery_prf_chacha8_krovetz_1_;
+extern const struct ottery_prf ottery_prf_chacha12_krovetz_1_;
+extern const struct ottery_prf ottery_prf_chacha20_krovetz_1_;
+#endif
+
+#ifdef HAVE_SIMD_CHACHA_2
+extern const struct ottery_prf ottery_prf_chacha8_krovetz_2_;
+extern const struct ottery_prf ottery_prf_chacha12_krovetz_2_;
+extern const struct ottery_prf ottery_prf_chacha20_krovetz_2_;
+#endif
+/** @} */
+
+#endif
diff --git a/contrib/libottery/ottery-threading.h b/contrib/libottery/ottery-threading.h
new file mode 100644
index 0000000..c5427ad
--- /dev/null
+++ b/contrib/libottery/ottery-threading.h
@@ -0,0 +1,96 @@
+/* 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/>.
+ */
+#ifndef OTTERY_LOCKING_H_HEADER_INCLUDED_
+#define OTTERY_LOCKING_H_HEADER_INCLUDED_
+
+/* We don't need locks when building rspamd */
+#ifdef BUILD_RSPAMD
+#define OTTERY_NO_LOCKS
+#endif
+
+/* Locks */
+#ifdef OTTERY_NO_LOCKS
+/* Nothing here. */
+#elif defined(__APPLE__) && !defined(OTTERY_NO_SPINLOCKS)
+#define OTTERY_OSATOMIC_LOCKS
+#include <libkern/OSAtomic.h>
+#elif defined(_WIN32)
+#define OTTERY_CRITICAL_SECTION
+#include <windows.h>
+#elif defined(HAVE_PTHREAD)
+#define OTTERY_PTHREADS
+#include <pthread.h>
+#else
+#define OTTERY_NO_LOCKS
+#endif
+
+#ifdef OTTERY_NO_LOCKS
+#define DECL_LOCK(mutex)
+#elif defined(OTTERY_OSATOMIC_LOCKS)
+#define DECL_LOCK(mutex) OSSpinLock mutex;
+#elif defined(OTTERY_CRITICAL_SECTION)
+#define DECL_LOCK(mutex) CRITICAL_SECTION mutex;
+#elif defined(OTTERY_PTHREADS)
+#define DECL_LOCK(mutex) pthread_mutex_t mutex;
+#endif
+
+#if defined(OTTERY_PTHREADS)
+#define INIT_LOCK(mutex) \
+ (pthread_mutex_init((mutex), NULL) != 0)
+/** Acquire the lock for the state "st". */
+#define ACQUIRE_LOCK(mutex) do { \
+ pthread_mutex_lock(mutex); \
+ } while (0)
+/** Release the lock for the state "st". */
+#define RELEASE_LOCK(mutex) do { \
+ pthread_mutex_unlock(mutex); \
+ } while (0)
+#define DESTROY_LOCK(mutex) do { \
+ pthread_mutex_destroy(mutex); \
+ } while (0)
+
+#elif defined(OTTERY_CRITICAL_SECTION)
+#define INIT_LOCK(mutex) \
+ (InitializeCriticalSectionAndSpinCount((mutex), 3000) == 0)
+#define ACQUIRE_LOCK(mutex) do { \
+ EnterCriticalSection(mutex); \
+ } while (0)
+#define RELEASE_LOCK(mutex) do { \
+ LeaveCriticalSection(mutex); \
+ } while (0)
+#define DESTROY_LOCK(mutex) do { \
+ DeleteCriticalSection(mutex); \
+ } while (0)
+
+#elif defined(OTTERY_OSATOMIC_LOCKS)
+#define INIT_LOCK(mutex) \
+ ((*(mutex) = 0), 0)
+#define ACQUIRE_LOCK(mutex) do { \
+ OSSpinLockLock(mutex); \
+ } while (0)
+#define RELEASE_LOCK(mutex) do { \
+ OSSpinLockUnlock(mutex); \
+ } while (0)
+#define DESTROY_LOCK(mutex) ((void)0)
+
+#elif defined(OTTERY_NO_LOCKS)
+#define INIT_LOCK(mutex) (0)
+#define DESTROY_LOCK(mutex) ((void)0)
+#define ACQUIRE_LOCK(mutex) ((void)0)
+#define RELEASE_LOCK(mutex) ((void)0)
+#else
+#error How do I lock?
+#endif
+
+#endif
diff --git a/contrib/libottery/ottery.c b/contrib/libottery/ottery.c
new file mode 100644
index 0000000..c58a901
--- /dev/null
+++ b/contrib/libottery/ottery.c
@@ -0,0 +1,847 @@
+/* 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 "ottery_st.h"
+#include "ottery_nolock.h"
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include <stdio.h>
+
+/* I've added a few assertions to sanity-check for debugging, but they should
+ * never ever ever trigger. It's fine to build this code with NDEBUG. */
+#include <assert.h>
+
+#ifdef _WIN32
+/* On Windows, there is no fork(), so we don't need to worry about forking. */
+#define OTTERY_NO_PID_CHECK
+#endif
+
+#ifdef BUILD_RSPAMD
+#include "cryptobox.h"
+#endif
+
+/** Magic number for deciding whether an ottery_state is initialized. */
+#define MAGIC_BASIS 0x11b07734
+
+/** Macro: yield the correct magic number for an ottery_state, based on
+ * its position in RAM. */
+#define MAGIC(ptr) (((uint32_t)(uintptr_t)(ptr)) ^ MAGIC_BASIS)
+
+static inline int ottery_st_rand_lock_and_check(struct ottery_state *st)
+__attribute__((always_inline));
+static int ottery_st_reseed(struct ottery_state *state);
+static int ottery_st_add_seed_impl(struct ottery_state *st, const uint8_t *seed, size_t n, int locking, int check_magic);
+
+#ifndef OTTERY_NO_WIPE_STACK
+static void ottery_wipe_stack_(void) __attribute__((noinline));
+#endif
+
+#define LOCK(st) ACQUIRE_LOCK(&(st)->mutex)
+#define UNLOCK(st) RELEASE_LOCK(&(st)->mutex)
+
+size_t
+ottery_get_sizeof_config(void)
+{
+ return sizeof(struct ottery_config);
+}
+
+size_t
+ottery_get_sizeof_state(void)
+{
+ return sizeof(struct ottery_state);
+}
+
+size_t
+ottery_get_sizeof_state_nolock(void)
+{
+ return sizeof(struct ottery_state_nolock);
+}
+
+const char *
+ottery_get_version_string(void)
+{
+ return OTTERY_VERSION_STRING;
+}
+
+uint32_t
+ottery_get_version(void)
+{
+ return OTTERY_VERSION;
+}
+
+uint32_t
+ottery_get_build_flags(void)
+{
+ uint32_t result = 0;
+#ifdef OTTERY_NO_PID_CHECK
+ result |= OTTERY_BLDFLG_NO_PID_CHECK;
+#endif
+#ifdef OTTERY_NO_INIT_CHECK
+ result |= OTTERY_BLDFLG_NO_INIT_CHECK;
+#endif
+#ifdef OTTERY_NO_LOCKS
+ result |= OTTERY_BLDFLG_NO_LOCKING;
+#endif
+#ifdef OTTERY_NO_CLEAR_AFTER_YIELD
+ result |= OTTERY_BLDFLG_NO_CLEAR_AFTER_YIELD;
+#endif
+#ifdef OTTERY_NO_WIPE_STACK
+ result |= OTTERY_BLDFLG_NO_WIPE_STACK;
+#endif
+#ifdef OTTERY_NO_SIMD
+ result |= OTTERY_BLDFLG_NO_SIMD;
+#endif
+ return result;
+}
+
+#ifndef OTTERY_NO_CLEAR_AFTER_YIELD
+/** Used to zero out the contents of our buffer after we've just given a few
+ * to the user. */
+#define CLEARBUF(ptr,n) do { memset((ptr), 0, (n)); } while (0)
+#else
+#define CLEARBUF(ptr,n) ((void)0)
+#endif
+
+/**
+ * Volatile pointer to memset: we use this to keep the compiler from
+ * eliminating our call to memset. (Don't make this static.)
+ */
+void * (*volatile ottery_memset_volatile_)(void *, int, size_t) = memset;
+
+
+void
+ottery_memclear_(void *mem, size_t len)
+{
+ /* NOTE: whenever we change this, change test/test_memclear.c accordingly */
+ ottery_memset_volatile_(mem, 0, len);
+}
+
+#ifndef OTTERY_NO_WIPE_STACK
+
+/* Chosen more or less arbitrarily */
+#define WIPE_STACK_LEN 512
+
+/**
+ * Try to clear memory on the stack to clean up after our PRF. This can't
+ * easily be done in standard C, so we're doing an ugly hack in hopes that it
+ * actually helps.
+ *
+ * This should never be necessary in a correct program, but if your program is
+ * doing something stupid like leaking uninitialized stack, it might keep an
+ * attacker from exploiting that.
+ **/
+static void
+ottery_wipe_stack_(void)
+{
+ char buf[WIPE_STACK_LEN];
+ ottery_memset_volatile_(buf, 0, sizeof(buf));
+}
+#else
+#define ottery_wipe_stack_() ((void)0)
+#endif
+
+int
+ottery_config_init(struct ottery_config *cfg)
+{
+ cfg->impl = NULL;
+ cfg->entropy_config.urandom_fname = NULL;
+ cfg->entropy_config.urandom_fd = -1;
+ cfg->entropy_config.urandom_fd_is_set = 0;
+ cfg->entropy_config.disabled_sources = 0;
+ cfg->entropy_config.weak_sources = 0;
+ cfg->entropy_config.egd_sockaddr = NULL;
+ cfg->entropy_config.egd_socklen = 0;
+ cfg->entropy_config.allow_nondev_urandom = 0;
+ return 0;
+}
+
+static const struct ottery_prf *
+ottery_get_impl(const char *impl)
+{
+ int i;
+ const struct ottery_prf *ALL_PRFS[] = {
+#ifdef HAVE_SIMD_CHACHA_2
+ &ottery_prf_chacha20_krovetz_2_,
+ &ottery_prf_chacha12_krovetz_2_,
+ &ottery_prf_chacha8_krovetz_2_,
+#endif
+#ifdef HAVE_SIMD_CHACHA
+ &ottery_prf_chacha20_krovetz_1_,
+ &ottery_prf_chacha12_krovetz_1_,
+ &ottery_prf_chacha8_krovetz_1_,
+#endif
+
+#ifdef BUILD_RSPAMD
+#if defined(__x86_64__) && defined(RSPAMD_HAS_TARGET_ATTR)
+ &ottery_prf_aes_cryptobox_,
+#endif
+ &ottery_prf_chacha20_cryptobox_,
+#endif
+ &ottery_prf_chacha20_merged_,
+ &ottery_prf_chacha12_merged_,
+ &ottery_prf_chacha8_merged_,
+
+ NULL,
+ };
+ const uint32_t cap = ottery_get_cpu_capabilities_();
+
+ for (i = 0; ALL_PRFS[i]; ++i) {
+ const struct ottery_prf *prf = ALL_PRFS[i];
+ if ((prf->required_cpucap & cap) != prf->required_cpucap)
+ continue;
+ if (impl == NULL)
+ return prf;
+ if (!strcmp(impl, prf->name))
+ return prf;
+ if (!strcmp(impl, prf->impl))
+ return prf;
+ if (!strcmp(impl, prf->flav))
+ return prf;
+ }
+ return NULL;
+}
+
+int
+ottery_config_force_implementation(struct ottery_config *cfg,
+ const char *impl)
+{
+ const struct ottery_prf *prf = ottery_get_impl(impl);
+ if (prf) {
+ cfg->impl = prf;
+ return 0;
+ }
+ return OTTERY_ERR_INVALID_ARGUMENT;
+}
+
+void
+ottery_config_set_manual_prf_(struct ottery_config *cfg,
+ const struct ottery_prf *prf)
+{
+ cfg->impl = prf;
+}
+
+void
+ottery_config_set_urandom_device(struct ottery_config *cfg,
+ const char *fname)
+{
+ cfg->entropy_config.urandom_fname = fname;
+}
+
+void
+ottery_config_set_urandom_fd(struct ottery_config *cfg,
+ int fd)
+{
+ cfg->entropy_config.urandom_fd = fd;
+ cfg->entropy_config.urandom_fd_is_set = (fd >= 0);
+}
+
+void
+ottery_config_set_egd_socket(struct ottery_config *cfg,
+ const struct sockaddr *addr,
+ int len)
+{
+ cfg->entropy_config.egd_sockaddr = addr;
+ cfg->entropy_config.egd_socklen = len;
+}
+
+void
+ottery_config_disable_entropy_sources(struct ottery_config *cfg,
+ uint32_t disabled_sources)
+{
+ cfg->entropy_config.disabled_sources =
+ (disabled_sources & OTTERY_ENTROPY_ALL_SOURCES);
+}
+
+void
+ottery_config_mark_entropy_sources_weak(struct ottery_config *cfg,
+ uint32_t disabled_sources)
+{
+ cfg->entropy_config.weak_sources =
+ (disabled_sources & OTTERY_ENTROPY_ALL_SOURCES);
+}
+
+/**
+ * As ottery_st_nextblock_nolock(), but fill the entire block with
+ * entropy, and don't try to rekey the state.
+ */
+static void
+ottery_st_nextblock_nolock_norekey(struct ottery_state *st)
+{
+ st->prf.generate(st->state, st->buffer, st->block_counter);
+ ottery_wipe_stack_();
+ ++st->block_counter;
+}
+
+/**
+ * Generate (st->output_len) bytes of pseudorandom data from the PRF into
+ * (st->buffer). Use the first st->prf.state_bytes of those bytes to replace
+ * the PRF state and advance (st->pos) to point after them.
+ *
+ * This function does not acquire the lock on the state; use it within
+ * another function that does.
+ *
+ * @param st The state to use when generating the block.
+ */
+static void
+ottery_st_nextblock_nolock(struct ottery_state_nolock *st)
+{
+ ottery_st_nextblock_nolock_norekey(st);
+ st->prf.setup(st->state, st->buffer);
+ CLEARBUF(st->buffer, st->prf.state_bytes);
+ st->block_counter = 0;
+ st->pos = st->prf.state_bytes;
+}
+
+/**
+ * Initialize or reinitialize a PRNG state.
+ *
+ * @param st The state to initialize or reinitialize.
+ * @param prf The configuration to use. (Ignored for reinit)
+ * @return An OTTERY_ERR_* value (zero on success, nonzero on failure).
+ */
+static int
+ottery_st_initialize(struct ottery_state *st,
+ const struct ottery_config *config,
+ int locked)
+{
+ const struct ottery_prf *prf = NULL;
+ struct ottery_config cfg_tmp;
+ int err;
+ /* We really need our state to be aligned. If it isn't, let's give an
+ * error now, and not a crash when the SIMD instructions start to fail.
+ */
+ if (((uintptr_t)st) & 0xf)
+ return OTTERY_ERR_STATE_ALIGNMENT;
+
+ if (!config) {
+ ottery_config_init(&cfg_tmp);
+ config = &cfg_tmp;
+ }
+
+ prf = config->impl;
+
+ if (!prf)
+ prf = ottery_get_impl(NULL);
+
+ memset(st, 0, sizeof(*st));
+
+ if (locked) {
+ /* Now set up the spinlock or mutex or hybrid thing. */
+ if (INIT_LOCK(&st->mutex))
+ return OTTERY_ERR_LOCK_INIT;
+ }
+
+ /* Check invariants for PRF, in case we wrote some bad code. */
+ if ((prf->state_len > MAX_STATE_LEN) ||
+ (prf->state_bytes > MAX_STATE_BYTES) ||
+ (prf->state_bytes > prf->output_len) ||
+ (prf->output_len > MAX_OUTPUT_LEN))
+ return OTTERY_ERR_INTERNAL;
+
+ /* Check whether some of our structure size assumptions are right. */
+ if ((sizeof(struct ottery_state) > OTTERY_STATE_DUMMY_SIZE_) ||
+ (sizeof(struct ottery_config) > OTTERY_CONFIG_DUMMY_SIZE_))
+ return OTTERY_ERR_INTERNAL;
+
+ memcpy(&st->entropy_config, &config->entropy_config,
+ sizeof(struct ottery_entropy_config));
+
+ /* Copy the PRF into place. */
+ memcpy(&st->prf, prf, sizeof(*prf));
+
+ if ((err = ottery_st_reseed(st)))
+ return err;
+
+ /* Set the magic number last, or else we might look like we succeeded
+ * when we didn't */
+ st->magic = MAGIC(st);
+
+ st->pid = getpid();
+
+ return 0;
+}
+
+static int
+ottery_st_reseed(struct ottery_state *st)
+{
+ /* Now seed the PRF: Generate some random bytes from the OS, and use them
+ * as whatever keys/nonces/whatever the PRF wants to have. */
+ /* XXXX Add seed rather than starting from scratch? */
+ int err;
+ uint32_t flags=0;
+ size_t buflen = ottery_get_entropy_bufsize_(st->prf.state_bytes);
+ uint8_t *buf = alloca(buflen);
+ if (!buf)
+ return OTTERY_ERR_INIT_STRONG_RNG;
+
+ if ((err = ottery_get_entropy_(&st->entropy_config, &st->entropy_state, 0,
+ buf, st->prf.state_bytes,
+ &buflen,
+ &flags)))
+ return err;
+ if (buflen < st->prf.state_bytes)
+ return OTTERY_ERR_ACCESS_STRONG_RNG;
+ /* The first state_bytes bytes become the initial key. */
+ st->prf.setup(st->state, buf);
+ /* If there are more bytes, we mix them into the key with add_seed */
+ if (buflen > st->prf.state_bytes)
+ ottery_st_add_seed_impl(st,
+ buf + st->prf.state_bytes,
+ buflen - st->prf.state_bytes,
+ 0,
+ 0);
+ ottery_memclear_(buf, buflen);
+ st->last_entropy_flags = flags;
+ st->entropy_src_flags = flags;
+
+ /* Generate the first block of output. */
+ st->block_counter = 0;
+ ottery_st_nextblock_nolock(st);
+
+ return 0;
+}
+
+int
+ottery_st_init(struct ottery_state *st, const struct ottery_config *cfg)
+{
+ return ottery_st_initialize(st, cfg, 1);
+}
+
+int
+ottery_st_init_nolock(struct ottery_state_nolock *st,
+ const struct ottery_config *cfg)
+{
+ return ottery_st_initialize(st, cfg, 0);
+}
+
+static int
+ottery_st_add_seed_impl(struct ottery_state *st, const uint8_t *seed, size_t n, int locking, int check_magic)
+{
+#ifndef OTTERY_NO_INIT_CHECK
+ if (check_magic && UNLIKELY(st->magic != MAGIC(st))) {
+ ottery_fatal_error_(OTTERY_ERR_STATE_INIT);
+ return OTTERY_ERR_STATE_INIT;
+ }
+#endif
+
+ /* If the user passed NULL, then we should reseed from the operating
+ * system. */
+ uint8_t *tmp_seed = NULL;
+ size_t tmp_seed_len = 0;
+ uint32_t flags = 0;
+
+ if (!seed || !n) {
+ int err;
+ tmp_seed_len = ottery_get_entropy_bufsize_(st->prf.state_bytes);
+ tmp_seed = alloca(tmp_seed_len);
+ if (!tmp_seed)
+ return OTTERY_ERR_INIT_STRONG_RNG;
+ n = tmp_seed_len;
+ if ((err = ottery_get_entropy_(&st->entropy_config, &st->entropy_state, 0,
+ tmp_seed, st->prf.state_bytes,
+ &n,
+ &flags)))
+ return err;
+ if (n < st->prf.state_bytes)
+ return OTTERY_ERR_ACCESS_STRONG_RNG;
+ seed = tmp_seed;
+ }
+
+ if (locking)
+ LOCK(st);
+ /* The algorithm here is really easy. We grab a block of output from the
+ * PRNG, that the first (state_bytes) bytes of that, XOR it with up to
+ * (state_bytes) bytes of our new seed data, and use that to set our new
+ * state. We do this over and over until we have no more seed data to add.
+ */
+ while (n) {
+ unsigned i;
+ size_t m = n > st->prf.state_bytes/2 ? st->prf.state_bytes/2 : n;
+ ottery_st_nextblock_nolock_norekey(st);
+ for (i = 0; i < m; ++i) {
+ st->buffer[i] ^= seed[i];
+ }
+ st->prf.setup(st->state, st->buffer);
+ st->block_counter = 0;
+ n -= m;
+ seed += m;
+ }
+
+ /* Now make sure that st->buffer is set up with the new state. */
+ ottery_st_nextblock_nolock(st);
+
+ st->entropy_src_flags |= flags;
+ st->last_entropy_flags = flags;
+
+ if (locking)
+ UNLOCK(st);
+
+ /* If we used stack-allocated seed material, wipe it. */
+ if (tmp_seed)
+ ottery_memclear_(tmp_seed, tmp_seed_len);
+
+ return 0;
+}
+
+int
+ottery_st_add_seed(struct ottery_state *st, const uint8_t *seed, size_t n)
+{
+ return ottery_st_add_seed_impl(st, seed, n, 1, 1);
+}
+int
+ottery_st_add_seed_nolock(struct ottery_state_nolock *st, const uint8_t *seed, size_t n)
+{
+ return ottery_st_add_seed_impl(st, seed, n, 0, 1);
+}
+
+
+void
+ottery_st_wipe(struct ottery_state *st)
+{
+ DESTROY_LOCK(&st->mutex);
+
+ ottery_st_wipe_nolock(st);
+}
+
+void
+ottery_st_wipe_nolock(struct ottery_state_nolock *st)
+{
+ ottery_memclear_(st, sizeof(struct ottery_state));
+}
+
+void
+ottery_st_prevent_backtracking_nolock(struct ottery_state_nolock *st)
+{
+#ifdef OTTERY_NO_CLEAR_AFTER_YIELD
+ memset(st->buffer, 0, st->pos);
+#else
+ (void)st;
+#endif
+}
+
+void
+ottery_st_prevent_backtracking(struct ottery_state *st)
+{
+ LOCK(st);
+ ottery_st_prevent_backtracking_nolock(st);
+ UNLOCK(st);
+}
+
+/** Function that's invoked on a fatal error. See
+ * ottery_set_fatal_handler() for more information. */
+static void (*ottery_fatal_handler)(int) = NULL;
+
+void
+ottery_fatal_error_(int error)
+{
+ if (ottery_fatal_handler)
+ ottery_fatal_handler(error);
+ else
+ abort();
+}
+
+void
+ottery_set_fatal_handler(void (*fn)(int))
+{
+ ottery_fatal_handler = fn;
+}
+
+/**
+ * Shared prologue for functions generating random bytes from an ottery_state.
+ * Make sure that the state is initialized.
+ */
+static inline int
+ottery_st_rand_check_init(struct ottery_state *st)
+{
+#ifndef OTTERY_NO_INIT_CHECK
+ if (UNLIKELY(st->magic != MAGIC(st))) {
+ ottery_fatal_error_(OTTERY_ERR_STATE_INIT);
+ return -1;
+ }
+#else
+ (void)st;
+#endif
+ return 0;
+}
+
+/* XXXX */
+static inline int
+ottery_st_rand_check_pid(struct ottery_state *st)
+{
+#ifndef OTTERY_NO_PID_CHECK
+ if (UNLIKELY(st->pid != getpid())) {
+ int err;
+ if ((err = ottery_st_reseed(st))) {
+ ottery_fatal_error_(OTTERY_ERR_FLAG_POSTFORK_RESEED|err);
+ return -1;
+ }
+ st->pid = getpid();
+ }
+#else
+ (void) st;
+#endif
+ return 0;
+}
+
+static inline int
+ottery_st_rand_lock_and_check(struct ottery_state *st)
+{
+ if (ottery_st_rand_check_init(st))
+ return -1;
+ LOCK(st);
+ if (ottery_st_rand_check_pid(st)) {
+ UNLOCK(st);
+ return -1;
+ }
+ return 0;
+}
+
+static inline int
+ottery_st_rand_check_nolock(struct ottery_state_nolock *st)
+{
+ if (ottery_st_rand_check_init(st))
+ return -1;
+ if (ottery_st_rand_check_pid(st))
+ return -1;
+ return 0;
+}
+
+/**
+ * Generate a small-ish number of bytes from an ottery_state, using
+ * buffered data. If there is insufficient data in the buffer right now,
+ * use what we have, and generate more.
+ *
+ * @param st The state to use.
+ * @param out A location to write to.
+ * @param n The number of bytes to write. Must not be greater than
+ * st->prf.output_len*2 - st->prf.state_bytes - st->pos - 1.
+ */
+static inline void
+ottery_st_rand_bytes_from_buf(struct ottery_state *st, uint8_t *out,
+ size_t n)
+{
+ if (n + st->pos < st->prf.output_len) {
+ memcpy(out, st->buffer+st->pos, n);
+ CLEARBUF(st->buffer+st->pos, n);
+ st->pos += n;
+ } else {
+ unsigned cpy = st->prf.output_len - st->pos;
+ memcpy(out, st->buffer+st->pos, cpy);
+ n -= cpy;
+ out += cpy;
+ ottery_st_nextblock_nolock(st);
+ memcpy(out, st->buffer+st->pos, n);
+ CLEARBUF(st->buffer, n);
+ st->pos += n;
+ assert(st->pos < st->prf.output_len);
+ }
+}
+
+static void
+ottery_st_rand_bytes_impl(struct ottery_state *st, void *out_,
+ size_t n)
+{
+ uint8_t *out = out_;
+ size_t cpy;
+
+ if (n + st->pos < st->prf.output_len * 2 - st->prf.state_bytes - 1) {
+ /* Fulfill it all from the buffer simply if possible. */
+ ottery_st_rand_bytes_from_buf(st, out, n);
+ return;
+ }
+
+ /* Okay. That's not going to happen. Well, take what we can... */
+ cpy = st->prf.output_len - st->pos;
+ memcpy(out, st->buffer + st->pos, cpy);
+ out += cpy;
+ n -= cpy;
+
+ /* Then take whole blocks so long as we need them, without stirring... */
+ while (n >= st->prf.output_len) {
+ /* (We could save a memcpy here if we generated the block directly at out
+ * rather than doing the memcpy here. First we'd need to make sure that we
+ * had gotten the block aligned to a 16-byte boundary, though, and we'd
+ * have some other tricky bookkeeping to do. Let's call this good enough
+ * for now.) */
+ ottery_st_nextblock_nolock_norekey(st);
+ memcpy(out, st->buffer, st->prf.output_len);
+ out += st->prf.output_len;
+ n -= st->prf.output_len;
+ }
+
+ /* Then stir for the last part. */
+ ottery_st_nextblock_nolock(st);
+ ottery_st_rand_bytes_from_buf(st, out, n);
+}
+
+void
+ottery_st_rand_bytes(struct ottery_state *st, void *out_, size_t n)
+{
+ if (ottery_st_rand_lock_and_check(st))
+ return;
+ ottery_st_rand_bytes_impl(st, out_, n);
+ UNLOCK(st);
+}
+
+void
+ottery_st_rand_bytes_nolock(struct ottery_state_nolock *st, void *out_, size_t n)
+{
+ if (ottery_st_rand_check_nolock(st))
+ return;
+ ottery_st_rand_bytes_impl(st, out_, n);
+}
+
+/**
+ * Assign an integer type from bytes at a possibly unaligned pointer.
+ *
+ * @param type the type of integer to assign.
+ * @param r the integer lvalue to write to.
+ * @param p a pointer to the bytes to read from.
+ **/
+#define INT_ASSIGN_PTR(type, r, p) do { \
+ memcpy(&r, p, sizeof(type)); \
+} while (0)
+
+/**
+ * Shared code for implementing rand_unsigned() and rand_uint64().
+ *
+ * @param st The state to use.
+ * @param inttype The type of integer to generate.
+ **/
+#define OTTERY_RETURN_RAND_INTTYPE_IMPL(st, inttype, unlock) do { \
+ inttype result; \
+ if (sizeof(inttype) + (st)->pos <= (st)->prf.output_len) { \
+ INT_ASSIGN_PTR(inttype, result, (st)->buffer + (st)->pos); \
+ CLEARBUF((st)->buffer + (st)->pos, sizeof(inttype)); \
+ (st)->pos += sizeof(inttype); \
+ if (st->pos == (st)->prf.output_len) { \
+ ottery_st_nextblock_nolock(st); \
+ } \
+ } else { \
+ /* Our handling of this case here is significantly simpler */ \
+ /* than that of ottery_st_rand_bytes_from_buf, at the expense */ \
+ /* of wasting up to sizeof(inttype)-1 bytes. Since inttype */ \
+ /* is at most 8 bytes long, that's not such a big deal. */ \
+ ottery_st_nextblock_nolock(st); \
+ INT_ASSIGN_PTR(inttype, result, (st)->buffer + (st)->pos); \
+ CLEARBUF((st)->buffer, sizeof(inttype)); \
+ (st)->pos += sizeof(inttype); \
+ } \
+ unlock; \
+ return result; \
+} while (0)
+
+#define OTTERY_RETURN_RAND_INTTYPE(st, inttype) do { \
+ if (ottery_st_rand_lock_and_check(st)) \
+ return (inttype)0; \
+ OTTERY_RETURN_RAND_INTTYPE_IMPL(st, inttype, UNLOCK(st)); \
+} while (0)
+
+#define OTTERY_RETURN_RAND_INTTYPE_NOLOCK(st, inttype) do { \
+ if (ottery_st_rand_check_nolock(st)) \
+ return (inttype)0; \
+ OTTERY_RETURN_RAND_INTTYPE_IMPL(st, inttype, ); \
+} while (0)
+
+unsigned
+ottery_st_rand_unsigned(struct ottery_state *st)
+{
+ OTTERY_RETURN_RAND_INTTYPE(st, unsigned);
+}
+
+unsigned
+ottery_st_rand_unsigned_nolock(struct ottery_state_nolock *st)
+{
+ OTTERY_RETURN_RAND_INTTYPE_NOLOCK(st, unsigned);
+}
+
+uint32_t
+ottery_st_rand_uint32(struct ottery_state *st)
+{
+ OTTERY_RETURN_RAND_INTTYPE(st, uint32_t);
+}
+
+uint32_t
+ottery_st_rand_uint32_nolock(struct ottery_state_nolock *st)
+{
+ OTTERY_RETURN_RAND_INTTYPE_NOLOCK(st, uint32_t);
+}
+
+uint64_t
+ottery_st_rand_uint64(struct ottery_state *st)
+{
+ OTTERY_RETURN_RAND_INTTYPE(st, uint64_t);
+}
+
+uint64_t
+ottery_st_rand_uint64_nolock(struct ottery_state_nolock *st)
+{
+ OTTERY_RETURN_RAND_INTTYPE_NOLOCK(st, uint64_t);
+}
+
+unsigned
+ottery_st_rand_range_nolock(struct ottery_state_nolock *st, unsigned upper)
+{
+ unsigned lim = upper+1;
+ unsigned divisor = lim ? (UINT_MAX / lim) : 1;
+ unsigned n;
+ do {
+ n = (ottery_st_rand_unsigned_nolock(st) / divisor);
+ } while (n > upper);
+
+ return n;
+}
+
+uint64_t
+ottery_st_rand_range64_nolock(struct ottery_state_nolock *st, uint64_t upper)
+{
+ uint64_t lim = upper+1;
+ uint64_t divisor = lim ? (UINT64_MAX / lim) : 1;
+ uint64_t n;
+ do {
+ n = (ottery_st_rand_uint64_nolock(st) / divisor);
+ } while (n > upper);
+
+ return n;
+}
+
+unsigned
+ottery_st_rand_range(struct ottery_state *state, unsigned upper)
+{
+ unsigned n;
+ if (ottery_st_rand_check_init(state))
+ return 0;
+ LOCK(state);
+ n = ottery_st_rand_range_nolock(state, upper);
+ UNLOCK(state);
+ return n;
+}
+
+uint64_t
+ottery_st_rand_range64(struct ottery_state *state, uint64_t upper)
+{
+ uint64_t n;
+ if (ottery_st_rand_check_init(state))
+ return 0;
+ LOCK(state);
+ n = ottery_st_rand_range64_nolock(state, upper);
+ UNLOCK(state);
+ return n;
+}
diff --git a/contrib/libottery/ottery.h b/contrib/libottery/ottery.h
new file mode 100644
index 0000000..e2caac2
--- /dev/null
+++ b/contrib/libottery/ottery.h
@@ -0,0 +1,143 @@
+/* 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/>.
+ */
+#ifndef OTTERY_H_HEADER_INCLUDED_
+#define OTTERY_H_HEADER_INCLUDED_
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ottery_common.h"
+
+/** @file */
+
+struct ottery_config;
+
+/* Functions that use an implicit global state */
+
+/**
+ * Fill a buffer with random bytes.
+ *
+ * @param buf The buffer to fill.
+ * @param n The number of bytes to write.
+ */
+void ottery_rand_bytes(void *buf, size_t n);
+/**
+ * Generate a random number of type unsigned.
+ *
+ * @return A random number between 0 and UINT_MAX included,
+ * chosen uniformly.
+ */
+unsigned ottery_rand_unsigned(void);
+/**
+ * Generate a random number of type uint32_t.
+ *
+ * @return A random number between 0 and UINT32_MAX included,
+ * chosen uniformly.
+ */
+uint32_t ottery_rand_uint32(void);
+/**
+ * Generate a random number of type uint64_t.
+ *
+ * @return A random number between 0 and UINT64_MAX included,
+ * chosen uniformly.
+ */
+uint64_t ottery_rand_uint64(void);
+/**
+ * Generate a random number of type unsigned in a given range.
+ *
+ * @param top The upper bound of the range (inclusive).
+ * @return A random number no larger than top, and no less than 0,
+ * chosen uniformly.
+ */
+unsigned ottery_rand_range(unsigned top);
+/**
+ * Generate a random number of type uint64_t in a given range.
+ *
+ * @param top The upper bound of the range (inclusive).
+ * @return A random number no larger than top, and no less than 0,
+ * chosen uniformly.
+ */
+uint64_t ottery_rand_range64(uint64_t top);
+
+/**
+ * Initialize the libottery global state.
+ *
+ * Most users should not need to use this function. If you use it, you must
+ * call it before any of: ottery_rand_bytes, ottery_rand_unsigned,
+ * ottery_rand_uint64, ottery_rand_range, ottery_rand_uint64_range,
+ * ottery_add_seed, ottery_wipe, ottery_stir.
+ *
+ * You would want to use this function if you want to select some non-default
+ * behavior using an ottery_config structure.
+ *
+ * @param cfg Either NULL, or an ottery_config structure that has been
+ * initialized with ottery_config_init().
+ * @return Zero on success, or one of the OTTERY_ERR_* error codes on failure.
+ */
+int ottery_init(const struct ottery_config *cfg);
+
+/**
+ * Add more entropy to the libottery global state.
+ *
+ * Calling this function should be needless, if you trust your operating
+ * system's random number generator and entropy extraction features. You
+ * would want to use this function if you think the operating system's random
+ * number generator might be inadequate, and you want to add more entropy from
+ * EGD or something.
+ *
+ * You might also want to call this function if your belief system says that
+ * it's useful to periodically add more raw entropy to a well-seeded
+ * cryptographically strong PRNG.
+ *
+ * @param seed Bytes to add to the state. If this value is NULL, we take
+ * more random bytes from the OS.
+ * @param n The number of bytes to add. If this value is 0, we take more
+ * random bytes from the OS, regardless of the value of seed.
+ * @return Zero on success, or one of the OTTERY_ERR_* error codes on failure.
+ */
+int ottery_add_seed(const uint8_t *seed, size_t n);
+
+/**
+ * Destroy the libottery global state and release any resources that it might
+ * hold.
+ *
+ * Ordinarily, you would only want to call this at exit, if at all.
+ */
+void ottery_wipe(void);
+
+/**
+ * Explicitly tell libottery to prevent backtracking attacks. (Usually
+ * needless.)
+ *
+ * Once this function has been called, an attacker who compromises the state
+ * later on will not be able to recover bytes that have previously been
+ * returned by any of the ottery_rand_* functions.
+ *
+ * You should not usually need to call this function: Libottery provides
+ * backtracking resistance by default, so unless you have manually recompiled
+ * with the OTTERY_NO_CLEAR_AFTER_YIELD option, this function isn't
+ * necessary and has no effect. Even *with* OTTERY_NO_CLEAR_AFTER_YIELD,
+ * this function isn't necessary in ordinary operation: the libottery state is
+ * implicitly "stirred" every 1k or so.
+ */
+void ottery_prevent_backtracking(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/libottery/ottery_common.h b/contrib/libottery/ottery_common.h
new file mode 100644
index 0000000..bac6f04
--- /dev/null
+++ b/contrib/libottery/ottery_common.h
@@ -0,0 +1,351 @@
+/* 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/>.
+ */
+#ifndef OTTERY_COMMON_H_HEADER_INCLUDED_
+#define OTTERY_COMMON_H_HEADER_INCLUDED_
+#include <stdint.h>
+#include <sys/types.h>
+
+/** @file */
+
+struct ottery_config;
+
+/* Error codes */
+
+/**
+ * @name libottery error codes and flags
+ *
+ * @{
+ */
+/** No error has occurred. */
+#define OTTERY_ERR_NONE 0x0000
+/** We failed to allocate or initialize a lock. */
+#define OTTERY_ERR_LOCK_INIT 0x0001
+/** An internal error occurrred. This is probably a programming mistake
+ * in libottery. */
+#define OTTERY_ERR_INTERNAL 0x0002
+/** We were unable to connect to the operating system's strong RNG. */
+#define OTTERY_ERR_INIT_STRONG_RNG 0x0003
+/** We were unable to retrieve sufficient random bytes from the
+ * operating system's strong RNG. */
+#define OTTERY_ERR_ACCESS_STRONG_RNG 0x0004
+/** At least one argument to the function was invalid. */
+#define OTTERY_ERR_INVALID_ARGUMENT 0x0005
+/** An ottery_state structure was not aligned to a 16-byte boundary. */
+#define OTTERY_ERR_STATE_ALIGNMENT 0x0006
+
+/** FATAL ERROR: An ottery_st function other than ottery_st_init() was
+ * called on and uninitialized state. */
+#define OTTERY_ERR_STATE_INIT 0x1000
+/** FLAG; FATAL ERROR: The error occurred while initializing the global
+ * state during the first call to an ottery_rand_* function. */
+#define OTTERY_ERR_FLAG_GLOBAL_PRNG_INIT 0x2000
+/** FLAG; FATAL ERROR: The error occurred while reinitializing a state
+ * after a fork(). (We need to do this, or else both processes would
+ * generate the same values, which could give dire results.)
+ */
+#define OTTERY_ERR_FLAG_POSTFORK_RESEED 0x4000
+
+/**
+ * Checks whether an OTTERY_ERR value is a fatal error.
+ *
+ * @param err an OTTERY_ERR_* valuer
+ * @return True if err is fatal; false if it is not fatal.
+ */
+#define OTTERY_ERR_IS_FATAL(err) \
+ (((err) & ~0xfff) != 0)
+
+/* Functions to interact with the library on a global level */
+
+/**
+ * Override the behavior of libottery on a fatal error.
+ *
+ * By default, libottery will call abort() in a few circumstances, in
+ * order to keep the program from operating insecurely. If you want,
+ * you can provide another function to call instead.
+ *
+ * If your function does not itself abort() or exit() the process, or throw an
+ * exception (assuming some C family that has exceptions), libottery will
+ * continue running insecurely -- it might return predictable random numbers,
+ * leak secrets, or just return 0 for everything -- so you should really be
+ * very careful here.
+ *
+ * (The alternative to fatal errors would have been having all the
+ * ottery_rand_* functions able to return an error, and requiring users
+ * to check those codes. But experience suggests that C programmers
+ * frequently do not check error codes.)
+ *
+ * @param fn A function to call in place of abort(). It will receive as
+ * its argument one of the OTTERY_ERR_* error codes.
+ */
+void ottery_set_fatal_handler(void (*fn)(int errorcode));
+
+/* Functions to manipulate parameters. */
+
+/**
+ * @name Names of prfs for use with ottery_config_force_implementation
+ *
+ * @{ */
+#define OTTERY_PRF_CHACHA "CHACHA"
+#define OTTERY_PRF_CHACHA8 "CHACHA8"
+#define OTTERY_PRF_CHACHA12 "CHACHA12"
+#define OTTERY_PRF_CHACHA20 "CHACHA20"
+#define OTTERY_PRF_CHACHA_SIMD "CHACHA-SIMD"
+#define OTTERY_PRF_CHACHA8_SIMD "CHACHA8-SIMD"
+#define OTTERY_PRF_CHACHA12_SIMD "CHACHA12-SIMD"
+#define OTTERY_PRF_CHACHA20_SIMD "CHACHA20-SIMD"
+#define OTTERY_PRF_CHACHA_NO_SIMD "CHACHA-NOSIMD"
+#define OTTERY_PRF_CHACHA8_NO_SIMD "CHACHA8-NOSIMD"
+#define OTTERY_PRF_CHACHA12_NO_SIMD "CHACHA12-NOSIMD"
+#define OTTERY_PRF_CHACHA20_NO_SIMD "CHACHA20-NOSIMD"
+/** @} */
+
+/**
+ * Initialize an ottery_config structure.
+ *
+ * You must call this function on any ottery_config structure before it
+ * can be passed to ottery_init() or ottery_st_init().
+ *
+ * @param cfg The configuration object to initialize.
+ * @return Zero on success, or one of the OTTERY_ERR_* error codes on
+ * failure.
+ */
+int ottery_config_init(struct ottery_config *cfg);
+
+/**
+ * Try to force the use of a particular pseudorandom function for a given
+ * libottery instance.
+ *
+ * To use this function, you call it on an ottery_config structure after
+ * ottery_config_init(), and before passing that structure to
+ * ottery_st_init() or ottery_init().
+ *
+ * @param cfg The configuration structure to configure.
+ * @param impl The name of a pseudorandom function. One of the
+ * OTTERY_PRF_* values.
+ * @return Zero on success, or one of the OTTERY_ERR_* error codes on
+ * failure.
+ */
+int ottery_config_force_implementation(struct ottery_config *cfg,
+ const char *impl);
+
+/**
+ * Set a device file to use as a source of strong entropy.
+ *
+ * To use this function, you call it on an ottery_config structure after
+ * ottery_config_init(), and before passing that structure to
+ * ottery_st_init() or ottery_init().
+ *
+ * By default, libottery will try /dev/urandom on Unix-like systems.
+ *
+ * @param cfg The configuration structure to configure.
+ * @param fname The name of the device to use instead of /dev/urandom. This
+ * pointer is copied around, and must not be freed while any libottery state
+ * configured using this structure is still in use.
+ *
+ */
+void ottery_config_set_urandom_device(struct ottery_config *cfg,
+ const char *fname);
+
+/**
+ * Set a device file to use as a source of strong entropy from the operating
+ * system.
+ *
+ * To use this function, you call it on an ottery_config structure after
+ * ottery_config_init(), and before passing that structure to
+ * ottery_st_init() or ottery_init().
+ *
+ * This function overrides the default behavior, and overrides any
+ * setting in ottery_config_set_urandom_device.
+ *
+ * You MUST NOT change the the file descriptor while any libottery PRNG
+ * configured with it is still running. For example, don't close it, or use
+ * dup2 to make it refer to a different file, or anything like that.
+ *
+ * It is probably a good idea to open the file with the CLOEXEC flag set.
+ *
+ * @param cfg The configuration structure to configure.
+ * @param fd A file descriptor to use as an OS rng source.
+ */
+void ottery_config_set_urandom_fd(struct ottery_config *cfg,
+ int fd);
+
+struct sockaddr;
+
+/**
+ * Configure a socket at which to find a local copy of some service
+ * implementing the EGD (entropy-gathering daemon) protocol.
+ *
+ * Unless this function is called, EGD is not used by default.
+
+ * To use this function, you call it on an ottery_config structure after
+ * ottery_config_init(), and before passing that structure to
+ * ottery_st_init() or ottery_init().
+ *
+ * TODO: This is not implemented for Windows yet.
+ *
+ * @param cfg The configuration structure to configure.
+ * @param addr The address of the daemon. Obviously, this should be
+ * some port on localhost, or a unix socket. This pointer is copied
+ * around, and must not be freed while any libottery state configured
+ * using this structure is still in use.
+ * @param len the length of the address.
+ *
+ */
+void ottery_config_set_egd_socket(struct ottery_config *cfg,
+ const struct sockaddr *addr,
+ int len);
+
+/**
+ * @brief External entropy sources.
+ *
+ * These can be passed as a bitmask to ottery_config_disable_entropy_sources.
+ *
+ * @{ */
+/** A unix-style /dev/urandom device. */
+#define OTTERY_ENTROPY_SRC_RANDOMDEV 0x0010000
+/** The Windows CryptGenRandom call. */
+#define OTTERY_ENTROPY_SRC_CRYPTGENRANDOM 0x0020000
+/** The Intel RDRAND instruction. */
+#define OTTERY_ENTROPY_SRC_RDRAND 0x0040000
+/** Some local server obeying the EGD protocol. Has no effect unless
+ * ottery_config_set_egd_socket was called. */
+#define OTTERY_ENTROPY_SRC_EGD 0x0080000
+/** @} */
+
+/**
+ * Disable the use of one or more entropy sources.
+ *
+ * Note that if enough entropy sources are disabled, the state will
+ * not be able to get initialized, and libottery might not work.
+ *
+ * To use this function, you call it on an ottery_config structure after
+ * ottery_config_init(), and before passing that structure to
+ * ottery_st_init() or ottery_init().
+ *
+ * @param cfg A configuration in which to disable one or more entropy sources.
+ * @param disabled_sources a bitwise combination of one or more
+ * OTTERY_ENTROPY_SRC_* values to disable. This will replace
+ * any previous bitmask of disabled sources.
+ *
+ */
+void ottery_config_disable_entropy_sources(struct ottery_config *cfg,
+ uint32_t disabled_sources);
+
+/**
+ * Mark one or more entropy sources as "weak".
+ *
+ * Unlike a disabled source, we will still try to read entropy from
+ * a weak source -- but we will fail if _only_ weak sources are available.
+ *
+ * Note that if enough entropy sources are disabled and/or weak sources are
+ * failing, the state will not be able to get initialized, and libottery might
+ * not work.
+ *
+ * To use this function, you call it on an ottery_config structure after
+ * ottery_config_init(), and before passing that structure to
+ * ottery_st_init() or ottery_init().
+ *
+ * @param cfg A configuration in which to disable one or more entropy sources.
+ * @param weak_sources a bitwise combination of one or more
+ * OTTERY_ENTROPY_SRC_* values to mark as weak. This will replace
+ * any previous bitmask of weak sources.
+ */
+void ottery_config_mark_entropy_sources_weak(struct ottery_config *cfg,
+ uint32_t weak_source);
+
+/** Size reserved for struct ottery_config */
+#define OTTERY_CONFIG_DUMMY_SIZE_ 1024
+
+#ifndef OTTERY_INTERNAL
+/**
+ * A configuration object for setting up a libottery instance.
+ *
+ * An ottery_config structure is initialized with ottery_config_init,
+ * and passed to ottery_init() or ottery_st_init().
+ *
+ * The contents of this structure are opaque; The definition here is
+ * defined to be large enough so that programs that allocate it will get
+ * more than enough room.
+ */
+struct ottery_config {
+ /** Nothing to see here */
+ uint8_t dummy_[OTTERY_CONFIG_DUMMY_SIZE_];
+};
+#endif
+
+/**
+ * Get the minimal size for allocating an ottery_config.
+ *
+ * sizeof(ottery_config) will give an overestimate to allow binary
+ * compatibility with future versions of libottery. Use this function instead
+ * to get the minimal number of bytes to allocate.
+ *
+ * @return The minimal number of bytes to use when allocating an
+ * ottery_config structure.
+ */
+size_t ottery_get_sizeof_config(void);
+
+/**
+ * @name libottery build flag
+ *
+ * @see ottery_Get_build_flags()
+ *
+ * @{
+ */
+/** Set if libottery was built with PID checking disabled. If this option is
+ * present, fork()ing can be dangerous. */
+#define OTTERY_BLDFLG_NO_PID_CHECK 0x00000001
+/** Set if libottery was built with initialization checking disabled. If this
+ * option is present, libottery might use an uninitialized, unseeded PRNGs.
+ */
+#define OTTERY_BLDFLG_NO_INIT_CHECK 0x00000002
+/** Set if locking was disabled. If this option is present, no libottery
+ * state, including the global state, is thread-safe. */
+#define OTTERY_BLDFLG_NO_LOCKING 0x00000004
+/** Set if the clear-after-yield feature was disabled. If this option is
+ * present, backtracking-resistance is somewhat compromised. */
+#define OTTERY_BLDFLG_NO_CLEAR_AFTER_YIELD 0x00000008
+/** Set if the stack-wiping feature was disabled. If this option is
+ * present, programs which accidentally read uninitialized data from the
+ * stack may leak some cryptographic state. */
+#define OTTERY_BLDFLG_NO_WIPE_STACK 0x00000010
+/** Set if SIMD support was disabled. This will make libottery slower. */
+#define OTTERY_BLDFLG_NO_SIMD 0x00010000
+/** @} */
+
+/** A bitmask of any flags that might affect safe and secure program
+ * operation. */
+#define OTTERY_BLDFLG_MASK_SAFETY 0x0000ffff
+
+/**
+ * Return a bitmask of flags describing the compile-time options that this
+ * libottery instance was built with. Some of these flags might make the
+ * library less safe to use!
+ */
+uint32_t ottery_get_build_flags(void);
+
+/**
+ * Return a run-time version number for Libottery. The first three bytes are
+ * the major number, minor number, and patch-level respectively. The final
+ * byte is 0 for a released version, and nonzero otherwise.
+ */
+uint32_t ottery_get_version(void);
+/**
+ * Return a human-readable string representing the run-time Libottery version.
+ */
+const char *ottery_get_version_string(void);
+
+const char *ottery_get_impl_name(void);
+
+#endif
diff --git a/contrib/libottery/ottery_cpuinfo.c b/contrib/libottery/ottery_cpuinfo.c
new file mode 100644
index 0000000..2e8bdaa
--- /dev/null
+++ b/contrib/libottery/ottery_cpuinfo.c
@@ -0,0 +1,88 @@
+/* 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/>.
+ */
+#include "ottery-internal.h"
+#include <stdint.h>
+
+#if defined(i386) || \
+ defined(__i386) || \
+ defined(__M_IX86) || \
+ defined(_M_IX86)
+#define X86
+#elif defined(__x86_64) || \
+ defined(_M_AMD64)
+#define X86
+#define X86_64
+#endif
+
+#if defined(__arm__) || \
+ defined(_M_ARM)
+#define ARM
+#endif
+
+#if defined(X86)
+#ifdef _MSC_VER
+#include <intrin.h>
+#define cpuid(a,b) __cpuid((b), (a))
+#else
+static void
+cpuid(int index, int regs[4])
+{
+ unsigned int eax, ebx, ecx, edx;
+#ifdef X86_64
+ __asm("cpuid" : "=a"(eax), "=b" (ebx), "=c"(ecx), "=d"(edx)
+ : "0"(index));
+#else
+ __asm volatile(
+ "xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+ : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+ : "0" (index)
+ : "cc" );
+#endif
+
+ regs[0] = eax;
+ regs[1] = ebx;
+ regs[2] = ecx;
+ regs[3] = edx;
+}
+#endif
+#endif
+
+static uint32_t disabled_cpu_capabilities = 0;
+
+void
+ottery_disable_cpu_capabilities_(uint32_t disable)
+{
+ disabled_cpu_capabilities |= disable;
+}
+
+uint32_t
+ottery_get_cpu_capabilities_(void)
+{
+#ifdef X86
+ uint32_t cap = 0;
+ int res[4];
+ cpuid(1, res);
+ if (res[3] & (1<<26))
+ cap |= OTTERY_CPUCAP_SIMD;
+ if (res[2] & (1<<9))
+ cap |= OTTERY_CPUCAP_SSSE3;
+ if (res[2] & (1<<25))
+ cap |= OTTERY_CPUCAP_AES;
+ if (res[2] & (1<<30))
+ cap |= OTTERY_CPUCAP_RAND;
+#else
+ uint32_t cap = OTTERY_CPUCAP_SIMD;
+#endif
+ return cap & ~disabled_cpu_capabilities;
+}
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;
+}
diff --git a/contrib/libottery/ottery_entropy_cryptgenrandom.c b/contrib/libottery/ottery_entropy_cryptgenrandom.c
new file mode 100644
index 0000000..d29d9d1
--- /dev/null
+++ b/contrib/libottery/ottery_entropy_cryptgenrandom.c
@@ -0,0 +1,51 @@
+/* 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"
+
+#ifdef _WIN32
+
+/** Generate random bytes using the Windows CryptGenRandom operating-system
+ * RNG. */
+static int
+ottery_get_entropy_cryptgenrandom(const struct ottery_entropy_config *cfg,
+ struct ottery_entropy_state *state,
+ uint8_t *out, size_t outlen)
+{
+ /* On Windows, CryptGenRandom is supposed to be a well-seeded
+ * cryptographically strong random number generator. */
+ HCRYPTPROV provider;
+ int retval = 0;
+ (void) cfg;
+ (void) state;
+
+ if (0 == CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ return OTTERY_ERR_INIT_STRONG_RNG;
+
+ if (0 == CryptGenRandom(provider, outlen, out))
+ retval = OTTERY_ERR_ACCESS_STRONG_RNG;
+
+ CryptReleaseContext(provider, 0);
+ return retval;
+}
+
+#define ENTROPY_SOURCE_CRYPTGENRANDOM \
+ { ottery_get_entropy_cryptgenrandom, \
+ SRC(CRYPTGENRANDOM)|DOM(OS)|FL(STRONG) }
+
+#endif
+
+
diff --git a/contrib/libottery/ottery_entropy_egd.c b/contrib/libottery/ottery_entropy_egd.c
new file mode 100644
index 0000000..7e9cb07
--- /dev/null
+++ b/contrib/libottery/ottery_entropy_egd.c
@@ -0,0 +1,75 @@
+/* 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/>.
+ */
+#ifndef _WIN32
+/* TODO: Support win32. */
+#include <sys/socket.h>
+
+/** Implement an entropy-source that uses the EGD protocol. The
+ * Entropy-Gathering Daemon is program (actually, one of several programs)
+ * that watches system events, periodically runs commands whose outputs have
+ * high variance, and so on. It communicates over a simple socket-based
+ * protocol, of which we use only a tiny piece. */
+static int
+ottery_get_entropy_egd(const struct ottery_entropy_config *cfg,
+ struct ottery_entropy_state *state,
+ uint8_t *out, size_t outlen)
+{
+ int sock, n, result;
+ unsigned char msg[2];
+ (void) state;
+
+ if (! cfg || ! cfg->egd_sockaddr || ! cfg->egd_socklen)
+ return OTTERY_ERR_INIT_STRONG_RNG;
+ if (outlen > 255)
+ return OTTERY_ERR_ACCESS_STRONG_RNG;
+
+ sock = socket(cfg->egd_sockaddr->sa_family, SOCK_STREAM, 0);
+ if (sock < 0)
+ return OTTERY_ERR_INIT_STRONG_RNG;
+
+ if (connect(sock, cfg->egd_sockaddr, cfg->egd_socklen) < 0) {
+ result = OTTERY_ERR_INIT_STRONG_RNG;
+ goto out;
+ }
+
+ msg[0] = 1; /* nonblocking request */
+ msg[1] = (unsigned char) outlen; /* for outlen bytes */
+
+ if (write(sock, msg, 2) != 2 ||
+ read(sock, msg, 1) != 1) {
+ result = OTTERY_ERR_ACCESS_STRONG_RNG;
+ goto out;
+ }
+
+ if (msg[0] != outlen) {
+ /* TODO Use any bytes we get, even if they aren't as many as we wanted. */
+ result = OTTERY_ERR_ACCESS_STRONG_RNG;
+ goto out;
+ }
+
+ n = ottery_read_n_bytes_from_file_(sock, out, outlen);
+ if (n < 0 || (size_t)n != outlen) {
+ result = OTTERY_ERR_ACCESS_STRONG_RNG;
+ goto out;
+ }
+ result = 0;
+ out:
+ close(sock);
+ return result;
+}
+
+#define ENTROPY_SOURCE_EGD \
+ { ottery_get_entropy_egd, SRC(EGD)|DOM(EGD)|FL(STRONG) }
+
+#endif
diff --git a/contrib/libottery/ottery_entropy_rdrand.c b/contrib/libottery/ottery_entropy_rdrand.c
new file mode 100644
index 0000000..4f227d3
--- /dev/null
+++ b/contrib/libottery/ottery_entropy_rdrand.c
@@ -0,0 +1,58 @@
+/* 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/>.
+ */
+
+#if defined(i386) || \
+ defined(__i386) || \
+ defined(__x86_64) || \
+ defined(__M_IX86) || \
+ defined(_M_IX86) || \
+ defined(__INTEL_COMPILER)
+
+extern int ottery_valgrind_;
+/** Helper: invoke the RDRAND instruction to get 4 random bytes in the output
+ * value. Return 1 on success, and 0 on failure. */
+#define rdrand32(x) ({ unsigned char err = 0; __asm volatile(".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1":"=a"(x), "=qm"(err) :"a"(0) :"cc"); err; })
+
+/** Generate bytes using the Intel RDRAND instruction. */
+static int
+ottery_get_entropy_rdrand(const struct ottery_entropy_config *cfg,
+ struct ottery_entropy_state *state,
+ uint8_t *out, size_t outlen)
+{
+ uint32_t up;
+ (void) cfg;
+ (void) state;
+ if (! (ottery_get_cpu_capabilities_() & OTTERY_CPUCAP_RAND) || ottery_valgrind_)
+ return OTTERY_ERR_INIT_STRONG_RNG;
+ while (outlen >= 4) {
+ if (rdrand32(up) != 1)
+ return OTTERY_ERR_INIT_STRONG_RNG;
+ memcpy (out, &up, sizeof (up));
+ out += sizeof (up);
+ outlen -= 4;
+ }
+
+ if (outlen) {
+ if (rdrand32(up) != 1)
+ return OTTERY_ERR_INIT_STRONG_RNG;
+ memcpy(out, &up, outlen);
+ }
+ return 0;
+}
+
+#define ENTROPY_SOURCE_RDRAND \
+ { ottery_get_entropy_rdrand, SRC(RDRAND)|DOM(CPU)|FL(FAST)|FL(STRONG) }
+
+#endif
+
diff --git a/contrib/libottery/ottery_entropy_urandom.c b/contrib/libottery/ottery_entropy_urandom.c
new file mode 100644
index 0000000..9eb761b
--- /dev/null
+++ b/contrib/libottery/ottery_entropy_urandom.c
@@ -0,0 +1,117 @@
+/* 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/>.
+ */
+
+#ifndef _WIN32
+
+/**
+ * Read from a file into an n-byte buffer until the buffer is full or until
+ * we reach an error. Returns the number of bytes read. If the return
+ * value is less than n, an error occurred.
+ */
+static int
+ottery_read_n_bytes_from_file_(int fd, uint8_t *out, size_t n)
+{
+ ssize_t r;
+ uint8_t *outp = out;
+ while (n) {
+ r = read(fd, outp, n);
+ if (r <= 0 || (size_t)r > n)
+ return outp - out;
+ outp += r;
+ n -= r;
+ }
+ return outp - out;
+}
+
+
+/** Generate random bytes using the unix-style /dev/urandom RNG, or another
+ * such device as configured in the configuration. */
+static int
+ottery_get_entropy_urandom(const struct ottery_entropy_config *cfg,
+ struct ottery_entropy_state *state,
+ uint8_t *out, size_t outlen)
+{
+ /* On most unixes these days, you can get strong random numbers from
+ * /dev/urandom.
+ *
+ * That's assuming that /dev/urandom is seeded. For most applications,
+ * that won't be a problem. But for stuff that starts close to system
+ * startup, before the operating system has added any entropy to the pool,
+ * it can be pretty bad.
+ *
+ * You could use /dev/random instead, if you want, but that has another
+ * problem. It will block if the OS PRNG has received less entropy than
+ * it has emitted. If we assume that the OS PRNG isn't cryptographically
+ * weak, blocking in that case is simple overkill.
+ *
+ * It would be best if there were an alternative that blocked if the PRNG
+ * had _never_ been seeded. But most operating systems don't have that.
+ */
+ int fd;
+ ssize_t n;
+ int result = 0;
+ const char *urandom_fname;
+ struct stat st;
+ int own_fd = 0;
+ int check_device = !cfg || !cfg->allow_nondev_urandom;
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+ if (cfg && cfg->urandom_fd_is_set && cfg->urandom_fd >= 0) {
+ fd = cfg->urandom_fd;
+ } else {
+ if (cfg && cfg->urandom_fname)
+ urandom_fname = cfg->urandom_fname;
+ else
+ urandom_fname = "/dev/urandom";
+
+ fd = open(urandom_fname, O_RDONLY|O_CLOEXEC);
+ own_fd = 1;
+ if (fd < 0)
+ return OTTERY_ERR_INIT_STRONG_RNG;
+ }
+ if (fstat(fd, &st) < 0) {
+ result = OTTERY_ERR_INIT_STRONG_RNG;
+ goto end;
+ }
+ if (check_device) {
+ if (0 == (st.st_mode & S_IFCHR)) {
+ result = OTTERY_ERR_INIT_STRONG_RNG;
+ goto end;
+ }
+
+ if (state) {
+ if (0 == state->urandom_fd_inode) {
+ state->urandom_fd_inode = (uint64_t) st.st_ino;
+ } else if ((uint64_t)st.st_ino != state->urandom_fd_inode) {
+ close(fd);
+ return OTTERY_ERR_ACCESS_STRONG_RNG;
+ }
+ }
+ }
+
+ n = ottery_read_n_bytes_from_file_(fd, out, outlen);
+ if (n < 0 || (size_t)n != outlen)
+ result = OTTERY_ERR_ACCESS_STRONG_RNG;
+
+ end:
+ if (own_fd)
+ close(fd);
+ return result;
+}
+
+#define ENTROPY_SOURCE_URANDOM \
+ { ottery_get_entropy_urandom, SRC(RANDOMDEV)|DOM(OS)|FL(STRONG) }
+
+#endif
diff --git a/contrib/libottery/ottery_global.c b/contrib/libottery/ottery_global.c
new file mode 100644
index 0000000..dd1efc5
--- /dev/null
+++ b/contrib/libottery/ottery_global.c
@@ -0,0 +1,116 @@
+/* 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 <stdlib.h>
+#include "ottery-internal.h"
+#include "ottery.h"
+#include "ottery_st.h"
+
+
+/** Flag: true iff ottery_global_state_ is initialized. */
+static int ottery_global_state_initialized_ = 0;
+int ottery_valgrind_ = 0;
+/** A global state to use for the ottery_* functions that don't take a
+ * state. */
+static struct ottery_state ottery_global_state_;
+
+/** Initialize ottery_global_state_ if it has not been initialize. */
+#define CHECK_INIT(rv) do { \
+ if (UNLIKELY(!ottery_global_state_initialized_)) { \
+ int err; \
+ if ((err = ottery_init(NULL))) { \
+ ottery_fatal_error_(OTTERY_ERR_FLAG_GLOBAL_PRNG_INIT|err); \
+ return rv; \
+ } \
+ } \
+} while (0)
+
+int
+ottery_init(const struct ottery_config *cfg)
+{
+ if (getenv("VALGRIND")) {
+ ottery_valgrind_ = 1;
+ }
+ int n = ottery_st_init(&ottery_global_state_, cfg);
+ if (n == 0)
+ ottery_global_state_initialized_ = 1;
+ return n;
+}
+
+int
+ottery_add_seed(const uint8_t *seed, size_t n)
+{
+ CHECK_INIT(0);
+ return ottery_st_add_seed(&ottery_global_state_, seed, n);
+}
+
+void
+ottery_wipe(void)
+{
+ if (ottery_global_state_initialized_) {
+ ottery_global_state_initialized_ = 0;
+ ottery_st_wipe(&ottery_global_state_);
+ }
+}
+
+void
+ottery_prevent_backtracking(void)
+{
+ CHECK_INIT();
+ ottery_st_prevent_backtracking(&ottery_global_state_);
+}
+
+void
+ottery_rand_bytes(void *out, size_t n)
+{
+ CHECK_INIT();
+ ottery_st_rand_bytes(&ottery_global_state_, out, n);
+}
+
+unsigned
+ottery_rand_unsigned(void)
+{
+ CHECK_INIT(0);
+ return ottery_st_rand_unsigned(&ottery_global_state_);
+}
+uint32_t
+ottery_rand_uint32(void)
+{
+ CHECK_INIT(0);
+ return ottery_st_rand_uint32(&ottery_global_state_);
+}
+uint64_t
+ottery_rand_uint64(void)
+{
+ CHECK_INIT(0);
+ return ottery_st_rand_uint64(&ottery_global_state_);
+}
+unsigned
+ottery_rand_range(unsigned top)
+{
+ CHECK_INIT(0);
+ return ottery_st_rand_range(&ottery_global_state_, top);
+}
+uint64_t
+ottery_rand_range64(uint64_t top)
+{
+ CHECK_INIT(0);
+ return ottery_st_rand_range64(&ottery_global_state_, top);
+}
+
+const char *ottery_get_impl_name(void)
+{
+ CHECK_INIT(0);
+ return ottery_global_state_.prf.name;
+} \ No newline at end of file
diff --git a/contrib/libottery/ottery_nolock.h b/contrib/libottery/ottery_nolock.h
new file mode 100644
index 0000000..b504e11
--- /dev/null
+++ b/contrib/libottery/ottery_nolock.h
@@ -0,0 +1,190 @@
+/* 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/>.
+ */
+#ifndef OTTERY_NOLOCK_H_HEADER_INCLUDED_
+#define OTTERY_NOLOCK_H_HEADER_INCLUDED_
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ottery_common.h"
+
+/** @file */
+
+struct ottery_config;
+struct ottery_state_nolock;
+
+/** Size reserved for struct ottery_state_nolock */
+#define OTTERY_STATE_NOLOCK_DUMMY_SIZE_ 1536
+
+#ifndef OTTERY_INTERNAL
+/**
+ * The state for a non-thread-safe libottery PRNG
+ *
+ * Like struct ottery_state, but this structure (and its associated functions)
+ * are not thread safe. If you try to use this structure in more than one
+ * thread at a time, your program's behavior will be undefined. It might
+ * crash. It might insecurely give the same random sequence to multiple
+ * threads. It might fail in strange ways that you'd never predict.
+ *
+ * An ottery_state_nolock structure is constucted with ottery_st_init(). It
+ * MUST be aligned on a 16-byte boundary.
+ *
+ * You may not use an ottery_state_nolock structure with any other function
+ * before you have first initialized it with ottery_st_init_nolock().
+ *
+ * The contents of this structure are opaque; The definition here is
+ * defined to be large enough so that programs that allocate it will get
+ * more than enough room.
+ */
+struct __attribute__((aligned(16))) ottery_state_nolock {
+ /** Nothing to see here */
+ uint8_t dummy_[OTTERY_STATE_NOLOCK_DUMMY_SIZE_];
+};
+#endif
+
+/**
+ * Get the minimal size for allocating an ottery_state_nolock.
+ *
+ * sizeof(ottery_state_nolock) will give an overestimate to allow binary
+ * compatibility with future versions of libottery. Use this function instead
+ * to get the minimal number of bytes to allocate.
+ *
+ * @return The minimal number of bytes to use when allocating an
+ * ottery_state_nolock structure.
+ */
+size_t ottery_get_sizeof_state_nolock(void);
+
+/**
+ * Initialize an ottery_state_nolock structure.
+ *
+ * You must call this function on any ottery_state_nolock structure before
+ * calling any other functions on it.
+ *
+ * @param st The ottery_state_nolock to initialize.
+ * @param cfg Either NULL, or an ottery_config structure that has been
+ * initialized with ottery_config_init().
+ * @return Zero on success, or one of the OTTERY_ERR_* error codes on failure.
+ */
+int ottery_st_init_nolock(struct ottery_state_nolock *st, const struct ottery_config *cfg);
+
+/**
+ * Add more entropy to an ottery_state_nolock structure.
+ *
+ * Calling this function should be needless, if you trust your operating
+ * system's random number generator and entropy extraction features. You
+ * would want to use this function if you think the operating system's random
+ * number generator might be inadequate, and you want to add more entropy from
+ * EGD or something.
+ *
+ * You might also want to call this function if your belief system says that
+ * it's useful to periodically add more raw entropy to a well-seeded
+ * cryptographically strong PRNG.
+ *
+ * @param st The state which will receive more entropy.
+ * @param seed Bytes to add to the state.
+ * @param n The number of bytes to add.
+ * @return Zero on success, or one of the OTTERY_ERR_* error codes on failure.
+ */
+int ottery_st_add_seed_nolock(struct ottery_state_nolock *st, const uint8_t *seed, size_t n);
+
+/**
+ * Destroy an ottery_state_nolock structure and release any resources that it
+ * might hold.
+ *
+ * Ordinarily, you would want to call this at exit, or before freeing an
+ * ottery_state_nolock
+ *
+ * @param st The state to wipe.
+ */
+void ottery_st_wipe_nolock(struct ottery_state_nolock *st);
+
+/**
+ * Explicitly prevent backtracking attacks. (Usually needless).
+ *
+ * Once this function has been called, an attacker who compromises the state
+ * later on will not be able to recover bytes that have previously been
+ * returned by any of the ottery_st_rand_*_nolock functions.
+ *
+ * You should not usually need to call this function: Libottery provides
+ * backtracking resistance by default, so unless you have manually recompiled
+ * with the OTTERY_NO_CLEAR_AFTER_YIELD option, this function isn't
+ * necessary and has no effect. Even *with* OTTERY_NO_CLEAR_AFTER_YIELD,
+ * this function isn't necessary in ordinary operation: the libottery state is
+ * implicitly "stirred" every 1k or so.
+ *
+ * @param st The state to stir.
+ */
+void ottery_st_prevent_backtracking_nolock(struct ottery_state_nolock *st);
+
+/**
+ * Use an ottery_state_nolock structure to fill a buffer with random bytes.
+ *
+ * @param st The state structure to use.
+ * @param buf The buffer to fill.
+ * @param n The number of bytes to write.
+ */
+void ottery_st_rand_bytes_nolock(struct ottery_state_nolock *st, void *buf, size_t n);
+/**
+ * Use an ottery_state_nolock structure to generate a random number of type unsigned.
+ *
+ * @param st The state structure to use.
+ * @return A random number between 0 and UINT_MAX included,
+ * chosen uniformly.
+ */
+unsigned ottery_st_rand_unsigned_nolock(struct ottery_state_nolock *st);
+/**
+ * Use an ottery_state_nolock structure to generate a random number of type uint32_t.
+ *
+ * @param st The state structure to use.
+ * @return A random number between 0 and UINT32_MAX included,
+ * chosen uniformly.
+ */
+uint32_t ottery_st_rand_uint32_nolock(struct ottery_state_nolock *st);
+/**
+ * Use an ottery_state_nolock structure to generate a random number of type uint64_t.
+ *
+ * @param st The state structure to use.
+ * @return A random number between 0 and UINT64_MAX included,
+ * chosen uniformly.
+ */
+uint64_t ottery_st_rand_uint64_nolock(struct ottery_state_nolock *st);
+/**
+ * Use an ottery_state_nolock structure to generate a random number of type unsigned
+ * in a given range.
+ *
+ * @param st The state structure to use.
+ * @param top The upper bound of the range (inclusive).
+ * @return A random number no larger than top, and no less than 0,
+ * chosen uniformly.
+ */
+unsigned ottery_st_rand_range_nolock(struct ottery_state_nolock *st, unsigned top);
+/**
+ * Use an ottery_state_nolock structure to generate a random number of type uint64_t
+ * in a given range.
+ *
+ * @param st The state structure to use.
+ * @param top The upper bound of the range (inclusive).
+ * @return A random number no larger than top, and no less than 0,
+ * chosen uniformly.
+ */
+uint64_t ottery_st_rand_range64_nolock(struct ottery_state_nolock *st, uint64_t top);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/libottery/ottery_st.h b/contrib/libottery/ottery_st.h
new file mode 100644
index 0000000..38955cb
--- /dev/null
+++ b/contrib/libottery/ottery_st.h
@@ -0,0 +1,184 @@
+/* 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/>.
+ */
+#ifndef OTTERY_ST_H_HEADER_INCLUDED_
+#define OTTERY_ST_H_HEADER_INCLUDED_
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ottery_common.h"
+
+/** @file */
+
+struct ottery_config;
+struct ottery_state;
+
+/** Size reserved for struct ottery_state */
+#define OTTERY_STATE_DUMMY_SIZE_ 1536
+
+#ifndef OTTERY_INTERNAL
+/**
+ * The state for a libottery PRNG.
+ *
+ * An ottery_state structure is constucted with ottery_st_init(). It MUST be
+ * aligned on a 16-byte boundary.
+ *
+ * You may not use an ottery_state structure with any other function before
+ * you have first initialized it with ottery_st_init().
+ *
+ * The contents of this structure are opaque; The definition here is
+ * defined to be large enough so that programs that allocate it will get
+ * more than enough room.
+ */
+struct __attribute__((aligned(16))) ottery_state {
+ /** Nothing to see here */
+ uint8_t dummy_[OTTERY_STATE_DUMMY_SIZE_];
+};
+#endif
+
+/**
+ * Get the minimal size for allocating an ottery_state.
+ *
+ * sizeof(ottery_state) will give an overestimate to allow binary
+ * compatibility with future versions of libottery. Use this function instead
+ * to get the minimal number of bytes to allocate.
+ *
+ * @return The minimal number of bytes to use when allocating an
+ * ottery_state structure.
+ */
+size_t ottery_get_sizeof_state(void);
+
+/**
+ * Initialize an ottery_state structure.
+ *
+ * You must call this function on any ottery_state structure before
+ * calling any other functions on it.
+ *
+ * @param st The ottery_state to initialize.
+ * @param cfg Either NULL, or an ottery_config structure that has been
+ * initialized with ottery_config_init().
+ * @return Zero on success, or one of the OTTERY_ERR_* error codes on failure.
+ */
+int ottery_st_init(struct ottery_state *st, const struct ottery_config *cfg);
+
+/**
+ * Add more entropy to an ottery_state structure.
+ *
+ * Calling this function should be needless, if you trust your operating
+ * system's random number generator and entropy extraction features. You
+ * would want to use this function if you think the operating system's random
+ * number generator might be inadequate, and you want to add more entropy from
+ * EGD or something.
+ *
+ * You might also want to call this function if your belief system says that
+ * it's useful to periodically add more raw entropy to a well-seeded
+ * cryptographically strong PRNG.
+ *
+ * @param st The state which will receive more entropy.
+ * @param seed Bytes to add to the state.
+ * @param n The number of bytes to add.
+ * @return Zero on success, or one of the OTTERY_ERR_* error codes on failure.
+ */
+int ottery_st_add_seed(struct ottery_state *st, const uint8_t *seed, size_t n);
+
+/**
+ * Destroy an ottery_state structure and release any resources that it might
+ * hold.
+ *
+ * Ordinarily, you would want to call this at exit, or before freeing an
+ * ottery_state
+ *
+ * @param st The state to wipe.
+ */
+void ottery_st_wipe(struct ottery_state *st);
+
+/**
+ * Explicitly prevent backtracking attacks. (Usually needless).
+ *
+ * Once this function has been called, an attacker who compromises the state
+ * later on will not be able to recover bytes that have previously been
+ * returned by any of the ottery_st_rand_* functions.
+ *
+ * You should not usually need to call this function: Libottery provides
+ * backtracking resistance by default, so unless you have manually recompiled
+ * with the OTTERY_NO_CLEAR_AFTER_YIELD option, this function isn't
+ * necessary and has no effect. Even *with* OTTERY_NO_CLEAR_AFTER_YIELD,
+ * this function isn't necessary in ordinary operation: the libottery state is
+ * implicitly "stirred" every 1k or so.
+ *
+ * @param st The state to stir.
+ */
+void ottery_st_prevent_backtracking(struct ottery_state *st);
+
+/**
+ * Use an ottery_state structure to fill a buffer with random bytes.
+ *
+ * @param st The state structure to use.
+ * @param buf The buffer to fill.
+ * @param n The number of bytes to write.
+ */
+void ottery_st_rand_bytes(struct ottery_state *st, void *buf, size_t n);
+/**
+ * Use an ottery_state structure to generate a random number of type unsigned.
+ *
+ * @param st The state structure to use.
+ * @return A random number between 0 and UINT_MAX included,
+ * chosen uniformly.
+ */
+unsigned ottery_st_rand_unsigned(struct ottery_state *st);
+/**
+ * Use an ottery_state structure to generate a random number of type uint32_t.
+ *
+ * @param st The state structure to use.
+ * @return A random number between 0 and UINT32_MAX included,
+ * chosen uniformly.
+ */
+uint32_t ottery_st_rand_uint32(struct ottery_state *st);
+/**
+ * Use an ottery_state structure to generate a random number of type uint64_t.
+ *
+ * @param st The state structure to use.
+ * @return A random number between 0 and UINT64_MAX included,
+ * chosen uniformly.
+ */
+uint64_t ottery_st_rand_uint64(struct ottery_state *st);
+/**
+ * Use an ottery_state structure to generate a random number of type unsigned
+ * in a given range.
+ *
+ * @param st The state structure to use.
+ * @param top The upper bound of the range (inclusive).
+ * @return A random number no larger than top, and no less than 0,
+ * chosen uniformly.
+ */
+unsigned ottery_st_rand_range(struct ottery_state *st, unsigned top);
+/**
+ * Use an ottery_state structure to generate a random number of type uint64_t
+ * in a given range.
+ *
+ * @param st The state structure to use.
+ * @param top The upper bound of the range (inclusive).
+ * @return A random number no larger than top, and no less than 0,
+ * chosen uniformly.
+ */
+uint64_t ottery_st_rand_range64(struct ottery_state *st, uint64_t top);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/libottery/ottery_version.h.in b/contrib/libottery/ottery_version.h.in
new file mode 100644
index 0000000..1b6a244
--- /dev/null
+++ b/contrib/libottery/ottery_version.h.in
@@ -0,0 +1,28 @@
+/* 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/>.
+ */
+#ifndef OTTERY_VERSION_H_HEADER_INCLUDED_
+#define OTTERY_VERSION_H_HEADER_INCLUDED_
+
+/**
+ * Version number for Libottery. The first three bytes are the major number,
+ * minor number, and patch-level respectively. The final byte is 0 for a
+ * released version, and nonzero otherwise.
+ */
+#undef OTTERY_VERSION
+/**
+ * Human-readable string representing the Libottery version.
+ */
+#undef OTTERY_VERSION_STRING
+
+#endif