summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--contrib/libottery/CMakeLists.txt15
-rw-r--r--contrib/libottery/Makefile314
-rw-r--r--contrib/libottery/chacha_krovetz.c320
-rw-r--r--contrib/libottery/chacha_merged.c218
-rw-r--r--contrib/libottery/chacha_merged_ecrypt.h133
-rw-r--r--contrib/libottery/ottery-internal.h314
-rw-r--r--contrib/libottery/ottery-threading.h91
-rw-r--r--contrib/libottery/ottery.c842
-rw-r--r--contrib/libottery/ottery.h143
-rw-r--r--contrib/libottery/ottery_common.h349
-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.c63
-rw-r--r--contrib/libottery/ottery_entropy_urandom.c117
-rw-r--r--contrib/libottery/ottery_global.c111
-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
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/chacha_private.h228
-rw-r--r--src/dns.c48
-rw-r--r--src/dns_private.h13
-rw-r--r--src/main.c3
-rw-r--r--src/util.c55
-rw-r--r--src/util.h12
28 files changed, 3769 insertions, 353 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 09da6c285..5eed2f089 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -877,7 +877,8 @@ INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/src"
"${CMAKE_BINARY_DIR}/src"
"${CMAKE_SOURCE_DIR}/src/ucl/include"
"${CMAKE_SOURCE_DIR}/contrib/uthash"
- "${CMAKE_SOURCE_DIR}/contrib/http-parser")
+ "${CMAKE_SOURCE_DIR}/contrib/http-parser"
+ "${CMAKE_SOURCE_DIR}/contrib/libottery")
SET(RSPAMDSRC src/modules.c
src/controller.c
@@ -919,6 +920,7 @@ ADD_SUBDIRECTORY(src/json)
ADD_SUBDIRECTORY(src/cdb)
ADD_SUBDIRECTORY(src/ucl)
ADD_SUBDIRECTORY(contrib/http-parser)
+ADD_SUBDIRECTORY(contrib/libottery)
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(src/client)
diff --git a/contrib/libottery/CMakeLists.txt b/contrib/libottery/CMakeLists.txt
new file mode 100644
index 000000000..499a080b3
--- /dev/null
+++ b/contrib/libottery/CMakeLists.txt
@@ -0,0 +1,15 @@
+SET(OTTERYSRC chacha_merged.c
+ ottery.c
+ ottery_cpuinfo.c
+ ottery_entropy.c
+ ottery_global.c)
+
+ADD_LIBRARY(rspamd-ottery ${LINK_TYPE} ${OTTERYSRC})
+SET_TARGET_PROPERTIES(rspamd-ottery PROPERTIES VERSION ${RSPAMD_VERSION})
+SET_TARGET_PROPERTIES(rspamd-ottery PROPERTIES COMPILE_FLAGS "-DRSPAMD_LIB")
+
+IF(NO_SHARED MATCHES "OFF")
+ INSTALL(TARGETS rspamd-ottery
+ LIBRARY DESTINATION ${LIBDIR}
+ PUBLIC_HEADER DESTINATION ${INCLUDEDIR})
+ENDIF(NO_SHARED MATCHES "OFF") \ No newline at end of file
diff --git a/contrib/libottery/Makefile b/contrib/libottery/Makefile
new file mode 100644
index 000000000..959090815
--- /dev/null
+++ b/contrib/libottery/Makefile
@@ -0,0 +1,314 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 2.8
+
+# Default target executed when no arguments are given to make.
+default_target: all
+.PHONY : default_target
+
+#=============================================================================
+# Special targets provided by cmake.
+
+# Disable implicit rules so canonical targets will work.
+.SUFFIXES:
+
+# Remove some rules from gmake that .SUFFIXES does not remove.
+SUFFIXES =
+
+.SUFFIXES: .hpux_make_needs_suffix_list
+
+# Suppress display of executed commands.
+$(VERBOSE).SILENT:
+
+# A target that is always out of date.
+cmake_force:
+.PHONY : cmake_force
+
+#=============================================================================
+# Set environment variables for the build.
+
+# The shell in which to execute make rules.
+SHELL = /bin/sh
+
+# The CMake executable.
+CMAKE_COMMAND = /usr/bin/cmake
+
+# The command to remove a file.
+RM = /usr/bin/cmake -E remove -f
+
+# The top-level source directory on which CMake was run.
+CMAKE_SOURCE_DIR = /home/vs374/rspamd
+
+# The top-level build directory on which CMake was run.
+CMAKE_BINARY_DIR = /home/vs374/rspamd
+
+#=============================================================================
+# Targets provided globally by CMake.
+
+# Special rule for the target edit_cache
+edit_cache:
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running interactive CMake command-line interface..."
+ /usr/bin/cmake -i .
+.PHONY : edit_cache
+
+# Special rule for the target edit_cache
+edit_cache/fast: edit_cache
+.PHONY : edit_cache/fast
+
+# Special rule for the target install
+install: preinstall
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
+ /usr/bin/cmake -P cmake_install.cmake
+.PHONY : install
+
+# Special rule for the target install
+install/fast: preinstall/fast
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
+ /usr/bin/cmake -P cmake_install.cmake
+.PHONY : install/fast
+
+# Special rule for the target install/local
+install/local: preinstall
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
+ /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
+.PHONY : install/local
+
+# Special rule for the target install/local
+install/local/fast: install/local
+.PHONY : install/local/fast
+
+# Special rule for the target install/strip
+install/strip: preinstall
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
+ /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
+.PHONY : install/strip
+
+# Special rule for the target install/strip
+install/strip/fast: install/strip
+.PHONY : install/strip/fast
+
+# Special rule for the target list_install_components
+list_install_components:
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\""
+.PHONY : list_install_components
+
+# Special rule for the target list_install_components
+list_install_components/fast: list_install_components
+.PHONY : list_install_components/fast
+
+# Special rule for the target rebuild_cache
+rebuild_cache:
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
+ /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
+.PHONY : rebuild_cache
+
+# Special rule for the target rebuild_cache
+rebuild_cache/fast: rebuild_cache
+.PHONY : rebuild_cache/fast
+
+# The main all target
+all: cmake_check_build_system
+ cd /home/vs374/rspamd && $(CMAKE_COMMAND) -E cmake_progress_start /home/vs374/rspamd/CMakeFiles /home/vs374/rspamd/contrib/libottery/CMakeFiles/progress.marks
+ cd /home/vs374/rspamd && $(MAKE) -f CMakeFiles/Makefile2 contrib/libottery/all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/vs374/rspamd/CMakeFiles 0
+.PHONY : all
+
+# The main clean target
+clean:
+ cd /home/vs374/rspamd && $(MAKE) -f CMakeFiles/Makefile2 contrib/libottery/clean
+.PHONY : clean
+
+# The main clean target
+clean/fast: clean
+.PHONY : clean/fast
+
+# Prepare targets for installation.
+preinstall: all
+ cd /home/vs374/rspamd && $(MAKE) -f CMakeFiles/Makefile2 contrib/libottery/preinstall
+.PHONY : preinstall
+
+# Prepare targets for installation.
+preinstall/fast:
+ cd /home/vs374/rspamd && $(MAKE) -f CMakeFiles/Makefile2 contrib/libottery/preinstall
+.PHONY : preinstall/fast
+
+# clear depends
+depend:
+ cd /home/vs374/rspamd && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
+.PHONY : depend
+
+# Convenience name for target.
+contrib/libottery/CMakeFiles/rspamd-ottery.dir/rule:
+ cd /home/vs374/rspamd && $(MAKE) -f CMakeFiles/Makefile2 contrib/libottery/CMakeFiles/rspamd-ottery.dir/rule
+.PHONY : contrib/libottery/CMakeFiles/rspamd-ottery.dir/rule
+
+# Convenience name for target.
+rspamd-ottery: contrib/libottery/CMakeFiles/rspamd-ottery.dir/rule
+.PHONY : rspamd-ottery
+
+# fast build rule for target.
+rspamd-ottery/fast:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/build
+.PHONY : rspamd-ottery/fast
+
+chacha_merged.o: chacha_merged.c.o
+.PHONY : chacha_merged.o
+
+# target to build an object file
+chacha_merged.c.o:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/chacha_merged.c.o
+.PHONY : chacha_merged.c.o
+
+chacha_merged.i: chacha_merged.c.i
+.PHONY : chacha_merged.i
+
+# target to preprocess a source file
+chacha_merged.c.i:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/chacha_merged.c.i
+.PHONY : chacha_merged.c.i
+
+chacha_merged.s: chacha_merged.c.s
+.PHONY : chacha_merged.s
+
+# target to generate assembly for a file
+chacha_merged.c.s:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/chacha_merged.c.s
+.PHONY : chacha_merged.c.s
+
+ottery.o: ottery.c.o
+.PHONY : ottery.o
+
+# target to build an object file
+ottery.c.o:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery.c.o
+.PHONY : ottery.c.o
+
+ottery.i: ottery.c.i
+.PHONY : ottery.i
+
+# target to preprocess a source file
+ottery.c.i:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery.c.i
+.PHONY : ottery.c.i
+
+ottery.s: ottery.c.s
+.PHONY : ottery.s
+
+# target to generate assembly for a file
+ottery.c.s:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery.c.s
+.PHONY : ottery.c.s
+
+ottery_cpuinfo.o: ottery_cpuinfo.c.o
+.PHONY : ottery_cpuinfo.o
+
+# target to build an object file
+ottery_cpuinfo.c.o:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery_cpuinfo.c.o
+.PHONY : ottery_cpuinfo.c.o
+
+ottery_cpuinfo.i: ottery_cpuinfo.c.i
+.PHONY : ottery_cpuinfo.i
+
+# target to preprocess a source file
+ottery_cpuinfo.c.i:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery_cpuinfo.c.i
+.PHONY : ottery_cpuinfo.c.i
+
+ottery_cpuinfo.s: ottery_cpuinfo.c.s
+.PHONY : ottery_cpuinfo.s
+
+# target to generate assembly for a file
+ottery_cpuinfo.c.s:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery_cpuinfo.c.s
+.PHONY : ottery_cpuinfo.c.s
+
+ottery_entropy.o: ottery_entropy.c.o
+.PHONY : ottery_entropy.o
+
+# target to build an object file
+ottery_entropy.c.o:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery_entropy.c.o
+.PHONY : ottery_entropy.c.o
+
+ottery_entropy.i: ottery_entropy.c.i
+.PHONY : ottery_entropy.i
+
+# target to preprocess a source file
+ottery_entropy.c.i:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery_entropy.c.i
+.PHONY : ottery_entropy.c.i
+
+ottery_entropy.s: ottery_entropy.c.s
+.PHONY : ottery_entropy.s
+
+# target to generate assembly for a file
+ottery_entropy.c.s:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery_entropy.c.s
+.PHONY : ottery_entropy.c.s
+
+ottery_global.o: ottery_global.c.o
+.PHONY : ottery_global.o
+
+# target to build an object file
+ottery_global.c.o:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery_global.c.o
+.PHONY : ottery_global.c.o
+
+ottery_global.i: ottery_global.c.i
+.PHONY : ottery_global.i
+
+# target to preprocess a source file
+ottery_global.c.i:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery_global.c.i
+.PHONY : ottery_global.c.i
+
+ottery_global.s: ottery_global.c.s
+.PHONY : ottery_global.s
+
+# target to generate assembly for a file
+ottery_global.c.s:
+ cd /home/vs374/rspamd && $(MAKE) -f contrib/libottery/CMakeFiles/rspamd-ottery.dir/build.make contrib/libottery/CMakeFiles/rspamd-ottery.dir/ottery_global.c.s
+.PHONY : ottery_global.c.s
+
+# Help Target
+help:
+ @echo "The following are some of the valid targets for this Makefile:"
+ @echo "... all (the default if no target is provided)"
+ @echo "... clean"
+ @echo "... depend"
+ @echo "... edit_cache"
+ @echo "... install"
+ @echo "... install/local"
+ @echo "... install/strip"
+ @echo "... list_install_components"
+ @echo "... rebuild_cache"
+ @echo "... rspamd-ottery"
+ @echo "... chacha_merged.o"
+ @echo "... chacha_merged.i"
+ @echo "... chacha_merged.s"
+ @echo "... ottery.o"
+ @echo "... ottery.i"
+ @echo "... ottery.s"
+ @echo "... ottery_cpuinfo.o"
+ @echo "... ottery_cpuinfo.i"
+ @echo "... ottery_cpuinfo.s"
+ @echo "... ottery_entropy.o"
+ @echo "... ottery_entropy.i"
+ @echo "... ottery_entropy.s"
+ @echo "... ottery_global.o"
+ @echo "... ottery_global.i"
+ @echo "... ottery_global.s"
+.PHONY : help
+
+
+
+#=============================================================================
+# Special targets to cleanup operation of make.
+
+# Special rule to run CMake to check the build system integrity.
+# No rule that depends on this can have commands that come from listfiles
+# because they might be regenerated.
+cmake_check_build_system:
+ cd /home/vs374/rspamd && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
+.PHONY : cmake_check_build_system
+
diff --git a/contrib/libottery/chacha_krovetz.c b/contrib/libottery/chacha_krovetz.c
new file mode 100644
index 000000000..10517795c
--- /dev/null
+++ b/contrib/libottery/chacha_krovetz.c
@@ -0,0 +1,320 @@
+/*
+ * This code is based on Ted Krovetz's 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 (partial) 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 implementation for 16-byte vectors by Ted Krovetz (ted@krovetz.net).
+ * Assumes 32-bit int, 64-bit long long. Public domain. Modified: 2012.07.26.
+ * Chacha is an improvement on the stream cipher Salsa, described at
+ * http://cr.yp.to/papers.html#chacha
+ */
+#include <string.h>
+#include <assert.h>
+#include "ottery-internal.h"
+
+/* Architecture-neutral way to specify 16-byte vector of ints */
+typedef unsigned vec __attribute__ ((vector_size (16)));
+
+/* This implementation is designed for Neon, SSE and AltiVec machines. The
+ * following specify how to do certain vector operations efficiently on
+ * each architecture, using intrinsics.
+ * This implementation supports parallel processing of multiple blocks,
+ * including potentially using general-purpose registers.
+ */
+#if __ARM_NEON__
+#include <arm_neon.h>
+#define GPR_TOO 1
+#define VBPI 2
+#define ONE (vec)vsetq_lane_u32(1,vdupq_n_u32(0),0)
+#define NONCE(ctr,p) (vec)vcombine_u32(vcreate_u32(ctr),vcreate_u32(*(uint64_t *)p))
+#define ROTV1(x) (vec)vextq_u32((uint32x4_t)x,(uint32x4_t)x,1)
+#define ROTV2(x) (vec)vextq_u32((uint32x4_t)x,(uint32x4_t)x,2)
+#define ROTV3(x) (vec)vextq_u32((uint32x4_t)x,(uint32x4_t)x,3)
+#define ROTW16(x) (vec)vrev32q_u16((uint16x8_t)x)
+#if __clang__
+#define ROTW7(x) (x << ((vec){ 7, 7, 7, 7})) ^ (x >> ((vec){25,25,25,25}))
+#define ROTW8(x) (x << ((vec){ 8, 8, 8, 8})) ^ (x >> ((vec){24,24,24,24}))
+#define ROTW12(x) (x << ((vec){12,12,12,12})) ^ (x >> ((vec){20,20,20,20}))
+#else
+#define ROTW7(x) (vec)vsriq_n_u32(vshlq_n_u32((uint32x4_t)x,7),(uint32x4_t)x,25)
+#define ROTW8(x) (vec)vsriq_n_u32(vshlq_n_u32((uint32x4_t)x,8),(uint32x4_t)x,24)
+#define ROTW12(x) (vec)vsriq_n_u32(vshlq_n_u32((uint32x4_t)x,12),(uint32x4_t)x,20)
+#endif
+#elif __ALTIVEC__
+#include <altivec.h>
+#define GPR_TOO 1
+#define VBPI 3
+#define ONE ((vec){1,0,0,0})
+#define NONCE(ctr,p) vec_sro(*(vec *)p, (vector char)(vec){0,0,0,8*8})+((vec){((ctr)&0xffffffff), (ctr)>>32, 0, 0})
+#error "Don't use this code till it can be tested on altivec"
+#define REVW_BE(x) __builtin_bswap32(x)
+#define REVV_BE(x) vec_perm(x,x,(vector char){3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12})
+#define ROTV1(x) vec_perm(x,x,(vector char){4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3})
+#define ROTV2(x) vec_perm(x,x,(vector char){8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7})
+#define ROTV3(x) vec_perm(x,x,(vector char){12,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11})
+#define ROTW7(x) vec_rl(x,vec_splat_u32(7))
+#define ROTW8(x) vec_rl(x,vec_splat_u32(8))
+#define ROTW12(x) vec_rl(x,vec_splat_u32(12))
+#define ROTW16(x) vec_rl(x,vec_splat_u32(-16)) /* trick to get 16 */
+#elif __SSE2__
+#include <emmintrin.h>
+#define GPR_TOO 0
+#if __clang__
+#define VBPI 4
+#else
+#define VBPI 3
+#endif
+#define ONE (vec)_mm_set_epi32(0,0,0,1)
+#define NONCE(ctr,p) (vec)(_mm_slli_si128(_mm_loadl_epi64((__m128i *)(p)),8)+_mm_set_epi64x(0,ctr))
+#define ROTV1(x) (vec)_mm_shuffle_epi32((__m128i)x,_MM_SHUFFLE(0,3,2,1))
+#define ROTV2(x) (vec)_mm_shuffle_epi32((__m128i)x,_MM_SHUFFLE(1,0,3,2))
+#define ROTV3(x) (vec)_mm_shuffle_epi32((__m128i)x,_MM_SHUFFLE(2,1,0,3))
+#define ROTW7(x) (vec)(_mm_slli_epi32((__m128i)x, 7) ^ _mm_srli_epi32((__m128i)x,25))
+#define ROTW12(x) (vec)(_mm_slli_epi32((__m128i)x,12) ^ _mm_srli_epi32((__m128i)x,20))
+#if __SSSE3__
+#include <tmmintrin.h>
+#define ROTW8(x) (vec)_mm_shuffle_epi8((__m128i)x,_mm_set_epi8(14,13,12,15,10,9,8,11,6,5,4,7,2,1,0,3))
+#define ROTW16(x) (vec)_mm_shuffle_epi8((__m128i)x,_mm_set_epi8(13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2))
+#else
+#define ROTW8(x) (vec)(_mm_slli_epi32((__m128i)x, 8) ^ _mm_srli_epi32((__m128i)x,24))
+#define ROTW16(x) (vec)(_mm_slli_epi32((__m128i)x,16) ^ _mm_srli_epi32((__m128i)x,16))
+#endif
+#else
+#error -- Implementation supports only machines with neon, altivec or SSE2
+#endif
+
+#ifndef REVV_BE
+#define REVV_BE(x) (x)
+#endif
+
+#ifndef REVW_BE
+#define REVW_BE(x) (x)
+#endif
+
+#define BPI (VBPI + GPR_TOO) /* Blocks computed per loop iteration */
+
+#define DQROUND_VECTORS(a,b,c,d) \
+ a += b; d ^= a; d = ROTW16(d); \
+ c += d; b ^= c; b = ROTW12(b); \
+ a += b; d ^= a; d = ROTW8(d); \
+ c += d; b ^= c; b = ROTW7(b); \
+ b = ROTV1(b); c = ROTV2(c); d = ROTV3(d); \
+ a += b; d ^= a; d = ROTW16(d); \
+ c += d; b ^= c; b = ROTW12(b); \
+ a += b; d ^= a; d = ROTW8(d); \
+ c += d; b ^= c; b = ROTW7(b); \
+ b = ROTV3(b); c = ROTV2(c); d = ROTV1(d);
+
+#define QROUND_WORDS(a,b,c,d) \
+ a = a+b; d ^= a; d = d<<16 | d>>16; \
+ c = c+d; b ^= c; b = b<<12 | b>>20; \
+ a = a+b; d ^= a; d = d<< 8 | d>>24; \
+ c = c+d; b ^= c; b = b<< 7 | b>>25;
+
+#define WRITE(op, d, v0, v1, v2, v3) \
+*(vec *)(op + d + 0) = REVV_BE(v0); \
+*(vec *)(op + d + 4) = REVV_BE(v1); \
+*(vec *)(op + d + 8) = REVV_BE(v2); \
+*(vec *)(op + d + 12) = REVV_BE(v3);
+
+struct chacha_state_krovetz {
+ __attribute__ ((aligned (16))) uint8_t key[32];
+ __attribute__ ((aligned (16))) uint8_t nonce[8];
+};
+
+#define LOOP_ITERATIONS 4
+
+static inline int
+ottery_blocks_chacha_krovetz(
+ const int chacha_rounds,
+ uint8_t *out,
+ uint32_t block_idx,
+ struct chacha_state_krovetz *st)
+ __attribute__((always_inline));
+
+/** Generates 64 * BPI * LOOP_ITERATIONS bytes of output using the key and
+ * nonce in st and the counter in block_idx, and store them in out.
+ */
+static inline int
+ottery_blocks_chacha_krovetz(
+ const int chacha_rounds,
+ uint8_t *out,
+ uint32_t block_idx,
+ struct chacha_state_krovetz *st)
+/* Assumes all pointers are aligned properly for vector reads */
+{
+ const unsigned char *k = st->key;
+ const unsigned char *n = st->nonce;
+ unsigned i, j, *op=(unsigned *)out, *kp, *np;
+ __attribute__ ((aligned (16))) unsigned chacha_const[] =
+ {0x61707865,0x3320646E,0x79622D32,0x6B206574};
+#if ( __ARM_NEON__ || __SSE2__)
+ kp = (unsigned *)k;
+ np = (unsigned *)n;
+#else
+ __attribute__ ((aligned (16))) unsigned key[8], nonce[2];
+ ((vec *)key)[0] = REVV_BE(((vec *)k)[0]);
+ ((vec *)key)[1] = REVV_BE(((vec *)k)[1]);
+ nonce[0] = REVW_BE(((unsigned *)n)[0]);
+ nonce[1] = REVW_BE(((unsigned *)n)[1]);
+ kp = (unsigned *)key;
+ np = (unsigned *)nonce;
+#endif
+ vec s0 = *(vec *)chacha_const;
+ vec s1 = ((vec *)kp)[0];
+ vec s2 = ((vec *)kp)[1];
+ vec s3 = NONCE(block_idx, np);
+ for (j = 0; j < LOOP_ITERATIONS; ++j) {
+ vec v0,v1,v2,v3,v4,v5,v6,v7;
+ v4 = v0 = s0; v5 = v1 = s1; v6 = v2 = s2; v3 = s3;
+ v7 = v3 + ONE;
+ #if VBPI > 2
+ vec v8,v9,v10,v11;
+ v8 = v4; v9 = v5; v10 = v6;
+ v11 = v7 + ONE;
+ #endif
+ #if VBPI > 3
+ vec v12,v13,v14,v15;
+ v12 = v8; v13 = v9; v14 = v10;
+ v15 = v11 + ONE;
+ #endif
+ #if GPR_TOO
+ register unsigned x0, x1, x2, x3, x4, x5, x6, x7, x8,
+ x9, x10, x11, x12, x13, x14, x15;
+ x0 = chacha_const[0]; x1 = chacha_const[1];
+ x2 = chacha_const[2]; x3 = chacha_const[3];
+ x4 = kp[0]; x5 = kp[1]; x6 = kp[2]; x7 = kp[3];
+ x8 = kp[4]; x9 = kp[5]; x10 = kp[6]; x11 = kp[7];
+ const uint64_t x_ctr = block_idx + BPI*iters+(BPI-1);
+ x12 = x_ctr & 0xffffffff; x13 = x_ctr>>32; x14 = np[0]; x15 = np[1];
+ #endif
+ for (i = chacha_rounds/2; i; i--) {
+ DQROUND_VECTORS(v0,v1,v2,v3)
+ DQROUND_VECTORS(v4,v5,v6,v7)
+ #if VBPI > 2
+ DQROUND_VECTORS(v8,v9,v10,v11)
+ #endif
+ #if VBPI > 3
+ DQROUND_VECTORS(v12,v13,v14,v15)
+ #endif
+ #if GPR_TOO
+ QROUND_WORDS( x0, x4, x8,x12)
+ QROUND_WORDS( x1, x5, x9,x13)
+ QROUND_WORDS( x2, x6,x10,x14)
+ QROUND_WORDS( x3, x7,x11,x15)
+ QROUND_WORDS( x0, x5,x10,x15)
+ QROUND_WORDS( x1, x6,x11,x12)
+ QROUND_WORDS( x2, x7, x8,x13)
+ QROUND_WORDS( x3, x4, x9,x14)
+ #endif
+ }
+ WRITE(op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
+ s3 += ONE;
+ WRITE(op, 16, v4+s0, v5+s1, v6+s2, v7+s3)
+ s3 += ONE;
+ #if VBPI > 2
+ WRITE(op, 32, v8+s0, v9+s1, v10+s2, v11+s3)
+ s3 += ONE;
+ #endif
+ #if VBPI > 3
+ WRITE(op, 48, v12+s0, v13+s1, v14+s2, v15+s3)
+ s3 += ONE;
+ #endif
+ op += VBPI*16;
+ #if GPR_TOO
+ op[0] = REVW_BE((x0 + chacha_const[0]));
+ op[1] = REVW_BE((x1 + chacha_const[1]));
+ op[2] = REVW_BE((x2 + chacha_const[2]));
+ op[3] = REVW_BE((x3 + chacha_const[3]));
+ op[4] = REVW_BE((x4 + kp[0]));
+ op[5] = REVW_BE((x5 + kp[1]));
+ op[6] = REVW_BE((x6 + kp[2]));
+ op[7] = REVW_BE((x7 + kp[3]));
+ op[8] = REVW_BE((x8 + kp[4]));
+ op[9] = REVW_BE((x9 + kp[5]));
+ op[10] = REVW_BE((x10 + kp[6]));
+ op[11] = REVW_BE((x11 + kp[7]));
+ op[12] = REVW_BE((x12 + (x_ctr & 0xffffffff)));
+ op[13] = REVW_BE((x13 + (x_ctr >> 32)));
+ op[14] = REVW_BE((x14 + np[0]));
+ op[15] = REVW_BE((x15 + np[1]));
+ s3 += ONE;
+ op += 16;
+ #endif
+ }
+ return 0;
+}
+
+#define STATE_LEN (sizeof(struct chacha_state_krovetz))
+#define STATE_BYTES 40
+#define IDX_STEP (BPI * LOOP_ITERATIONS)
+#define OUTPUT_LEN (IDX_STEP * 64)
+
+static void
+chacha_krovetz_state_setup(void *state, const uint8_t *bytes)
+{
+ struct chacha_state_krovetz *st = state;
+ memcpy(st->key, bytes, 32);
+ memcpy(st->nonce, bytes+32, 8);
+}
+
+static void
+chacha8_krovetz_generate(void *state, uint8_t *output, uint32_t idx)
+{
+ struct chacha_state_krovetz *st = state;
+ ottery_blocks_chacha_krovetz(8, output, idx * IDX_STEP, st);
+}
+
+static void
+chacha12_krovetz_generate(void *state, uint8_t *output, uint32_t idx)
+{
+ struct chacha_state_krovetz *st = state;
+ ottery_blocks_chacha_krovetz(12, output, idx * IDX_STEP, st);
+}
+
+static void
+chacha20_krovetz_generate(void *state, uint8_t *output, uint32_t idx)
+{
+ struct chacha_state_krovetz *st = state;
+ ottery_blocks_chacha_krovetz(20, output, idx * IDX_STEP, st);
+}
+
+#ifdef __SSSE3__
+#define NEED_CPUCAP OTTERY_CPUCAP_SSSE3|OTTERY_CPUCAP_SIMD
+#define FLAV "-SSSE3"
+#else
+#define NEED_CPUCAP OTTERY_CPUCAP_SIMD
+#define FLAV "-DEFAULT"
+#endif
+
+#define PRF_CHACHA(r) { \
+ "CHACHA" #r, \
+ "CHACHA" #r "-SIMD", \
+ "CHACHA" #r "-SIMD" FLAV, \
+ STATE_LEN, \
+ STATE_BYTES, \
+ OUTPUT_LEN, \
+ NEED_CPUCAP, \
+ chacha_krovetz_state_setup, \
+ chacha ## r ## _krovetz_generate \
+}
+
+#if defined OTTERY_BUILDING_SIMD1
+const struct ottery_prf ottery_prf_chacha8_krovetz_1_ = PRF_CHACHA(8);
+const struct ottery_prf ottery_prf_chacha12_krovetz_1_ = PRF_CHACHA(12);
+const struct ottery_prf ottery_prf_chacha20_krovetz_1_ = PRF_CHACHA(20);
+#elif defined OTTERY_BUILDING_SIMD2
+const struct ottery_prf ottery_prf_chacha8_krovetz_2_ = PRF_CHACHA(8);
+const struct ottery_prf ottery_prf_chacha12_krovetz_2_ = PRF_CHACHA(12);
+const struct ottery_prf ottery_prf_chacha20_krovetz_2_ = PRF_CHACHA(20);
+#else
+#error "Which PRF symbols am I supposed to define?"
+#endif
diff --git a/contrib/libottery/chacha_merged.c b/contrib/libottery/chacha_merged.c
new file mode 100644
index 000000000..c31a8bbd5
--- /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 000000000..5cc94a934
--- /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 000000000..2d8a03185
--- /dev/null
+++ b/contrib/libottery/ottery-internal.h
@@ -0,0 +1,314 @@
+/* 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>
+#include "config.h"
+#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 intialize 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);
+};
+
+#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 __attribute__((aligned(16))) ottery_state {
+ /**
+ * Holds up to prf.output_len bytes that have been generated by the
+ * pseudorandom function. */
+ __attribute__ ((aligned (16))) uint8_t buffer[MAX_OUTPUT_LEN];
+ /**
+ * Holds the state information (typically nonces and keys) used by the
+ * pseudorandom function. */
+
+ __attribute__ ((aligned (16))) uint8_t state[MAX_STATE_LEN];
+ /**
+ * 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_;
+/**@}*/
+
+/**
+ * @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 000000000..383d9cd83
--- /dev/null
+++ b/contrib/libottery/ottery-threading.h
@@ -0,0 +1,91 @@
+/* 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_
+
+/* 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 000000000..851932e94
--- /dev/null
+++ b/contrib/libottery/ottery.c
@@ -0,0 +1,842 @@
+/* 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
+
+/**
+ * Evaluate the condition 'x', while hinting to the compiler that it is
+ * likely to be false.
+ */
+#define UNLIKELY(x) __builtin_expect((x), 0)
+
+/** 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
+ &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 000000000..e2caac2af
--- /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 000000000..5b3359c97
--- /dev/null
+++ b/contrib/libottery/ottery_common.h
@@ -0,0 +1,349 @@
+/* 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);
+
+#endif
diff --git a/contrib/libottery/ottery_cpuinfo.c b/contrib/libottery/ottery_cpuinfo.c
new file mode 100644
index 000000000..2e8bdaae0
--- /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 000000000..819a380df
--- /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 000000000..d29d9d1aa
--- /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 000000000..7e9cb076d
--- /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 000000000..62e158c83
--- /dev/null
+++ b/contrib/libottery/ottery_entropy_rdrand.c
@@ -0,0 +1,63 @@
+/* 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)
+
+/** Helper: invoke the RDRAND instruction to get 4 random bytes in the output
+ * value. Return 0 on success, and an error on failure. */
+static int
+rdrand(uint32_t *therand) {
+ unsigned char status;
+ __asm volatile(".byte 0x0F, 0xC7, 0xF0 ; setc %1"
+ : "=a" (*therand), "=qm" (status));
+ return (status)==1 ? 0 : OTTERY_ERR_INIT_STRONG_RNG;
+}
+
+/** 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)
+{
+ int err;
+ uint32_t *up = (uint32_t *) out;
+ (void) cfg;
+ (void) state;
+ if (! (ottery_get_cpu_capabilities_() & OTTERY_CPUCAP_RAND))
+ return OTTERY_ERR_INIT_STRONG_RNG;
+ while (outlen >= 4) {
+ if ((err = rdrand(up)))
+ return err;
+ up += 1;
+ outlen -= 4;
+ }
+ if (outlen) {
+ uint32_t tmp;
+ if ((err = rdrand(&tmp)))
+ return err;
+ memcpy(up, &tmp, 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 000000000..9eb761b4a
--- /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 000000000..8b4a6300e
--- /dev/null
+++ b/contrib/libottery/ottery_global.c
@@ -0,0 +1,111 @@
+/* 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"
+
+/**
+ * Evaluate the condition 'x', while hinting to the compiler that it is
+ * likely to be false.
+ */
+#define UNLIKELY(x) __builtin_expect((x), 0)
+
+/** Flag: true iff ottery_global_state_ is initialized. */
+static int ottery_global_state_initialized_ = 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)
+{
+ 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);
+}
diff --git a/contrib/libottery/ottery_nolock.h b/contrib/libottery/ottery_nolock.h
new file mode 100644
index 000000000..b504e11af
--- /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 000000000..38955cb5b
--- /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 000000000..1b6a244c5
--- /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
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4e24448c3..220825336 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -67,6 +67,7 @@ ENDIF(CMAKE_COMPILER_IS_GNUCC)
TARGET_LINK_LIBRARIES(rspamd-util ${RSPAMD_REQUIRED_LIBRARIES})
TARGET_LINK_LIBRARIES(rspamd-util pcre)
TARGET_LINK_LIBRARIES(rspamd-util rspamd-ucl)
+TARGET_LINK_LIBRARIES(rspamd-util rspamd-ottery)
TARGET_LINK_LIBRARIES(rspamd-util rspamd-http-parser)
TARGET_LINK_LIBRARIES(rspamd-util event)
diff --git a/src/chacha_private.h b/src/chacha_private.h
deleted file mode 100644
index 5034f4955..000000000
--- a/src/chacha_private.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
-chacha-merged.c version 20080118
-D. J. Bernstein
-Public domain.
-*/
-
-#ifndef CHACHA_PRIVATE_H_
-#define CHACHA_PRIVATE_H_
-
-#include <stddef.h>
-
-typedef unsigned char u8;
-typedef unsigned int u32;
-
-typedef struct
-{
- u32 input[16]; /* could be compressed */
-} chacha_ctx;
-
-#define U8C(v) (v##U)
-#define U32C(v) (v##U)
-
-#define U8V(v) ((u8)(v) & U8C(0xFF))
-#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
-
-#define ROTL32(v, n) \
- (U32V((v) << (n)) | ((v) >> (32 - (n))))
-
-#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)
-
-#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 const char tau[16] = "expand 16-byte k";
-
-static void chacha_keysetup(chacha_ctx *x, const u8 *k, u32 kbits, u32 ivbits)
-{
- const char *constants;
-
- 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);
- if (kbits == 256) { /* recommended */
- k += 16;
- constants = sigma;
- }
- else { /* kbits == 128 */
- constants = tau;
- }
- 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 chacha_ivsetup(chacha_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);
-}
-
-static void chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, u32 bytes)
-{
- 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;
- u8 *ctarget = NULL;
- u8 tmp[64];
- unsigned int i;
-
- if (!bytes)
- return;
-
- 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 (;;) {
- if (bytes < 64) {
- for (i = 0; i < bytes; ++i)
- tmp[i] = m[i];
- m = tmp;
- ctarget = c;
- c = tmp;
- }
- 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 = 20; 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);
-
-#ifndef KEYSTREAM_ONLY
- x0 = XOR(x0,U8TO32_LITTLE(m + 0));
- x1 = XOR(x1,U8TO32_LITTLE(m + 4));
- x2 = XOR(x2,U8TO32_LITTLE(m + 8));
- x3 = XOR(x3,U8TO32_LITTLE(m + 12));
- x4 = XOR(x4,U8TO32_LITTLE(m + 16));
- x5 = XOR(x5,U8TO32_LITTLE(m + 20));
- x6 = XOR(x6,U8TO32_LITTLE(m + 24));
- x7 = XOR(x7,U8TO32_LITTLE(m + 28));
- x8 = XOR(x8,U8TO32_LITTLE(m + 32));
- x9 = XOR(x9,U8TO32_LITTLE(m + 36));
- x10 = XOR(x10,U8TO32_LITTLE(m + 40));
- x11 = XOR(x11,U8TO32_LITTLE(m + 44));
- x12 = XOR(x12,U8TO32_LITTLE(m + 48));
- x13 = XOR(x13,U8TO32_LITTLE(m + 52));
- x14 = XOR(x14,U8TO32_LITTLE(m + 56));
- x15 = XOR(x15,U8TO32_LITTLE(m + 60));
-#endif
-
- j12 = PLUSONE(j12);
- if (!j12) {
- j13 = PLUSONE(j13);
- /* stopping at 2^70 bytes per nonce is user's responsibility */
- }
-
- 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);
-
- if (bytes <= 64) {
- if (bytes < 64) {
- for (i = 0; i < bytes; ++i)
- ctarget[i] = c[i];
- }
- x->input[12] = j12;
- x->input[13] = j13;
- return;
- }
- bytes -= 64;
- c += 64;
-#ifndef KEYSTREAM_ONLY
- m += 64;
-#endif
- }
-}
-
-#endif /* CHACHA_PRIVATE_H_ */
diff --git a/src/dns.c b/src/dns.c
index 375ec9811..3d714c240 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -29,6 +29,7 @@
#include "main.h"
#include "utlist.h"
#include "uthash.h"
+#include "ottery.h"
#ifdef HAVE_OPENSSL
#include <openssl/rand.h>
@@ -36,50 +37,12 @@
static void dns_retransmit_handler (gint fd, short what, void *arg);
-/*
- * DNS permutor utilities
- */
-
-/**
- * Init chacha20 context
- * @param p
- */
-static void
-dns_permutor_init (struct dns_permutor *p)
-{
- /* Init random key and IV */
- rspamd_random_bytes (p->perm_buf, PERMUTOR_KSIZE + PERMUTOR_IVSIZE);
-
- /* Setup ctx */
- chacha_keysetup (&p->ctx, p->perm_buf, PERMUTOR_KSIZE * 8, 0);
- chacha_ivsetup (&p->ctx, p->perm_buf + PERMUTOR_KSIZE * 8);
-
- chacha_encrypt_bytes (&p->ctx, p->perm_buf, p->perm_buf, sizeof (p->perm_buf));
-
- p->pos = 0;
-}
-
-static struct dns_permutor *
-dns_permutor_new (void)
-{
- struct dns_permutor *new;
-
- new = g_slice_alloc0 (sizeof (struct dns_permutor));
- dns_permutor_init (new);
-
- return new;
-}
-
static guint16
-dns_permutor_generate_id (struct dns_permutor *p)
+dns_permutor_generate_id (void)
{
guint16 id;
- if (p->pos + sizeof (guint16) >= sizeof (p->perm_buf)) {
- dns_permutor_init (p);
- }
- memcpy (&id, &p->perm_buf[p->pos], sizeof (guint16));
- p->pos += sizeof (guint16);
+ id = ottery_rand_unsigned ();
return id;
}
@@ -280,7 +243,7 @@ make_dns_header (struct rspamd_dns_request *req)
/* Set DNS header values */
header = (struct dns_header *)req->packet;
memset (header, 0 , sizeof (struct dns_header));
- header->qid = dns_permutor_generate_id (req->resolver->permutor);
+ header->qid = dns_permutor_generate_id ();
header->rd = 1;
header->qdcount = htons (1);
header->arcount = htons (1);
@@ -1284,7 +1247,7 @@ make_dns_request (struct rspamd_dns_resolver *resolver,
while (g_hash_table_lookup (req->io->requests, &req->id)) {
/* Check for unique id */
header = (struct dns_header *)req->packet;
- header->qid = dns_permutor_generate_id (resolver->permutor);
+ header->qid = dns_permutor_generate_id ();
req->id = header->qid;
if (++r > max_id_cycles) {
msg_err ("cannot generate new id for server %s", serv->name);
@@ -1376,7 +1339,6 @@ dns_resolver_init (struct event_base *ev_base, struct config_file *cfg)
new = g_slice_alloc0 (sizeof (struct rspamd_dns_resolver));
new->ev_base = ev_base;
- new->permutor = dns_permutor_new ();
new->io_channels = g_hash_table_new (g_direct_hash, g_direct_equal);
new->request_timeout = cfg->dns_timeout;
new->max_retransmits = cfg->dns_retransmits;
diff --git a/src/dns_private.h b/src/dns_private.h
index 46483918e..1c1df8ded 100644
--- a/src/dns_private.h
+++ b/src/dns_private.h
@@ -25,7 +25,6 @@
#define DNS_PRIVATE_H_
#include "config.h"
-#include "chacha_private.h"
#define MAX_SERVERS 16
/* Upstream timeouts */
@@ -50,10 +49,6 @@ static const gint dns_port = 53;
#define DNS_D_MAXLABEL 63 /* + 1 '\0' */
#define DNS_D_MAXNAME 255 /* + 1 '\0' */
-#define PERMUTOR_BUF_SIZE 32768
-#define PERMUTOR_KSIZE 32
-#define PERMUTOR_IVSIZE 8
-
#define RESOLV_CONF "/etc/resolv.conf"
/**
@@ -78,12 +73,10 @@ struct rspamd_dns_io_channel {
struct rspamd_dns_io_channel *prev, *next;
};
-struct dns_permutor;
struct rspamd_dns_resolver {
struct rspamd_dns_server servers[MAX_SERVERS];
gint servers_num; /**< number of DNS servers registered */
- struct dns_permutor *permutor; /**< permutor for randomizing request id */
guint request_timeout;
guint max_retransmits;
guint max_errors;
@@ -189,12 +182,6 @@ enum dns_type {
};
/* enum dns_type */
-struct dns_permutor {
- chacha_ctx ctx;
- guchar perm_buf[PERMUTOR_BUF_SIZE];
- guint pos;
-};
-
static const gchar dns_rcodes[16][16] = {
[DNS_RC_NOERROR] = "NOERROR",
[DNS_RC_FORMERR] = "FORMERR",
diff --git a/src/main.c b/src/main.c
index 1cb641cda..ae4d5d409 100644
--- a/src/main.c
+++ b/src/main.c
@@ -34,6 +34,7 @@
#include "cfg_xml.h"
#include "symbols_cache.h"
#include "lua/lua_common.h"
+#include "ottery.h"
#ifdef HAVE_OPENSSL
#include <openssl/rand.h>
#include <openssl/err.h>
@@ -1055,7 +1056,7 @@ main (gint argc, gchar **argv, gchar **env)
OpenSSL_add_all_ciphers ();
#endif
- rspamd_prng_seed ();
+ g_random_set_seed (ottery_rand_uint32 ());
/* First set logger to console logger */
rspamd_main->cfg->log_type = RSPAMD_LOG_CONSOLE;
diff --git a/src/util.c b/src/util.c
index 3eed9a765..2acf58845 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2110,61 +2110,6 @@ restart:
#endif
}
-void
-rspamd_random_bytes (gchar *buf, gsize buflen)
-{
- gint fd;
- gsize i;
-#ifdef HAVE_CLOCK_GETTIME
- struct timespec ts;
-#else
- struct timeval tv;
-#endif
-#ifdef HAVE_OPENSSL
-
- /* Init random generator */
- if (RAND_bytes (buf, buflen) != 1) {
- msg_err ("cannot seed random generator using openssl: %s, using time",
- ERR_error_string (ERR_get_error (), NULL));
- goto fallback;
- }
-#else
- goto fallback;
-#endif
- return;
-
-fallback:
- /* Try to use /dev/random if no openssl is found */
- fd = open ("/dev/random", O_RDONLY);
- if (fd != -1) {
- if (read (fd, buf, buflen) == (gssize)buflen) {
- close (fd);
- return;
- }
- close (fd);
- }
- /* No /dev/random */
-#ifdef HAVE_CLOCK_GETTIME
- (void)clock_gettime (CLOCK_REALTIME, &ts);
- g_random_set_seed (ts.tv_nsec);
-#else
- (void)gettimeofday (&tv, NULL);
- g_random_set_seed (tv.tv_usec);
-#endif
- for (i = 0; i < buflen; i ++) {
- buf[i] = g_random_int () & 0xff;
- }
-}
-
-void
-rspamd_prng_seed (void)
-{
- guint32 rand_seed = 0;
-
- rspamd_random_bytes ((gchar *)&rand_seed, sizeof (rand_seed));
- g_random_set_seed (rand_seed);
-}
-
gboolean
rspamd_ip_is_valid (void *ptr, int af)
{
diff --git a/src/util.h b/src/util.h
index 2f33e91ee..35d915698 100644
--- a/src/util.h
+++ b/src/util.h
@@ -439,18 +439,6 @@ gboolean parse_ipmask_v4 (const char *line, struct in_addr *ina, int *mask);
gint rspamd_read_passphrase (gchar *buf, gint size, gint rwflag, gpointer key);
/**
- * Seed glib prng using openssl if possible
- */
-void rspamd_prng_seed (void);
-
-/**
- * Generate random bytes using the most suitable generator
- * @param buf
- * @param buflen
- */
-void rspamd_random_bytes (gchar *buf, gsize buflen);
-
-/**
* Check whether specified ip is valid (not INADDR_ANY or INADDR_NONE) for ipv4 or ipv6
* @param ptr pointer to struct in_addr or struct in6_addr
* @param af address family (AF_INET or AF_INET6)