aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/utils')
-rw-r--r--src/lib/utils/asm_x86_32/asm_x86_32.h128
-rw-r--r--src/lib/utils/asm_x86_32/info.txt29
-rw-r--r--src/lib/utils/asm_x86_64/asm_x86_64.h127
-rw-r--r--src/lib/utils/asm_x86_64/info.txt27
-rw-r--r--src/lib/utils/assert.cpp36
-rw-r--r--src/lib/utils/assert.h83
-rw-r--r--src/lib/utils/bit_ops.h103
-rw-r--r--src/lib/utils/boost/info.txt7
-rw-r--r--src/lib/utils/bswap.h142
-rw-r--r--src/lib/utils/calendar.cpp52
-rw-r--r--src/lib/utils/calendar.h63
-rw-r--r--src/lib/utils/charset.cpp201
-rw-r--r--src/lib/utils/charset.h46
-rw-r--r--src/lib/utils/cpuid.cpp236
-rw-r--r--src/lib/utils/cpuid.h153
-rw-r--r--src/lib/utils/datastor/datastor.cpp165
-rw-r--r--src/lib/utils/datastor/datastor.h57
-rw-r--r--src/lib/utils/datastor/info.txt3
-rw-r--r--src/lib/utils/dyn_load/dyn_load.cpp79
-rw-r--r--src/lib/utils/dyn_load/dyn_load.h67
-rw-r--r--src/lib/utils/dyn_load/info.txt24
-rw-r--r--src/lib/utils/exceptn.h181
-rw-r--r--src/lib/utils/get_byte.h30
-rw-r--r--src/lib/utils/http_util/http_util.cpp220
-rw-r--r--src/lib/utils/http_util/http_util.h97
-rw-r--r--src/lib/utils/http_util/info.txt1
-rw-r--r--src/lib/utils/info.txt29
-rw-r--r--src/lib/utils/loadstor.h627
-rw-r--r--src/lib/utils/mem_ops.h75
-rw-r--r--src/lib/utils/mul128.h121
-rw-r--r--src/lib/utils/parsing.cpp302
-rw-r--r--src/lib/utils/parsing.h133
-rw-r--r--src/lib/utils/prefetch.h39
-rw-r--r--src/lib/utils/read_cfg.cpp115
-rw-r--r--src/lib/utils/rotate.h43
-rw-r--r--src/lib/utils/rounding.h61
-rw-r--r--src/lib/utils/semaphore.cpp39
-rw-r--r--src/lib/utils/semaphore.h34
-rw-r--r--src/lib/utils/sqlite3/info.txt14
-rw-r--r--src/lib/utils/sqlite3/sqlite3.cpp137
-rw-r--r--src/lib/utils/sqlite3/sqlite3.h68
-rw-r--r--src/lib/utils/stl_util.h94
-rw-r--r--src/lib/utils/types.h48
-rw-r--r--src/lib/utils/version.cpp55
-rw-r--r--src/lib/utils/version.h72
-rw-r--r--src/lib/utils/xor_buf.h113
-rw-r--r--src/lib/utils/zero_mem.cpp20
47 files changed, 4596 insertions, 0 deletions
diff --git a/src/lib/utils/asm_x86_32/asm_x86_32.h b/src/lib/utils/asm_x86_32/asm_x86_32.h
new file mode 100644
index 000000000..d5482c419
--- /dev/null
+++ b/src/lib/utils/asm_x86_32/asm_x86_32.h
@@ -0,0 +1,128 @@
+/*
+* Assembly Macros for 32-bit x86
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ASM_MACROS_X86_32_H__
+#define BOTAN_ASM_MACROS_X86_32_H__
+
+/*
+* General/Global Macros
+*/
+#define ALIGN .p2align 4,,15
+
+#define START_LISTING(FILENAME) \
+ .file #FILENAME; \
+ .text; \
+ ALIGN;
+
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+/*
+* Function Definitions
+*/
+#define START_FUNCTION(func_name) \
+ ALIGN; \
+ .global func_name; \
+ .type func_name,@function; \
+func_name:
+
+#define END_FUNCTION(func_name) \
+ ret
+
+/*
+* Loop Control
+*/
+#define START_LOOP(LABEL) \
+ ALIGN; \
+ LABEL##_LOOP:
+
+#define LOOP_UNTIL_EQ(REG, NUM, LABEL) \
+ cmpl IMM(NUM), REG; \
+ jne LABEL##_LOOP
+
+#define LOOP_UNTIL_LT(REG, NUM, LABEL) \
+ cmpl IMM(NUM), REG; \
+ jge LABEL##_LOOP
+
+/*
+ Conditional Jumps
+*/
+#define JUMP_IF_ZERO(REG, LABEL) \
+ cmpl IMM(0), REG; \
+ jz LABEL
+
+#define JUMP_IF_LT(REG, NUM, LABEL) \
+ cmpl IMM(NUM), REG; \
+ jl LABEL
+
+/*
+* Register Names
+*/
+#define EAX %eax
+#define EBX %ebx
+#define ECX %ecx
+#define EDX %edx
+#define EBP %ebp
+#define EDI %edi
+#define ESI %esi
+#define ESP %esp
+
+/*
+* Memory Access Operations
+*/
+#define ARRAY1(REG, NUM) (NUM)(REG)
+#define ARRAY4(REG, NUM) 4*(NUM)(REG)
+#define ARRAY4_INDIRECT(BASE, OFFSET, NUM) 4*(NUM)(BASE,OFFSET,4)
+#define ARG(NUM) 4*(PUSHED) + ARRAY4(ESP, NUM)
+
+#define ASSIGN(TO, FROM) movl FROM, TO
+#define ASSIGN_BYTE(TO, FROM) movzbl FROM, TO
+
+#define PUSH(REG) pushl REG
+#define POP(REG) popl REG
+
+#define SPILL_REGS() \
+ PUSH(EBP) ; \
+ PUSH(EDI) ; \
+ PUSH(ESI) ; \
+ PUSH(EBX)
+
+#define RESTORE_REGS() \
+ POP(EBX) ; \
+ POP(ESI) ; \
+ POP(EDI) ; \
+ POP(EBP)
+
+/*
+* ALU Operations
+*/
+#define IMM(VAL) $VAL
+
+#define ADD(TO, FROM) addl FROM, TO
+#define ADD_IMM(TO, NUM) ADD(TO, IMM(NUM))
+#define ADD_W_CARRY(TO1, TO2, FROM) addl FROM, TO1; adcl IMM(0), TO2;
+#define SUB_IMM(TO, NUM) subl IMM(NUM), TO
+#define ADD2_IMM(TO, FROM, NUM) leal NUM(FROM), TO
+#define ADD3_IMM(TO, FROM, NUM) leal NUM(TO,FROM,1), TO
+#define MUL(REG) mull REG
+
+#define SHL_IMM(REG, SHIFT) shll IMM(SHIFT), REG
+#define SHR_IMM(REG, SHIFT) shrl IMM(SHIFT), REG
+#define SHL2_3(TO, FROM) leal 0(,FROM,8), TO
+
+#define XOR(TO, FROM) xorl FROM, TO
+#define AND(TO, FROM) andl FROM, TO
+#define OR(TO, FROM) orl FROM, TO
+#define NOT(REG) notl REG
+#define ZEROIZE(REG) XOR(REG, REG)
+
+#define ROTL_IMM(REG, NUM) roll IMM(NUM), REG
+#define ROTR_IMM(REG, NUM) rorl IMM(NUM), REG
+#define BSWAP(REG) bswapl REG
+
+#endif
diff --git a/src/lib/utils/asm_x86_32/info.txt b/src/lib/utils/asm_x86_32/info.txt
new file mode 100644
index 000000000..d29b25fa3
--- /dev/null
+++ b/src/lib/utils/asm_x86_32/info.txt
@@ -0,0 +1,29 @@
+load_on dep
+
+<header:internal>
+asm_x86_32.h
+</header:internal>
+
+<arch>
+x86_32
+</arch>
+
+# ELF systems
+<os>
+linux
+freebsd
+dragonfly
+netbsd
+openbsd
+solaris
+</os>
+
+<cc>
+gcc
+clang
+icc
+</cc>
+
+<requires>
+asm_engine
+</requires>
diff --git a/src/lib/utils/asm_x86_64/asm_x86_64.h b/src/lib/utils/asm_x86_64/asm_x86_64.h
new file mode 100644
index 000000000..7abc1f392
--- /dev/null
+++ b/src/lib/utils/asm_x86_64/asm_x86_64.h
@@ -0,0 +1,127 @@
+/*
+* Assembly Macros for 64-bit x86
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ASM_MACROS_X86_64_H__
+#define BOTAN_ASM_MACROS_X86_64_H__
+
+/*
+* General/Global Macros
+*/
+#define ALIGN .p2align 4,,15
+
+#define START_LISTING(FILENAME) \
+ .file #FILENAME; \
+ .text; \
+ ALIGN;
+
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+/*
+* Function Definitions
+*/
+#define START_FUNCTION(func_name) \
+ ALIGN; \
+ .global func_name; \
+ .type func_name,@function; \
+func_name:
+
+#define END_FUNCTION(func_name) \
+ ret
+
+/*
+* Conditional Jumps
+*/
+#define JUMP_IF_ZERO(REG, LABEL) \
+ cmp IMM(0), REG; \
+ jz LABEL
+
+#define JUMP_IF_LT(REG, NUM, LABEL) \
+ cmp IMM(NUM), REG; \
+ jl LABEL
+
+/*
+* Register Names
+*/
+#define R0 %rax
+#define R1 %rbx
+#define R2 %rcx
+#define R2_32 %ecx
+#define R3 %rdx
+#define R3_32 %edx
+#define R4 %rsp
+#define R5 %rbp
+#define R6 %rsi
+#define R6_32 %esi
+#define R7 %rdi
+#define R8 %r8
+#define R9 %r9
+#define R9_32 %r9d
+#define R10 %r10
+#define R11 %r11
+#define R12 %r12
+#define R13 %r13
+#define R14 %r14
+#define R15 %r15
+#define R16 %r16
+
+#define ARG_1 R7
+#define ARG_2 R6
+#define ARG_2_32 R6_32
+#define ARG_3 R3
+#define ARG_3_32 R3_32
+#define ARG_4 R2
+#define ARG_4_32 R2_32
+#define ARG_5 R8
+#define ARG_6 R9
+#define ARG_6_32 R9_32
+
+#define TEMP_1 R10
+#define TEMP_2 R11
+#define TEMP_3 ARG_6
+#define TEMP_4 ARG_5
+#define TEMP_5 ARG_4
+#define TEMP_5_32 ARG_4_32
+#define TEMP_6 ARG_3
+#define TEMP_7 ARG_2
+#define TEMP_8 ARG_1
+#define TEMP_9 R0
+
+/*
+* Memory Access Operations
+*/
+#define ARRAY8(REG, NUM) 8*(NUM)(REG)
+#define ARRAY4(REG, NUM) 4*(NUM)(REG)
+
+#define ASSIGN(TO, FROM) mov FROM, TO
+
+/*
+* ALU Operations
+*/
+#define IMM(VAL) $VAL
+
+#define ADD(TO, FROM) add FROM, TO
+#define ADD_LAST_CARRY(REG) adc IMM(0), REG
+#define ADD_IMM(TO, NUM) ADD(TO, IMM(NUM))
+#define ADD_W_CARRY(TO1, TO2, FROM) add FROM, TO1; adc IMM(0), TO2;
+#define SUB_IMM(TO, NUM) sub IMM(NUM), TO
+#define MUL(REG) mul REG
+
+#define XOR(TO, FROM) xor FROM, TO
+#define AND(TO, FROM) and FROM, TO
+#define OR(TO, FROM) or FROM, TO
+#define NOT(REG) not REG
+#define ZEROIZE(REG) XOR(REG, REG)
+
+#define RETURN_VALUE_IS(V) ASSIGN(%rax, V)
+
+#define ROTL_IMM(REG, NUM) rol IMM(NUM), REG
+#define ROTR_IMM(REG, NUM) ror IMM(NUM), REG
+#define ADD3_IMM(TO, FROM, NUM) lea NUM(TO,FROM,1), TO
+
+#endif
diff --git a/src/lib/utils/asm_x86_64/info.txt b/src/lib/utils/asm_x86_64/info.txt
new file mode 100644
index 000000000..3173f3b14
--- /dev/null
+++ b/src/lib/utils/asm_x86_64/info.txt
@@ -0,0 +1,27 @@
+load_on dep
+
+<header:internal>
+asm_x86_64.h
+</header:internal>
+
+<arch>
+x86_64
+</arch>
+
+<cc>
+clang
+gcc
+icc
+</cc>
+
+# ELF systems
+<os>
+linux
+netbsd
+openbsd
+solaris
+</os>
+
+<requires>
+asm_engine
+</requires>
diff --git a/src/lib/utils/assert.cpp b/src/lib/utils/assert.cpp
new file mode 100644
index 000000000..b6d4f4240
--- /dev/null
+++ b/src/lib/utils/assert.cpp
@@ -0,0 +1,36 @@
+/*
+* Runtime assertion checking
+* (C) 2010,2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/exceptn.h>
+#include <sstream>
+
+namespace Botan {
+
+void assertion_failure(const char* expr_str,
+ const char* assertion_made,
+ const char* func,
+ const char* file,
+ int line)
+ {
+ std::ostringstream format;
+
+ format << "False assertion ";
+
+ if(assertion_made && assertion_made[0] != 0)
+ format << "'" << assertion_made << "' (expression " << expr_str << ") ";
+ else
+ format << expr_str << " ";
+
+ if(func)
+ format << "in " << func << " ";
+
+ format << "@" << file << ":" << line;
+
+ throw std::runtime_error(format.str());
+ }
+
+}
diff --git a/src/lib/utils/assert.h b/src/lib/utils/assert.h
new file mode 100644
index 000000000..f62fae63e
--- /dev/null
+++ b/src/lib/utils/assert.h
@@ -0,0 +1,83 @@
+/*
+* Runtime assertion checking
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ASSERTION_CHECKING_H__
+#define BOTAN_ASSERTION_CHECKING_H__
+
+#include <botan/build.h>
+
+namespace Botan {
+
+/**
+* Called when an assertion fails
+*/
+void BOTAN_DLL assertion_failure(const char* expr_str,
+ const char* assertion_made,
+ const char* func,
+ const char* file,
+ int line);
+
+/**
+* Make an assertion
+*/
+#define BOTAN_ASSERT(expr, assertion_made) \
+ do { \
+ if(!(expr)) \
+ Botan::assertion_failure(#expr, \
+ assertion_made, \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+ } while(0)
+
+/**
+* Assert that value1 == value2
+*/
+#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made) \
+ do { \
+ if((expr1) != (expr2)) \
+ Botan::assertion_failure(#expr1 " == " #expr2, \
+ assertion_made, \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+ } while(0)
+
+/**
+* Assert that expr1 (if true) implies expr2 is also true
+*/
+#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg) \
+ do { \
+ if((expr1) && !(expr2)) \
+ Botan::assertion_failure(#expr1 " implies " #expr2, \
+ msg, \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+ } while(0)
+
+/**
+* Assert that a pointer is not null
+*/
+#define BOTAN_ASSERT_NONNULL(ptr) \
+ do { \
+ if(static_cast<bool>(ptr) == false) \
+ Botan::assertion_failure(#ptr " is not null", \
+ "", \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+ } while(0)
+
+/**
+* Mark variable as unused
+*/
+#define BOTAN_UNUSED(v) static_cast<void>(v)
+
+}
+
+#endif
diff --git a/src/lib/utils/bit_ops.h b/src/lib/utils/bit_ops.h
new file mode 100644
index 000000000..0072fde71
--- /dev/null
+++ b/src/lib/utils/bit_ops.h
@@ -0,0 +1,103 @@
+/*
+* Bit/Word Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BIT_OPS_H__
+#define BOTAN_BIT_OPS_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/**
+* Power of 2 test. T should be an unsigned integer type
+* @param arg an integer value
+* @return true iff arg is 2^n for some n > 0
+*/
+template<typename T>
+inline bool is_power_of_2(T arg)
+ {
+ return ((arg != 0 && arg != 1) && ((arg & (arg-1)) == 0));
+ }
+
+/**
+* Return the index of the highest set bit
+* T is an unsigned integer type
+* @param n an integer value
+* @return index of the highest set bit in n
+*/
+template<typename T>
+inline size_t high_bit(T n)
+ {
+ for(size_t i = 8*sizeof(T); i > 0; --i)
+ if((n >> (i - 1)) & 0x01)
+ return i;
+ return 0;
+ }
+
+/**
+* Return the index of the lowest set bit
+* T is an unsigned integer type
+* @param n an integer value
+* @return index of the lowest set bit in n
+*/
+template<typename T>
+inline size_t low_bit(T n)
+ {
+ for(size_t i = 0; i != 8*sizeof(T); ++i)
+ if((n >> i) & 0x01)
+ return (i + 1);
+ return 0;
+ }
+
+/**
+* Return the number of significant bytes in n
+* @param n an integer value
+* @return number of significant bytes in n
+*/
+template<typename T>
+inline size_t significant_bytes(T n)
+ {
+ for(size_t i = 0; i != sizeof(T); ++i)
+ if(get_byte(i, n))
+ return sizeof(T)-i;
+ return 0;
+ }
+
+/**
+* Compute Hamming weights
+* @param n an integer value
+* @return number of bits in n set to 1
+*/
+template<typename T>
+inline size_t hamming_weight(T n)
+ {
+ const byte NIBBLE_WEIGHTS[] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+
+ size_t weight = 0;
+ for(size_t i = 0; i != 2*sizeof(T); ++i)
+ weight += NIBBLE_WEIGHTS[(n >> (4*i)) & 0x0F];
+ return weight;
+ }
+
+/**
+* Count the trailing zero bits in n
+* @param n an integer value
+* @return maximum x st 2^x divides n
+*/
+template<typename T>
+inline size_t ctz(T n)
+ {
+ for(size_t i = 0; i != 8*sizeof(T); ++i)
+ if((n >> i) & 0x01)
+ return i;
+ return 8*sizeof(T);
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/boost/info.txt b/src/lib/utils/boost/info.txt
new file mode 100644
index 000000000..e87fd5b88
--- /dev/null
+++ b/src/lib/utils/boost/info.txt
@@ -0,0 +1,7 @@
+define BOOST_FILESYSTEM 20131228
+define BOOST_ASIO 20131228
+
+<libs>
+all -> boost_system,boost_filesystem
+</libs>
+
diff --git a/src/lib/utils/bswap.h b/src/lib/utils/bswap.h
new file mode 100644
index 000000000..9d2c9bc28
--- /dev/null
+++ b/src/lib/utils/bswap.h
@@ -0,0 +1,142 @@
+/*
+* Byte Swapping Operations
+* (C) 1999-2011 Jack Lloyd
+* (C) 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BYTE_SWAP_H__
+#define BOTAN_BYTE_SWAP_H__
+
+#include <botan/types.h>
+#include <botan/rotate.h>
+
+#if defined(BOTAN_TARGET_CPU_HAS_SSE2) && !defined(BOTAN_NO_SSE_INTRINSICS)
+ #include <emmintrin.h>
+#endif
+
+namespace Botan {
+
+/**
+* Swap a 16 bit integer
+*/
+inline u16bit reverse_bytes(u16bit val)
+ {
+ return rotate_left(val, 8);
+ }
+
+/**
+* Swap a 32 bit integer
+*/
+inline u32bit reverse_bytes(u32bit val)
+ {
+#if BOTAN_GCC_VERSION >= 430 && !defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
+ /*
+ GCC intrinsic added in 4.3, works for a number of CPUs
+
+ However avoid under ARM, as it branches to a function in libgcc
+ instead of generating inline asm, so slower even than the generic
+ rotate version below.
+ */
+ return __builtin_bswap32(val);
+
+#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+
+ // GCC-style inline assembly for x86 or x86-64
+ asm("bswapl %0" : "=r" (val) : "0" (val));
+ return val;
+
+#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
+
+ asm ("eor r3, %1, %1, ror #16\n\t"
+ "bic r3, r3, #0x00FF0000\n\t"
+ "mov %0, %1, ror #8\n\t"
+ "eor %0, %0, r3, lsr #8"
+ : "=r" (val)
+ : "0" (val)
+ : "r3", "cc");
+
+ return val;
+
+#elif defined(_MSC_VER) && defined(BOTAN_TARGET_ARCH_IS_X86_32)
+
+ // Visual C++ inline asm for 32-bit x86, by Yves Jerschow
+ __asm mov eax, val;
+ __asm bswap eax;
+
+#else
+
+ // Generic implementation
+ return (rotate_right(val, 8) & 0xFF00FF00) |
+ (rotate_left (val, 8) & 0x00FF00FF);
+
+#endif
+ }
+
+/**
+* Swap a 64 bit integer
+*/
+inline u64bit reverse_bytes(u64bit val)
+ {
+#if BOTAN_GCC_VERSION >= 430
+
+ // GCC intrinsic added in 4.3, works for a number of CPUs
+ return __builtin_bswap64(val);
+
+#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_ARCH_IS_X86_64)
+ // GCC-style inline assembly for x86-64
+ asm("bswapq %0" : "=r" (val) : "0" (val));
+ return val;
+
+#else
+ /* Generic implementation. Defined in terms of 32-bit bswap so any
+ * optimizations in that version can help here (particularly
+ * useful for 32-bit x86).
+ */
+
+ u32bit hi = static_cast<u32bit>(val >> 32);
+ u32bit lo = static_cast<u32bit>(val);
+
+ hi = reverse_bytes(hi);
+ lo = reverse_bytes(lo);
+
+ return (static_cast<u64bit>(lo) << 32) | hi;
+#endif
+ }
+
+/**
+* Swap 4 Ts in an array
+*/
+template<typename T>
+inline void bswap_4(T x[4])
+ {
+ x[0] = reverse_bytes(x[0]);
+ x[1] = reverse_bytes(x[1]);
+ x[2] = reverse_bytes(x[2]);
+ x[3] = reverse_bytes(x[3]);
+ }
+
+#if defined(BOTAN_TARGET_CPU_HAS_SSE2) && !defined(BOTAN_NO_SSE_INTRINSICS)
+
+/**
+* Swap 4 u32bits in an array using SSE2 shuffle instructions
+*/
+template<>
+inline void bswap_4(u32bit x[4])
+ {
+ __m128i T = _mm_loadu_si128(reinterpret_cast<const __m128i*>(x));
+
+ T = _mm_shufflehi_epi16(T, _MM_SHUFFLE(2, 3, 0, 1));
+ T = _mm_shufflelo_epi16(T, _MM_SHUFFLE(2, 3, 0, 1));
+
+ T = _mm_or_si128(_mm_srli_epi16(T, 8), _mm_slli_epi16(T, 8));
+
+ _mm_storeu_si128(reinterpret_cast<__m128i*>(x), T);
+ }
+
+#endif
+
+}
+
+#endif
diff --git a/src/lib/utils/calendar.cpp b/src/lib/utils/calendar.cpp
new file mode 100644
index 000000000..14f0113f2
--- /dev/null
+++ b/src/lib/utils/calendar.cpp
@@ -0,0 +1,52 @@
+/*
+* Calendar Functions
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/calendar.h>
+#include <botan/exceptn.h>
+#include <ctime>
+
+namespace Botan {
+
+namespace {
+
+std::tm do_gmtime(std::time_t time_val)
+ {
+ std::tm tm;
+
+#if defined(BOTAN_TARGET_OS_HAS_GMTIME_S)
+ gmtime_s(&tm, &time_val); // Windows
+#elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R)
+ gmtime_r(&time_val, &tm); // Unix/SUSv2
+#else
+ std::tm* tm_p = std::gmtime(&time_val);
+ if (tm_p == 0)
+ throw Encoding_Error("time_t_to_tm could not convert");
+ tm = *tm_p;
+#endif
+
+ return tm;
+ }
+
+}
+
+/*
+* Convert a time_point to a calendar_point
+*/
+calendar_point calendar_value(
+ const std::chrono::system_clock::time_point& time_point)
+ {
+ std::tm tm = do_gmtime(std::chrono::system_clock::to_time_t(time_point));
+
+ return calendar_point(tm.tm_year + 1900,
+ tm.tm_mon + 1,
+ tm.tm_mday,
+ tm.tm_hour,
+ tm.tm_min,
+ tm.tm_sec);
+ }
+
+}
diff --git a/src/lib/utils/calendar.h b/src/lib/utils/calendar.h
new file mode 100644
index 000000000..d617cc9a0
--- /dev/null
+++ b/src/lib/utils/calendar.h
@@ -0,0 +1,63 @@
+/*
+* Calendar Functions
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CALENDAR_H__
+#define BOTAN_CALENDAR_H__
+
+#include <botan/types.h>
+#include <chrono>
+
+namespace Botan {
+
+/**
+* Struct representing a particular date and time
+*/
+struct BOTAN_DLL calendar_point
+ {
+ /** The year */
+ u32bit year;
+
+ /** The month, 1 through 12 for Jan to Dec */
+ byte month;
+
+ /** The day of the month, 1 through 31 (or 28 or 30 based on month */
+ byte day;
+
+ /** Hour in 24-hour form, 0 to 23 */
+ byte hour;
+
+ /** Minutes in the hour, 0 to 60 */
+ byte minutes;
+
+ /** Seconds in the minute, 0 to 60, but might be slightly
+ larger to deal with leap seconds on some systems
+ */
+ byte seconds;
+
+ /**
+ * Initialize a calendar_point
+ * @param y the year
+ * @param mon the month
+ * @param d the day
+ * @param h the hour
+ * @param min the minute
+ * @param sec the second
+ */
+ calendar_point(u32bit y, byte mon, byte d, byte h, byte min, byte sec) :
+ year(y), month(mon), day(d), hour(h), minutes(min), seconds(sec) {}
+ };
+
+/*
+* @param time_point a time point from the system clock
+* @return calendar_point object representing this time point
+*/
+BOTAN_DLL calendar_point calendar_value(
+ const std::chrono::system_clock::time_point& time_point);
+
+}
+
+#endif
diff --git a/src/lib/utils/charset.cpp b/src/lib/utils/charset.cpp
new file mode 100644
index 000000000..7ee637f80
--- /dev/null
+++ b/src/lib/utils/charset.cpp
@@ -0,0 +1,201 @@
+/*
+* Character Set Handling
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/charset.h>
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+#include <cctype>
+
+namespace Botan {
+
+namespace Charset {
+
+namespace {
+
+/*
+* Convert from UCS-2 to ISO 8859-1
+*/
+std::string ucs2_to_latin1(const std::string& ucs2)
+ {
+ if(ucs2.size() % 2 == 1)
+ throw Decoding_Error("UCS-2 string has an odd number of bytes");
+
+ std::string latin1;
+
+ for(size_t i = 0; i != ucs2.size(); i += 2)
+ {
+ const byte c1 = ucs2[i];
+ const byte c2 = ucs2[i+1];
+
+ if(c1 != 0)
+ throw Decoding_Error("UCS-2 has non-Latin1 characters");
+
+ latin1 += static_cast<char>(c2);
+ }
+
+ return latin1;
+ }
+
+/*
+* Convert from UTF-8 to ISO 8859-1
+*/
+std::string utf8_to_latin1(const std::string& utf8)
+ {
+ std::string iso8859;
+
+ size_t position = 0;
+ while(position != utf8.size())
+ {
+ const byte c1 = static_cast<byte>(utf8[position++]);
+
+ if(c1 <= 0x7F)
+ iso8859 += static_cast<char>(c1);
+ else if(c1 >= 0xC0 && c1 <= 0xC7)
+ {
+ if(position == utf8.size())
+ throw Decoding_Error("UTF-8: sequence truncated");
+
+ const byte c2 = static_cast<byte>(utf8[position++]);
+ const byte iso_char = ((c1 & 0x07) << 6) | (c2 & 0x3F);
+
+ if(iso_char <= 0x7F)
+ throw Decoding_Error("UTF-8: sequence longer than needed");
+
+ iso8859 += static_cast<char>(iso_char);
+ }
+ else
+ throw Decoding_Error("UTF-8: Unicode chars not in Latin1 used");
+ }
+
+ return iso8859;
+ }
+
+/*
+* Convert from ISO 8859-1 to UTF-8
+*/
+std::string latin1_to_utf8(const std::string& iso8859)
+ {
+ std::string utf8;
+ for(size_t i = 0; i != iso8859.size(); ++i)
+ {
+ const byte c = static_cast<byte>(iso8859[i]);
+
+ if(c <= 0x7F)
+ utf8 += static_cast<char>(c);
+ else
+ {
+ utf8 += static_cast<char>((0xC0 | (c >> 6)));
+ utf8 += static_cast<char>((0x80 | (c & 0x3F)));
+ }
+ }
+ return utf8;
+ }
+
+}
+
+/*
+* Perform character set transcoding
+*/
+std::string transcode(const std::string& str,
+ Character_Set to, Character_Set from)
+ {
+ if(to == LOCAL_CHARSET)
+ to = LATIN1_CHARSET;
+ if(from == LOCAL_CHARSET)
+ from = LATIN1_CHARSET;
+
+ if(to == from)
+ return str;
+
+ if(from == LATIN1_CHARSET && to == UTF8_CHARSET)
+ return latin1_to_utf8(str);
+ if(from == UTF8_CHARSET && to == LATIN1_CHARSET)
+ return utf8_to_latin1(str);
+ if(from == UCS2_CHARSET && to == LATIN1_CHARSET)
+ return ucs2_to_latin1(str);
+
+ throw Invalid_Argument("Unknown transcoding operation from " +
+ std::to_string(from) + " to " + std::to_string(to));
+ }
+
+/*
+* Check if a character represents a digit
+*/
+bool is_digit(char c)
+ {
+ if(c == '0' || c == '1' || c == '2' || c == '3' || c == '4' ||
+ c == '5' || c == '6' || c == '7' || c == '8' || c == '9')
+ return true;
+ return false;
+ }
+
+/*
+* Check if a character represents whitespace
+*/
+bool is_space(char c)
+ {
+ if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
+ return true;
+ return false;
+ }
+
+/*
+* Convert a character to a digit
+*/
+byte char2digit(char c)
+ {
+ switch(c)
+ {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ }
+
+ throw Invalid_Argument("char2digit: Input is not a digit character");
+ }
+
+/*
+* Convert a digit to a character
+*/
+char digit2char(byte b)
+ {
+ switch(b)
+ {
+ case 0: return '0';
+ case 1: return '1';
+ case 2: return '2';
+ case 3: return '3';
+ case 4: return '4';
+ case 5: return '5';
+ case 6: return '6';
+ case 7: return '7';
+ case 8: return '8';
+ case 9: return '9';
+ }
+
+ throw Invalid_Argument("digit2char: Input is not a digit");
+ }
+
+/*
+* Case-insensitive character comparison
+*/
+bool caseless_cmp(char a, char b)
+ {
+ return (std::tolower(static_cast<unsigned char>(a)) ==
+ std::tolower(static_cast<unsigned char>(b)));
+ }
+
+}
+
+}
diff --git a/src/lib/utils/charset.h b/src/lib/utils/charset.h
new file mode 100644
index 000000000..afb11733b
--- /dev/null
+++ b/src/lib/utils/charset.h
@@ -0,0 +1,46 @@
+/*
+* Character Set Handling
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CHARSET_H__
+#define BOTAN_CHARSET_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* The different charsets (nominally) supported by Botan.
+*/
+enum Character_Set {
+ LOCAL_CHARSET,
+ UCS2_CHARSET,
+ UTF8_CHARSET,
+ LATIN1_CHARSET
+};
+
+namespace Charset {
+
+/*
+* Character Set Handling
+*/
+std::string BOTAN_DLL transcode(const std::string& str,
+ Character_Set to,
+ Character_Set from);
+
+bool BOTAN_DLL is_digit(char c);
+bool BOTAN_DLL is_space(char c);
+bool BOTAN_DLL caseless_cmp(char x, char y);
+
+byte BOTAN_DLL char2digit(char c);
+char BOTAN_DLL digit2char(byte b);
+
+}
+
+}
+
+#endif
diff --git a/src/lib/utils/cpuid.cpp b/src/lib/utils/cpuid.cpp
new file mode 100644
index 000000000..6da5673c1
--- /dev/null
+++ b/src/lib/utils/cpuid.cpp
@@ -0,0 +1,236 @@
+/*
+* Runtime CPU detection
+* (C) 2009-2010,2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cpuid.h>
+#include <botan/types.h>
+#include <botan/get_byte.h>
+#include <botan/mem_ops.h>
+#include <ostream>
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+
+#if defined(BOTAN_TARGET_OS_IS_DARWIN)
+ #include <sys/sysctl.h>
+#endif
+
+#if defined(BOTAN_TARGET_OS_IS_OPENBSD)
+ #include <sys/param.h>
+ #include <sys/sysctl.h>
+ #include <machine/cpu.h>
+#endif
+
+#endif
+
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+
+#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
+
+#include <intrin.h>
+
+#define X86_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)
+#define X86_CPUID_SUBLEVEL(type, level, out) do { __cpuidex((int*)out, type, level); } while(0)
+
+#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
+
+#include <ia32intrin.h>
+
+#define X86_CPUID(type, out) do { __cpuid(out, type); } while(0)
+#define X86_CPUID_SUBLEVEL(type, level, out) do { __cpuidex((int*)out, type, level); } while(0)
+
+#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && BOTAN_USE_GCC_INLINE_ASM
+
+#define X86_CPUID(type, out) \
+ asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
+ : "0" (type))
+
+#define X86_CPUID_SUBLEVEL(type, level, out) \
+ asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
+ : "0" (type), "2" (level))
+
+#elif defined(BOTAN_BUILD_COMPILER_IS_GCC)
+
+#include <cpuid.h>
+
+#define X86_CPUID(type, out) do { __get_cpuid(type, out, out+1, out+2, out+3); } while(0)
+
+#define X86_CPUID_SUBLEVEL(type, level, out) \
+ do { __cpuid_count(type, level, out[0], out[1], out[2], out[3]); } while(0)
+
+#else
+
+#warning "No way of calling cpuid for this compiler"
+
+#define X86_CPUID(type, out) do { clear_mem(out, 4); } while(0)
+#define X86_CPUID_SUBLEVEL(type, level, out) do { clear_mem(out, 4); } while(0)
+
+#endif
+
+#endif
+
+namespace Botan {
+
+u64bit CPUID::m_x86_processor_flags[2] = { 0, 0 };
+size_t CPUID::m_cache_line_size = 0;
+bool CPUID::m_altivec_capable = false;
+
+namespace {
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+
+bool altivec_check_sysctl()
+ {
+#if defined(BOTAN_TARGET_OS_IS_DARWIN) || defined(BOTAN_TARGET_OS_IS_OPENBSD)
+
+#if defined(BOTAN_TARGET_OS_IS_OPENBSD)
+ int sels[2] = { CTL_MACHDEP, CPU_ALTIVEC };
+#else
+ // From Apple's docs
+ int sels[2] = { CTL_HW, HW_VECTORUNIT };
+#endif
+ int vector_type = 0;
+ size_t length = sizeof(vector_type);
+ int error = sysctl(sels, 2, &vector_type, &length, NULL, 0);
+
+ if(error == 0 && vector_type > 0)
+ return true;
+#endif
+
+ return false;
+ }
+
+bool altivec_check_pvr_emul()
+ {
+ bool altivec_capable = false;
+
+#if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD)
+
+ /*
+ On PowerPC, MSR 287 is PVR, the Processor Version Number
+ Normally it is only accessible to ring 0, but Linux and NetBSD
+ (others, too, maybe?) will trap and emulate it for us.
+
+ PVR identifiers for various AltiVec enabled CPUs. Taken from
+ PearPC and Linux sources, mostly.
+ */
+
+ const u16bit PVR_G4_7400 = 0x000C;
+ const u16bit PVR_G5_970 = 0x0039;
+ const u16bit PVR_G5_970FX = 0x003C;
+ const u16bit PVR_G5_970MP = 0x0044;
+ const u16bit PVR_G5_970GX = 0x0045;
+ const u16bit PVR_POWER6 = 0x003E;
+ const u16bit PVR_POWER7 = 0x003F;
+ const u16bit PVR_CELL_PPU = 0x0070;
+
+ // Motorola produced G4s with PVR 0x800[0123C] (at least)
+ const u16bit PVR_G4_74xx_24 = 0x800;
+
+ u32bit pvr = 0;
+
+ asm volatile("mfspr %0, 287" : "=r" (pvr));
+
+ // Top 16 bit suffice to identify model
+ pvr >>= 16;
+
+ altivec_capable |= (pvr == PVR_G4_7400);
+ altivec_capable |= ((pvr >> 4) == PVR_G4_74xx_24);
+ altivec_capable |= (pvr == PVR_G5_970);
+ altivec_capable |= (pvr == PVR_G5_970FX);
+ altivec_capable |= (pvr == PVR_G5_970MP);
+ altivec_capable |= (pvr == PVR_G5_970GX);
+ altivec_capable |= (pvr == PVR_POWER6);
+ altivec_capable |= (pvr == PVR_POWER7);
+ altivec_capable |= (pvr == PVR_CELL_PPU);
+#endif
+
+ return altivec_capable;
+ }
+
+#endif
+
+}
+
+void CPUID::print(std::ostream& o)
+ {
+ o << "CPUID flags: ";
+
+#define CPUID_PRINT(flag) do { if(has_##flag()) o << #flag << " "; } while(0)
+ CPUID_PRINT(sse2);
+ CPUID_PRINT(ssse3);
+ CPUID_PRINT(sse41);
+ CPUID_PRINT(sse42);
+ CPUID_PRINT(avx2);
+ CPUID_PRINT(avx512f);
+ CPUID_PRINT(altivec);
+
+ CPUID_PRINT(rdtsc);
+ CPUID_PRINT(bmi2);
+ CPUID_PRINT(clmul);
+ CPUID_PRINT(aes_ni);
+ CPUID_PRINT(rdrand);
+ CPUID_PRINT(rdseed);
+ CPUID_PRINT(intel_sha);
+ CPUID_PRINT(adx);
+#undef CPUID_PRINT
+ o << "\n";
+ }
+
+void CPUID::initialize()
+ {
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+ if(altivec_check_sysctl() || altivec_check_pvr_emul())
+ altivec_capable = true;
+#endif
+
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+ const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
+ const u32bit AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };
+
+ u32bit cpuid[4] = { 0 };
+ X86_CPUID(0, cpuid);
+
+ const u32bit max_supported_sublevel = cpuid[0];
+
+ if(max_supported_sublevel == 0)
+ return;
+
+ const bool is_intel = same_mem(cpuid + 1, INTEL_CPUID, 3);
+ const bool is_amd = same_mem(cpuid + 1, AMD_CPUID, 3);
+
+ X86_CPUID(1, cpuid);
+
+ m_x86_processor_flags[0] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];
+
+ if(is_intel)
+ m_cache_line_size = 8 * get_byte(2, cpuid[1]);
+
+ if(max_supported_sublevel >= 7)
+ {
+ clear_mem(cpuid, 4);
+ X86_CPUID_SUBLEVEL(7, 0, cpuid);
+ m_x86_processor_flags[1] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[1];
+ }
+
+ if(is_amd)
+ {
+ X86_CPUID(0x80000005, cpuid);
+ m_cache_line_size = get_byte(3, cpuid[2]);
+ }
+
+#endif
+
+#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
+ /*
+ * If we don't have access to CPUID, we can still safely assume that
+ * any x86-64 processor has SSE2 and RDTSC
+ */
+ if(m_x86_processor_flags[0] == 0)
+ m_x86_processor_flags[0] = (1 << CPUID_SSE2_BIT) | (1 << CPUID_RDTSC_BIT);
+#endif
+ }
+
+}
diff --git a/src/lib/utils/cpuid.h b/src/lib/utils/cpuid.h
new file mode 100644
index 000000000..1c4c1df0b
--- /dev/null
+++ b/src/lib/utils/cpuid.h
@@ -0,0 +1,153 @@
+/*
+* Runtime CPU detection
+* (C) 2009-2010,2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CPUID_H__
+#define BOTAN_CPUID_H__
+
+#include <botan/types.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* A class handling runtime CPU feature detection
+*/
+class BOTAN_DLL CPUID
+ {
+ public:
+ /**
+ * Probe the CPU and see what extensions are supported
+ */
+ static void initialize();
+
+ /**
+ * Return a best guess of the cache line size
+ */
+ static size_t cache_line_size() { return m_cache_line_size; }
+
+ /**
+ * Check if the processor supports RDTSC
+ */
+ static bool has_rdtsc()
+ { return x86_processor_flags_has(CPUID_RDTSC_BIT); }
+
+ /**
+ * Check if the processor supports SSE2
+ */
+ static bool has_sse2()
+ { return x86_processor_flags_has(CPUID_SSE2_BIT); }
+
+ /**
+ * Check if the processor supports SSSE3
+ */
+ static bool has_ssse3()
+ { return x86_processor_flags_has(CPUID_SSSE3_BIT); }
+
+ /**
+ * Check if the processor supports SSE4.1
+ */
+ static bool has_sse41()
+ { return x86_processor_flags_has(CPUID_SSE41_BIT); }
+
+ /**
+ * Check if the processor supports SSE4.2
+ */
+ static bool has_sse42()
+ { return x86_processor_flags_has(CPUID_SSE42_BIT); }
+
+ /**
+ * Check if the processor supports AVX2
+ */
+ static bool has_avx2()
+ { return x86_processor_flags_has(CPUID_AVX2_BIT); }
+
+ /**
+ * Check if the processor supports AVX-512F
+ */
+ static bool has_avx512f()
+ { return x86_processor_flags_has(CPUID_AVX512F_BIT); }
+
+ /**
+ * Check if the processor supports BMI2
+ */
+ static bool has_bmi2()
+ { return x86_processor_flags_has(CPUID_BMI2_BIT); }
+
+ /**
+ * Check if the processor supports AES-NI
+ */
+ static bool has_aes_ni()
+ { return x86_processor_flags_has(CPUID_AESNI_BIT); }
+
+ /**
+ * Check if the processor supports CLMUL
+ */
+ static bool has_clmul()
+ { return x86_processor_flags_has(CPUID_CLMUL_BIT); }
+
+ /**
+ * Check if the processor supports Intel SHA extension
+ */
+ static bool has_intel_sha()
+ { return x86_processor_flags_has(CPUID_SHA_BIT); }
+
+ /**
+ * Check if the processor supports ADX extension
+ */
+ static bool has_adx()
+ { return x86_processor_flags_has(CPUID_ADX_BIT); }
+
+ /**
+ * Check if the processor supports RDRAND
+ */
+ static bool has_rdrand()
+ { return x86_processor_flags_has(CPUID_RDRAND_BIT); }
+
+ /**
+ * Check if the processor supports RDSEED
+ */
+ static bool has_rdseed()
+ { return x86_processor_flags_has(CPUID_RDSEED_BIT); }
+
+ /**
+ * Check if the processor supports AltiVec/VMX
+ */
+ static bool has_altivec() { return m_altivec_capable; }
+
+ static void print(std::ostream& o);
+ private:
+ enum CPUID_bits {
+ CPUID_RDTSC_BIT = 4,
+ CPUID_SSE2_BIT = 26,
+ CPUID_CLMUL_BIT = 33,
+ CPUID_SSSE3_BIT = 41,
+ CPUID_SSE41_BIT = 51,
+ CPUID_SSE42_BIT = 52,
+ CPUID_AESNI_BIT = 57,
+ CPUID_RDRAND_BIT = 62,
+
+ CPUID_AVX2_BIT = 64+5,
+ CPUID_BMI2_BIT = 64+8,
+ CPUID_AVX512F_BIT = 64+16,
+ CPUID_RDSEED_BIT = 64+18,
+ CPUID_ADX_BIT = 64+19,
+ CPUID_SHA_BIT = 64+29,
+ };
+
+ static bool x86_processor_flags_has(u64bit bit)
+ {
+ return ((m_x86_processor_flags[bit/64] >> (bit % 64)) & 1);
+ }
+
+ static u64bit m_x86_processor_flags[2];
+ static size_t m_cache_line_size;
+ static bool m_altivec_capable;
+ };
+
+}
+
+#endif
diff --git a/src/lib/utils/datastor/datastor.cpp b/src/lib/utils/datastor/datastor.cpp
new file mode 100644
index 000000000..7563e9309
--- /dev/null
+++ b/src/lib/utils/datastor/datastor.cpp
@@ -0,0 +1,165 @@
+/*
+* Data Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/datastor.h>
+#include <botan/exceptn.h>
+#include <botan/parsing.h>
+#include <botan/hex.h>
+#include <botan/internal/stl_util.h>
+
+namespace Botan {
+
+/*
+* Data_Store Equality Comparison
+*/
+bool Data_Store::operator==(const Data_Store& other) const
+ {
+ return (contents == other.contents);
+ }
+
+/*
+* Check if this key has at least one value
+*/
+bool Data_Store::has_value(const std::string& key) const
+ {
+ return (contents.lower_bound(key) != contents.end());
+ }
+
+/*
+* Search based on an arbitrary predicate
+*/
+std::multimap<std::string, std::string> Data_Store::search_for(
+ std::function<bool (std::string, std::string)> predicate) const
+ {
+ std::multimap<std::string, std::string> out;
+
+ for(auto i = contents.begin(); i != contents.end(); ++i)
+ if(predicate(i->first, i->second))
+ out.insert(std::make_pair(i->first, i->second));
+
+ return out;
+ }
+
+/*
+* Search based on key equality
+*/
+std::vector<std::string> Data_Store::get(const std::string& looking_for) const
+ {
+ std::vector<std::string> out;
+ auto range = contents.equal_range(looking_for);
+ for(auto i = range.first; i != range.second; ++i)
+ out.push_back(i->second);
+ return out;
+ }
+
+/*
+* Get a single atom
+*/
+std::string Data_Store::get1(const std::string& key) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.empty())
+ throw Invalid_State("Data_Store::get1: No values set for " + key);
+ if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1: More than one value for " + key);
+
+ return vals[0];
+ }
+
+std::string Data_Store::get1(const std::string& key,
+ const std::string& default_value) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1: More than one value for " + key);
+
+ if(vals.empty())
+ return default_value;
+
+ return vals[0];
+ }
+
+/*
+* Get a single std::vector atom
+*/
+std::vector<byte>
+Data_Store::get1_memvec(const std::string& key) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.empty())
+ return std::vector<byte>();
+
+ if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1_memvec: Multiple values for " +
+ key);
+
+ return hex_decode(vals[0]);
+ }
+
+/*
+* Get a single u32bit atom
+*/
+u32bit Data_Store::get1_u32bit(const std::string& key,
+ u32bit default_val) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.empty())
+ return default_val;
+ else if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1_u32bit: Multiple values for " +
+ key);
+
+ return to_u32bit(vals[0]);
+ }
+
+/*
+* Insert a single key and value
+*/
+void Data_Store::add(const std::string& key, const std::string& val)
+ {
+ multimap_insert(contents, key, val);
+ }
+
+/*
+* Insert a single key and value
+*/
+void Data_Store::add(const std::string& key, u32bit val)
+ {
+ add(key, std::to_string(val));
+ }
+
+/*
+* Insert a single key and value
+*/
+void Data_Store::add(const std::string& key, const secure_vector<byte>& val)
+ {
+ add(key, hex_encode(&val[0], val.size()));
+ }
+
+void Data_Store::add(const std::string& key, const std::vector<byte>& val)
+ {
+ add(key, hex_encode(&val[0], val.size()));
+ }
+
+/*
+* Insert a mapping of key/value pairs
+*/
+void Data_Store::add(const std::multimap<std::string, std::string>& in)
+ {
+ std::multimap<std::string, std::string>::const_iterator i = in.begin();
+ while(i != in.end())
+ {
+ contents.insert(*i);
+ ++i;
+ }
+ }
+
+}
diff --git a/src/lib/utils/datastor/datastor.h b/src/lib/utils/datastor/datastor.h
new file mode 100644
index 000000000..1c0504fc9
--- /dev/null
+++ b/src/lib/utils/datastor/datastor.h
@@ -0,0 +1,57 @@
+/*
+* Data Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DATA_STORE_H__
+#define BOTAN_DATA_STORE_H__
+
+#include <botan/secmem.h>
+#include <functional>
+#include <utility>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/**
+* Data Store
+*/
+class BOTAN_DLL Data_Store
+ {
+ public:
+ /**
+ * A search function
+ */
+ bool operator==(const Data_Store&) const;
+
+ std::multimap<std::string, std::string> search_for(
+ std::function<bool (std::string, std::string)> predicate) const;
+
+ std::vector<std::string> get(const std::string&) const;
+
+ std::string get1(const std::string& key) const;
+
+ std::string get1(const std::string& key,
+ const std::string& default_value) const;
+
+ std::vector<byte> get1_memvec(const std::string&) const;
+ u32bit get1_u32bit(const std::string&, u32bit = 0) const;
+
+ bool has_value(const std::string&) const;
+
+ void add(const std::multimap<std::string, std::string>&);
+ void add(const std::string&, const std::string&);
+ void add(const std::string&, u32bit);
+ void add(const std::string&, const secure_vector<byte>&);
+ void add(const std::string&, const std::vector<byte>&);
+ private:
+ std::multimap<std::string, std::string> contents;
+ };
+
+}
+
+#endif
diff --git a/src/lib/utils/datastor/info.txt b/src/lib/utils/datastor/info.txt
new file mode 100644
index 000000000..b91fe5082
--- /dev/null
+++ b/src/lib/utils/datastor/info.txt
@@ -0,0 +1,3 @@
+<requires>
+alloc
+</requires>
diff --git a/src/lib/utils/dyn_load/dyn_load.cpp b/src/lib/utils/dyn_load/dyn_load.cpp
new file mode 100644
index 000000000..51afb1afe
--- /dev/null
+++ b/src/lib/utils/dyn_load/dyn_load.cpp
@@ -0,0 +1,79 @@
+/**
+* Dynamically Loaded Object
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/dyn_load.h>
+#include <botan/build.h>
+#include <stdexcept>
+
+#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
+ #include <dlfcn.h>
+#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY)
+ #include <windows.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+void raise_runtime_loader_exception(const std::string& lib_name,
+ const char* msg)
+ {
+ throw std::runtime_error("Failed to load " + lib_name + ": " +
+ (msg ? msg : "Unknown error"));
+ }
+
+}
+
+Dynamically_Loaded_Library::Dynamically_Loaded_Library(
+ const std::string& library) :
+ lib_name(library), lib(nullptr)
+ {
+#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
+ lib = ::dlopen(lib_name.c_str(), RTLD_LAZY);
+
+ if(!lib)
+ raise_runtime_loader_exception(lib_name, dlerror());
+
+#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY)
+ lib = ::LoadLibraryA(lib_name.c_str());
+
+ if(!lib)
+ raise_runtime_loader_exception(lib_name, "LoadLibrary failed");
+#endif
+
+ if(!lib)
+ raise_runtime_loader_exception(lib_name, "Dynamic load not supported");
+ }
+
+Dynamically_Loaded_Library::~Dynamically_Loaded_Library()
+ {
+#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
+ ::dlclose(lib);
+#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY)
+ ::FreeLibrary((HMODULE)lib);
+#endif
+ }
+
+void* Dynamically_Loaded_Library::resolve_symbol(const std::string& symbol)
+ {
+ void* addr = nullptr;
+
+#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
+ addr = ::dlsym(lib, symbol.c_str());
+#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY)
+ addr = reinterpret_cast<void*>(::GetProcAddress((HMODULE)lib,
+ symbol.c_str()));
+#endif
+
+ if(!addr)
+ throw std::runtime_error("Failed to resolve symbol " + symbol +
+ " in " + lib_name);
+
+ return addr;
+ }
+
+}
diff --git a/src/lib/utils/dyn_load/dyn_load.h b/src/lib/utils/dyn_load/dyn_load.h
new file mode 100644
index 000000000..9edaed202
--- /dev/null
+++ b/src/lib/utils/dyn_load/dyn_load.h
@@ -0,0 +1,67 @@
+/*
+* Dynamically Loaded Object
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DYNAMIC_LOADER_H__
+#define BOTAN_DYNAMIC_LOADER_H__
+
+#include <string>
+
+namespace Botan {
+
+/**
+* Represents a DLL or shared object
+*/
+class Dynamically_Loaded_Library
+ {
+ public:
+ /**
+ * Load a DLL (or fail with an exception)
+ * @param lib_name name or path to a library
+ *
+ * If you don't use a full path, the search order will be defined
+ * by whatever the system linker does by default. Always using fully
+ * qualified pathnames can help prevent code injection attacks (eg
+ * via manipulation of LD_LIBRARY_PATH on Linux)
+ */
+ Dynamically_Loaded_Library(const std::string& lib_name);
+
+ /**
+ * Unload the DLL
+ * @warning Any pointers returned by resolve()/resolve_symbol()
+ * should not be used after this destructor runs.
+ */
+ ~Dynamically_Loaded_Library();
+
+ /**
+ * Load a symbol (or fail with an exception)
+ * @param symbol names the symbol to load
+ * @return address of the loaded symbol
+ */
+ void* resolve_symbol(const std::string& symbol);
+
+ /**
+ * Convenience function for casting symbol to the right type
+ * @param symbol names the symbol to load
+ * @return address of the loaded symbol
+ */
+ template<typename T>
+ T resolve(const std::string& symbol)
+ {
+ return reinterpret_cast<T>(resolve_symbol(symbol));
+ }
+
+ private:
+ Dynamically_Loaded_Library(const Dynamically_Loaded_Library&);
+ Dynamically_Loaded_Library& operator=(const Dynamically_Loaded_Library&);
+
+ std::string lib_name;
+ void* lib;
+ };
+
+}
+
+#endif
diff --git a/src/lib/utils/dyn_load/info.txt b/src/lib/utils/dyn_load/info.txt
new file mode 100644
index 000000000..c8d91dd75
--- /dev/null
+++ b/src/lib/utils/dyn_load/info.txt
@@ -0,0 +1,24 @@
+define DYNAMIC_LOADER 20131128
+
+<os>
+freebsd
+linux
+netbsd
+openbsd
+qnx
+solaris
+windows
+</os>
+
+<libs>
+linux -> dl
+solaris -> dl
+</libs>
+
+<source>
+dyn_load.cpp
+</source>
+
+<header:internal>
+dyn_load.h
+</header:internal>
diff --git a/src/lib/utils/exceptn.h b/src/lib/utils/exceptn.h
new file mode 100644
index 000000000..c480ffd48
--- /dev/null
+++ b/src/lib/utils/exceptn.h
@@ -0,0 +1,181 @@
+/*
+* Exceptions
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EXCEPTION_H__
+#define BOTAN_EXCEPTION_H__
+
+#include <botan/types.h>
+#include <botan/parsing.h>
+#include <exception>
+#include <stdexcept>
+#include <string>
+
+namespace Botan {
+
+typedef std::runtime_error Exception;
+typedef std::invalid_argument Invalid_Argument;
+
+/**
+* Invalid_State Exception
+*/
+struct BOTAN_DLL Invalid_State : public Exception
+ {
+ Invalid_State(const std::string& err) :
+ Exception(err)
+ {}
+ };
+
+/**
+* Lookup_Error Exception
+*/
+struct BOTAN_DLL Lookup_Error : public Exception
+ {
+ Lookup_Error(const std::string& err) :
+ Exception(err)
+ {}
+ };
+
+/**
+* Internal_Error Exception
+*/
+struct BOTAN_DLL Internal_Error : public Exception
+ {
+ Internal_Error(const std::string& err) :
+ Exception("Internal error: " + err)
+ {}
+ };
+
+/**
+* Invalid_Key_Length Exception
+*/
+struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument
+ {
+ Invalid_Key_Length(const std::string& name, size_t length) :
+ Invalid_Argument(name + " cannot accept a key of length " +
+ std::to_string(length))
+ {}
+ };
+
+/**
+* Invalid_IV_Length Exception
+*/
+struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument
+ {
+ Invalid_IV_Length(const std::string& mode, size_t bad_len) :
+ Invalid_Argument("IV length " + std::to_string(bad_len) +
+ " is invalid for " + mode)
+ {}
+ };
+
+/**
+* PRNG_Unseeded Exception
+*/
+struct BOTAN_DLL PRNG_Unseeded : public Invalid_State
+ {
+ PRNG_Unseeded(const std::string& algo) :
+ Invalid_State("PRNG not seeded: " + algo)
+ {}
+ };
+
+/**
+* Policy_Violation Exception
+*/
+struct BOTAN_DLL Policy_Violation : public Invalid_State
+ {
+ Policy_Violation(const std::string& err) :
+ Invalid_State("Policy violation: " + err)
+ {}
+ };
+
+/**
+* Algorithm_Not_Found Exception
+*/
+struct BOTAN_DLL Algorithm_Not_Found : public Lookup_Error
+ {
+ Algorithm_Not_Found(const std::string& name) :
+ Lookup_Error("Could not find any algorithm named \"" + name + "\"")
+ {}
+ };
+
+/**
+* Invalid_Algorithm_Name Exception
+*/
+struct BOTAN_DLL Invalid_Algorithm_Name : public Invalid_Argument
+ {
+ Invalid_Algorithm_Name(const std::string& name):
+ Invalid_Argument("Invalid algorithm name: " + name)
+ {}
+ };
+
+/**
+* Encoding_Error Exception
+*/
+struct BOTAN_DLL Encoding_Error : public Invalid_Argument
+ {
+ Encoding_Error(const std::string& name) :
+ Invalid_Argument("Encoding error: " + name) {}
+ };
+
+/**
+* Decoding_Error Exception
+*/
+struct BOTAN_DLL Decoding_Error : public Invalid_Argument
+ {
+ Decoding_Error(const std::string& name) :
+ Invalid_Argument("Decoding error: " + name) {}
+ };
+
+/**
+* Integrity_Failure Exception
+*/
+struct BOTAN_DLL Integrity_Failure : public Exception
+ {
+ Integrity_Failure(const std::string& msg) :
+ Exception("Integrity failure: " + msg) {}
+ };
+
+/**
+* Invalid_OID Exception
+*/
+struct BOTAN_DLL Invalid_OID : public Decoding_Error
+ {
+ Invalid_OID(const std::string& oid) :
+ Decoding_Error("Invalid ASN.1 OID: " + oid) {}
+ };
+
+/**
+* Stream_IO_Error Exception
+*/
+struct BOTAN_DLL Stream_IO_Error : public Exception
+ {
+ Stream_IO_Error(const std::string& err) :
+ Exception("I/O error: " + err)
+ {}
+ };
+
+/**
+* Self Test Failure Exception
+*/
+struct BOTAN_DLL Self_Test_Failure : public Internal_Error
+ {
+ Self_Test_Failure(const std::string& err) :
+ Internal_Error("Self test failed: " + err)
+ {}
+ };
+
+/**
+* Memory Allocation Exception
+*/
+struct BOTAN_DLL Memory_Exhaustion : public std::bad_alloc
+ {
+ const char* what() const noexcept
+ { return "Ran out of memory, allocation failed"; }
+ };
+
+}
+
+#endif
diff --git a/src/lib/utils/get_byte.h b/src/lib/utils/get_byte.h
new file mode 100644
index 000000000..6f8ef2632
--- /dev/null
+++ b/src/lib/utils/get_byte.h
@@ -0,0 +1,30 @@
+/*
+* Read out bytes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_GET_BYTE_H__
+#define BOTAN_GET_BYTE_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/**
+* Byte extraction
+* @param byte_num which byte to extract, 0 == highest byte
+* @param input the value to extract from
+* @return byte byte_num of input
+*/
+template<typename T> inline byte get_byte(size_t byte_num, T input)
+ {
+ return static_cast<byte>(
+ input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3)
+ );
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/http_util/http_util.cpp b/src/lib/utils/http_util/http_util.cpp
new file mode 100644
index 000000000..a233c1c60
--- /dev/null
+++ b/src/lib/utils/http_util/http_util.cpp
@@ -0,0 +1,220 @@
+/*
+* Sketchy HTTP client
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/http_util.h>
+#include <botan/parsing.h>
+#include <botan/hex.h>
+#include <sstream>
+
+#if defined(BOTAN_HAS_BOOST_ASIO)
+#include <boost/asio.hpp>
+#endif
+
+namespace Botan {
+
+namespace HTTP {
+
+#if defined(BOTAN_HAS_BOOST_ASIO)
+std::string http_transact_asio(const std::string& hostname,
+ const std::string& message)
+ {
+ using namespace boost::asio::ip;
+
+ boost::asio::ip::tcp::iostream tcp;
+
+ tcp.connect(hostname, "http");
+
+ if(!tcp)
+ throw std::runtime_error("HTTP connection to " + hostname + " failed");
+
+ tcp << message;
+ tcp.flush();
+
+ std::ostringstream oss;
+ oss << tcp.rdbuf();
+
+ return oss.str();
+ }
+#endif
+
+std::string http_transact_fail(const std::string& hostname,
+ const std::string&)
+ {
+ throw std::runtime_error("Cannot connect to " + hostname +
+ ": network code disabled in build");
+ }
+
+std::string url_encode(const std::string& in)
+ {
+ std::ostringstream out;
+
+ for(auto c : in)
+ {
+ if(c >= 'A' && c <= 'Z')
+ out << c;
+ else if(c >= 'a' && c <= 'z')
+ out << c;
+ else if(c >= '0' && c <= '9')
+ out << c;
+ else if(c == '-' || c == '_' || c == '.' || c == '~')
+ out << c;
+ else
+ out << '%' << hex_encode(reinterpret_cast<byte*>(&c), 1);
+ }
+
+ return out.str();
+ }
+
+std::ostream& operator<<(std::ostream& o, const Response& resp)
+ {
+ o << "HTTP " << resp.status_code() << " " << resp.status_message() << "\n";
+ for(auto h : resp.headers())
+ o << "Header '" << h.first << "' = '" << h.second << "'\n";
+ o << "Body " << std::to_string(resp.body().size()) << " bytes:\n";
+ o.write(reinterpret_cast<const char*>(&resp.body()[0]), resp.body().size());
+ return o;
+ }
+
+Response http_sync(http_exch_fn http_transact,
+ const std::string& verb,
+ const std::string& url,
+ const std::string& content_type,
+ const std::vector<byte>& body,
+ size_t allowable_redirects)
+ {
+ const auto protocol_host_sep = url.find("://");
+ if(protocol_host_sep == std::string::npos)
+ throw std::runtime_error("Invalid URL " + url);
+ const std::string protocol = url.substr(0, protocol_host_sep);
+
+ const auto host_loc_sep = url.find('/', protocol_host_sep + 3);
+
+ std::string hostname, loc;
+
+ if(host_loc_sep == std::string::npos)
+ {
+ hostname = url.substr(protocol_host_sep + 3, std::string::npos);
+ loc = "/";
+ }
+ else
+ {
+ hostname = url.substr(protocol_host_sep + 3, host_loc_sep-protocol_host_sep-3);
+ loc = url.substr(host_loc_sep, std::string::npos);
+ }
+
+ std::ostringstream outbuf;
+
+ outbuf << verb << " " << loc << " HTTP/1.0\r\n";
+ outbuf << "Host: " << hostname << "\r\n";
+
+ if(verb == "GET")
+ {
+ outbuf << "Accept: */*\r\n";
+ outbuf << "Cache-Control: no-cache\r\n";
+ }
+ else if(verb == "POST")
+ outbuf << "Content-Length: " << body.size() << "\r\n";
+
+ if(content_type != "")
+ outbuf << "Content-Type: " << content_type << "\r\n";
+ outbuf << "Connection: close\r\n\r\n";
+ outbuf.write(reinterpret_cast<const char*>(&body[0]), body.size());
+
+ std::istringstream io(http_transact(hostname, outbuf.str()));
+
+ std::string line1;
+ std::getline(io, line1);
+ if(!io || line1.empty())
+ throw std::runtime_error("No response");
+
+ std::stringstream response_stream(line1);
+ std::string http_version;
+ unsigned int status_code;
+ std::string status_message;
+
+ response_stream >> http_version >> status_code;
+
+ std::getline(response_stream, status_message);
+
+ if(!response_stream || http_version.substr(0,5) != "HTTP/")
+ throw std::runtime_error("Not an HTTP response");
+
+ std::map<std::string, std::string> headers;
+ std::string header_line;
+ while (std::getline(io, header_line) && header_line != "\r")
+ {
+ auto sep = header_line.find(": ");
+ if(sep == std::string::npos || sep > header_line.size() - 2)
+ throw std::runtime_error("Invalid HTTP header " + header_line);
+ const std::string key = header_line.substr(0, sep);
+
+ if(sep + 2 < header_line.size() - 1)
+ {
+ const std::string val = header_line.substr(sep + 2, (header_line.size() - 1) - (sep + 2));
+ headers[key] = val;
+ }
+ }
+
+ if(status_code == 301 && headers.count("Location"))
+ {
+ if(allowable_redirects == 0)
+ throw std::runtime_error("HTTP redirection count exceeded");
+ return GET_sync(headers["Location"], allowable_redirects - 1);
+ }
+
+ // Use Content-Length if set
+ std::vector<byte> resp_body;
+ std::vector<byte> buf(4096);
+ while(io.good())
+ {
+ io.read(reinterpret_cast<char*>(&buf[0]), buf.size());
+ resp_body.insert(resp_body.end(), &buf[0], &buf[io.gcount()]);
+ }
+
+ return Response(status_code, status_message, resp_body, headers);
+ }
+
+Response http_sync(const std::string& verb,
+ const std::string& url,
+ const std::string& content_type,
+ const std::vector<byte>& body,
+ size_t allowable_redirects)
+ {
+ return http_sync(
+#if defined(BOTAN_HAS_BOOST_ASIO)
+ http_transact_asio,
+#else
+ http_transact_fail,
+#endif
+ verb,
+ url,
+ content_type,
+ body,
+ allowable_redirects);
+ }
+
+Response GET_sync(const std::string& url, size_t allowable_redirects)
+ {
+ return http_sync("GET", url, "", std::vector<byte>(), allowable_redirects);
+ }
+
+Response POST_sync(const std::string& url,
+ const std::string& content_type,
+ const std::vector<byte>& body,
+ size_t allowable_redirects)
+ {
+ return http_sync("POST", url, content_type, body, allowable_redirects);
+ }
+
+std::future<Response> GET_async(const std::string& url, size_t allowable_redirects)
+ {
+ return std::async(std::launch::async, GET_sync, url, allowable_redirects);
+ }
+
+}
+
+}
diff --git a/src/lib/utils/http_util/http_util.h b/src/lib/utils/http_util/http_util.h
new file mode 100644
index 000000000..d024add4d
--- /dev/null
+++ b/src/lib/utils/http_util/http_util.h
@@ -0,0 +1,97 @@
+/*
+* HTTP utilities
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_UTILS_URLGET_H__
+#define BOTAN_UTILS_URLGET_H__
+
+#include <botan/types.h>
+#include <future>
+#include <vector>
+#include <map>
+#include <chrono>
+#include <string>
+
+namespace Botan {
+
+namespace HTTP {
+
+struct Response
+ {
+ public:
+ Response(unsigned int status_code, const std::string& status_message,
+ const std::vector<byte>& body,
+ const std::map<std::string, std::string>& headers) :
+ m_status_code(status_code),
+ m_status_message(status_message),
+ m_body(body),
+ m_headers(headers) {}
+
+ unsigned int status_code() const { return m_status_code; }
+
+ const std::vector<byte>& body() const { return m_body; }
+
+ const std::map<std::string, std::string>& headers() const { return m_headers; }
+
+ std::string status_message() const { return m_status_message; }
+
+ void throw_unless_ok()
+ {
+ if(status_code() != 200)
+ throw std::runtime_error("HTTP error: " + status_message());
+ }
+
+ private:
+ unsigned int m_status_code;
+ std::string m_status_message;
+ std::vector<byte> m_body;
+ std::map<std::string, std::string> m_headers;
+ };
+
+BOTAN_DLL std::ostream& operator<<(std::ostream& o, const Response& resp);
+
+typedef std::function<std::string (const std::string&, const std::string&)> http_exch_fn;
+
+#if defined(BOTAN_HAS_BOOST_ASIO)
+std::string BOTAN_DLL http_transact_asio(const std::string& hostname,
+ const std::string& message);
+#endif
+
+std::string BOTAN_DLL http_transact_fail(const std::string& hostname,
+ const std::string& message);
+
+
+BOTAN_DLL Response http_sync(http_exch_fn fn,
+ const std::string& verb,
+ const std::string& url,
+ const std::string& content_type,
+ const std::vector<byte>& body,
+ size_t allowable_redirects);
+
+BOTAN_DLL Response http_sync(const std::string& verb,
+ const std::string& url,
+ const std::string& content_type,
+ const std::vector<byte>& body,
+ size_t allowable_redirects);
+
+BOTAN_DLL Response GET_sync(const std::string& url,
+ size_t allowable_redirects = 1);
+
+BOTAN_DLL Response POST_sync(const std::string& url,
+ const std::string& content_type,
+ const std::vector<byte>& body,
+ size_t allowable_redirects = 1);
+
+std::future<Response> BOTAN_DLL GET_async(const std::string& url,
+ size_t allowable_redirects = 1);
+
+BOTAN_DLL std::string url_encode(const std::string& url);
+
+}
+
+}
+
+#endif
diff --git a/src/lib/utils/http_util/info.txt b/src/lib/utils/http_util/info.txt
new file mode 100644
index 000000000..a23a43a3d
--- /dev/null
+++ b/src/lib/utils/http_util/info.txt
@@ -0,0 +1 @@
+define HTTP_UTIL 20131128
diff --git a/src/lib/utils/info.txt b/src/lib/utils/info.txt
new file mode 100644
index 000000000..0e8edeb00
--- /dev/null
+++ b/src/lib/utils/info.txt
@@ -0,0 +1,29 @@
+define UTIL_FUNCTIONS 20131128
+
+load_on always
+
+<header:internal>
+bit_ops.h
+prefetch.h
+rounding.h
+semaphore.h
+stl_util.h
+xor_buf.h
+</header:internal>
+
+<header:public>
+assert.h
+bswap.h
+calendar.h
+charset.h
+cpuid.h
+exceptn.h
+get_byte.h
+loadstor.h
+mem_ops.h
+mul128.h
+parsing.h
+rotate.h
+types.h
+version.h
+</header:public>
diff --git a/src/lib/utils/loadstor.h b/src/lib/utils/loadstor.h
new file mode 100644
index 000000000..29e00592a
--- /dev/null
+++ b/src/lib/utils/loadstor.h
@@ -0,0 +1,627 @@
+/*
+* Load/Store Operators
+* (C) 1999-2007 Jack Lloyd
+* 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LOAD_STORE_H__
+#define BOTAN_LOAD_STORE_H__
+
+#include <botan/types.h>
+#include <botan/bswap.h>
+#include <botan/get_byte.h>
+#include <cstring>
+
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+
+#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
+
+#define BOTAN_ENDIAN_N2B(x) (x)
+#define BOTAN_ENDIAN_B2N(x) (x)
+
+#define BOTAN_ENDIAN_N2L(x) reverse_bytes(x)
+#define BOTAN_ENDIAN_L2N(x) reverse_bytes(x)
+
+#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
+
+#define BOTAN_ENDIAN_N2L(x) (x)
+#define BOTAN_ENDIAN_L2N(x) (x)
+
+#define BOTAN_ENDIAN_N2B(x) reverse_bytes(x)
+#define BOTAN_ENDIAN_B2N(x) reverse_bytes(x)
+
+#endif
+
+#endif
+
+namespace Botan {
+
+/**
+* Make a u16bit from two bytes
+* @param i0 the first byte
+* @param i1 the second byte
+* @return i0 || i1
+*/
+inline u16bit make_u16bit(byte i0, byte i1)
+ {
+ return ((static_cast<u16bit>(i0) << 8) | i1);
+ }
+
+/**
+* Make a u32bit from four bytes
+* @param i0 the first byte
+* @param i1 the second byte
+* @param i2 the third byte
+* @param i3 the fourth byte
+* @return i0 || i1 || i2 || i3
+*/
+inline u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
+ {
+ return ((static_cast<u32bit>(i0) << 24) |
+ (static_cast<u32bit>(i1) << 16) |
+ (static_cast<u32bit>(i2) << 8) |
+ (static_cast<u32bit>(i3)));
+ }
+
+/**
+* Make a u32bit from eight bytes
+* @param i0 the first byte
+* @param i1 the second byte
+* @param i2 the third byte
+* @param i3 the fourth byte
+* @param i4 the fifth byte
+* @param i5 the sixth byte
+* @param i6 the seventh byte
+* @param i7 the eighth byte
+* @return i0 || i1 || i2 || i3 || i4 || i5 || i6 || i7
+*/
+inline u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3,
+ byte i4, byte i5, byte i6, byte i7)
+ {
+ return ((static_cast<u64bit>(i0) << 56) |
+ (static_cast<u64bit>(i1) << 48) |
+ (static_cast<u64bit>(i2) << 40) |
+ (static_cast<u64bit>(i3) << 32) |
+ (static_cast<u64bit>(i4) << 24) |
+ (static_cast<u64bit>(i5) << 16) |
+ (static_cast<u64bit>(i6) << 8) |
+ (static_cast<u64bit>(i7)));
+ }
+
+/**
+* Load a big-endian word
+* @param in a pointer to some bytes
+* @param off an offset into the array
+* @return off'th T of in, as a big-endian value
+*/
+template<typename T>
+inline T load_be(const byte in[], size_t off)
+ {
+ in += off * sizeof(T);
+ T out = 0;
+ for(size_t i = 0; i != sizeof(T); ++i)
+ out = (out << 8) | in[i];
+ return out;
+ }
+
+/**
+* Load a little-endian word
+* @param in a pointer to some bytes
+* @param off an offset into the array
+* @return off'th T of in, as a litte-endian value
+*/
+template<typename T>
+inline T load_le(const byte in[], size_t off)
+ {
+ in += off * sizeof(T);
+ T out = 0;
+ for(size_t i = 0; i != sizeof(T); ++i)
+ out = (out << 8) | in[sizeof(T)-1-i];
+ return out;
+ }
+
+/**
+* Load a big-endian u16bit
+* @param in a pointer to some bytes
+* @param off an offset into the array
+* @return off'th u16bit of in, as a big-endian value
+*/
+template<>
+inline u16bit load_be<u16bit>(const byte in[], size_t off)
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u16bit*>(in) + off));
+#else
+ in += off * sizeof(u16bit);
+ return make_u16bit(in[0], in[1]);
+#endif
+ }
+
+/**
+* Load a little-endian u16bit
+* @param in a pointer to some bytes
+* @param off an offset into the array
+* @return off'th u16bit of in, as a little-endian value
+*/
+template<>
+inline u16bit load_le<u16bit>(const byte in[], size_t off)
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u16bit*>(in) + off));
+#else
+ in += off * sizeof(u16bit);
+ return make_u16bit(in[1], in[0]);
+#endif
+ }
+
+/**
+* Load a big-endian u32bit
+* @param in a pointer to some bytes
+* @param off an offset into the array
+* @return off'th u32bit of in, as a big-endian value
+*/
+template<>
+inline u32bit load_be<u32bit>(const byte in[], size_t off)
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u32bit*>(in) + off));
+#else
+ in += off * sizeof(u32bit);
+ return make_u32bit(in[0], in[1], in[2], in[3]);
+#endif
+ }
+
+/**
+* Load a little-endian u32bit
+* @param in a pointer to some bytes
+* @param off an offset into the array
+* @return off'th u32bit of in, as a little-endian value
+*/
+template<>
+inline u32bit load_le<u32bit>(const byte in[], size_t off)
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u32bit*>(in) + off));
+#else
+ in += off * sizeof(u32bit);
+ return make_u32bit(in[3], in[2], in[1], in[0]);
+#endif
+ }
+
+/**
+* Load a big-endian u64bit
+* @param in a pointer to some bytes
+* @param off an offset into the array
+* @return off'th u64bit of in, as a big-endian value
+*/
+template<>
+inline u64bit load_be<u64bit>(const byte in[], size_t off)
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u64bit*>(in) + off));
+#else
+ in += off * sizeof(u64bit);
+ return make_u64bit(in[0], in[1], in[2], in[3],
+ in[4], in[5], in[6], in[7]);
+#endif
+ }
+
+/**
+* Load a little-endian u64bit
+* @param in a pointer to some bytes
+* @param off an offset into the array
+* @return off'th u64bit of in, as a little-endian value
+*/
+template<>
+inline u64bit load_le<u64bit>(const byte in[], size_t off)
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u64bit*>(in) + off));
+#else
+ in += off * sizeof(u64bit);
+ return make_u64bit(in[7], in[6], in[5], in[4],
+ in[3], in[2], in[1], in[0]);
+#endif
+ }
+
+/**
+* Load two little-endian words
+* @param in a pointer to some bytes
+* @param x0 where the first word will be written
+* @param x1 where the second word will be written
+*/
+template<typename T>
+inline void load_le(const byte in[], T& x0, T& x1)
+ {
+ x0 = load_le<T>(in, 0);
+ x1 = load_le<T>(in, 1);
+ }
+
+/**
+* Load four little-endian words
+* @param in a pointer to some bytes
+* @param x0 where the first word will be written
+* @param x1 where the second word will be written
+* @param x2 where the third word will be written
+* @param x3 where the fourth word will be written
+*/
+template<typename T>
+inline void load_le(const byte in[],
+ T& x0, T& x1, T& x2, T& x3)
+ {
+ x0 = load_le<T>(in, 0);
+ x1 = load_le<T>(in, 1);
+ x2 = load_le<T>(in, 2);
+ x3 = load_le<T>(in, 3);
+ }
+
+/**
+* Load eight little-endian words
+* @param in a pointer to some bytes
+* @param x0 where the first word will be written
+* @param x1 where the second word will be written
+* @param x2 where the third word will be written
+* @param x3 where the fourth word will be written
+* @param x4 where the fifth word will be written
+* @param x5 where the sixth word will be written
+* @param x6 where the seventh word will be written
+* @param x7 where the eighth word will be written
+*/
+template<typename T>
+inline void load_le(const byte in[],
+ T& x0, T& x1, T& x2, T& x3,
+ T& x4, T& x5, T& x6, T& x7)
+ {
+ x0 = load_le<T>(in, 0);
+ x1 = load_le<T>(in, 1);
+ x2 = load_le<T>(in, 2);
+ x3 = load_le<T>(in, 3);
+ x4 = load_le<T>(in, 4);
+ x5 = load_le<T>(in, 5);
+ x6 = load_le<T>(in, 6);
+ x7 = load_le<T>(in, 7);
+ }
+
+/**
+* Load a variable number of little-endian words
+* @param out the output array of words
+* @param in the input array of bytes
+* @param count how many words are in in
+*/
+template<typename T>
+inline void load_le(T out[],
+ const byte in[],
+ size_t count)
+ {
+#if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS)
+ std::memcpy(out, in, sizeof(T)*count);
+
+#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
+ const size_t blocks = count - (count % 4);
+ const size_t left = count - blocks;
+
+ for(size_t i = 0; i != blocks; i += 4)
+ bswap_4(out + i);
+
+ for(size_t i = 0; i != left; ++i)
+ out[blocks+i] = reverse_bytes(out[blocks+i]);
+#endif
+
+#else
+ for(size_t i = 0; i != count; ++i)
+ out[i] = load_le<T>(in, i);
+#endif
+ }
+
+/**
+* Load two big-endian words
+* @param in a pointer to some bytes
+* @param x0 where the first word will be written
+* @param x1 where the second word will be written
+*/
+template<typename T>
+inline void load_be(const byte in[], T& x0, T& x1)
+ {
+ x0 = load_be<T>(in, 0);
+ x1 = load_be<T>(in, 1);
+ }
+
+/**
+* Load four big-endian words
+* @param in a pointer to some bytes
+* @param x0 where the first word will be written
+* @param x1 where the second word will be written
+* @param x2 where the third word will be written
+* @param x3 where the fourth word will be written
+*/
+template<typename T>
+inline void load_be(const byte in[],
+ T& x0, T& x1, T& x2, T& x3)
+ {
+ x0 = load_be<T>(in, 0);
+ x1 = load_be<T>(in, 1);
+ x2 = load_be<T>(in, 2);
+ x3 = load_be<T>(in, 3);
+ }
+
+/**
+* Load eight big-endian words
+* @param in a pointer to some bytes
+* @param x0 where the first word will be written
+* @param x1 where the second word will be written
+* @param x2 where the third word will be written
+* @param x3 where the fourth word will be written
+* @param x4 where the fifth word will be written
+* @param x5 where the sixth word will be written
+* @param x6 where the seventh word will be written
+* @param x7 where the eighth word will be written
+*/
+template<typename T>
+inline void load_be(const byte in[],
+ T& x0, T& x1, T& x2, T& x3,
+ T& x4, T& x5, T& x6, T& x7)
+ {
+ x0 = load_be<T>(in, 0);
+ x1 = load_be<T>(in, 1);
+ x2 = load_be<T>(in, 2);
+ x3 = load_be<T>(in, 3);
+ x4 = load_be<T>(in, 4);
+ x5 = load_be<T>(in, 5);
+ x6 = load_be<T>(in, 6);
+ x7 = load_be<T>(in, 7);
+ }
+
+/**
+* Load a variable number of big-endian words
+* @param out the output array of words
+* @param in the input array of bytes
+* @param count how many words are in in
+*/
+template<typename T>
+inline void load_be(T out[],
+ const byte in[],
+ size_t count)
+ {
+#if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS)
+ std::memcpy(out, in, sizeof(T)*count);
+
+#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
+ const size_t blocks = count - (count % 4);
+ const size_t left = count - blocks;
+
+ for(size_t i = 0; i != blocks; i += 4)
+ bswap_4(out + i);
+
+ for(size_t i = 0; i != left; ++i)
+ out[blocks+i] = reverse_bytes(out[blocks+i]);
+#endif
+
+#else
+ for(size_t i = 0; i != count; ++i)
+ out[i] = load_be<T>(in, i);
+#endif
+ }
+
+/**
+* Store a big-endian u16bit
+* @param in the input u16bit
+* @param out the byte array to write to
+*/
+inline void store_be(u16bit in, byte out[2])
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_B2N(in);
+#else
+ out[0] = get_byte(0, in);
+ out[1] = get_byte(1, in);
+#endif
+ }
+
+/**
+* Store a little-endian u16bit
+* @param in the input u16bit
+* @param out the byte array to write to
+*/
+inline void store_le(u16bit in, byte out[2])
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_L2N(in);
+#else
+ out[0] = get_byte(1, in);
+ out[1] = get_byte(0, in);
+#endif
+ }
+
+/**
+* Store a big-endian u32bit
+* @param in the input u32bit
+* @param out the byte array to write to
+*/
+inline void store_be(u32bit in, byte out[4])
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_B2N(in);
+#else
+ out[0] = get_byte(0, in);
+ out[1] = get_byte(1, in);
+ out[2] = get_byte(2, in);
+ out[3] = get_byte(3, in);
+#endif
+ }
+
+/**
+* Store a little-endian u32bit
+* @param in the input u32bit
+* @param out the byte array to write to
+*/
+inline void store_le(u32bit in, byte out[4])
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_L2N(in);
+#else
+ out[0] = get_byte(3, in);
+ out[1] = get_byte(2, in);
+ out[2] = get_byte(1, in);
+ out[3] = get_byte(0, in);
+#endif
+ }
+
+/**
+* Store a big-endian u64bit
+* @param in the input u64bit
+* @param out the byte array to write to
+*/
+inline void store_be(u64bit in, byte out[8])
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_B2N(in);
+#else
+ out[0] = get_byte(0, in);
+ out[1] = get_byte(1, in);
+ out[2] = get_byte(2, in);
+ out[3] = get_byte(3, in);
+ out[4] = get_byte(4, in);
+ out[5] = get_byte(5, in);
+ out[6] = get_byte(6, in);
+ out[7] = get_byte(7, in);
+#endif
+ }
+
+/**
+* Store a little-endian u64bit
+* @param in the input u64bit
+* @param out the byte array to write to
+*/
+inline void store_le(u64bit in, byte out[8])
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_L2N(in);
+#else
+ out[0] = get_byte(7, in);
+ out[1] = get_byte(6, in);
+ out[2] = get_byte(5, in);
+ out[3] = get_byte(4, in);
+ out[4] = get_byte(3, in);
+ out[5] = get_byte(2, in);
+ out[6] = get_byte(1, in);
+ out[7] = get_byte(0, in);
+#endif
+ }
+
+/**
+* Store two little-endian words
+* @param out the output byte array
+* @param x0 the first word
+* @param x1 the second word
+*/
+template<typename T>
+inline void store_le(byte out[], T x0, T x1)
+ {
+ store_le(x0, out + (0 * sizeof(T)));
+ store_le(x1, out + (1 * sizeof(T)));
+ }
+
+/**
+* Store two big-endian words
+* @param out the output byte array
+* @param x0 the first word
+* @param x1 the second word
+*/
+template<typename T>
+inline void store_be(byte out[], T x0, T x1)
+ {
+ store_be(x0, out + (0 * sizeof(T)));
+ store_be(x1, out + (1 * sizeof(T)));
+ }
+
+/**
+* Store four little-endian words
+* @param out the output byte array
+* @param x0 the first word
+* @param x1 the second word
+* @param x2 the third word
+* @param x3 the fourth word
+*/
+template<typename T>
+inline void store_le(byte out[], T x0, T x1, T x2, T x3)
+ {
+ store_le(x0, out + (0 * sizeof(T)));
+ store_le(x1, out + (1 * sizeof(T)));
+ store_le(x2, out + (2 * sizeof(T)));
+ store_le(x3, out + (3 * sizeof(T)));
+ }
+
+/**
+* Store four big-endian words
+* @param out the output byte array
+* @param x0 the first word
+* @param x1 the second word
+* @param x2 the third word
+* @param x3 the fourth word
+*/
+template<typename T>
+inline void store_be(byte out[], T x0, T x1, T x2, T x3)
+ {
+ store_be(x0, out + (0 * sizeof(T)));
+ store_be(x1, out + (1 * sizeof(T)));
+ store_be(x2, out + (2 * sizeof(T)));
+ store_be(x3, out + (3 * sizeof(T)));
+ }
+
+/**
+* Store eight little-endian words
+* @param out the output byte array
+* @param x0 the first word
+* @param x1 the second word
+* @param x2 the third word
+* @param x3 the fourth word
+* @param x4 the fifth word
+* @param x5 the sixth word
+* @param x6 the seventh word
+* @param x7 the eighth word
+*/
+template<typename T>
+inline void store_le(byte out[], T x0, T x1, T x2, T x3,
+ T x4, T x5, T x6, T x7)
+ {
+ store_le(x0, out + (0 * sizeof(T)));
+ store_le(x1, out + (1 * sizeof(T)));
+ store_le(x2, out + (2 * sizeof(T)));
+ store_le(x3, out + (3 * sizeof(T)));
+ store_le(x4, out + (4 * sizeof(T)));
+ store_le(x5, out + (5 * sizeof(T)));
+ store_le(x6, out + (6 * sizeof(T)));
+ store_le(x7, out + (7 * sizeof(T)));
+ }
+
+/**
+* Store eight big-endian words
+* @param out the output byte array
+* @param x0 the first word
+* @param x1 the second word
+* @param x2 the third word
+* @param x3 the fourth word
+* @param x4 the fifth word
+* @param x5 the sixth word
+* @param x6 the seventh word
+* @param x7 the eighth word
+*/
+template<typename T>
+inline void store_be(byte out[], T x0, T x1, T x2, T x3,
+ T x4, T x5, T x6, T x7)
+ {
+ store_be(x0, out + (0 * sizeof(T)));
+ store_be(x1, out + (1 * sizeof(T)));
+ store_be(x2, out + (2 * sizeof(T)));
+ store_be(x3, out + (3 * sizeof(T)));
+ store_be(x4, out + (4 * sizeof(T)));
+ store_be(x5, out + (5 * sizeof(T)));
+ store_be(x6, out + (6 * sizeof(T)));
+ store_be(x7, out + (7 * sizeof(T)));
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/mem_ops.h b/src/lib/utils/mem_ops.h
new file mode 100644
index 000000000..be617ff19
--- /dev/null
+++ b/src/lib/utils/mem_ops.h
@@ -0,0 +1,75 @@
+/*
+* Memory Operations
+* (C) 1999-2009,2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MEMORY_OPS_H__
+#define BOTAN_MEMORY_OPS_H__
+
+#include <botan/types.h>
+#include <cstring>
+
+namespace Botan {
+
+/**
+* Zeroize memory
+* @param ptr a pointer to memory to zero out
+* @param n the number of bytes pointed to by ptr
+*/
+BOTAN_DLL void zero_mem(void* ptr, size_t n);
+
+/**
+* Zeroize memory
+* @param ptr a pointer to an array
+* @param n the number of Ts pointed to by ptr
+*/
+template<typename T> inline void clear_mem(T* ptr, size_t n)
+ {
+ zero_mem(ptr, sizeof(T)*n);
+ }
+
+/**
+* Copy memory
+* @param out the destination array
+* @param in the source array
+* @param n the number of elements of in/out
+*/
+template<typename T> inline void copy_mem(T* out, const T* in, size_t n)
+ {
+ std::memmove(out, in, sizeof(T)*n);
+ }
+
+/**
+* Set memory to a fixed value
+* @param ptr a pointer to an array
+* @param n the number of Ts pointed to by ptr
+* @param val the value to set each byte to
+*/
+template<typename T>
+inline void set_mem(T* ptr, size_t n, byte val)
+ {
+ std::memset(ptr, val, sizeof(T)*n);
+ }
+
+/**
+* Memory comparison, input insensitive
+* @param p1 a pointer to an array
+* @param p2 a pointer to another array
+* @param n the number of Ts in p1 and p2
+* @return true iff p1[i] == p2[i] forall i in [0...n)
+*/
+template<typename T> inline bool same_mem(const T* p1, const T* p2, size_t n)
+ {
+ volatile T difference = 0;
+
+ for(size_t i = 0; i != n; ++i)
+ difference |= (p1[i] ^ p2[i]);
+
+ return difference == 0;
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/mul128.h b/src/lib/utils/mul128.h
new file mode 100644
index 000000000..6725021ba
--- /dev/null
+++ b/src/lib/utils/mul128.h
@@ -0,0 +1,121 @@
+/*
+* 64x64->128 bit multiply operation
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_UTIL_MUL128_H__
+#define BOTAN_UTIL_MUL128_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+#if defined(__SIZEOF_INT128__)
+ #define BOTAN_TARGET_HAS_NATIVE_UINT128
+ typedef unsigned __int128 uint128_t;
+
+#elif (BOTAN_GCC_VERSION > 440) && defined(BOTAN_TARGET_CPU_HAS_NATIVE_64BIT)
+ #define BOTAN_TARGET_HAS_NATIVE_UINT128
+ typedef unsigned int uint128_t __attribute__((mode(TI)));
+#endif
+
+}
+
+#if defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
+
+#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) \
+ do { \
+ const uint128_t r = static_cast<uint128_t>(a) * b; \
+ *hi = (r >> 64) & 0xFFFFFFFFFFFFFFFF; \
+ *lo = (r ) & 0xFFFFFFFFFFFFFFFF; \
+ } while(0)
+
+#elif defined(BOTAN_BUILD_COMPILER_IS_MSVC) && defined(BOTAN_TARGET_CPU_HAS_NATIVE_64BIT)
+
+#include <intrin.h>
+#pragma intrinsic(_umul128)
+
+#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) \
+ do { *lo = _umul128(a, b, hi); } while(0)
+
+#elif defined(BOTAN_USE_GCC_INLINE_ASM)
+
+#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
+
+#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) do { \
+ asm("mulq %3" : "=d" (*hi), "=a" (*lo) : "a" (a), "rm" (b) : "cc"); \
+ } while(0)
+
+#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
+
+#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) do { \
+ asm("umulh %1,%2,%0" : "=r" (*hi) : "r" (a), "r" (b)); \
+ *lo = a * b; \
+} while(0)
+
+#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
+
+#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) do { \
+ asm("xmpy.hu %0=%1,%2" : "=f" (*hi) : "f" (a), "f" (b)); \
+ *lo = a * b; \
+} while(0)
+
+#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
+
+#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) do { \
+ asm("mulhdu %0,%1,%2" : "=r" (*hi) : "r" (a), "r" (b) : "cc"); \
+ *lo = a * b; \
+} while(0)
+
+#endif
+
+#endif
+
+namespace Botan {
+
+/**
+* Perform a 64x64->128 bit multiplication
+*/
+inline void mul64x64_128(u64bit a, u64bit b, u64bit* lo, u64bit* hi)
+ {
+#if defined(BOTAN_FAST_64X64_MUL)
+ BOTAN_FAST_64X64_MUL(a, b, lo, hi);
+#else
+
+ /*
+ * Do a 64x64->128 multiply using four 32x32->64 multiplies plus
+ * some adds and shifts. Last resort for CPUs like UltraSPARC (with
+ * 64-bit registers/ALU, but no 64x64->128 multiply) or 32-bit CPUs.
+ */
+ const size_t HWORD_BITS = 32;
+ const u32bit HWORD_MASK = 0xFFFFFFFF;
+
+ const u32bit a_hi = (a >> HWORD_BITS);
+ const u32bit a_lo = (a & HWORD_MASK);
+ const u32bit b_hi = (b >> HWORD_BITS);
+ const u32bit b_lo = (b & HWORD_MASK);
+
+ u64bit x0 = static_cast<u64bit>(a_hi) * b_hi;
+ u64bit x1 = static_cast<u64bit>(a_lo) * b_hi;
+ u64bit x2 = static_cast<u64bit>(a_hi) * b_lo;
+ u64bit x3 = static_cast<u64bit>(a_lo) * b_lo;
+
+ // this cannot overflow as (2^32-1)^2 + 2^32-1 < 2^64-1
+ x2 += x3 >> HWORD_BITS;
+
+ // this one can overflow
+ x2 += x1;
+
+ // propagate the carry if any
+ x0 += static_cast<u64bit>(static_cast<bool>(x2 < x1)) << HWORD_BITS;
+
+ *hi = x0 + (x2 >> HWORD_BITS);
+ *lo = ((x2 & HWORD_MASK) << HWORD_BITS) + (x3 & HWORD_MASK);
+#endif
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/parsing.cpp b/src/lib/utils/parsing.cpp
new file mode 100644
index 000000000..cf47e24f8
--- /dev/null
+++ b/src/lib/utils/parsing.cpp
@@ -0,0 +1,302 @@
+/*
+* Various string utils and parsing functions
+* (C) 1999-2007,2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+#include <botan/charset.h>
+#include <botan/get_byte.h>
+#include <set>
+
+namespace Botan {
+
+u32bit to_u32bit(const std::string& str)
+ {
+ return std::stoul(str, nullptr);
+ }
+
+/*
+* Convert a string into a time duration
+*/
+u32bit timespec_to_u32bit(const std::string& timespec)
+ {
+ if(timespec == "")
+ return 0;
+
+ const char suffix = timespec[timespec.size()-1];
+ std::string value = timespec.substr(0, timespec.size()-1);
+
+ u32bit scale = 1;
+
+ if(Charset::is_digit(suffix))
+ value += suffix;
+ else if(suffix == 's')
+ scale = 1;
+ else if(suffix == 'm')
+ scale = 60;
+ else if(suffix == 'h')
+ scale = 60 * 60;
+ else if(suffix == 'd')
+ scale = 24 * 60 * 60;
+ else if(suffix == 'y')
+ scale = 365 * 24 * 60 * 60;
+ else
+ throw Decoding_Error("timespec_to_u32bit: Bad input " + timespec);
+
+ return scale * to_u32bit(value);
+ }
+
+/*
+* Parse a SCAN-style algorithm name
+*/
+std::vector<std::string> parse_algorithm_name(const std::string& namex)
+ {
+ if(namex.find('(') == std::string::npos &&
+ namex.find(')') == std::string::npos)
+ return std::vector<std::string>(1, namex);
+
+ std::string name = namex, substring;
+ std::vector<std::string> elems;
+ size_t level = 0;
+
+ elems.push_back(name.substr(0, name.find('(')));
+ name = name.substr(name.find('('));
+
+ for(auto i = name.begin(); i != name.end(); ++i)
+ {
+ char c = *i;
+
+ if(c == '(')
+ ++level;
+ if(c == ')')
+ {
+ if(level == 1 && i == name.end() - 1)
+ {
+ if(elems.size() == 1)
+ elems.push_back(substring.substr(1));
+ else
+ elems.push_back(substring);
+ return elems;
+ }
+
+ if(level == 0 || (level == 1 && i != name.end() - 1))
+ throw Invalid_Algorithm_Name(namex);
+ --level;
+ }
+
+ if(c == ',' && level == 1)
+ {
+ if(elems.size() == 1)
+ elems.push_back(substring.substr(1));
+ else
+ elems.push_back(substring);
+ substring.clear();
+ }
+ else
+ substring += c;
+ }
+
+ if(substring != "")
+ throw Invalid_Algorithm_Name(namex);
+
+ return elems;
+ }
+
+/*
+* Split the string on slashes
+*/
+std::vector<std::string> split_on(const std::string& str, char delim)
+ {
+ std::vector<std::string> elems;
+ if(str == "") return elems;
+
+ std::string substr;
+ for(auto i = str.begin(); i != str.end(); ++i)
+ {
+ if(*i == delim)
+ {
+ if(substr != "")
+ elems.push_back(substr);
+ substr.clear();
+ }
+ else
+ substr += *i;
+ }
+
+ if(substr == "")
+ throw Invalid_Argument("Unable to split string: " + str);
+ elems.push_back(substr);
+
+ return elems;
+ }
+
+/*
+* Join a string
+*/
+std::string string_join(const std::vector<std::string>& strs, char delim)
+ {
+ std::string out = "";
+
+ for(size_t i = 0; i != strs.size(); ++i)
+ {
+ if(i != 0)
+ out += delim;
+ out += strs[i];
+ }
+
+ return out;
+ }
+
+/*
+* Parse an ASN.1 OID string
+*/
+std::vector<u32bit> parse_asn1_oid(const std::string& oid)
+ {
+ std::string substring;
+ std::vector<u32bit> oid_elems;
+
+ for(auto i = oid.begin(); i != oid.end(); ++i)
+ {
+ char c = *i;
+
+ if(c == '.')
+ {
+ if(substring == "")
+ throw Invalid_OID(oid);
+ oid_elems.push_back(to_u32bit(substring));
+ substring.clear();
+ }
+ else
+ substring += c;
+ }
+
+ if(substring == "")
+ throw Invalid_OID(oid);
+ oid_elems.push_back(to_u32bit(substring));
+
+ if(oid_elems.size() < 2)
+ throw Invalid_OID(oid);
+
+ return oid_elems;
+ }
+
+/*
+* X.500 String Comparison
+*/
+bool x500_name_cmp(const std::string& name1, const std::string& name2)
+ {
+ auto p1 = name1.begin();
+ auto p2 = name2.begin();
+
+ while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
+ while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
+
+ while(p1 != name1.end() && p2 != name2.end())
+ {
+ if(Charset::is_space(*p1))
+ {
+ if(!Charset::is_space(*p2))
+ return false;
+
+ while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
+ while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
+
+ if(p1 == name1.end() && p2 == name2.end())
+ return true;
+ }
+
+ if(!Charset::caseless_cmp(*p1, *p2))
+ return false;
+ ++p1;
+ ++p2;
+ }
+
+ while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
+ while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
+
+ if((p1 != name1.end()) || (p2 != name2.end()))
+ return false;
+ return true;
+ }
+
+/*
+* Convert a decimal-dotted string to binary IP
+*/
+u32bit string_to_ipv4(const std::string& str)
+ {
+ std::vector<std::string> parts = split_on(str, '.');
+
+ if(parts.size() != 4)
+ throw Decoding_Error("Invalid IP string " + str);
+
+ u32bit ip = 0;
+
+ for(auto part = parts.begin(); part != parts.end(); ++part)
+ {
+ u32bit octet = to_u32bit(*part);
+
+ if(octet > 255)
+ throw Decoding_Error("Invalid IP string " + str);
+
+ ip = (ip << 8) | (octet & 0xFF);
+ }
+
+ return ip;
+ }
+
+/*
+* Convert an IP address to decimal-dotted string
+*/
+std::string ipv4_to_string(u32bit ip)
+ {
+ std::string str;
+
+ for(size_t i = 0; i != sizeof(ip); ++i)
+ {
+ if(i)
+ str += ".";
+ str += std::to_string(get_byte(i, ip));
+ }
+
+ return str;
+ }
+
+std::string erase_chars(const std::string& str, const std::set<char>& chars)
+ {
+ std::string out;
+
+ for(auto c: str)
+ if(chars.count(c) == 0)
+ out += c;
+
+ return out;
+ }
+
+std::string replace_chars(const std::string& str,
+ const std::set<char>& chars,
+ char to_char)
+ {
+ std::string out = str;
+
+ for(size_t i = 0; i != out.size(); ++i)
+ if(chars.count(out[i]))
+ out[i] = to_char;
+
+ return out;
+ }
+
+std::string replace_char(const std::string& str, char from_char, char to_char)
+ {
+ std::string out = str;
+
+ for(size_t i = 0; i != out.size(); ++i)
+ if(out[i] == from_char)
+ out[i] = to_char;
+
+ return out;
+ }
+
+}
diff --git a/src/lib/utils/parsing.h b/src/lib/utils/parsing.h
new file mode 100644
index 000000000..b37e3cb62
--- /dev/null
+++ b/src/lib/utils/parsing.h
@@ -0,0 +1,133 @@
+/*
+* Various string utils and parsing functions
+* (C) 1999-2007,2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PARSER_H__
+#define BOTAN_PARSER_H__
+
+#include <botan/types.h>
+#include <string>
+#include <vector>
+#include <set>
+
+#include <istream>
+#include <functional>
+#include <map>
+
+namespace Botan {
+
+/**
+* Parse a SCAN-style algorithm name
+* @param scan_name the name
+* @return the name components
+*/
+BOTAN_DLL std::vector<std::string>
+parse_algorithm_name(const std::string& scan_name);
+
+/**
+* Split a string
+* @param str the input string
+* @param delim the delimitor
+* @return string split by delim
+*/
+BOTAN_DLL std::vector<std::string> split_on(
+ const std::string& str, char delim);
+
+/**
+* Erase characters from a string
+*/
+BOTAN_DLL std::string erase_chars(const std::string& str, const std::set<char>& chars);
+
+/**
+* Replace a character in a string
+* @param str the input string
+* @param from_char the character to replace
+* @param to_char the character to replace it with
+* @return str with all instances of from_char replaced by to_char
+*/
+BOTAN_DLL std::string replace_char(const std::string& str,
+ char from_char,
+ char to_char);
+
+/**
+* Replace a character in a string
+* @param str the input string
+* @param from_chars the characters to replace
+* @param to_char the character to replace it with
+* @return str with all instances of from_chars replaced by to_char
+*/
+BOTAN_DLL std::string replace_chars(const std::string& str,
+ const std::set<char>& from_chars,
+ char to_char);
+
+/**
+* Join a string
+* @param strs strings to join
+* @param delim the delimitor
+* @return string joined by delim
+*/
+BOTAN_DLL std::string string_join(const std::vector<std::string>& strs,
+ char delim);
+
+/**
+* Parse an ASN.1 OID
+* @param oid the OID in string form
+* @return OID components
+*/
+BOTAN_DLL std::vector<u32bit> parse_asn1_oid(const std::string& oid);
+
+/**
+* Compare two names using the X.509 comparison algorithm
+* @param name1 the first name
+* @param name2 the second name
+* @return true if name1 is the same as name2 by the X.509 comparison rules
+*/
+BOTAN_DLL bool x500_name_cmp(const std::string& name1,
+ const std::string& name2);
+
+/**
+* Convert a string to a number
+* @param str the string to convert
+* @return number value of the string
+*/
+BOTAN_DLL u32bit to_u32bit(const std::string& str);
+
+/**
+* Convert a time specification to a number
+* @param timespec the time specification
+* @return number of seconds represented by timespec
+*/
+BOTAN_DLL u32bit timespec_to_u32bit(const std::string& timespec);
+
+/**
+* Convert a string representation of an IPv4 address to a number
+* @param ip_str the string representation
+* @return integer IPv4 address
+*/
+BOTAN_DLL u32bit string_to_ipv4(const std::string& ip_str);
+
+/**
+* Convert an IPv4 address to a string
+* @param ip_addr the IPv4 address to convert
+* @return string representation of the IPv4 address
+*/
+BOTAN_DLL std::string ipv4_to_string(u32bit ip_addr);
+
+void BOTAN_DLL lex_cfg(std::istream& is,
+ std::function<void (std::string)> cb);
+
+void BOTAN_DLL lex_cfg_w_headers(std::istream& is,
+ std::function<void (std::string)> cb,
+ std::function<void (std::string)> header_cb);
+
+std::map<std::string, std::map<std::string, std::string>>
+BOTAN_DLL
+parse_cfg(std::istream& is);
+
+
+}
+
+#endif
diff --git a/src/lib/utils/prefetch.h b/src/lib/utils/prefetch.h
new file mode 100644
index 000000000..66024e5ce
--- /dev/null
+++ b/src/lib/utils/prefetch.h
@@ -0,0 +1,39 @@
+/*
+* Prefetching Operations
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PREFETCH_H__
+#define BOTAN_PREFETCH_H__
+
+#include <botan/cpuid.h>
+
+namespace Botan {
+
+template<typename T>
+inline void prefetch_readonly(const T* addr, size_t length)
+ {
+#if defined(__GNUG__)
+ const size_t Ts_per_cache_line = CPUID::cache_line_size() / sizeof(T);
+
+ for(size_t i = 0; i <= length; i += Ts_per_cache_line)
+ __builtin_prefetch(addr + i, 0);
+#endif
+ }
+
+template<typename T>
+inline void prefetch_readwrite(const T* addr, size_t length)
+ {
+#if defined(__GNUG__)
+ const size_t Ts_per_cache_line = CPUID::cache_line_size() / sizeof(T);
+
+ for(size_t i = 0; i <= length; i += Ts_per_cache_line)
+ __builtin_prefetch(addr + i, 1);
+#endif
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/read_cfg.cpp b/src/lib/utils/read_cfg.cpp
new file mode 100644
index 000000000..ad57a8b3e
--- /dev/null
+++ b/src/lib/utils/read_cfg.cpp
@@ -0,0 +1,115 @@
+/*
+* Simple config/test file reader
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/parsing.h>
+#include <boost/algorithm/string.hpp>
+
+namespace Botan {
+
+void lex_cfg(std::istream& is,
+ std::function<void (std::string)> cb)
+ {
+ while(is.good())
+ {
+ std::string s;
+
+ std::getline(is, s);
+
+ while(is.good() && s.back() == '\\')
+ {
+ boost::trim_if(s, boost::is_any_of("\\\n"));
+ std::string x;
+ std::getline(is, x);
+ boost::trim_left(x);
+ s += x;
+ }
+
+ auto comment = s.find('#');
+ if(comment)
+ s = s.substr(0, comment);
+
+ if(s.empty())
+ continue;
+
+ std::vector<std::string> parts;
+ boost::split(parts, s, boost::is_any_of(" \t\n"), boost::token_compress_on);
+
+ for(auto p : parts)
+ {
+ if(p.empty())
+ continue;
+
+ auto eq = p.find("=");
+
+ if(eq == std::string::npos || p.size() < 2)
+ {
+ cb(p);
+ }
+ else if(eq == 0)
+ {
+ cb("=");
+ cb(p.substr(1, std::string::npos));
+ }
+ else if(eq == p.size() - 1)
+ {
+ cb(p.substr(0, p.size() - 1));
+ cb("=");
+ }
+ else if(eq != std::string::npos)
+ {
+ cb(p.substr(0, eq));
+ cb("=");
+ cb(p.substr(eq + 1, std::string::npos));
+ }
+ }
+ }
+ }
+
+void lex_cfg_w_headers(std::istream& is,
+ std::function<void (std::string)> cb,
+ std::function<void (std::string)> hdr_cb)
+ {
+ auto intercept = [cb,hdr_cb](const std::string& s)
+ {
+ if(s[0] == '[' && s[s.length()-1] == ']')
+ hdr_cb(s.substr(1, s.length()-2));
+ else
+ cb(s);
+ };
+
+ lex_cfg(is, intercept);
+ }
+
+std::map<std::string, std::map<std::string, std::string>>
+ parse_cfg(std::istream& is)
+ {
+ std::string header = "default";
+ std::map<std::string, std::map<std::string, std::string>> vals;
+ std::string key;
+
+ auto header_cb = [&header](const std::string i) { header = i; };
+ auto cb = [&header,&key,&vals](const std::string s)
+ {
+ if(s == "=")
+ {
+ BOTAN_ASSERT(!key.empty(), "Valid assignment in config");
+ }
+ else if(key.empty())
+ key = s;
+ else
+ {
+ vals[header][key] = s;
+ key = "";
+ }
+ };
+
+ lex_cfg_w_headers(is, cb, header_cb);
+
+ return vals;
+ }
+
+}
diff --git a/src/lib/utils/rotate.h b/src/lib/utils/rotate.h
new file mode 100644
index 000000000..2593010b4
--- /dev/null
+++ b/src/lib/utils/rotate.h
@@ -0,0 +1,43 @@
+/*
+* Word Rotation Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_WORD_ROTATE_H__
+#define BOTAN_WORD_ROTATE_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/**
+* Bit rotation left
+* @param input the input word
+* @param rot the number of bits to rotate
+* @return input rotated left by rot bits
+*/
+template<typename T> inline T rotate_left(T input, size_t rot)
+ {
+ if(rot == 0)
+ return input;
+ return static_cast<T>((input << rot) | (input >> (8*sizeof(T)-rot)));;
+ }
+
+/**
+* Bit rotation right
+* @param input the input word
+* @param rot the number of bits to rotate
+* @return input rotated right by rot bits
+*/
+template<typename T> inline T rotate_right(T input, size_t rot)
+ {
+ if(rot == 0)
+ return input;
+ return static_cast<T>((input >> rot) | (input << (8*sizeof(T)-rot)));
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/rounding.h b/src/lib/utils/rounding.h
new file mode 100644
index 000000000..4ddd7a432
--- /dev/null
+++ b/src/lib/utils/rounding.h
@@ -0,0 +1,61 @@
+/*
+* Integer Rounding Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ROUNDING_H__
+#define BOTAN_ROUNDING_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/**
+* Round up
+* @param n an integer
+* @param align_to the alignment boundary
+* @return n rounded up to a multiple of align_to
+*/
+template<typename T>
+inline T round_up(T n, T align_to)
+ {
+ if(align_to == 0)
+ return n;
+
+ if(n % align_to || n == 0)
+ n += align_to - (n % align_to);
+ return n;
+ }
+
+/**
+* Round down
+* @param n an integer
+* @param align_to the alignment boundary
+* @return n rounded down to a multiple of align_to
+*/
+template<typename T>
+inline T round_down(T n, T align_to)
+ {
+ if(align_to == 0)
+ return n;
+
+ return (n - (n % align_to));
+ }
+
+/**
+* Clamp
+*/
+inline size_t clamp(size_t n, size_t lower_bound, size_t upper_bound)
+ {
+ if(n < lower_bound)
+ return lower_bound;
+ if(n > upper_bound)
+ return upper_bound;
+ return n;
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/semaphore.cpp b/src/lib/utils/semaphore.cpp
new file mode 100644
index 000000000..f4f5b2b53
--- /dev/null
+++ b/src/lib/utils/semaphore.cpp
@@ -0,0 +1,39 @@
+/*
+* Semaphore
+* by Pierre Gaston (http://p9as.blogspot.com/2012/06/c11-semaphores.html)
+* modified by Joel Low for Botan
+*
+*/
+
+#include <botan/internal/semaphore.h>
+
+namespace Botan {
+
+void Semaphore::release(size_t n)
+ {
+ for(size_t i = 0; i != n; ++i)
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+
+ ++m_value;
+
+ if(m_value <= 0)
+ {
+ ++m_wakeups;
+ m_cond.notify_one();
+ }
+ }
+ }
+
+void Semaphore::acquire()
+ {
+ std::unique_lock<std::mutex> lock(m_mutex);
+ --m_value;
+ if(m_value < 0)
+ {
+ m_cond.wait(lock, [this] { return m_wakeups > 0; });
+ --m_wakeups;
+ }
+ }
+
+}
diff --git a/src/lib/utils/semaphore.h b/src/lib/utils/semaphore.h
new file mode 100644
index 000000000..c3ce73680
--- /dev/null
+++ b/src/lib/utils/semaphore.h
@@ -0,0 +1,34 @@
+/*
+* Semaphore
+* by Pierre Gaston (http://p9as.blogspot.com/2012/06/c11-semaphores.html)
+* modified by Joel Low for Botan
+*
+*/
+
+#ifndef BOTAN_SEMAPHORE_H__
+#define BOTAN_SEMAPHORE_H__
+
+#include <mutex>
+#include <condition_variable>
+
+namespace Botan {
+
+class Semaphore
+ {
+ public:
+ Semaphore(int value = 0) : m_value(value), m_wakeups(0) {}
+
+ void acquire();
+
+ void release(size_t n = 1);
+
+ private:
+ int m_value;
+ int m_wakeups;
+ std::mutex m_mutex;
+ std::condition_variable m_cond;
+ };
+
+}
+
+#endif
diff --git a/src/lib/utils/sqlite3/info.txt b/src/lib/utils/sqlite3/info.txt
new file mode 100644
index 000000000..97d59d697
--- /dev/null
+++ b/src/lib/utils/sqlite3/info.txt
@@ -0,0 +1,14 @@
+
+load_on request
+
+<libs>
+all -> sqlite3
+</libs>
+
+<header:internal>
+sqlite3.h
+</header:internal>
+
+<source>
+sqlite3.cpp
+</source>
diff --git a/src/lib/utils/sqlite3/sqlite3.cpp b/src/lib/utils/sqlite3/sqlite3.cpp
new file mode 100644
index 000000000..7f6626759
--- /dev/null
+++ b/src/lib/utils/sqlite3/sqlite3.cpp
@@ -0,0 +1,137 @@
+/*
+* SQLite wrapper
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/sqlite3.h>
+#include <stdexcept>
+#include <sqlite3.h>
+
+namespace Botan {
+
+sqlite3_database::sqlite3_database(const std::string& db_filename)
+ {
+ int rc = ::sqlite3_open(db_filename.c_str(), &m_db);
+
+ if(rc)
+ {
+ const std::string err_msg = ::sqlite3_errmsg(m_db);
+ ::sqlite3_close(m_db);
+ m_db = nullptr;
+ throw std::runtime_error("sqlite3_open failed - " + err_msg);
+ }
+ }
+
+sqlite3_database::~sqlite3_database()
+ {
+ if(m_db)
+ ::sqlite3_close(m_db);
+ m_db = nullptr;
+ }
+
+size_t sqlite3_database::row_count(const std::string& table_name)
+ {
+ sqlite3_statement stmt(this, "select count(*) from " + table_name);
+
+ if(stmt.step())
+ return stmt.get_size_t(0);
+ else
+ throw std::runtime_error("Querying size of table " + table_name + " failed");
+ }
+
+void sqlite3_database::create_table(const std::string& table_schema)
+ {
+ char* errmsg = nullptr;
+ int rc = ::sqlite3_exec(m_db, table_schema.c_str(), nullptr, nullptr, &errmsg);
+
+ if(rc != SQLITE_OK)
+ {
+ const std::string err_msg = errmsg;
+ ::sqlite3_free(errmsg);
+ ::sqlite3_close(m_db);
+ m_db = nullptr;
+ throw std::runtime_error("sqlite3_exec for table failed - " + err_msg);
+ }
+ }
+
+
+sqlite3_statement::sqlite3_statement(sqlite3_database* db, const std::string& base_sql)
+ {
+ int rc = ::sqlite3_prepare_v2(db->m_db, base_sql.c_str(), -1, &m_stmt, nullptr);
+
+ if(rc != SQLITE_OK)
+ throw std::runtime_error("sqlite3_prepare failed " + base_sql +
+ ", code " + std::to_string(rc));
+ }
+
+void sqlite3_statement::bind(int column, const std::string& val)
+ {
+ int rc = ::sqlite3_bind_text(m_stmt, column, val.c_str(), -1, SQLITE_TRANSIENT);
+ if(rc != SQLITE_OK)
+ throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc));
+ }
+
+void sqlite3_statement::bind(int column, int val)
+ {
+ int rc = ::sqlite3_bind_int(m_stmt, column, val);
+ if(rc != SQLITE_OK)
+ throw std::runtime_error("sqlite3_bind_int failed, code " + std::to_string(rc));
+ }
+
+void sqlite3_statement::bind(int column, std::chrono::system_clock::time_point time)
+ {
+ const int timeval = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count();
+ bind(column, timeval);
+ }
+
+void sqlite3_statement::bind(int column, const std::vector<byte>& val)
+ {
+ int rc = ::sqlite3_bind_blob(m_stmt, column, &val[0], val.size(), SQLITE_TRANSIENT);
+ if(rc != SQLITE_OK)
+ throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc));
+ }
+
+std::pair<const byte*, size_t> sqlite3_statement::get_blob(int column)
+ {
+ BOTAN_ASSERT(::sqlite3_column_type(m_stmt, 0) == SQLITE_BLOB,
+ "Return value is a blob");
+
+ const void* session_blob = ::sqlite3_column_blob(m_stmt, column);
+ const int session_blob_size = ::sqlite3_column_bytes(m_stmt, column);
+
+ BOTAN_ASSERT(session_blob_size >= 0, "Blob size is non-negative");
+
+ return std::make_pair(static_cast<const byte*>(session_blob),
+ static_cast<size_t>(session_blob_size));
+ }
+
+size_t sqlite3_statement::get_size_t(int column)
+ {
+ BOTAN_ASSERT(::sqlite3_column_type(m_stmt, column) == SQLITE_INTEGER,
+ "Return count is an integer");
+
+ const int sessions_int = ::sqlite3_column_int(m_stmt, column);
+
+ BOTAN_ASSERT(sessions_int >= 0, "Expected size_t is non-negative");
+
+ return static_cast<size_t>(sessions_int);
+ }
+
+void sqlite3_statement::spin()
+ {
+ while(step()) {}
+ }
+
+bool sqlite3_statement::step()
+ {
+ return (::sqlite3_step(m_stmt) == SQLITE_ROW);
+ }
+
+sqlite3_statement::~sqlite3_statement()
+ {
+ ::sqlite3_finalize(m_stmt);
+ }
+
+}
diff --git a/src/lib/utils/sqlite3/sqlite3.h b/src/lib/utils/sqlite3/sqlite3.h
new file mode 100644
index 000000000..aef04ab4d
--- /dev/null
+++ b/src/lib/utils/sqlite3/sqlite3.h
@@ -0,0 +1,68 @@
+/*
+* SQLite wrapper
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_UTILS_SQLITE_WRAPPER_H__
+#define BOTAN_UTILS_SQLITE_WRAPPER_H__
+
+#include <botan/types.h>
+#include <string>
+#include <chrono>
+#include <vector>
+
+class sqlite3;
+class sqlite3_stmt;
+
+namespace Botan {
+
+class sqlite3_database
+ {
+ public:
+ sqlite3_database(const std::string& file);
+
+ ~sqlite3_database();
+
+ size_t row_count(const std::string& table_name);
+
+ void create_table(const std::string& table_schema);
+ private:
+ friend class sqlite3_statement;
+
+ sqlite3* m_db;
+ };
+
+class sqlite3_statement
+ {
+ public:
+ sqlite3_statement(sqlite3_database* db,
+ const std::string& base_sql);
+
+ void bind(int column, const std::string& val);
+
+ void bind(int column, int val);
+
+ void bind(int column, std::chrono::system_clock::time_point time);
+
+ void bind(int column, const std::vector<byte>& val);
+
+ std::pair<const byte*, size_t> get_blob(int column);
+
+ size_t get_size_t(int column);
+
+ void spin();
+
+ bool step();
+
+ sqlite3_stmt* stmt() { return m_stmt; }
+
+ ~sqlite3_statement();
+ private:
+ sqlite3_stmt* m_stmt;
+ };
+
+}
+
+#endif
diff --git a/src/lib/utils/stl_util.h b/src/lib/utils/stl_util.h
new file mode 100644
index 000000000..0710d61a5
--- /dev/null
+++ b/src/lib/utils/stl_util.h
@@ -0,0 +1,94 @@
+/*
+* STL Utility Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_STL_UTIL_H__
+#define BOTAN_STL_UTIL_H__
+
+#include <vector>
+#include <string>
+#include <map>
+
+namespace Botan {
+
+inline std::vector<byte> to_byte_vector(const std::string& s)
+ {
+ return std::vector<byte>(reinterpret_cast<const byte*>(&s[0]),
+ reinterpret_cast<const byte*>(&s[s.size()]));
+ }
+
+/*
+* Searching through a std::map
+* @param mapping the map to search
+* @param key is what to look for
+* @param null_result is the value to return if key is not in mapping
+* @return mapping[key] or null_result
+*/
+template<typename K, typename V>
+inline V search_map(const std::map<K, V>& mapping,
+ const K& key,
+ const V& null_result = V())
+ {
+ auto i = mapping.find(key);
+ if(i == mapping.end())
+ return null_result;
+ return i->second;
+ }
+
+template<typename K, typename V, typename R>
+inline R search_map(const std::map<K, V>& mapping, const K& key,
+ const R& null_result, const R& found_result)
+ {
+ auto i = mapping.find(key);
+ if(i == mapping.end())
+ return null_result;
+ return found_result;
+ }
+
+/*
+* Insert a key/value pair into a multimap
+*/
+template<typename K, typename V>
+void multimap_insert(std::multimap<K, V>& multimap,
+ const K& key, const V& value)
+ {
+#if defined(BOTAN_BUILD_COMPILER_IS_SUN_STUDIO)
+ // Work around a strange bug in Sun Studio
+ multimap.insert(std::make_pair<const K, V>(key, value));
+#else
+ multimap.insert(std::make_pair(key, value));
+#endif
+ }
+
+/**
+* Existence check for values
+*/
+template<typename T>
+bool value_exists(const std::vector<T>& vec,
+ const T& val)
+ {
+ for(size_t i = 0; i != vec.size(); ++i)
+ if(vec[i] == val)
+ return true;
+ return false;
+ }
+
+template<typename T, typename Pred>
+void map_remove_if(Pred pred, T& assoc)
+ {
+ auto i = assoc.begin();
+ while(i != assoc.end())
+ {
+ if(pred(i->first))
+ assoc.erase(i++);
+ else
+ i++;
+ }
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/types.h b/src/lib/utils/types.h
new file mode 100644
index 000000000..f4a2eeacd
--- /dev/null
+++ b/src/lib/utils/types.h
@@ -0,0 +1,48 @@
+/*
+* Low Level Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TYPES_H__
+#define BOTAN_TYPES_H__
+
+#include <botan/build.h>
+#include <botan/assert.h>
+#include <cstddef>
+#include <cstdint>
+
+/**
+* The primary namespace for the botan library
+*/
+namespace Botan {
+
+using std::uint8_t;
+using std::uint16_t;
+using std::uint32_t;
+using std::uint64_t;
+using std::size_t;
+
+typedef uint8_t byte;
+typedef uint16_t u16bit;
+typedef uint32_t u32bit;
+typedef uint64_t u64bit;
+
+typedef std::int32_t s32bit;
+
+/**
+* A default buffer size; typically a memory page
+*/
+static const size_t DEFAULT_BUFFERSIZE = BOTAN_DEFAULT_BUFFER_SIZE;
+
+}
+
+namespace Botan_types {
+
+using Botan::byte;
+using Botan::u32bit;
+
+}
+
+#endif
diff --git a/src/lib/utils/version.cpp b/src/lib/utils/version.cpp
new file mode 100644
index 000000000..32679cf63
--- /dev/null
+++ b/src/lib/utils/version.cpp
@@ -0,0 +1,55 @@
+/*
+* Version Information
+* (C) 1999-2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/version.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+ These are intentionally compiled rather than inlined, so an
+ application running against a shared library can test the true
+ version they are running against.
+*/
+
+/*
+* Return the version as a string
+*/
+std::string version_string()
+ {
+#define QUOTE(name) #name
+#define STR(macro) QUOTE(macro)
+
+ /*
+ It is intentional that this string is a compile-time constant;
+ it makes it much easier to find in binaries.
+ */
+
+ return "Botan " STR(BOTAN_VERSION_MAJOR) "."
+ STR(BOTAN_VERSION_MINOR) "."
+ STR(BOTAN_VERSION_PATCH) " ("
+ BOTAN_VERSION_RELEASE_TYPE
+#if (BOTAN_VERSION_DATESTAMP != 0)
+ ", dated " STR(BOTAN_VERSION_DATESTAMP)
+#endif
+ ", revision " BOTAN_VERSION_VC_REVISION
+ ", distribution " BOTAN_DISTRIBUTION_INFO ")";
+
+#undef STR
+#undef QUOTE
+ }
+
+u32bit version_datestamp() { return BOTAN_VERSION_DATESTAMP; }
+
+/*
+* Return parts of the version as integers
+*/
+u32bit version_major() { return BOTAN_VERSION_MAJOR; }
+u32bit version_minor() { return BOTAN_VERSION_MINOR; }
+u32bit version_patch() { return BOTAN_VERSION_PATCH; }
+
+}
diff --git a/src/lib/utils/version.h b/src/lib/utils/version.h
new file mode 100644
index 000000000..219c261a5
--- /dev/null
+++ b/src/lib/utils/version.h
@@ -0,0 +1,72 @@
+/*
+* Version Information
+* (C) 1999-2011 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_VERSION_H__
+#define BOTAN_VERSION_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Get information describing the version
+*/
+
+/**
+* Get a human-readable string identifying the version of Botan.
+* No particular format should be assumed.
+* @return version string
+*/
+BOTAN_DLL std::string version_string();
+
+/**
+* Return the date this version of botan was released, in an integer of
+* the form YYYYMMDD. For instance a version released on May 21, 2013
+* would return the integer 20130521. If the currently running version
+* is not an official release, this function will return 0 instead.
+*
+* @return release date, or zero if unreleased
+*/
+BOTAN_DLL u32bit version_datestamp();
+
+/**
+* Get the major version number.
+* @return major version number
+*/
+BOTAN_DLL u32bit version_major();
+
+/**
+* Get the minor version number.
+* @return minor version number
+*/
+BOTAN_DLL u32bit version_minor();
+
+/**
+* Get the patch number.
+* @return patch number
+*/
+BOTAN_DLL u32bit version_patch();
+
+/*
+* Macros for compile-time version checks
+*/
+#define BOTAN_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c))
+
+/**
+* Compare using BOTAN_VERSION_CODE_FOR, as in
+* # if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,8,0)
+* # error "Botan version too old"
+* # endif
+*/
+#define BOTAN_VERSION_CODE BOTAN_VERSION_CODE_FOR(BOTAN_VERSION_MAJOR, \
+ BOTAN_VERSION_MINOR, \
+ BOTAN_VERSION_PATCH)
+
+}
+
+#endif
diff --git a/src/lib/utils/xor_buf.h b/src/lib/utils/xor_buf.h
new file mode 100644
index 000000000..5773a619c
--- /dev/null
+++ b/src/lib/utils/xor_buf.h
@@ -0,0 +1,113 @@
+/*
+* XOR operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_XOR_BUF_H__
+#define BOTAN_XOR_BUF_H__
+
+#include <botan/types.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
+* @param out the input/output buffer
+* @param in the read-only input buffer
+* @param length the length of the buffers
+*/
+inline void xor_buf(byte out[], const byte in[], size_t length)
+ {
+ while(length >= 8)
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ *reinterpret_cast<u64bit*>(out) ^= *reinterpret_cast<const u64bit*>(in);
+#else
+ out[0] ^= in[0]; out[1] ^= in[1];
+ out[2] ^= in[2]; out[3] ^= in[3];
+ out[4] ^= in[4]; out[5] ^= in[5];
+ out[6] ^= in[6]; out[7] ^= in[7];
+#endif
+
+ out += 8; in += 8; length -= 8;
+ }
+
+ for(size_t i = 0; i != length; ++i)
+ out[i] ^= in[i];
+ }
+
+/**
+* XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length
+* @param out the output buffer
+* @param in the first input buffer
+* @param in2 the second output buffer
+* @param length the length of the three buffers
+*/
+inline void xor_buf(byte out[],
+ const byte in[],
+ const byte in2[],
+ size_t length)
+ {
+ while(length >= 8)
+ {
+#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
+ *reinterpret_cast<u64bit*>(out) =
+ *reinterpret_cast<const u64bit*>(in) ^
+ *reinterpret_cast<const u64bit*>(in2);
+#else
+ out[0] = in[0] ^ in2[0]; out[1] = in[1] ^ in2[1];
+ out[2] = in[2] ^ in2[2]; out[3] = in[3] ^ in2[3];
+ out[4] = in[4] ^ in2[4]; out[5] = in[5] ^ in2[5];
+ out[6] = in[6] ^ in2[6]; out[7] = in[7] ^ in2[7];
+#endif
+
+ in += 8; in2 += 8; out += 8; length -= 8;
+ }
+
+ for(size_t i = 0; i != length; ++i)
+ out[i] = in[i] ^ in2[i];
+ }
+
+template<typename Alloc, typename Alloc2>
+void xor_buf(std::vector<byte, Alloc>& out,
+ const std::vector<byte, Alloc2>& in,
+ size_t n)
+ {
+ xor_buf(&out[0], &in[0], n);
+ }
+
+template<typename Alloc>
+void xor_buf(std::vector<byte, Alloc>& out,
+ const byte* in,
+ size_t n)
+ {
+ xor_buf(&out[0], in, n);
+ }
+
+template<typename Alloc, typename Alloc2>
+void xor_buf(std::vector<byte, Alloc>& out,
+ const byte* in,
+ const std::vector<byte, Alloc2>& in2,
+ size_t n)
+ {
+ xor_buf(&out[0], &in[0], &in2[0], n);
+ }
+
+template<typename T, typename Alloc, typename Alloc2>
+std::vector<T, Alloc>&
+operator^=(std::vector<T, Alloc>& out,
+ const std::vector<T, Alloc2>& in)
+ {
+ if(out.size() < in.size())
+ out.resize(in.size());
+
+ xor_buf(&out[0], &in[0], in.size());
+ return out;
+ }
+
+}
+
+#endif
diff --git a/src/lib/utils/zero_mem.cpp b/src/lib/utils/zero_mem.cpp
new file mode 100644
index 000000000..e812ced0c
--- /dev/null
+++ b/src/lib/utils/zero_mem.cpp
@@ -0,0 +1,20 @@
+/*
+* Zero Memory
+* (C) 2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+void zero_mem(void* ptr, size_t n)
+ {
+ volatile byte* p = reinterpret_cast<volatile byte*>(ptr);
+
+ for(size_t i = 0; i != n; ++i)
+ p[i] = 0;
+ }
+
+}