From 9d8f4cf1e81322ca7290b6551b82d4943dfa62a0 Mon Sep 17 00:00:00 2001 From: lloyd Date: Thu, 5 Feb 2015 04:44:06 +0000 Subject: Enable OpenSSL for providing ciphers and hashes again. --- configure.py | 2 +- doc/dev/todo.rst | 9 +- src/cmd/speed.cpp | 23 +-- src/lib/base/algo_registry.h | 35 +++-- src/lib/block/block_utils.h | 1 + src/lib/entropy/egd/info.txt | 2 +- src/lib/openssl/ossl_arc4.cpp | 89 ----------- src/lib/openssl/ossl_bc.cpp | 248 ------------------------------- src/lib/openssl/ossl_md.cpp | 150 ------------------- src/lib/stream/stream_utils.h | 1 + src/lib/utils/boost/info.txt | 8 - src/lib/utils/sqlite3/info.txt | 10 -- src/lib/utils/sqlite3/sqlite3.cpp | 143 ------------------ src/lib/utils/sqlite3/sqlite3.h | 56 ------- src/lib/vendor/boost/info.txt | 8 + src/lib/vendor/openssl/openssl_block.cpp | 212 ++++++++++++++++++++++++++ src/lib/vendor/openssl/openssl_hash.cpp | 115 ++++++++++++++ src/lib/vendor/openssl/openssl_rc4.cpp | 49 ++++++ src/lib/vendor/sqlite3/info.txt | 10 ++ src/lib/vendor/sqlite3/sqlite3.cpp | 143 ++++++++++++++++++ src/lib/vendor/sqlite3/sqlite3.h | 56 +++++++ 21 files changed, 635 insertions(+), 735 deletions(-) delete mode 100644 src/lib/openssl/ossl_arc4.cpp delete mode 100644 src/lib/openssl/ossl_bc.cpp delete mode 100644 src/lib/openssl/ossl_md.cpp delete mode 100644 src/lib/utils/boost/info.txt delete mode 100644 src/lib/utils/sqlite3/info.txt delete mode 100644 src/lib/utils/sqlite3/sqlite3.cpp delete mode 100644 src/lib/utils/sqlite3/sqlite3.h create mode 100644 src/lib/vendor/boost/info.txt create mode 100644 src/lib/vendor/openssl/openssl_block.cpp create mode 100644 src/lib/vendor/openssl/openssl_hash.cpp create mode 100644 src/lib/vendor/openssl/openssl_rc4.cpp create mode 100644 src/lib/vendor/sqlite3/info.txt create mode 100644 src/lib/vendor/sqlite3/sqlite3.cpp create mode 100644 src/lib/vendor/sqlite3/sqlite3.h diff --git a/configure.py b/configure.py index 371e8390f..947d85066 100755 --- a/configure.py +++ b/configure.py @@ -386,7 +386,7 @@ def process_command_line(args): mods_group.add_option('--no-autoload', action='store_true', default=False, help='disable automatic loading') - third_party = ['boost', 'sqlite3', 'zlib', 'bzip2', 'lzma'] + third_party = ['boost', 'sqlite3', 'openssl', 'zlib', 'bzip2', 'lzma'] hidden_third_party = ['gnump'] for mod in third_party + hidden_third_party: diff --git a/doc/dev/todo.rst b/doc/dev/todo.rst index 6c89367e0..ae1853dbf 100644 --- a/doc/dev/todo.rst +++ b/doc/dev/todo.rst @@ -14,7 +14,6 @@ Basic Crypto * BLAKE2 * EdDSA * Skein-MAC -* IETF standard HKDF (RFC 5869) * ARIA (Korean block cipher, RFCs 5794 and 6209) * Extend Cascade_Cipher to support arbitrary number of ciphers @@ -54,16 +53,14 @@ New Protocols Accelerators / backends ---------------------------------------- +* Improve OpenSSL provider (add cipher modes, RSA, etc) * /dev/crypto * Windows CryptoAPI * Apple CommonCrypto * ARMv8 crypto extensions * Intel Skylake SHA-1/SHA-2 -FFI +Python ---------------------------------------- -* Expose TLS to Python -* Expose ECC to Python -* Expose bcrypt to Python - +* TLS, ECDSA, bcrypt, ... diff --git a/src/cmd/speed.cpp b/src/cmd/speed.cpp index 7e8dbd412..185105ee2 100644 --- a/src/cmd/speed.cpp +++ b/src/cmd/speed.cpp @@ -120,9 +120,6 @@ void report_results(const std::string& algo, void time_transform(std::unique_ptr tf, RandomNumberGenerator& rng) { - if(!tf) - return; - const std::chrono::seconds runtime(2); for(size_t buf_size : { 16, 64, 256, 1024, 8192 }) @@ -156,15 +153,18 @@ void time_transform(std::unique_ptr tf, } } -void time_transform(const std::string& algo, RandomNumberGenerator& rng) +bool time_transform(const std::string& algo, RandomNumberGenerator& rng) { std::unique_ptr tf; tf.reset(get_cipher_mode(algo, ENCRYPTION)); + if(!tf) + return false; if(Keyed_Transform* keyed = dynamic_cast(tf.get())) keyed->set_key(rng.random_vec(keyed->key_spec().maximum_keylength())); time_transform(std::move(tf), rng); + return true; } void bench_algo(const std::string& algo, @@ -175,15 +175,18 @@ void bench_algo(const std::string& algo, std::chrono::milliseconds ms( static_cast(seconds * 1000)); - std::map speeds = algorithm_benchmark(algo, rng, ms, buf_size); + if(time_transform(algo, rng)) + return; - report_results(algo, speeds); + std::map speeds = algorithm_benchmark(algo, rng, ms, buf_size); - if(speeds.empty()) - time_transform(algo, rng); + if(!speeds.empty()) + { + report_results(algo, speeds); + return; + } - if(speeds.empty()) - bench_pk(rng, algo, seconds); + bench_pk(rng, algo, seconds); } int speed(int argc, char* argv[]) diff --git a/src/lib/base/algo_registry.h b/src/lib/base/algo_registry.h index 9582180bd..709b035fc 100644 --- a/src/lib/base/algo_registry.h +++ b/src/lib/base/algo_registry.h @@ -63,7 +63,7 @@ class Algo_Registry class Add { public: - Add(const std::string& basename, maker_fn fn, const std::string& provider = "builtin", byte pref = 128) + Add(const std::string& basename, maker_fn fn, const std::string& provider, byte pref) { Algo_Registry::global_registry().add(basename, provider, fn, pref); } @@ -190,21 +190,30 @@ make_new_T_1X(const typename Algo_Registry::Spec& spec) return new T(x.release()); } -#define BOTAN_REGISTER_NAMED_T(T, namestr, type, maker) \ - namespace { Algo_Registry::Add g_ ## type ## _reg(namestr, maker); } -#define BOTAN_REGISTER_T(T, name, maker) \ - namespace { Algo_Registry::Add g_ ## name ## _reg(#name, maker); } -#define BOTAN_REGISTER_T_NOARGS(T, name) \ - namespace { Algo_Registry::Add g_ ## name ## _reg(#name, make_new_T); } -#define BOTAN_REGISTER_T_1LEN(T, name, def) \ - namespace { Algo_Registry::Add g_ ## name ## _reg(#name, make_new_T_1len); } +#define BOTAN_REGISTER_TYPE(T, type, name, maker, provider, pref) \ + namespace { Algo_Registry::Add g_ ## type ## _reg(name, maker, provider, pref); } + +#define BOTAN_REGISTER_TYPE_COND(cond, T, type, name, maker, provider, pref) \ + namespace { Algo_Registry::Add g_ ## type ## _reg(cond, name, maker, provider, pref); } + +#define BOTAN_REGISTER_NAMED_T(T, name, type, maker) \ + BOTAN_REGISTER_TYPE(T, type, name, maker, "builtin", 128) + +#define BOTAN_REGISTER_T(T, type, maker) \ + BOTAN_REGISTER_TYPE(T, type, #type, maker, "builtin", 128) + +#define BOTAN_REGISTER_T_NOARGS(T, type) \ + BOTAN_REGISTER_TYPE(T, type, #type, make_new_T, "builtin", 128) +#define BOTAN_REGISTER_T_1LEN(T, type, def) \ + BOTAN_REGISTER_TYPE(T, type, #type, (make_new_T_1len), "builtin", 128) #define BOTAN_REGISTER_NAMED_T_NOARGS(T, type, name, provider) \ - namespace { Algo_Registry::Add g_ ## type ## _reg(name, make_new_T, provider); } + BOTAN_REGISTER_TYPE(T, type, name, make_new_T, provider, 128) #define BOTAN_COND_REGISTER_NAMED_T_NOARGS(cond, T, type, name, provider, pref) \ - namespace { Algo_Registry::Add g_ ## type ## _reg(cond, name, make_new_T, provider, pref); } -#define BOTAN_REGISTER_NAMED_T_2LEN(T, type, name, provider, len1, len2) \ - namespace { Algo_Registry::Add g_ ## type ## _reg(name, make_new_T_2len, provider); } + BOTAN_REGISTER_TYPE_COND(cond, T, type, name, make_new_T, provider, pref) + +#define BOTAN_REGISTER_NAMED_T_2LEN(T, type, name, provider, len1, len2) \ + BOTAN_REGISTER_TYPE(T, type, name, (make_new_T_2len), provider, 128) // TODO move elsewhere: #define BOTAN_REGISTER_TRANSFORM(name, maker) BOTAN_REGISTER_T(Transform, name, maker) diff --git a/src/lib/block/block_utils.h b/src/lib/block/block_utils.h index ebf6354e0..dacc79a45 100644 --- a/src/lib/block/block_utils.h +++ b/src/lib/block/block_utils.h @@ -8,6 +8,7 @@ #ifndef BOTAN_BLOCK_CIPHER_UTILS_H__ #define BOTAN_BLOCK_CIPHER_UTILS_H__ +#include #include #include #include diff --git a/src/lib/entropy/egd/info.txt b/src/lib/entropy/egd/info.txt index bdf6db71e..fdf5c4959 100644 --- a/src/lib/entropy/egd/info.txt +++ b/src/lib/entropy/egd/info.txt @@ -1,6 +1,6 @@ define ENTROPY_SRC_EGD 20131128 -load_on request +load_on auto es_egd.cpp diff --git a/src/lib/openssl/ossl_arc4.cpp b/src/lib/openssl/ossl_arc4.cpp deleted file mode 100644 index 4533c2688..000000000 --- a/src/lib/openssl/ossl_arc4.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* -* OpenSSL RC4 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include -#include -#include - -namespace Botan { - -namespace { - -/** -* RC4 as implemented by OpenSSL -*/ -class RC4_OpenSSL : public StreamCipher - { - public: - void clear() { clear_mem(&state, 1); } - - std::string name() const; - StreamCipher* clone() const { return new RC4_OpenSSL(SKIP); } - - Key_Length_Specification key_spec() const - { - return Key_Length_Specification(1, 32); - } - - - RC4_OpenSSL(size_t s = 0) : SKIP(s) { clear(); } - ~RC4_OpenSSL() { clear(); } - private: - void cipher(const byte[], byte[], size_t); - void key_schedule(const byte[], size_t); - - const size_t SKIP; - RC4_KEY state; - }; - -/* -* Return the name of this type -*/ -std::string RC4_OpenSSL::name() const - { - if(SKIP == 0) return "RC4"; - if(SKIP == 256) return "MARK-4"; - else return "RC4_skip(" + std::to_string(SKIP) + ")"; - } - -/* -* RC4 Key Schedule -*/ -void RC4_OpenSSL::key_schedule(const byte key[], size_t length) - { - RC4_set_key(&state, length, key); - byte dummy = 0; - for(size_t i = 0; i != SKIP; ++i) - RC4(&state, 1, &dummy, &dummy); - } - -/* -* RC4 Encryption -*/ -void RC4_OpenSSL::cipher(const byte in[], byte out[], size_t length) - { - RC4(&state, length, in, out); - } - -} - -/** -* Look for an OpenSSL-supported stream cipher (RC4) -*/ -StreamCipher* -OpenSSL_Engine::find_stream_cipher(const SCAN_Name& request, - Algorithm_Factory&) const - { - if(request.algo_name() == "RC4") - return new RC4_OpenSSL(request.arg_as_integer(0, 0)); - if(request.algo_name() == "RC4_drop") - return new RC4_OpenSSL(768); - - return 0; - } - -} diff --git a/src/lib/openssl/ossl_bc.cpp b/src/lib/openssl/ossl_bc.cpp deleted file mode 100644 index 8e8c6e5a8..000000000 --- a/src/lib/openssl/ossl_bc.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* -* OpenSSL Block Cipher -* (C) 1999-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include -#include - -namespace Botan { - -namespace { - -/* -* EVP Block Cipher -*/ -class EVP_BlockCipher : public BlockCipher - { - public: - void clear(); - std::string name() const { return cipher_name; } - BlockCipher* clone() const; - - size_t block_size() const { return block_sz; } - - EVP_BlockCipher(const EVP_CIPHER*, const std::string&); - - EVP_BlockCipher(const EVP_CIPHER*, const std::string&, - size_t, size_t, size_t); - - Key_Length_Specification key_spec() const { return cipher_key_spec; } - - ~EVP_BlockCipher(); - private: - void encrypt_n(const byte in[], byte out[], size_t blocks) const; - void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void key_schedule(const byte[], size_t); - - size_t block_sz; - Key_Length_Specification cipher_key_spec; - std::string cipher_name; - mutable EVP_CIPHER_CTX encrypt, decrypt; - }; - -/* -* EVP Block Cipher Constructor -*/ -EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo, - const std::string& algo_name) : - block_sz(EVP_CIPHER_block_size(algo)), - cipher_key_spec(EVP_CIPHER_key_length(algo)), - cipher_name(algo_name) - { - if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) - throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in"); - - EVP_CIPHER_CTX_init(&encrypt); - EVP_CIPHER_CTX_init(&decrypt); - - EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0); - EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0); - - EVP_CIPHER_CTX_set_padding(&encrypt, 0); - EVP_CIPHER_CTX_set_padding(&decrypt, 0); - } - -/* -* EVP Block Cipher Constructor -*/ -EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo, - const std::string& algo_name, - size_t key_min, size_t key_max, - size_t key_mod) : - block_sz(EVP_CIPHER_block_size(algo)), - cipher_key_spec(key_min, key_max, key_mod), - cipher_name(algo_name) - { - if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) - throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in"); - - EVP_CIPHER_CTX_init(&encrypt); - EVP_CIPHER_CTX_init(&decrypt); - - EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0); - EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0); - - EVP_CIPHER_CTX_set_padding(&encrypt, 0); - EVP_CIPHER_CTX_set_padding(&decrypt, 0); - } - -/* -* EVP Block Cipher Destructor -*/ -EVP_BlockCipher::~EVP_BlockCipher() - { - EVP_CIPHER_CTX_cleanup(&encrypt); - EVP_CIPHER_CTX_cleanup(&decrypt); - } - -/* -* Encrypt a block -*/ -void EVP_BlockCipher::encrypt_n(const byte in[], byte out[], - size_t blocks) const - { - int out_len = 0; - EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * block_sz); - } - -/* -* Decrypt a block -*/ -void EVP_BlockCipher::decrypt_n(const byte in[], byte out[], - size_t blocks) const - { - int out_len = 0; - EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * block_sz); - } - -/* -* Set the key -*/ -void EVP_BlockCipher::key_schedule(const byte key[], size_t length) - { - secure_vector full_key(key, key + length); - - if(cipher_name == "TripleDES" && length == 16) - { - full_key += std::make_pair(key, 8); - } - else - if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 || - EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0) - throw Invalid_Argument("EVP_BlockCipher: Bad key length for " + - cipher_name); - - if(cipher_name == "RC2") - { - EVP_CIPHER_CTX_ctrl(&encrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0); - EVP_CIPHER_CTX_ctrl(&decrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0); - } - - EVP_EncryptInit_ex(&encrypt, 0, 0, &full_key[0], 0); - EVP_DecryptInit_ex(&decrypt, 0, 0, &full_key[0], 0); - } - -/* -* Return a clone of this object -*/ -BlockCipher* EVP_BlockCipher::clone() const - { - return new EVP_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt), - cipher_name, - cipher_key_spec.minimum_keylength(), - cipher_key_spec.maximum_keylength(), - cipher_key_spec.keylength_multiple()); - } - -/* -* Clear memory of sensitive data -*/ -void EVP_BlockCipher::clear() - { - const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt); - - EVP_CIPHER_CTX_cleanup(&encrypt); - EVP_CIPHER_CTX_cleanup(&decrypt); - EVP_CIPHER_CTX_init(&encrypt); - EVP_CIPHER_CTX_init(&decrypt); - EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0); - EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0); - EVP_CIPHER_CTX_set_padding(&encrypt, 0); - EVP_CIPHER_CTX_set_padding(&decrypt, 0); - } - -} - -/* -* Look for an algorithm with this name -*/ -BlockCipher* -OpenSSL_Engine::find_block_cipher(const SCAN_Name& request, - Algorithm_Factory&) const - { -#define HANDLE_EVP_CIPHER(NAME, EVP) \ - if(request.algo_name() == NAME && request.arg_count() == 0) \ - return new EVP_BlockCipher(EVP, NAME); - -#define HANDLE_EVP_CIPHER_KEYLEN(NAME, EVP, MIN, MAX, MOD) \ - if(request.algo_name() == NAME && request.arg_count() == 0) \ - return new EVP_BlockCipher(EVP, NAME, MIN, MAX, MOD); - -#if !defined(OPENSSL_NO_AES) - /* - Using OpenSSL's AES causes crashes inside EVP on x86-64 with OpenSSL 0.9.8g - cause is unknown - */ - HANDLE_EVP_CIPHER("AES-128", EVP_aes_128_ecb()); - HANDLE_EVP_CIPHER("AES-192", EVP_aes_192_ecb()); - HANDLE_EVP_CIPHER("AES-256", EVP_aes_256_ecb()); -#endif - -#if !defined(OPENSSL_NO_DES) - HANDLE_EVP_CIPHER("DES", EVP_des_ecb()); - HANDLE_EVP_CIPHER_KEYLEN("TripleDES", EVP_des_ede3_ecb(), 16, 24, 8); -#endif - -#if !defined(OPENSSL_NO_BF) - HANDLE_EVP_CIPHER_KEYLEN("Blowfish", EVP_bf_ecb(), 1, 56, 1); -#endif - -#if !defined(OPENSSL_NO_CAST) - HANDLE_EVP_CIPHER_KEYLEN("CAST-128", EVP_cast5_ecb(), 1, 16, 1); -#endif - -#if !defined(OPENSSL_NO_CAMELLIA) - HANDLE_EVP_CIPHER("Camellia-128", EVP_camellia_128_ecb()); - HANDLE_EVP_CIPHER("Camellia-192", EVP_camellia_192_ecb()); - HANDLE_EVP_CIPHER("Camellia-256", EVP_camellia_256_ecb()); -#endif - -#if !defined(OPENSSL_NO_RC2) - HANDLE_EVP_CIPHER_KEYLEN("RC2", EVP_rc2_ecb(), 1, 32, 1); -#endif - -#if !defined(OPENSSL_NO_RC5) && 0 - if(request.algo_name() == "RC5") - if(request.arg_as_integer(0, 12) == 12) - return new EVP_BlockCipher(EVP_rc5_32_12_16_ecb(), - "RC5(12)", 1, 32, 1); -#endif - -#if !defined(OPENSSL_NO_IDEA) && 0 - HANDLE_EVP_CIPHER("IDEA", EVP_idea_ecb()); -#endif - -#if !defined(OPENSSL_NO_SEED) - HANDLE_EVP_CIPHER("SEED", EVP_seed_ecb()); -#endif - -#undef HANDLE_EVP_CIPHER -#undef HANDLE_EVP_CIPHER_KEYLEN - - return 0; - } - -} diff --git a/src/lib/openssl/ossl_md.cpp b/src/lib/openssl/ossl_md.cpp deleted file mode 100644 index 063271151..000000000 --- a/src/lib/openssl/ossl_md.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* -* OpenSSL Hash Functions -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include -#include - -namespace Botan { - -namespace { - -/* -* EVP Hash Function -*/ -class EVP_HashFunction : public HashFunction - { - public: - void clear(); - std::string name() const { return algo_name; } - HashFunction* clone() const; - - size_t output_length() const - { - return EVP_MD_size(EVP_MD_CTX_md(&md)); - } - - size_t hash_block_size() const - { - return EVP_MD_block_size(EVP_MD_CTX_md(&md)); - } - - EVP_HashFunction(const EVP_MD*, const std::string&); - ~EVP_HashFunction(); - private: - void add_data(const byte[], size_t); - void final_result(byte[]); - - std::string algo_name; - EVP_MD_CTX md; - }; - -/* -* Update an EVP Hash Calculation -*/ -void EVP_HashFunction::add_data(const byte input[], size_t length) - { - EVP_DigestUpdate(&md, input, length); - } - -/* -* Finalize an EVP Hash Calculation -*/ -void EVP_HashFunction::final_result(byte output[]) - { - EVP_DigestFinal_ex(&md, output, 0); - const EVP_MD* algo = EVP_MD_CTX_md(&md); - EVP_DigestInit_ex(&md, algo, 0); - } - -/* -* Clear memory of sensitive data -*/ -void EVP_HashFunction::clear() - { - const EVP_MD* algo = EVP_MD_CTX_md(&md); - EVP_DigestInit_ex(&md, algo, 0); - } - -/* -* Return a clone of this object -*/ -HashFunction* EVP_HashFunction::clone() const - { - const EVP_MD* algo = EVP_MD_CTX_md(&md); - return new EVP_HashFunction(algo, name()); - } - -/* -* Create an EVP hash function -*/ -EVP_HashFunction::EVP_HashFunction(const EVP_MD* algo, - const std::string& name) : - algo_name(name) - { - EVP_MD_CTX_init(&md); - EVP_DigestInit_ex(&md, algo, 0); - } - -/* -* Destroy an EVP hash function -*/ -EVP_HashFunction::~EVP_HashFunction() - { - EVP_MD_CTX_cleanup(&md); - } - -} - -/* -* Look for an algorithm with this name -*/ -HashFunction* OpenSSL_Engine::find_hash(const SCAN_Name& request, - Algorithm_Factory&) const - { -#if !defined(OPENSSL_NO_SHA) - if(request.algo_name() == "SHA-160") - return new EVP_HashFunction(EVP_sha1(), "SHA-160"); -#endif - -#if !defined(OPENSSL_NO_SHA256) - if(request.algo_name() == "SHA-224") - return new EVP_HashFunction(EVP_sha224(), "SHA-224"); - if(request.algo_name() == "SHA-256") - return new EVP_HashFunction(EVP_sha256(), "SHA-256"); -#endif - -#if !defined(OPENSSL_NO_SHA512) - if(request.algo_name() == "SHA-384") - return new EVP_HashFunction(EVP_sha384(), "SHA-384"); - if(request.algo_name() == "SHA-512") - return new EVP_HashFunction(EVP_sha512(), "SHA-512"); -#endif - -#if !defined(OPENSSL_NO_MD2) - if(request.algo_name() == "MD2") - return new EVP_HashFunction(EVP_md2(), "MD2"); -#endif - -#if !defined(OPENSSL_NO_MD4) - if(request.algo_name() == "MD4") - return new EVP_HashFunction(EVP_md4(), "MD4"); -#endif - -#if !defined(OPENSSL_NO_MD5) - if(request.algo_name() == "MD5") - return new EVP_HashFunction(EVP_md5(), "MD5"); -#endif - -#if !defined(OPENSSL_NO_RIPEMD) - if(request.algo_name() == "RIPEMD-160") - return new EVP_HashFunction(EVP_ripemd160(), "RIPEMD-160"); -#endif - - return 0; - } - -} diff --git a/src/lib/stream/stream_utils.h b/src/lib/stream/stream_utils.h index 2e8f58562..8ba8d4b01 100644 --- a/src/lib/stream/stream_utils.h +++ b/src/lib/stream/stream_utils.h @@ -8,6 +8,7 @@ #ifndef BOTAN_STREAM_CIPHER_UTILS_H__ #define BOTAN_STREAM_CIPHER_UTILS_H__ +#include #include #include #include diff --git a/src/lib/utils/boost/info.txt b/src/lib/utils/boost/info.txt deleted file mode 100644 index 119a54175..000000000 --- a/src/lib/utils/boost/info.txt +++ /dev/null @@ -1,8 +0,0 @@ -define BOOST_FILESYSTEM 20131228 -define BOOST_ASIO 20131228 - - -all -> boost_system,boost_filesystem - - -load_on request diff --git a/src/lib/utils/sqlite3/info.txt b/src/lib/utils/sqlite3/info.txt deleted file mode 100644 index 6370f4b2b..000000000 --- a/src/lib/utils/sqlite3/info.txt +++ /dev/null @@ -1,10 +0,0 @@ - -load_on request - - -all -> sqlite3 - - - -sqlite3.h - diff --git a/src/lib/utils/sqlite3/sqlite3.cpp b/src/lib/utils/sqlite3/sqlite3.cpp deleted file mode 100644 index 61c7f15bc..000000000 --- a/src/lib/utils/sqlite3/sqlite3.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* -* SQLite wrapper -* (C) 2012 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include -#include -#include - -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; - } - -std::shared_ptr Sqlite3_Database::new_statement(const std::string& base_sql) const - { - return std::make_shared(m_db, base_sql); - } - -size_t Sqlite3_Database::row_count(const std::string& table_name) - { - auto stmt = new_statement("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_Database::Sqlite3_Statement::Sqlite3_Statement(sqlite3* db, const std::string& base_sql) - { - int rc = ::sqlite3_prepare_v2(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_Database::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_Database::Sqlite3_Statement::bind(int column, size_t val) - { - if(val != static_cast(static_cast(val))) // is this legit? - throw std::runtime_error("sqlite3 cannot store " + std::to_string(val) + " without truncation"); - 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_Database::Sqlite3_Statement::bind(int column, std::chrono::system_clock::time_point time) - { - const int timeval = std::chrono::duration_cast(time.time_since_epoch()).count(); - bind(column, timeval); - } - -void Sqlite3_Database::Sqlite3_Statement::bind(int column, const std::vector& 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 Sqlite3_Database::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(session_blob), - static_cast(session_blob_size)); - } - -size_t Sqlite3_Database::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(sessions_int); - } - -void Sqlite3_Database::Sqlite3_Statement::spin() - { - while(step()) {} - } - -bool Sqlite3_Database::Sqlite3_Statement::step() - { - return (::sqlite3_step(m_stmt) == SQLITE_ROW); - } - -Sqlite3_Database::Sqlite3_Statement::~Sqlite3_Statement() - { - ::sqlite3_finalize(m_stmt); - } - -} diff --git a/src/lib/utils/sqlite3/sqlite3.h b/src/lib/utils/sqlite3/sqlite3.h deleted file mode 100644 index 8495a1d1b..000000000 --- a/src/lib/utils/sqlite3/sqlite3.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -* SQLite3 wrapper -* (C) 2012,2014 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_UTILS_SQLITE3_H__ -#define BOTAN_UTILS_SQLITE3_H__ - -#include - -class sqlite3; -class sqlite3_stmt; - -namespace Botan { - -class BOTAN_DLL Sqlite3_Database : public SQL_Database - { - public: - Sqlite3_Database(const std::string& file); - - ~Sqlite3_Database(); - - size_t row_count(const std::string& table_name) override; - - void create_table(const std::string& table_schema) override; - - std::shared_ptr new_statement(const std::string& sql) const override; - private: - class Sqlite3_Statement : public Statement - { - public: - void bind(int column, const std::string& val) override; - void bind(int column, size_t val) override; - void bind(int column, std::chrono::system_clock::time_point time) override; - void bind(int column, const std::vector& val) override; - - std::pair get_blob(int column) override; - size_t get_size_t(int column) override; - - void spin() override; - bool step() override; - - Sqlite3_Statement(sqlite3* db, const std::string& base_sql); - ~Sqlite3_Statement(); - private: - sqlite3_stmt* m_stmt; - }; - - sqlite3* m_db; - }; - -} - -#endif diff --git a/src/lib/vendor/boost/info.txt b/src/lib/vendor/boost/info.txt new file mode 100644 index 000000000..119a54175 --- /dev/null +++ b/src/lib/vendor/boost/info.txt @@ -0,0 +1,8 @@ +define BOOST_FILESYSTEM 20131228 +define BOOST_ASIO 20131228 + + +all -> boost_system,boost_filesystem + + +load_on request diff --git a/src/lib/vendor/openssl/openssl_block.cpp b/src/lib/vendor/openssl/openssl_block.cpp new file mode 100644 index 000000000..34f0e5607 --- /dev/null +++ b/src/lib/vendor/openssl/openssl_block.cpp @@ -0,0 +1,212 @@ +/* +* OpenSSL Block Cipher +* (C) 1999-2010,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include + +namespace Botan { + +namespace { + +class OpenSSL_BlockCipher : public BlockCipher + { + public: + void clear(); + std::string name() const { return cipher_name; } + BlockCipher* clone() const; + + size_t block_size() const { return block_sz; } + + OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&); + + OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&, + size_t, size_t, size_t); + + Key_Length_Specification key_spec() const { return cipher_key_spec; } + + ~OpenSSL_BlockCipher(); + private: + void encrypt_n(const byte in[], byte out[], size_t blocks) const + { + int out_len = 0; + EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * block_sz); + } + + void decrypt_n(const byte in[], byte out[], size_t blocks) const + { + int out_len = 0; + EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * block_sz); + } + + void key_schedule(const byte[], size_t); + + size_t block_sz; + Key_Length_Specification cipher_key_spec; + std::string cipher_name; + mutable EVP_CIPHER_CTX encrypt, decrypt; + }; + +OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo, + const std::string& algo_name) : + block_sz(EVP_CIPHER_block_size(algo)), + cipher_key_spec(EVP_CIPHER_key_length(algo)), + cipher_name(algo_name) + { + if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) + throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in"); + + EVP_CIPHER_CTX_init(&encrypt); + EVP_CIPHER_CTX_init(&decrypt); + + EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr); + EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr); + + EVP_CIPHER_CTX_set_padding(&encrypt, 0); + EVP_CIPHER_CTX_set_padding(&decrypt, 0); + } + +OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo, + const std::string& algo_name, + size_t key_min, size_t key_max, + size_t key_mod) : + block_sz(EVP_CIPHER_block_size(algo)), + cipher_key_spec(key_min, key_max, key_mod), + cipher_name(algo_name) + { + if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) + throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in"); + + EVP_CIPHER_CTX_init(&encrypt); + EVP_CIPHER_CTX_init(&decrypt); + + EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr); + EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr); + + EVP_CIPHER_CTX_set_padding(&encrypt, 0); + EVP_CIPHER_CTX_set_padding(&decrypt, 0); + } + +OpenSSL_BlockCipher::~OpenSSL_BlockCipher() + { + EVP_CIPHER_CTX_cleanup(&encrypt); + EVP_CIPHER_CTX_cleanup(&decrypt); + } + +/* +* Set the key +*/ +void OpenSSL_BlockCipher::key_schedule(const byte key[], size_t length) + { + secure_vector full_key(key, key + length); + + if(cipher_name == "TripleDES" && length == 16) + { + full_key += std::make_pair(key, 8); + } + else + if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 || + EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0) + throw Invalid_Argument("OpenSSL_BlockCipher: Bad key length for " + + cipher_name); + + EVP_EncryptInit_ex(&encrypt, nullptr, nullptr, &full_key[0], nullptr); + EVP_DecryptInit_ex(&decrypt, nullptr, nullptr, &full_key[0], nullptr); + } + +/* +* Return a clone of this object +*/ +BlockCipher* OpenSSL_BlockCipher::clone() const + { + return new OpenSSL_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt), + cipher_name, + cipher_key_spec.minimum_keylength(), + cipher_key_spec.maximum_keylength(), + cipher_key_spec.keylength_multiple()); + } + +/* +* Clear memory of sensitive data +*/ +void OpenSSL_BlockCipher::clear() + { + const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt); + + EVP_CIPHER_CTX_cleanup(&encrypt); + EVP_CIPHER_CTX_cleanup(&decrypt); + EVP_CIPHER_CTX_init(&encrypt); + EVP_CIPHER_CTX_init(&decrypt); + EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr); + EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr); + EVP_CIPHER_CTX_set_padding(&encrypt, 0); + EVP_CIPHER_CTX_set_padding(&decrypt, 0); + } + +std::function +make_evp_block_maker(const EVP_CIPHER* cipher, const char* algo) + { + return [cipher,algo](const BlockCipher::Spec&) + { + return new OpenSSL_BlockCipher(cipher, algo); + }; + } + +std::function +make_evp_block_maker_keylen(const EVP_CIPHER* cipher, const char* algo, + size_t kmin, size_t kmax, size_t kmod) + { + return [cipher,algo,kmin,kmax,kmod](const BlockCipher::Spec&) + { + return new OpenSSL_BlockCipher(cipher, algo, kmin, kmax, kmod); + }; + } + +#define BOTAN_REGISTER_OPENSSL_EVP_BLOCK(NAME, EVP) \ + BOTAN_REGISTER_TYPE(BlockCipher, EVP_BlockCipher ## EVP, NAME, \ + make_evp_block_maker(EVP(), NAME), "openssl", 96); + +#define BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN(NAME, EVP, KMIN, KMAX, KMOD) \ + BOTAN_REGISTER_TYPE(BlockCipher, OpenSSL_BlockCipher ## EVP, NAME, \ + make_evp_block_maker_keylen(EVP(), NAME, KMIN, KMAX, KMOD), \ + "openssl", 96); + +#if !defined(OPENSSL_NO_AES) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-128", EVP_aes_128_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-192", EVP_aes_192_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-256", EVP_aes_256_ecb); +#endif + +#if !defined(OPENSSL_NO_DES) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("DES", EVP_des_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("TripleDES", EVP_des_ede3_ecb, 16, 24, 8); +#endif + +#if !defined(OPENSSL_NO_BF) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("Blowfish", EVP_bf_ecb, 1, 56, 1); +#endif + +#if !defined(OPENSSL_NO_CAST) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("CAST-128", EVP_cast5_ecb, 1, 16, 1); +#endif + +#if !defined(OPENSSL_NO_CAMELLIA) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-128", EVP_camellia_128_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-192", EVP_camellia_192_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-256", EVP_camellia_256_ecb); +#endif + +#if !defined(OPENSSL_NO_IDEA) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("IDEA", EVP_idea_ecb); +#endif + +#if !defined(OPENSSL_NO_SEED) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("SEED", EVP_seed_ecb); +#endif + +} + +} diff --git a/src/lib/vendor/openssl/openssl_hash.cpp b/src/lib/vendor/openssl/openssl_hash.cpp new file mode 100644 index 000000000..6133e36a4 --- /dev/null +++ b/src/lib/vendor/openssl/openssl_hash.cpp @@ -0,0 +1,115 @@ +/* +* OpenSSL Hash Functions +* (C) 1999-2007,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include + +namespace Botan { + +namespace { + +class OpenSSL_HashFunction : public HashFunction + { + public: + void clear() + { + const EVP_MD* algo = EVP_MD_CTX_md(&m_md); + EVP_DigestInit_ex(&m_md, algo, nullptr); + } + + std::string name() const { return m_name; } + + HashFunction* clone() const + { + const EVP_MD* algo = EVP_MD_CTX_md(&m_md); + return new OpenSSL_HashFunction(algo, name()); + } + + size_t output_length() const + { + return EVP_MD_size(EVP_MD_CTX_md(&m_md)); + } + + size_t hash_block_size() const + { + return EVP_MD_block_size(EVP_MD_CTX_md(&m_md)); + } + + OpenSSL_HashFunction(const EVP_MD* md, const std::string& name) : m_name(name) + { + EVP_MD_CTX_init(&m_md); + EVP_DigestInit_ex(&m_md, md, nullptr); + } + + ~OpenSSL_HashFunction() + { + EVP_MD_CTX_cleanup(&m_md); + } + + private: + void add_data(const byte input[], size_t length) + { + EVP_DigestUpdate(&m_md, input, length); + } + + void final_result(byte output[]) + { + EVP_DigestFinal_ex(&m_md, output, nullptr); + const EVP_MD* algo = EVP_MD_CTX_md(&m_md); + EVP_DigestInit_ex(&m_md, algo, nullptr); + } + + std::string m_name; + EVP_MD_CTX m_md; + }; + +std::function +make_evp_hash_maker(const EVP_MD* md, const char* algo) + { + return [md,algo](const HashFunction::Spec&) + { + return new OpenSSL_HashFunction(md, algo); + }; + } + +#define BOTAN_REGISTER_OPENSSL_EVP_HASH(NAME, EVP) \ + BOTAN_REGISTER_TYPE(HashFunction, OpenSSL_HashFunction ## EVP, NAME, \ + make_evp_hash_maker(EVP(), NAME), "openssl", 32); + +#if !defined(OPENSSL_NO_SHA) + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-160", EVP_sha1); +#endif + +#if !defined(OPENSSL_NO_SHA256) + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-224", EVP_sha224); + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-256", EVP_sha256); +#endif + +#if !defined(OPENSSL_NO_SHA512) + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-384", EVP_sha384); + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-512", EVP_sha512); +#endif + +#if !defined(OPENSSL_NO_MD2) + BOTAN_REGISTER_OPENSSL_EVP_HASH("MD2", EVP_md2); +#endif + +#if !defined(OPENSSL_NO_MD4) + BOTAN_REGISTER_OPENSSL_EVP_HASH("MD4", EVP_md4); +#endif + +#if !defined(OPENSSL_NO_MD5) + BOTAN_REGISTER_OPENSSL_EVP_HASH("MD5", EVP_md5); +#endif + +#if !defined(OPENSSL_NO_RIPEMD) + BOTAN_REGISTER_OPENSSL_EVP_HASH("RIPEMD-160", EVP_ripemd160); +#endif + +} + +} diff --git a/src/lib/vendor/openssl/openssl_rc4.cpp b/src/lib/vendor/openssl/openssl_rc4.cpp new file mode 100644 index 000000000..966aecd66 --- /dev/null +++ b/src/lib/vendor/openssl/openssl_rc4.cpp @@ -0,0 +1,49 @@ +/* +* OpenSSL RC4 +* (C) 1999-2007,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include +#include + +namespace Botan { + +namespace { + +class OpenSSL_RC4 : public StreamCipher + { + public: + void clear() { clear_mem(&m_rc4, 1); } + + std::string name() const { return "RC4"; } + StreamCipher* clone() const { return new OpenSSL_RC4; } + + Key_Length_Specification key_spec() const + { + return Key_Length_Specification(1, 32); + } + + OpenSSL_RC4() { clear(); } + ~OpenSSL_RC4() { clear(); } + private: + void cipher(const byte in[], byte out[], size_t length) + { + RC4(&m_rc4, length, in, out); + } + + void key_schedule(const byte key[], size_t length) + { + RC4_set_key(&m_rc4, length, key); + } + + RC4_KEY m_rc4; + }; + +} + +BOTAN_REGISTER_TYPE(StreamCipher, OpenSSL_RC4, "RC4", make_new_T, "openssl", 64); + +} diff --git a/src/lib/vendor/sqlite3/info.txt b/src/lib/vendor/sqlite3/info.txt new file mode 100644 index 000000000..6370f4b2b --- /dev/null +++ b/src/lib/vendor/sqlite3/info.txt @@ -0,0 +1,10 @@ + +load_on request + + +all -> sqlite3 + + + +sqlite3.h + diff --git a/src/lib/vendor/sqlite3/sqlite3.cpp b/src/lib/vendor/sqlite3/sqlite3.cpp new file mode 100644 index 000000000..61c7f15bc --- /dev/null +++ b/src/lib/vendor/sqlite3/sqlite3.cpp @@ -0,0 +1,143 @@ +/* +* SQLite wrapper +* (C) 2012 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include +#include + +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; + } + +std::shared_ptr Sqlite3_Database::new_statement(const std::string& base_sql) const + { + return std::make_shared(m_db, base_sql); + } + +size_t Sqlite3_Database::row_count(const std::string& table_name) + { + auto stmt = new_statement("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_Database::Sqlite3_Statement::Sqlite3_Statement(sqlite3* db, const std::string& base_sql) + { + int rc = ::sqlite3_prepare_v2(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_Database::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_Database::Sqlite3_Statement::bind(int column, size_t val) + { + if(val != static_cast(static_cast(val))) // is this legit? + throw std::runtime_error("sqlite3 cannot store " + std::to_string(val) + " without truncation"); + 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_Database::Sqlite3_Statement::bind(int column, std::chrono::system_clock::time_point time) + { + const int timeval = std::chrono::duration_cast(time.time_since_epoch()).count(); + bind(column, timeval); + } + +void Sqlite3_Database::Sqlite3_Statement::bind(int column, const std::vector& 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 Sqlite3_Database::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(session_blob), + static_cast(session_blob_size)); + } + +size_t Sqlite3_Database::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(sessions_int); + } + +void Sqlite3_Database::Sqlite3_Statement::spin() + { + while(step()) {} + } + +bool Sqlite3_Database::Sqlite3_Statement::step() + { + return (::sqlite3_step(m_stmt) == SQLITE_ROW); + } + +Sqlite3_Database::Sqlite3_Statement::~Sqlite3_Statement() + { + ::sqlite3_finalize(m_stmt); + } + +} diff --git a/src/lib/vendor/sqlite3/sqlite3.h b/src/lib/vendor/sqlite3/sqlite3.h new file mode 100644 index 000000000..8495a1d1b --- /dev/null +++ b/src/lib/vendor/sqlite3/sqlite3.h @@ -0,0 +1,56 @@ +/* +* SQLite3 wrapper +* (C) 2012,2014 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_UTILS_SQLITE3_H__ +#define BOTAN_UTILS_SQLITE3_H__ + +#include + +class sqlite3; +class sqlite3_stmt; + +namespace Botan { + +class BOTAN_DLL Sqlite3_Database : public SQL_Database + { + public: + Sqlite3_Database(const std::string& file); + + ~Sqlite3_Database(); + + size_t row_count(const std::string& table_name) override; + + void create_table(const std::string& table_schema) override; + + std::shared_ptr new_statement(const std::string& sql) const override; + private: + class Sqlite3_Statement : public Statement + { + public: + void bind(int column, const std::string& val) override; + void bind(int column, size_t val) override; + void bind(int column, std::chrono::system_clock::time_point time) override; + void bind(int column, const std::vector& val) override; + + std::pair get_blob(int column) override; + size_t get_size_t(int column) override; + + void spin() override; + bool step() override; + + Sqlite3_Statement(sqlite3* db, const std::string& base_sql); + ~Sqlite3_Statement(); + private: + sqlite3_stmt* m_stmt; + }; + + sqlite3* m_db; + }; + +} + +#endif -- cgit v1.2.3