aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--checks/aead.vec8
-rw-r--r--checks/bench.h2
-rw-r--r--checks/ecdh.cpp2
-rw-r--r--checks/ecdsa.cpp2
-rw-r--r--checks/ocb.cpp27
-rw-r--r--checks/tests.cpp12
-rw-r--r--checks/tls.cpp9
-rw-r--r--checks/transform.cpp83
-rw-r--r--checks/transform.vec12
-rw-r--r--checks/validate.cpp1
-rw-r--r--checks/validate.h1
-rwxr-xr-xconfigure.py37
-rw-r--r--doc/aead.rst6
-rw-r--r--doc/examples/cpuid.cpp7
-rw-r--r--doc/relnotes/1_11_6.rst3
-rw-r--r--src/algo_base/info.txt2
-rw-r--r--src/algo_base/transform.h6
-rw-r--r--src/benchmark/benchmark.cpp4
-rw-r--r--src/benchmark/benchmark.h3
-rw-r--r--src/block/threefish/info.txt1
-rw-r--r--src/block/threefish/threefish.cpp164
-rw-r--r--src/block/threefish/threefish.h52
-rw-r--r--src/build-data/cc/clang.txt12
-rw-r--r--src/build-data/cc/gcc.txt7
-rw-r--r--src/build-data/makefile/unix.in4
-rw-r--r--src/build-data/makefile/unix_shr.in4
-rwxr-xr-xsrc/build-data/scripts/dist.py44
-rw-r--r--src/cert/x509/info.txt4
-rw-r--r--src/engine/simd_engine/simd_engine.cpp2
-rw-r--r--src/filters/transform_filter.cpp2
-rw-r--r--src/hash/bmw_512/bmw_512.cpp6
-rw-r--r--src/libstate/info.txt4
-rw-r--r--src/modes/aead/aead.h2
-rw-r--r--src/modes/aead/ccm/ccm.cpp2
-rw-r--r--src/modes/aead/ccm/ccm.h2
-rw-r--r--src/modes/cbc/cbc.cpp2
-rw-r--r--src/modes/cbc/cbc.h2
-rw-r--r--src/modes/cfb/cfb.cpp2
-rw-r--r--src/modes/cfb/cfb.h2
-rw-r--r--src/modes/ecb/ecb.cpp2
-rw-r--r--src/modes/ecb/ecb.h2
-rw-r--r--src/modes/xts/xts.cpp2
-rw-r--r--src/modes/xts/xts.h2
-rw-r--r--src/simd/simd_32.h2
-rw-r--r--src/simd/simd_scalar/simd_scalar.h129
-rw-r--r--src/tls/tls_policy.cpp22
-rw-r--r--src/tls/tls_policy.h3
-rw-r--r--src/utils/assert.h5
-rw-r--r--src/utils/cpuid.cpp146
-rw-r--r--src/utils/cpuid.h53
-rw-r--r--src/utils/http_util/info.txt4
-rw-r--r--src/utils/info.txt11
-rw-r--r--src/utils/parsing.h16
-rw-r--r--src/utils/read_cfg.cpp115
54 files changed, 800 insertions, 261 deletions
diff --git a/checks/aead.vec b/checks/aead.vec
index 4d9f39556..bc75ca489 100644
--- a/checks/aead.vec
+++ b/checks/aead.vec
@@ -1,3 +1,4 @@
+
AEAD = AES-128/SIV
Plaintext = 112233445566778899AABBCCDDEE
Key = FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
@@ -10,3 +11,10 @@ Key = 7F7E7D7C7B7A79787776757473727170404142434445464748494A4B4C4D4E4F
AD = 00112233445566778899AABBCCDDEEFFDEADDADADEADDADAFFEEDDCCBBAA99887766554433221100
Nonce = 09F911029D74E35BD84156C5635688C1
Ciphertext = E21A9D0FE3BD3ED189C71F29B24C39E1E40B9BAB82D428D0A9B392F13EA14C9B4433F393595A8E031F032350F50D2B21825B3EE64958103BD8445C3F48E5CF
+
+AEAD = AES-128/OCB
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627
+AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627
+Nonce = 000102030405060708090A0B
+Key = 000102030405060708090A0B0C0D0E0F
+Ciphertext = BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A657149D53773463CB68C65778B058A635659C623211DEEA0DE30D2C381879F4C8
diff --git a/checks/bench.h b/checks/bench.h
index b423a2215..3840bc112 100644
--- a/checks/bench.h
+++ b/checks/bench.h
@@ -17,4 +17,6 @@ bool bench_algo(const std::string& algo_name,
void bench_pk(Botan::RandomNumberGenerator&,
const std::string&, double seconds);
+void time_transform(const std::string& algo);
+
#endif
diff --git a/checks/ecdh.cpp b/checks/ecdh.cpp
index 841bce55b..178282047 100644
--- a/checks/ecdh.cpp
+++ b/checks/ecdh.cpp
@@ -12,7 +12,7 @@
#include "validate.h"
#include "common.h"
-#if defined(BOTAN_HAS_ECDH)
+#if defined(BOTAN_HAS_ECDH) && defined(BOTAN_HAS_X509)
#include <iostream>
#include <fstream>
diff --git a/checks/ecdsa.cpp b/checks/ecdsa.cpp
index a43de69c5..2506e1389 100644
--- a/checks/ecdsa.cpp
+++ b/checks/ecdsa.cpp
@@ -8,7 +8,7 @@
#include "validate.h"
-#if defined(BOTAN_HAS_ECDSA)
+#if defined(BOTAN_HAS_ECDSA) && defined(BOTAN_HAS_X509)
#include <botan/botan.h>
#include <botan/pubkey.h>
diff --git a/checks/ocb.cpp b/checks/ocb.cpp
index d2fbbeeb3..3cb9c4c09 100644
--- a/checks/ocb.cpp
+++ b/checks/ocb.cpp
@@ -126,33 +126,6 @@ void test_ocb_long(size_t taglen, const std::string &expected)
void test_ocb()
{
- SymmetricKey key("000102030405060708090A0B0C0D0E0F");
-
- std::vector<byte> nonce = hex_decode("000102030405060708090A0B");
-
- std::vector<byte> pt = hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627");
- std::vector<byte> ad = hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627");
-
- const std::string expected = "BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A657149D53773463CB68C65778B058A635659C623211DEEA0DE30D2C381879F4C8";
-
- std::vector<byte> ctext = ocb_encrypt(key, nonce, pt, ad);
-
- const std::string ctext_hex = hex_encode(ctext);
-
- if(ctext_hex != expected)
- std::cout << "OCB/AES-128 encrypt test failure\n" << ctext_hex << " !=\n" << expected << "\n";
-
- try
- {
- std::vector<byte> dec = ocb_decrypt(key, nonce, ctext, ad);
-
- if(dec != pt) std::cout << "OCB fails to decrypt\n";
- }
- catch(std::exception& e)
- {
- std::cout << "Correct OCB message rejected - " << e.what() << "\n";
- }
-
test_ocb_long(128, "B2B41CBF9B05037DA7F16C24A35C1C94");
test_ocb_long(96, "1A4F0654277709A5BDA0D380");
test_ocb_long(64, "B7ECE9D381FE437F");
diff --git a/checks/tests.cpp b/checks/tests.cpp
index fdaccd805..db934735e 100644
--- a/checks/tests.cpp
+++ b/checks/tests.cpp
@@ -31,10 +31,16 @@ void run_tests_bb(std::istream& src,
if(key == output_key)
{
++test_cnt;
- bool passed = cb(vars);
-
- if(!passed)
+ try
+ {
+ if(!cb(vars))
+ ++test_fail;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << "\n";
++test_fail;
+ }
if(clear_between_cb)
vars.clear();
diff --git a/checks/tls.cpp b/checks/tls.cpp
index 55236515d..c0b85cc7e 100644
--- a/checks/tls.cpp
+++ b/checks/tls.cpp
@@ -1,3 +1,7 @@
+#include "validate.h"
+
+#if defined(BOTAN_HAS_TLS)
+
#include <botan/tls_server.h>
#include <botan/tls_client.h>
#include <botan/pkcs10.h>
@@ -6,7 +10,6 @@
#include <botan/x509_ca.h>
#include <botan/hex.h>
-#include "validate.h"
#include <iostream>
#include <vector>
#include <memory>
@@ -268,3 +271,7 @@ size_t do_tls_tests(RandomNumberGenerator& rng)
return errors;
}
+
+#else
+size_t do_tls_tests(RandomNumberGenerator&) { return 0; }
+#endif
diff --git a/checks/transform.cpp b/checks/transform.cpp
new file mode 100644
index 000000000..71ecc35e7
--- /dev/null
+++ b/checks/transform.cpp
@@ -0,0 +1,83 @@
+#include "validate.h"
+#include "bench.h"
+
+#include <botan/libstate.h>
+#include <botan/botan.h>
+#include <botan/threefish.h>
+#include <botan/benchmark.h>
+#include <botan/hex.h>
+#include <iostream>
+#include <fstream>
+
+using namespace Botan;
+
+namespace {
+
+Transformation* get_transform(const std::string& algo)
+ {
+ if(algo == "Threefish-512")
+ return new Threefish_512;
+
+ throw std::runtime_error("Unknown transform " + algo);
+ }
+
+secure_vector<byte> transform_test(const std::string& algo,
+ const secure_vector<byte>& nonce,
+ const secure_vector<byte>& key,
+ const secure_vector<byte>& in)
+ {
+ std::unique_ptr<Transformation> transform(get_transform(algo));
+
+ transform->set_key(key);
+ transform->start_vec(nonce);
+
+ secure_vector<byte> out = in;
+ transform->update(out, 0);
+
+ return out;
+ }
+
+}
+
+void test_transform()
+ {
+ std::ifstream vec("checks/transform.vec");
+
+ run_tests(vec, "Transform", "Output", true,
+ [](std::map<std::string, std::string> m)
+ {
+ return hex_encode(transform_test(m["Transform"],
+ hex_decode_locked(m["Nonce"]),
+ hex_decode_locked(m["Key"]),
+ hex_decode_locked(m["Input"])));
+ });
+
+ //time_transform("Threefish-512");
+ }
+
+void time_transform(const std::string& algo)
+ {
+ std::unique_ptr<Transformation> tf(get_transform(algo));
+
+ AutoSeeded_RNG rng;
+
+ tf->set_key(rng.random_vec(tf->maximum_keylength()));
+ tf->start_vec(rng.random_vec(tf->default_nonce_length()));
+
+ for(size_t mult : { 1, 2, 4, 8, 16, 128 })
+ {
+ const size_t buf_size = mult*tf->update_granularity();
+
+ secure_vector<byte> buffer(buf_size);
+
+ double res = time_op(std::chrono::seconds(1),
+ [&tf,&buffer,buf_size]{
+ tf->update(buffer);
+ buffer.resize(buf_size);
+ });
+
+ const u64bit Mbytes = (res * buf_size) / 1024 / 1024;
+
+ std::cout << Mbytes << " MiB / second in " << buf_size << " byte blocks\n";
+ }
+ }
diff --git a/checks/transform.vec b/checks/transform.vec
new file mode 100644
index 000000000..8f8a155e0
--- /dev/null
+++ b/checks/transform.vec
@@ -0,0 +1,12 @@
+
+Transform = Threefish-512
+Input = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Key = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Nonce = 00000000000000000000000000000000
+Output = B1A2BBC6EF6025BC40EB3822161F36E375D1BB0AEE3186FBD19E47C5D479947B7BC2F8586E35F0CFF7E7F03084B0B7B1F1AB3961A580A3E97EB41EA14A6D7BBE
+
+Transform = Threefish-512
+Input = FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0
+Nonce = 000102030405060708090A0B0C0D0E0F
+Key = 101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F
+Output = E304439626D45A2CB401CAD8D636249A6338330EB06D45DD8B36B90E97254779272A0A8D99463504784420EA18C9A725AF11DFFEA10162348927673D5C1CAF3D
diff --git a/checks/validate.cpp b/checks/validate.cpp
index 48932f0e4..866f414eb 100644
--- a/checks/validate.cpp
+++ b/checks/validate.cpp
@@ -418,6 +418,7 @@ u32bit do_validation_tests(const std::string& filename,
if(should_pass)
{
+ test_transform();
test_ocb();
test_hkdf();
test_pbkdf();
diff --git a/checks/validate.h b/checks/validate.h
index 48830619b..bb4114c3f 100644
--- a/checks/validate.h
+++ b/checks/validate.h
@@ -39,6 +39,7 @@ void test_hkdf();
void test_pbkdf();
void test_kdf();
void test_aead();
+void test_transform();
void run_tests_bb(std::istream& src,
const std::string& name_key,
diff --git a/configure.py b/configure.py
index 211b59547..607471e27 100755
--- a/configure.py
+++ b/configure.py
@@ -229,8 +229,11 @@ def process_command_line(args):
metavar='BINARY',
help='set the name of the compiler binary')
- target_group.add_option('--chost', dest='chost',
- help=optparse.SUPPRESS_HELP)
+ target_group.add_option('--cc-abi-flags', metavar='FLAG',
+ help='set compiler ABI flags',
+ default='')
+
+ target_group.add_option('--chost', help=optparse.SUPPRESS_HELP)
target_group.add_option('--with-endian', metavar='ORDER', default=None,
help='override guess of CPU byte order')
@@ -811,21 +814,23 @@ class CompilerInfo(object):
"""
Return the machine specific ABI flags
"""
- def mach_abi_link_flags(self, osname, arch, submodel, debug_p):
-
+ def mach_abi_link_flags(self, options):
def all():
- if debug_p:
+ if options.debug_build:
return 'all-debug'
return 'all'
abi_link = set()
- for what in [all(), osname, arch, submodel]:
+ for what in [all(), options.os, options.arch, options.cpu]:
if self.mach_abi_linking.get(what) != None:
abi_link.add(self.mach_abi_linking.get(what))
+ for flag in options.cc_abi_flags.split(' '):
+ abi_link.add(flag)
+
if len(abi_link) == 0:
return ''
- return ' ' + ' '.join(abi_link)
+ return ' ' + ' '.join(sorted(list(abi_link)))
"""
@@ -1048,6 +1053,9 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
for mod in modules:
if src in mod.sources():
if mod.need_isa != None:
+ if mod.need_isa not in cc.isa_flags:
+ raise Exception('Compiler does not support %s, required by %s' % (
+ mod.need_isa, src))
return cc.isa_flags[mod.need_isa]
return ''
@@ -1056,12 +1064,12 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
"""
def build_commands(sources, obj_dir, flags):
for (obj_file,src) in zip(objectfile_list(sources, obj_dir), sources):
- yield '%s: %s\n\t$(CXX) %s%s $(%s_FLAGS) %s %s$? %s$@\n' % (
+ yield '%s: %s\n\t$(CXX) %s $(%s_FLAGS) %s%s %s$? %s$@\n' % (
obj_file, src,
+ isa_specific_flags(cc, src),
+ flags,
cc.add_include_dir_option,
build_config.include_dir,
- flags,
- isa_specific_flags(cc, src),
cc.compile_option,
cc.output_to_option)
@@ -1079,8 +1087,9 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
maintainer_flags,
maintainer_mode):
if maintainer_mode and maintainer_flags != '':
- return maintainer_flags
- return normal_flags
+ return maintainer_flags + ' ' + normal_flags
+ else:
+ return normal_flags
def innosetup_arch(os, arch):
if os != 'windows':
@@ -1139,9 +1148,7 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
'mp_bits': choose_mp_bits(),
- 'cc': (options.compiler_binary or cc.binary_name) +
- cc.mach_abi_link_flags(options.os, options.arch,
- options.cpu, options.debug_build),
+ 'cc': (options.compiler_binary or cc.binary_name) + cc.mach_abi_link_flags(options),
'lib_opt': cc.library_opt_flags(options),
'check_opt': '' if options.no_optimizations else cc.check_opt_flags,
diff --git a/doc/aead.rst b/doc/aead.rst
index cb49f8a51..dbd06bbe1 100644
--- a/doc/aead.rst
+++ b/doc/aead.rst
@@ -81,3 +81,9 @@ AEAD modes currently available include GCM, OCB, and EAX. All three use a
Returns true if *nonce_len* is a valid nonce length for this scheme. For
EAX and GCM, any length nonces are allowed. OCB allows any value between
8 and 15 bytes.
+
+ .. cpp:function:: size_t default_nonce_length() const
+
+ Returns a reasonable length for the nonce, typically either 96
+ bits, or the only supported length for modes which don't
+ support 96 bit nonces.
diff --git a/doc/examples/cpuid.cpp b/doc/examples/cpuid.cpp
index ac3f50580..9ffb810a9 100644
--- a/doc/examples/cpuid.cpp
+++ b/doc/examples/cpuid.cpp
@@ -35,12 +35,15 @@ int main()
print_if_feature("SSSE3", CPUID::has_ssse3());
print_if_feature("SSE4.1", CPUID::has_sse41());
print_if_feature("SSE4.2", CPUID::has_sse42());
- print_if_feature("AVX", CPUID::has_avx());
+ print_if_feature("AVX2", CPUID::has_avx2());
+ print_if_feature("BMI2", CPUID::has_bmi2());
print_if_feature("AltiVec", CPUID::has_altivec());
print_header("Other extensions");
print_if_feature("RDTSC", CPUID::has_rdtsc());
print_if_feature("PCMUL", CPUID::has_pcmuludq());
print_if_feature("AES-NI", CPUID::has_aes_ni());
- print_if_feature("RDRND", CPUID::has_rdrand());
+ print_if_feature("RDRAND", CPUID::has_rdrand());
+ print_if_feature("RDSEED", CPUID::has_rdseed());
+ print_if_feature("SHA", CPUID::has_intel_sha());
}
diff --git a/doc/relnotes/1_11_6.rst b/doc/relnotes/1_11_6.rst
index 79b2dca2e..434d8c499 100644
--- a/doc/relnotes/1_11_6.rst
+++ b/doc/relnotes/1_11_6.rst
@@ -8,7 +8,8 @@ Version 1.11.6, Not Yet Released
* Botan now requires Boost, specifically the filesystem and asio libraries.
- * The default TLS policy no longer includes RC4 in the cipher list.
+ * The default TLS policy no longer includes RC4 in the cipher list, and
+ refuses to negotation SSLv3 by default.
* Add HKDF from :rfc:`5869`
diff --git a/src/algo_base/info.txt b/src/algo_base/info.txt
index cfdd9b691..a2c509f2c 100644
--- a/src/algo_base/info.txt
+++ b/src/algo_base/info.txt
@@ -1,3 +1,5 @@
+define TRANSFORM 20131209
+
<requires>
alloc
filters
diff --git a/src/algo_base/transform.h b/src/algo_base/transform.h
index 3f4e80b94..2eec9d85b 100644
--- a/src/algo_base/transform.h
+++ b/src/algo_base/transform.h
@@ -72,7 +72,11 @@ class BOTAN_DLL Transformation : public SymmetricAlgorithm
/**
* Return the default size for a nonce
*/
- virtual size_t default_nonce_size() const = 0;
+ virtual size_t default_nonce_length() const = 0;
+
+ BOTAN_DEPRECATED("Use default_nonce_length")
+ size_t default_nonce_size() const
+ { return default_nonce_length(); }
/**
* Return true iff nonce_len is a valid length for the nonce
diff --git a/src/benchmark/benchmark.cpp b/src/benchmark/benchmark.cpp
index 83fd87d1b..396670168 100644
--- a/src/benchmark/benchmark.cpp
+++ b/src/benchmark/benchmark.cpp
@@ -18,8 +18,6 @@
namespace Botan {
-namespace {
-
double time_op(std::chrono::nanoseconds runtime, std::function<void ()> op)
{
std::chrono::nanoseconds time_used(0);
@@ -41,8 +39,6 @@ double time_op(std::chrono::nanoseconds runtime, std::function<void ()> op)
return reps / seconds_used; // ie, return ops per second
}
-}
-
std::map<std::string, double>
time_algorithm_ops(const std::string& name,
Algorithm_Factory& af,
diff --git a/src/benchmark/benchmark.h b/src/benchmark/benchmark.h
index 93224dd2e..40784a767 100644
--- a/src/benchmark/benchmark.h
+++ b/src/benchmark/benchmark.h
@@ -50,6 +50,9 @@ BOTAN_DLL algorithm_benchmark(const std::string& name,
std::chrono::milliseconds milliseconds,
size_t buf_size);
+double BOTAN_DLL
+time_op(std::chrono::nanoseconds runtime, std::function<void ()> op);
+
}
#endif
diff --git a/src/block/threefish/info.txt b/src/block/threefish/info.txt
new file mode 100644
index 000000000..91fc7bfb1
--- /dev/null
+++ b/src/block/threefish/info.txt
@@ -0,0 +1 @@
+define THREEFISH 20131209
diff --git a/src/block/threefish/threefish.cpp b/src/block/threefish/threefish.cpp
new file mode 100644
index 000000000..6fb65a37e
--- /dev/null
+++ b/src/block/threefish/threefish.cpp
@@ -0,0 +1,164 @@
+/*
+* Threefish-512
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/threefish.h>
+#include <botan/rotate.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+secure_vector<byte> Threefish_512::start(const byte tweak[], size_t tweak_len)
+ {
+ if(!valid_nonce_length(tweak_len))
+ throw Invalid_IV_Length(name(), tweak_len);
+
+ m_T.resize(3);
+
+ m_T[0] = load_le<u64bit>(tweak, 0);
+ m_T[1] = load_le<u64bit>(tweak, 1);
+ m_T[2] = m_T[0] ^ m_T[1];
+
+ return secure_vector<byte>();
+ }
+
+void Threefish_512::update(secure_vector<byte>& blocks, size_t offset)
+ {
+ byte* buf = &blocks[offset];
+ size_t sz = blocks.size() - offset;
+
+ BOTAN_ASSERT(sz % update_granularity() == 0, "Block sized input");
+
+ BOTAN_ASSERT(m_T.size() == 3, "Tweak was set");
+
+#define THREEFISH_ROUND(I1,I2,I3,I4,I5,I6,I7,I8,ROT1,ROT2,ROT3,ROT4) \
+ do { \
+ X##I1 += X##I2; X##I2 = rotate_left(X##I2, ROT1) ^ X##I1; \
+ X##I3 += X##I4; X##I4 = rotate_left(X##I4, ROT2) ^ X##I3; \
+ X##I5 += X##I6; X##I6 = rotate_left(X##I6, ROT3) ^ X##I5; \
+ X##I7 += X##I8; X##I8 = rotate_left(X##I8, ROT4) ^ X##I7; \
+ } while(0)
+
+#define THREEFISH_INJECT_KEY(r) \
+ do { \
+ X0 += m_K[(r ) % 9]; \
+ X1 += m_K[(r+1) % 9]; \
+ X2 += m_K[(r+2) % 9]; \
+ X3 += m_K[(r+3) % 9]; \
+ X4 += m_K[(r+4) % 9]; \
+ X5 += m_K[(r+5) % 9] + m_T[(r ) % 3]; \
+ X6 += m_K[(r+6) % 9] + m_T[(r+1) % 3]; \
+ X7 += m_K[(r+7) % 9] + (r); \
+ } while(0)
+
+#define THREEFISH_8_ROUNDS(R1,R2) \
+ do { \
+ THREEFISH_ROUND(0,1,2,3,4,5,6,7, 46,36,19,37); \
+ THREEFISH_ROUND(2,1,4,7,6,5,0,3, 33,27,14,42); \
+ THREEFISH_ROUND(4,1,6,3,0,5,2,7, 17,49,36,39); \
+ THREEFISH_ROUND(6,1,0,7,2,5,4,3, 44, 9,54,56); \
+ \
+ THREEFISH_INJECT_KEY(R1); \
+ \
+ THREEFISH_ROUND(0,1,2,3,4,5,6,7, 39,30,34,24); \
+ THREEFISH_ROUND(2,1,4,7,6,5,0,3, 13,50,10,17); \
+ THREEFISH_ROUND(4,1,6,3,0,5,2,7, 25,29,39,43); \
+ THREEFISH_ROUND(6,1,0,7,2,5,4,3, 8,35,56,22); \
+ \
+ THREEFISH_INJECT_KEY(R2); \
+ } while(0)
+
+ while(sz)
+ {
+ u64bit X0 = load_le<u64bit>(buf, 0);
+ u64bit X1 = load_le<u64bit>(buf, 1);
+ u64bit X2 = load_le<u64bit>(buf, 2);
+ u64bit X3 = load_le<u64bit>(buf, 3);
+ u64bit X4 = load_le<u64bit>(buf, 4);
+ u64bit X5 = load_le<u64bit>(buf, 5);
+ u64bit X6 = load_le<u64bit>(buf, 6);
+ u64bit X7 = load_le<u64bit>(buf, 7);
+
+ THREEFISH_INJECT_KEY(0);
+
+ THREEFISH_8_ROUNDS(1,2);
+ THREEFISH_8_ROUNDS(3,4);
+ THREEFISH_8_ROUNDS(5,6);
+ THREEFISH_8_ROUNDS(7,8);
+ THREEFISH_8_ROUNDS(9,10);
+ THREEFISH_8_ROUNDS(11,12);
+ THREEFISH_8_ROUNDS(13,14);
+ THREEFISH_8_ROUNDS(15,16);
+ THREEFISH_8_ROUNDS(17,18);
+
+ store_le(buf, X0, X1, X2, X3, X4, X5, X6, X7);
+
+ buf += 64;
+ sz -= 64;
+ }
+
+#undef THREEFISH_8_ROUNDS
+#undef THREEFISH_INJECT_KEY
+#undef THREEFISH_ROUND
+ }
+
+Key_Length_Specification Threefish_512::key_spec() const
+ {
+ return Key_Length_Specification(64);
+ }
+
+void Threefish_512::key_schedule(const byte key[], size_t)
+ {
+ // todo: define key schedule for smaller keys
+ m_K.resize(9);
+
+ for(size_t i = 0; i != 8; ++i)
+ m_K[i] = load_le<u64bit>(key, i);
+
+ m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
+ m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
+ }
+
+void Threefish_512::finish(secure_vector<byte>& blocks, size_t offset)
+ {
+ update(blocks, offset);
+ m_T.clear();
+ }
+
+size_t Threefish_512::output_length(size_t input_length) const
+ {
+ if(input_length % update_granularity() == 0)
+ throw std::invalid_argument("Threefish - invalid input length " + std::to_string(input_length));
+
+ return input_length;
+ }
+
+size_t Threefish_512::update_granularity() const
+ {
+ return 64; // single block
+ }
+
+size_t Threefish_512::minimum_final_size() const
+ {
+ return 0;
+ }
+
+size_t Threefish_512::default_nonce_length() const
+ {
+ return 16;
+ }
+
+bool Threefish_512::valid_nonce_length(size_t nonce_len) const
+ {
+ return default_nonce_length() == nonce_len;
+ }
+
+void Threefish_512::clear()
+ {
+ zeroise(m_K);
+ }
+
+}
diff --git a/src/block/threefish/threefish.h b/src/block/threefish/threefish.h
new file mode 100644
index 000000000..b7806a93d
--- /dev/null
+++ b/src/block/threefish/threefish.h
@@ -0,0 +1,52 @@
+/*
+* Threefish
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_THREEFISH_H__
+#define BOTAN_THREEFISH_H__
+
+#include <botan/transform.h>
+
+namespace Botan {
+
+/**
+* Threefish-512
+*/
+class BOTAN_DLL Threefish_512 : public Transformation
+ {
+ public:
+ secure_vector<byte> start(const byte tweak[], size_t tweak_len) override;
+
+ void update(secure_vector<byte>& blocks, size_t offset) override;
+
+ void finish(secure_vector<byte>& final_block, size_t offset) override;
+
+ size_t output_length(size_t input_length) const override;
+
+ size_t update_granularity() const override;
+
+ size_t minimum_final_size() const override;
+
+ size_t default_nonce_length() const override;
+
+ bool valid_nonce_length(size_t nonce_len) const override;
+
+ Key_Length_Specification key_spec() const override;
+
+ std::string name() const { return "Threefish-512"; }
+
+ void clear();
+
+ private:
+ void key_schedule(const byte key[], size_t key_len) override;
+
+ secure_vector<u64bit> m_T;
+ secure_vector<u64bit> m_K;
+ };
+
+}
+
+#endif
diff --git a/src/build-data/cc/clang.txt b/src/build-data/cc/clang.txt
index 0af44768b..163e64272 100644
--- a/src/build-data/cc/clang.txt
+++ b/src/build-data/cc/clang.txt
@@ -30,9 +30,14 @@ darwin -> "$(CXX) -dynamiclib -fPIC -install_name $(LIBDIR)/$(SONAME)"
</so_link_flags>
<isa_flags>
+"sse2" -> "-msse2"
+"ssse3" -> "-mssse3"
+"sse4.1" -> "-msse4.1"
+"sse4.2" -> "-msse4.2"
+"avx" -> "-mavx"
"aes-ni" -> "-maes"
-"ssse3" -> "-mssse3"
-"sse2" -> "-msse2"
+"avx2" -> "-mavx2"
+"bmi2" -> "-mbmi2"
</isa_flags>
<mach_opt>
@@ -43,7 +48,8 @@ ivybridge -> "-march=core-avx-i"
</mach_opt>
<mach_abi_linking>
-all -> "-stdlib=libc++ -pthread"
+#all -> "-stdlib=libc++ -pthread"
+all -> "-stdlib=libstdc++ -pthread"
x86_64 -> "-m64"
ppc64 -> "-m64"
diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt
index ed425ca84..52d5020e2 100644
--- a/src/build-data/cc/gcc.txt
+++ b/src/build-data/cc/gcc.txt
@@ -8,8 +8,9 @@ add_include_dir_option -I
add_lib_dir_option -L
add_lib_option -l
-lang_flags "-D_REENTRANT -std=c++11"
-warning_flags "-Werror -Wno-error=old-style-cast -Wno-error=zero-as-null-pointer-constant -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast -Wzero-as-null-pointer-constant"
+lang_flags "-std=c++11 -D_REENTRANT -fstack-protector"
+maintainer_warning_flags "-Werror -Wno-error=old-style-cast -Wno-error=zero-as-null-pointer-constant"
+warning_flags "-Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast -Wzero-as-null-pointer-constant"
lib_opt_flags "-O3"
check_opt_flags "-O2"
@@ -43,6 +44,8 @@ solaris -> "$(CXX) -shared -fPIC -Wl,-h,$(SONAME)"
"sse4.2" -> "-msse4.2"
"avx" -> "-mavx"
"aes-ni" -> "-maes"
+"avx2" -> "-mavx2"
+"bmi2" -> "-mbmi2"
</isa_flags>
<mach_opt>
diff --git a/src/build-data/makefile/unix.in b/src/build-data/makefile/unix.in
index 0b6afe0c3..fbc45a681 100644
--- a/src/build-data/makefile/unix.in
+++ b/src/build-data/makefile/unix.in
@@ -6,8 +6,8 @@ LANG_FLAGS = %{lang_flags}
WARN_FLAGS = %{warn_flags}
LINK_TO = %{link_to}
-LIB_FLAGS = $(LIB_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
-CHECK_FLAGS = $(CHECK_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
+LIB_FLAGS = $(LANG_FLAGS) $(LIB_OPT) $(WARN_FLAGS)
+CHECK_FLAGS = $(LANG_FLAGS) $(CHECK_OPT) $(WARN_FLAGS)
# Version Numbers
VERSION = %{version}
diff --git a/src/build-data/makefile/unix_shr.in b/src/build-data/makefile/unix_shr.in
index 806969a00..c412a94fd 100644
--- a/src/build-data/makefile/unix_shr.in
+++ b/src/build-data/makefile/unix_shr.in
@@ -8,8 +8,8 @@ SO_OBJ_FLAGS = %{shared_flags}
SO_LINK_CMD = %{so_link}
LINK_TO = %{link_to}
-LIB_FLAGS = $(LIB_OPT) $(LANG_FLAGS) $(WARN_FLAGS) $(SO_OBJ_FLAGS)
-CHECK_FLAGS = $(CHECK_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
+LIB_FLAGS = $(SO_OBJ_FLAGS) $(LANG_FLAGS) $(LIB_OPT) $(WARN_FLAGS)
+CHECK_FLAGS = $(LANG_FLAGS) $(CHECK_OPT) $(WARN_FLAGS)
# Version Numbers
VERSION = %{version}
diff --git a/src/build-data/scripts/dist.py b/src/build-data/scripts/dist.py
index 316057d22..4271492f8 100755
--- a/src/build-data/scripts/dist.py
+++ b/src/build-data/scripts/dist.py
@@ -19,6 +19,7 @@ import subprocess
import sys
import tarfile
import datetime
+import hashlib
def check_subprocess_results(subproc, name):
(stdout, stderr) = subproc.communicate()
@@ -90,14 +91,18 @@ def datestamp(db, rev_id):
logging.info('Could not retreive date for %s' % (rev_id))
return 0
-def gpg_sign(keyid, passphrase_file, files):
+def gpg_sign(keyid, passphrase_file, files, detached = True):
+
+ options = ['--armor', '--detach-sign'] if detached else ['--clearsign']
+
+ gpg_cmd = ['gpg', '--batch'] + options + ['--local-user', keyid]
+ if passphrase_file != None:
+ gpg_cmd[1:1] = ['--passphrase-file', passphrase_file]
+
for filename in files:
logging.info('Signing %s using PGP id %s' % (filename, keyid))
- cmd = ['gpg', '--batch', '--armor', '--detach-sign', '--local-user', keyid, filename]
-
- if passphrase_file != None:
- cmd[1:1] = ['--passphrase-file', passphrase_file]
+ cmd = gpg_cmd + [filename]
logging.debug('Running %s' % (' '.join(cmd)))
@@ -137,12 +142,15 @@ def parse_args(args):
parser.add_option('--pgp-key-id', metavar='KEYID',
default='EFBADFBC',
- help='PGP signing key (default %default)')
+ help='PGP signing key (default %default, "none" to disable)')
parser.add_option('--pgp-passphrase-file', metavar='FILE',
default=None,
help='PGP signing key passphrase file')
+ parser.add_option('--write-hash-file', metavar='FILE', default=None,
+ help='Write a file with checksums')
+
return parser.parse_args(args)
def remove_file_if_exists(fspath):
@@ -238,6 +246,8 @@ def main(args = None):
output_basename = output_name(args)
+ logging.debug('Output basename %s' % (output_basename))
+
if os.access(output_basename, os.X_OK):
logging.info('Removing existing output dir %s' % (output_basename))
shutil.rmtree(output_basename)
@@ -285,6 +295,10 @@ def main(args = None):
archives = options.archive_types.split(',') if options.archive_types != '' else []
+ hash_file = None
+ if options.write_hash_file != None:
+ hash_file = open(options.write_hash_file, 'w')
+
for archive in archives:
logging.debug('Writing archive type "%s"' % (archive))
@@ -304,19 +318,31 @@ def main(args = None):
archive = tarfile.open(output_archive, write_mode())
archive.add(output_basename)
archive.close()
+
+ if hash_file != None:
+ sha256 = hashlib.new('sha256')
+ sha256.update(open(output_archive).read())
+ hash_file.write("%s %s\n" % (sha256.hexdigest(), output_archive))
else:
raise Exception('Unknown archive type "%s"' % (archive))
output_files.append(output_archive)
+ hash_file.close()
+
shutil.rmtree(output_basename)
if options.print_output_names:
for output_file in output_files:
- print output_file
+ print(output_file)
- if options.pgp_key_id != '':
- output_files += gpg_sign(options.pgp_key_id, options.pgp_passphrase_file, output_files)
+ if options.pgp_key_id != 'none':
+ if options.write_hash_file != None:
+ output_files += gpg_sign(options.pgp_key_id, options.pgp_passphrase_file,
+ [options.write_hash_file], False)
+ else:
+ output_files += gpg_sign(options.pgp_key_id, options.pgp_passphrase_file,
+ output_files, True)
if options.output_dir != '.':
for output_file in output_files:
diff --git a/src/cert/x509/info.txt b/src/cert/x509/info.txt
index ef3043e9e..a74fd6631 100644
--- a/src/cert/x509/info.txt
+++ b/src/cert/x509/info.txt
@@ -5,3 +5,7 @@ define OCSP 20131128
datastor
http_util
</requires>
+
+<libs>
+all -> boost_filesystem
+</libs>
diff --git a/src/engine/simd_engine/simd_engine.cpp b/src/engine/simd_engine/simd_engine.cpp
index 70529f1fd..3f4e2b7aa 100644
--- a/src/engine/simd_engine/simd_engine.cpp
+++ b/src/engine/simd_engine/simd_engine.cpp
@@ -80,6 +80,8 @@ SIMD_Engine::find_hash(const SCAN_Name& request,
return new SHA_160_SSE2;
#endif
+ BOTAN_UNUSED(request);
+
return nullptr;
}
diff --git a/src/filters/transform_filter.cpp b/src/filters/transform_filter.cpp
index e8033b1a8..2f25aa2c5 100644
--- a/src/filters/transform_filter.cpp
+++ b/src/filters/transform_filter.cpp
@@ -12,7 +12,7 @@ namespace Botan {
Transformation_Filter::Transformation_Filter(Transformation* transform) :
Buffered_Filter(transform->update_granularity(),
transform->minimum_final_size()),
- m_nonce(transform->default_nonce_size() == 0),
+ m_nonce(transform->default_nonce_length() == 0),
m_transform(transform),
m_buffer(m_transform->update_granularity())
{
diff --git a/src/hash/bmw_512/bmw_512.cpp b/src/hash/bmw_512/bmw_512.cpp
index 40338fdf0..9dfa62214 100644
--- a/src/hash/bmw_512/bmw_512.cpp
+++ b/src/hash/bmw_512/bmw_512.cpp
@@ -82,6 +82,8 @@ void BMW_512_compress(u64bit H[16], const u64bit M[16], u64bit Q[32])
Q[14] = S4(Q[30]) + H[15];
Q[15] = S0(Q[31]) + H[ 0];
+ const u64bit EXPANSION_CONSTANT = 0x0555555555555555;
+
for(size_t i = 16; i != 16 + EXPAND_1_ROUNDS; ++i)
{
Q[i] = S1(Q[i-16]) + S2(Q[i-15]) + S3(Q[i-14]) + S0(Q[i-13]) +
@@ -91,7 +93,7 @@ void BMW_512_compress(u64bit H[16], const u64bit M[16], u64bit Q[32])
((rotate_left(M[(i-16) % 16], ((i-16)%16) + 1) +
rotate_left(M[(i-13) % 16], ((i-13)%16) + 1) -
rotate_left(M[(i- 6) % 16], ((i-6)%16) + 1) +
- (0x0555555555555555 * i)) ^ H[(i-16+7)%16]);
+ (EXPANSION_CONSTANT * i)) ^ H[(i-16+7)%16]);
}
for(size_t i = 16 + EXPAND_1_ROUNDS; i != 32; ++i)
@@ -107,7 +109,7 @@ void BMW_512_compress(u64bit H[16], const u64bit M[16], u64bit Q[32])
((rotate_left(M[(i-16) % 16], ((i-16)%16 + 1)) +
rotate_left(M[(i-13) % 16], ((i-13)%16 + 1)) -
rotate_left(M[(i- 6) % 16], ((i-6)%16 + 1)) +
- (0x0555555555555555 * i)) ^ H[(i-16+7)%16]);
+ (EXPANSION_CONSTANT * i)) ^ H[(i-16+7)%16]);
}
u64bit XL = Q[16] ^ Q[17] ^ Q[18] ^ Q[19] ^
diff --git a/src/libstate/info.txt b/src/libstate/info.txt
index 7e2bac6ee..49a6d38ee 100644
--- a/src/libstate/info.txt
+++ b/src/libstate/info.txt
@@ -19,7 +19,3 @@ pubkey
rng
stream
</requires>
-
-<libs>
-all -> boost_system,boost_filesystem
-</libs>
diff --git a/src/modes/aead/aead.h b/src/modes/aead/aead.h
index d03cb295d..8df98fcad 100644
--- a/src/modes/aead/aead.h
+++ b/src/modes/aead/aead.h
@@ -48,7 +48,7 @@ class BOTAN_DLL AEAD_Mode : public Cipher_Mode
* Default AEAD nonce size (a commonly supported value among AEAD
* modes, and large enough that random collisions are unlikely).
*/
- size_t default_nonce_size() const override { return 12; }
+ size_t default_nonce_length() const override { return 12; }
/**
* Return the size of the authentication tag used (in bytes)
diff --git a/src/modes/aead/ccm/ccm.cpp b/src/modes/aead/ccm/ccm.cpp
index fb35172cc..50fc38738 100644
--- a/src/modes/aead/ccm/ccm.cpp
+++ b/src/modes/aead/ccm/ccm.cpp
@@ -47,7 +47,7 @@ bool CCM_Mode::valid_nonce_length(size_t n) const
return (n == (15-L()));
}
-size_t CCM_Mode::default_nonce_size() const
+size_t CCM_Mode::default_nonce_length() const
{
return (15-L());
}
diff --git a/src/modes/aead/ccm/ccm.h b/src/modes/aead/ccm/ccm.h
index a62c84f55..b9ce0b30b 100644
--- a/src/modes/aead/ccm/ccm.h
+++ b/src/modes/aead/ccm/ccm.h
@@ -37,7 +37,7 @@ class BOTAN_DLL CCM_Mode : public AEAD_Mode
bool valid_nonce_length(size_t) const override;
- size_t default_nonce_size() const override;
+ size_t default_nonce_length() const override;
void clear();
diff --git a/src/modes/cbc/cbc.cpp b/src/modes/cbc/cbc.cpp
index 482588cf5..31834bade 100644
--- a/src/modes/cbc/cbc.cpp
+++ b/src/modes/cbc/cbc.cpp
@@ -47,7 +47,7 @@ Key_Length_Specification CBC_Mode::key_spec() const
return cipher().key_spec();
}
-size_t CBC_Mode::default_nonce_size() const
+size_t CBC_Mode::default_nonce_length() const
{
return cipher().block_size();
}
diff --git a/src/modes/cbc/cbc.h b/src/modes/cbc/cbc.h
index 8638c8a05..726d5d080 100644
--- a/src/modes/cbc/cbc.h
+++ b/src/modes/cbc/cbc.h
@@ -29,7 +29,7 @@ class BOTAN_DLL CBC_Mode : public Cipher_Mode
Key_Length_Specification key_spec() const override;
- size_t default_nonce_size() const override;
+ size_t default_nonce_length() const override;
bool valid_nonce_length(size_t n) const override;
diff --git a/src/modes/cfb/cfb.cpp b/src/modes/cfb/cfb.cpp
index 2edb917b4..7721e1487 100644
--- a/src/modes/cfb/cfb.cpp
+++ b/src/modes/cfb/cfb.cpp
@@ -54,7 +54,7 @@ Key_Length_Specification CFB_Mode::key_spec() const
return cipher().key_spec();
}
-size_t CFB_Mode::default_nonce_size() const
+size_t CFB_Mode::default_nonce_length() const
{
return cipher().block_size();
}
diff --git a/src/modes/cfb/cfb.h b/src/modes/cfb/cfb.h
index 46b1997d2..984e5cb96 100644
--- a/src/modes/cfb/cfb.h
+++ b/src/modes/cfb/cfb.h
@@ -33,7 +33,7 @@ class BOTAN_DLL CFB_Mode : public Cipher_Mode
size_t output_length(size_t input_length) const override;
- size_t default_nonce_size() const override;
+ size_t default_nonce_length() const override;
bool valid_nonce_length(size_t n) const override;
diff --git a/src/modes/ecb/ecb.cpp b/src/modes/ecb/ecb.cpp
index 1b73da64f..f026eb035 100644
--- a/src/modes/ecb/ecb.cpp
+++ b/src/modes/ecb/ecb.cpp
@@ -42,7 +42,7 @@ Key_Length_Specification ECB_Mode::key_spec() const
return cipher().key_spec();
}
-size_t ECB_Mode::default_nonce_size() const
+size_t ECB_Mode::default_nonce_length() const
{
return 0;
}
diff --git a/src/modes/ecb/ecb.h b/src/modes/ecb/ecb.h
index 8ab62fa45..9545a33ea 100644
--- a/src/modes/ecb/ecb.h
+++ b/src/modes/ecb/ecb.h
@@ -29,7 +29,7 @@ class BOTAN_DLL ECB_Mode : public Cipher_Mode
Key_Length_Specification key_spec() const override;
- size_t default_nonce_size() const override;
+ size_t default_nonce_length() const override;
bool valid_nonce_length(size_t n) const override;
diff --git a/src/modes/xts/xts.cpp b/src/modes/xts/xts.cpp
index 80b7ed7f3..02da5fa5d 100644
--- a/src/modes/xts/xts.cpp
+++ b/src/modes/xts/xts.cpp
@@ -86,7 +86,7 @@ Key_Length_Specification XTS_Mode::key_spec() const
return cipher().key_spec().multiple(2);
}
-size_t XTS_Mode::default_nonce_size() const
+size_t XTS_Mode::default_nonce_length() const
{
return cipher().block_size();
}
diff --git a/src/modes/xts/xts.h b/src/modes/xts/xts.h
index a1f0f1626..49f2a3458 100644
--- a/src/modes/xts/xts.h
+++ b/src/modes/xts/xts.h
@@ -30,7 +30,7 @@ class BOTAN_DLL XTS_Mode : public Cipher_Mode
Key_Length_Specification key_spec() const override;
- size_t default_nonce_size() const override;
+ size_t default_nonce_length() const override;
bool valid_nonce_length(size_t n) const override;
diff --git a/src/simd/simd_32.h b/src/simd/simd_32.h
index 4ef0cea85..17cf5b91e 100644
--- a/src/simd/simd_32.h
+++ b/src/simd/simd_32.h
@@ -20,7 +20,7 @@
#elif defined(BOTAN_HAS_SIMD_SCALAR)
#include <botan/internal/simd_scalar.h>
- namespace Botan { typedef SIMD_Scalar SIMD_32; }
+ namespace Botan { typedef SIMD_4_Scalar<u32bit> SIMD_32; }
#else
#error "No SIMD module defined"
diff --git a/src/simd/simd_scalar/simd_scalar.h b/src/simd/simd_scalar/simd_scalar.h
index 2c68622af..cf1145794 100644
--- a/src/simd/simd_scalar/simd_scalar.h
+++ b/src/simd/simd_scalar/simd_scalar.h
@@ -1,6 +1,6 @@
/*
-* Scalar emulation of SIMD 32-bit operations
-* (C) 2009 Jack Lloyd
+* Scalar emulation of SIMD
+* (C) 2009,2013 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -17,12 +17,13 @@ namespace Botan {
* Fake SIMD, using plain scalar operations
* Often still faster than iterative on superscalar machines
*/
-class SIMD_Scalar
+template<typename T>
+class SIMD_4_Scalar
{
public:
static bool enabled() { return true; }
- SIMD_Scalar(const u32bit B[4])
+ SIMD_4_Scalar(const T B[4])
{
R0 = B[0];
R1 = B[1];
@@ -30,7 +31,7 @@ class SIMD_Scalar
R3 = B[3];
}
- SIMD_Scalar(u32bit B0, u32bit B1, u32bit B2, u32bit B3)
+ SIMD_4_Scalar(T B0, T B1, T B2, T B3)
{
R0 = B0;
R1 = B1;
@@ -38,7 +39,7 @@ class SIMD_Scalar
R3 = B3;
}
- SIMD_Scalar(u32bit B)
+ SIMD_4_Scalar(T B)
{
R0 = B;
R1 = B;
@@ -46,22 +47,22 @@ class SIMD_Scalar
R3 = B;
}
- static SIMD_Scalar load_le(const void* in)
+ static SIMD_4_Scalar<T> load_le(const void* in)
{
const byte* in_b = static_cast<const byte*>(in);
- return SIMD_Scalar(Botan::load_le<u32bit>(in_b, 0),
- Botan::load_le<u32bit>(in_b, 1),
- Botan::load_le<u32bit>(in_b, 2),
- Botan::load_le<u32bit>(in_b, 3));
+ return SIMD_4_Scalar<T>(Botan::load_le<T>(in_b, 0),
+ Botan::load_le<T>(in_b, 1),
+ Botan::load_le<T>(in_b, 2),
+ Botan::load_le<T>(in_b, 3));
}
- static SIMD_Scalar load_be(const void* in)
+ static SIMD_4_Scalar<T> load_be(const void* in)
{
const byte* in_b = static_cast<const byte*>(in);
- return SIMD_Scalar(Botan::load_be<u32bit>(in_b, 0),
- Botan::load_be<u32bit>(in_b, 1),
- Botan::load_be<u32bit>(in_b, 2),
- Botan::load_be<u32bit>(in_b, 3));
+ return SIMD_4_Scalar<T>(Botan::load_be<T>(in_b, 0),
+ Botan::load_be<T>(in_b, 1),
+ Botan::load_be<T>(in_b, 2),
+ Botan::load_be<T>(in_b, 3));
}
void store_le(byte out[]) const
@@ -90,7 +91,7 @@ class SIMD_Scalar
R3 = Botan::rotate_right(R3, rot);
}
- void operator+=(const SIMD_Scalar& other)
+ void operator+=(const SIMD_4_Scalar<T>& other)
{
R0 += other.R0;
R1 += other.R1;
@@ -98,15 +99,15 @@ class SIMD_Scalar
R3 += other.R3;
}
- SIMD_Scalar operator+(const SIMD_Scalar& other) const
+ SIMD_4_Scalar<T> operator+(const SIMD_4_Scalar<T>& other) const
{
- return SIMD_Scalar(R0 + other.R0,
+ return SIMD_4_Scalar<T>(R0 + other.R0,
R1 + other.R1,
R2 + other.R2,
R3 + other.R3);
}
- void operator-=(const SIMD_Scalar& other)
+ void operator-=(const SIMD_4_Scalar<T>& other)
{
R0 -= other.R0;
R1 -= other.R1;
@@ -114,15 +115,15 @@ class SIMD_Scalar
R3 -= other.R3;
}
- SIMD_Scalar operator-(const SIMD_Scalar& other) const
+ SIMD_4_Scalar<T> operator-(const SIMD_4_Scalar<T>& other) const
{
- return SIMD_Scalar(R0 - other.R0,
- R1 - other.R1,
- R2 - other.R2,
- R3 - other.R3);
+ return SIMD_4_Scalar<T>(R0 - other.R0,
+ R1 - other.R1,
+ R2 - other.R2,
+ R3 - other.R3);
}
- void operator^=(const SIMD_Scalar& other)
+ void operator^=(const SIMD_4_Scalar<T>& other)
{
R0 ^= other.R0;
R1 ^= other.R1;
@@ -130,15 +131,15 @@ class SIMD_Scalar
R3 ^= other.R3;
}
- SIMD_Scalar operator^(const SIMD_Scalar& other) const
+ SIMD_4_Scalar<T> operator^(const SIMD_4_Scalar<T>& other) const
{
- return SIMD_Scalar(R0 ^ other.R0,
+ return SIMD_4_Scalar<T>(R0 ^ other.R0,
R1 ^ other.R1,
R2 ^ other.R2,
R3 ^ other.R3);
}
- void operator|=(const SIMD_Scalar& other)
+ void operator|=(const SIMD_4_Scalar<T>& other)
{
R0 |= other.R0;
R1 |= other.R1;
@@ -146,15 +147,15 @@ class SIMD_Scalar
R3 |= other.R3;
}
- SIMD_Scalar operator&(const SIMD_Scalar& other)
+ SIMD_4_Scalar<T> operator&(const SIMD_4_Scalar<T>& other)
{
- return SIMD_Scalar(R0 & other.R0,
- R1 & other.R1,
- R2 & other.R2,
- R3 & other.R3);
+ return SIMD_4_Scalar<T>(R0 & other.R0,
+ R1 & other.R1,
+ R2 & other.R2,
+ R3 & other.R3);
}
- void operator&=(const SIMD_Scalar& other)
+ void operator&=(const SIMD_4_Scalar<T>& other)
{
R0 &= other.R0;
R1 &= other.R1;
@@ -162,51 +163,51 @@ class SIMD_Scalar
R3 &= other.R3;
}
- SIMD_Scalar operator<<(size_t shift) const
+ SIMD_4_Scalar<T> operator<<(size_t shift) const
{
- return SIMD_Scalar(R0 << shift,
- R1 << shift,
- R2 << shift,
- R3 << shift);
+ return SIMD_4_Scalar<T>(R0 << shift,
+ R1 << shift,
+ R2 << shift,
+ R3 << shift);
}
- SIMD_Scalar operator>>(size_t shift) const
+ SIMD_4_Scalar<T> operator>>(size_t shift) const
{
- return SIMD_Scalar(R0 >> shift,
- R1 >> shift,
- R2 >> shift,
- R3 >> shift);
+ return SIMD_4_Scalar<T>(R0 >> shift,
+ R1 >> shift,
+ R2 >> shift,
+ R3 >> shift);
}
- SIMD_Scalar operator~() const
+ SIMD_4_Scalar<T> operator~() const
{
- return SIMD_Scalar(~R0, ~R1, ~R2, ~R3);
+ return SIMD_4_Scalar<T>(~R0, ~R1, ~R2, ~R3);
}
// (~reg) & other
- SIMD_Scalar andc(const SIMD_Scalar& other)
+ SIMD_4_Scalar<T> andc(const SIMD_4_Scalar<T>& other)
{
- return SIMD_Scalar(~R0 & other.R0,
- ~R1 & other.R1,
- ~R2 & other.R2,
- ~R3 & other.R3);
+ return SIMD_4_Scalar<T>(~R0 & other.R0,
+ ~R1 & other.R1,
+ ~R2 & other.R2,
+ ~R3 & other.R3);
}
- SIMD_Scalar bswap() const
+ SIMD_4_Scalar<T> bswap() const
{
- return SIMD_Scalar(reverse_bytes(R0),
- reverse_bytes(R1),
- reverse_bytes(R2),
- reverse_bytes(R3));
+ return SIMD_4_Scalar<T>(reverse_bytes(R0),
+ reverse_bytes(R1),
+ reverse_bytes(R2),
+ reverse_bytes(R3));
}
- static void transpose(SIMD_Scalar& B0, SIMD_Scalar& B1,
- SIMD_Scalar& B2, SIMD_Scalar& B3)
+ static void transpose(SIMD_4_Scalar<T>& B0, SIMD_4_Scalar<T>& B1,
+ SIMD_4_Scalar<T>& B2, SIMD_4_Scalar<T>& B3)
{
- SIMD_Scalar T0(B0.R0, B1.R0, B2.R0, B3.R0);
- SIMD_Scalar T1(B0.R1, B1.R1, B2.R1, B3.R1);
- SIMD_Scalar T2(B0.R2, B1.R2, B2.R2, B3.R2);
- SIMD_Scalar T3(B0.R3, B1.R3, B2.R3, B3.R3);
+ SIMD_4_Scalar<T> T0(B0.R0, B1.R0, B2.R0, B3.R0);
+ SIMD_4_Scalar<T> T1(B0.R1, B1.R1, B2.R1, B3.R1);
+ SIMD_4_Scalar<T> T2(B0.R2, B1.R2, B2.R2, B3.R2);
+ SIMD_4_Scalar<T> T3(B0.R3, B1.R3, B2.R3, B3.R3);
B0 = T0;
B1 = T1;
@@ -215,7 +216,7 @@ class SIMD_Scalar
}
private:
- u32bit R0, R1, R2, R3;
+ T R0, R1, R2, R3;
};
}
diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp
index 3271c3abe..05251e186 100644
--- a/src/tls/tls_policy.cpp
+++ b/src/tls/tls_policy.cpp
@@ -20,10 +20,10 @@ std::vector<std::string> Policy::allowed_ciphers() const
return std::vector<std::string>({
"AES-256/GCM",
"AES-128/GCM",
- "AES-256/CCM(16,3)",
- "AES-128/CCM(16,3)",
- "AES-256/CCM(8,3)",
- "AES-128/CCM(8,3)",
+ "AES-256/CCM",
+ "AES-128/CCM",
+ "AES-256/CCM-8",
+ "AES-128/CCM-8",
//"Camellia-256/GCM",
//"Camellia-128/GCM",
"AES-256",
@@ -141,11 +141,16 @@ u32bit Policy::session_ticket_lifetime() const
bool Policy::acceptable_protocol_version(Protocol_Version version) const
{
- if(!version.known_version())
+ // By default require TLS to minimize surprise
+ if(version.is_datagram_protocol())
return false;
- // By default require TLS to minimize surprise
- return !version.is_datagram_protocol();
+ return (version > Protocol_Version::SSL_V3);
+ }
+
+bool Policy::acceptable_ciphersuite(const Ciphersuite&) const
+ {
+ return true;
}
namespace {
@@ -235,6 +240,9 @@ std::vector<u16bit> Policy::ciphersuite_list(Protocol_Version version,
for(auto suite : Ciphersuite::all_known_ciphersuites())
{
+ if(!acceptable_ciphersuite(suite))
+ continue;
+
if(!have_srp && suite.kex_algo() == "SRP_SHA")
continue;
diff --git a/src/tls/tls_policy.h b/src/tls/tls_policy.h
index 6a51f2bbf..5b205dfeb 100644
--- a/src/tls/tls_policy.h
+++ b/src/tls/tls_policy.h
@@ -9,6 +9,7 @@
#define BOTAN_TLS_POLICY_H__
#include <botan/tls_version.h>
+#include <botan/tls_ciphersuite.h>
#include <botan/x509cert.h>
#include <botan/dl_group.h>
#include <vector>
@@ -127,6 +128,8 @@ class BOTAN_DLL Policy
*/
virtual bool acceptable_protocol_version(Protocol_Version version) const;
+ virtual bool acceptable_ciphersuite(const Ciphersuite& suite) const;
+
/**
* @return true if servers should choose the ciphersuite matching
* their highest preference, rather than the clients.
diff --git a/src/utils/assert.h b/src/utils/assert.h
index 9265be450..f62fae63e 100644
--- a/src/utils/assert.h
+++ b/src/utils/assert.h
@@ -73,6 +73,11 @@ void BOTAN_DLL assertion_failure(const char* expr_str,
__LINE__); \
} while(0)
+/**
+* Mark variable as unused
+*/
+#define BOTAN_UNUSED(v) static_cast<void>(v)
+
}
#endif
diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp
index f6581f09c..4cb6c826f 100644
--- a/src/utils/cpuid.cpp
+++ b/src/utils/cpuid.cpp
@@ -1,6 +1,6 @@
/*
* Runtime CPU detection
-* (C) 2009-2010 Jack Lloyd
+* (C) 2009-2010,2013 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -28,90 +28,60 @@
#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
- #include <intrin.h>
- #define CALL_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)
+#include <intrin.h>
+
+#define X86_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)
+
+#define X86_CPUID_SUBLEVEL(type, level, out) do { __cpuid((int*)out, type, level); } while(0)
#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
- #include <ia32intrin.h>
- #define CALL_CPUID(type, out) do { __cpuid(out, type); } while(0)
+#include <ia32intrin.h>
-#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) && (BOTAN_GCC_VERSION >= 430)
+#define X86_CPUID(type, out) do { __cpuid(out, type); } while(0)
- // Only available starting in GCC 4.3
- #include <cpuid.h>
+#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) && 0
-namespace {
+#include <cpuid.h>
- /*
- * Prevent inlining to work around GCC bug 44174
- */
- void __attribute__((__noinline__)) call_gcc_cpuid(Botan::u32bit type,
- Botan::u32bit out[4])
- {
- __get_cpuid(type, out, out+1, out+2, out+3);
- }
+#define X86_CPUID(type, out) do { __get_cpuid(type, out, out+1, out+2, out+3); } while(0)
- #define CALL_CPUID call_gcc_cpuid
+namespace {
+
+// avoids asm clobber errors in gcc 4.7.3
+void gcc_cpuid(unsigned int type, unsigned int level, unsigned int* eax, unsigned int* ebx,
+ unsigned int* ecx, unsigned int* edx)
+ {
+ __cpuid_count(type, level, eax, ebx, ecx, edx);
+ }
}
-#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && \
- (defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_GCC))
+#define X86_CPUID_SUBLEVEL(type, level, out) \
+ do { gcc_cpuid(type, level, out, out+1, out+2, out+3); } while(0)
- /*
- * We can't safely use this on x86-32 as some 32-bit ABIs use ebx as
- * a PIC register, and in theory there are some x86-32s still out
- * there that don't support cpuid at all; it requires strange
- * contortions to detect them.
- */
+#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && BOTAN_USE_GCC_INLINE_ASM
- #define CALL_CPUID(type, out) \
- asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
- : "0" (type))
+#define X86_CPUID(type, out) \
+ asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
+ : "0" (type))
-#else
- #warning "No method of calling CPUID for this compiler"
-#endif
+#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))
#endif
-#ifndef CALL_CPUID
- // In all other cases, just zeroize the supposed cpuid output
- #define CALL_CPUID(type, out) \
- do { out[0] = out[1] = out[2] = out[3] = 0; } while(0);
#endif
namespace Botan {
-u64bit CPUID::x86_processor_flags = 0;
-size_t CPUID::cache_line = 32;
-bool CPUID::altivec_capable = false;
+u64bit CPUID::m_x86_processor_flags[2] = { 0, 0 };
+size_t CPUID::m_cache_line_size = 0;
+bool CPUID::m_altivec_capable = false;
namespace {
-u32bit get_x86_cache_line_size()
- {
- const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
- const u32bit AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };
-
- u32bit cpuid[4] = { 0 };
- CALL_CPUID(0, cpuid);
-
- if(same_mem(cpuid + 1, INTEL_CPUID, 3))
- {
- CALL_CPUID(1, cpuid);
- return 8 * get_byte(2, cpuid[1]);
- }
- else if(same_mem(cpuid + 1, AMD_CPUID, 3))
- {
- CALL_CPUID(0x80000005, cpuid);
- return get_byte(3, cpuid[2]);
- }
- else
- return 32; // default cache line guess
- }
-
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
bool altivec_check_sysctl()
@@ -189,27 +159,55 @@ bool altivec_check_pvr_emul()
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 };
- CALL_CPUID(1, cpuid);
+ X86_CPUID(0, cpuid);
+
+ const u32bit max_supported_sublevel = cpuid[0];
+
+ if(max_supported_sublevel == 0)
+ return;
- x86_processor_flags = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];
+ 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.
*/
- if(x86_processor_flags == 0)
- x86_processor_flags |= (1 << CPUID_SSE2_BIT);
-#endif
-
- cache_line = get_x86_cache_line_size();
-
- altivec_capable = false;
-
-#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
- if(altivec_check_sysctl() || altivec_check_pvr_emul())
- altivec_capable = true;
+ if(m_x86_processor_flags[0] == 0)
+ m_x86_processor_flags[0] = (1 << CPUID_SSE2_BIT);
#endif
}
diff --git a/src/utils/cpuid.h b/src/utils/cpuid.h
index 14ac6ad39..eaf1c1330 100644
--- a/src/utils/cpuid.h
+++ b/src/utils/cpuid.h
@@ -1,6 +1,6 @@
/*
* Runtime CPU detection
-* (C) 2009-2010 Jack Lloyd
+* (C) 2009-2010,2013 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -26,7 +26,7 @@ class BOTAN_DLL CPUID
/**
* Return a best guess of the cache line size
*/
- static size_t cache_line_size() { return cache_line; }
+ static size_t cache_line_size() { return m_cache_line_size; }
/**
* Check if the processor supports RDTSC
@@ -59,10 +59,16 @@ class BOTAN_DLL CPUID
{ return x86_processor_flags_has(CPUID_SSE42_BIT); }
/**
- * Check if the processor supports extended AVX vector instructions
+ * Check if the processor supports AVX2
*/
- static bool has_avx()
- { return x86_processor_flags_has(CPUID_AVX_BIT); }
+ static bool has_avx2()
+ { return x86_processor_flags_has(CPUID_AVX2_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
@@ -77,15 +83,33 @@ class BOTAN_DLL CPUID
{ return x86_processor_flags_has(CPUID_PCMUL_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 altivec_capable; }
+ static bool has_altivec() { return m_altivec_capable; }
private:
enum CPUID_bits {
CPUID_RDTSC_BIT = 4,
@@ -95,18 +119,23 @@ class BOTAN_DLL CPUID
CPUID_SSE41_BIT = 51,
CPUID_SSE42_BIT = 52,
CPUID_AESNI_BIT = 57,
- CPUID_AVX_BIT = 60,
- CPUID_RDRAND_BIT = 62
+ CPUID_RDRAND_BIT = 62,
+
+ CPUID_AVX2_BIT = 64+5,
+ CPUID_BMI2_BIT = 64+8,
+ CPUID_RDSEED_BIT = 64+18,
+ CPUID_ADX_BIT = 64+19,
+ CPUID_SHA_BIT = 64+29,
};
static bool x86_processor_flags_has(u64bit bit)
{
- return ((x86_processor_flags >> bit) & 1);
+ return ((m_x86_processor_flags[bit/64] >> (bit % 64)) & 1);
}
- static u64bit x86_processor_flags;
- static size_t cache_line;
- static bool altivec_capable;
+ static u64bit m_x86_processor_flags[2];
+ static size_t m_cache_line_size;
+ static bool m_altivec_capable;
};
}
diff --git a/src/utils/http_util/info.txt b/src/utils/http_util/info.txt
index 39b8ffba6..279e93352 100644
--- a/src/utils/http_util/info.txt
+++ b/src/utils/http_util/info.txt
@@ -1,3 +1,7 @@
define HTTP_UTIL 20131128
load_on auto
+
+<libs>
+all -> boost_system
+</libs>
diff --git a/src/utils/info.txt b/src/utils/info.txt
index 33f38386d..0e8edeb00 100644
--- a/src/utils/info.txt
+++ b/src/utils/info.txt
@@ -2,17 +2,6 @@ define UTIL_FUNCTIONS 20131128
load_on always
-<source>
-assert.cpp
-calendar.cpp
-charset.cpp
-cpuid.cpp
-parsing.cpp
-semaphore.cpp
-version.cpp
-zero_mem.cpp
-</source>
-
<header:internal>
bit_ops.h
prefetch.h
diff --git a/src/utils/parsing.h b/src/utils/parsing.h
index 88c5a7bc0..b37e3cb62 100644
--- a/src/utils/parsing.h
+++ b/src/utils/parsing.h
@@ -13,6 +13,10 @@
#include <vector>
#include <set>
+#include <istream>
+#include <functional>
+#include <map>
+
namespace Botan {
/**
@@ -112,6 +116,18 @@ BOTAN_DLL u32bit string_to_ipv4(const std::string& ip_str);
*/
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/utils/read_cfg.cpp b/src/utils/read_cfg.cpp
new file mode 100644
index 000000000..ad57a8b3e
--- /dev/null
+++ b/src/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;
+ }
+
+}