From 04f07aa429c8f20d9afda4f3dda6fc01d8841715 Mon Sep 17 00:00:00 2001 From: vogel76 Date: Mon, 2 Jun 2014 17:31:28 +0200 Subject: [PATCH 1/3] [BW]: [Fix] Eliminated OpenSSL initialization from CRT init time (which caused random problems on windows7 machines leading the application to silent crash). Right now it is done at first use of fc parts using it. Also added method to setup OpenSSL configuration path to custom one (to avoid using path compiled into OpenSSL at configuration & build time). --- CMakeLists.txt | 7 +++++++ include/fc/crypto/openssl.hpp | 8 ++++++++ src/crypto/aes.cpp | 15 +++++++++++---- src/crypto/elliptic.cpp | 5 +++-- src/crypto/openssl.cpp | 19 ++++++++++++++++++- src/crypto/rand.cpp | 6 ++++-- 6 files changed, 51 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f3e8f5..e00f7a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -305,5 +305,12 @@ if(WIN32) endif(WIN32) +SET(POST_BUILD_STEP_COMMANDS ${POST_BUILD_STEP_COMMANDS} + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OPENSSL_ROOT_DIR}/ssl/openssl.cnf" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/openssl.cnf") + +ADD_CUSTOM_COMMAND(TARGET fc POST_BUILD ${POST_BUILD_STEP_COMMANDS} + COMMENT "Copying OpenSSL/ssl/openssl.cnf into target directory." +) + MESSAGE(STATUS "Finished fc module configuration...") diff --git a/include/fc/crypto/openssl.hpp b/include/fc/crypto/openssl.hpp index f21ee3c..0bf0fe8 100644 --- a/include/fc/crypto/openssl.hpp +++ b/include/fc/crypto/openssl.hpp @@ -15,6 +15,7 @@ */ namespace fc { + class path; template struct ssl_wrapper @@ -55,6 +56,13 @@ namespace fc ~ssl_bignum() { BN_free(obj); } }; + /** Allows to explicitly specify OpenSSL configuration file path to be loaded at OpenSSL library init. + If not set OpenSSL will try to load the conf. file (openssl.cnf) from the path it was + configured with what caused serious Keyhotee startup bugs on some Win7 machines. + \warning to be effective this method should be used before any part using OpenSSL, especially + before init_openssl call + */ + void store_configuration_path(const path& filePath); int init_openssl(); } // namespace fc diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index 26c464b..8e51519 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -10,17 +10,20 @@ namespace fc { -static int init = init_openssl(); - struct aes_encoder::impl { evp_cipher_ctx ctx; }; -aes_encoder::aes_encoder(){} +aes_encoder::aes_encoder() +{ + static int init = init_openssl(); +} + aes_encoder::~aes_encoder() { } + void aes_encoder::init( const fc::sha256& key, const fc::uint128& init_value ) { my->ctx.obj = EVP_CIPHER_CTX_new(); @@ -80,7 +83,11 @@ struct aes_decoder::impl evp_cipher_ctx ctx; }; -aes_decoder::aes_decoder(){} +aes_decoder::aes_decoder() + { + static int init = init_openssl(); + } + void aes_decoder::init( const fc::sha256& key, const fc::uint128& init_value ) { my->ctx.obj = EVP_CIPHER_CTX_new(); diff --git a/src/crypto/elliptic.cpp b/src/crypto/elliptic.cpp index ac79aed..dd3c4cb 100644 --- a/src/crypto/elliptic.cpp +++ b/src/crypto/elliptic.cpp @@ -10,8 +10,6 @@ #include namespace fc { namespace ecc { - static int init = init_openssl(); - namespace detail { class public_key_impl @@ -20,7 +18,9 @@ namespace fc { namespace ecc { public_key_impl() :_key(nullptr) { + static int init = init_openssl(); } + ~public_key_impl() { if( _key != nullptr ) @@ -40,6 +40,7 @@ namespace fc { namespace ecc { private_key_impl() :_key(nullptr) { + static int init = init_openssl(); } ~private_key_impl() { diff --git a/src/crypto/openssl.cpp b/src/crypto/openssl.cpp index ae43cfb..82e453c 100644 --- a/src/crypto/openssl.cpp +++ b/src/crypto/openssl.cpp @@ -1,20 +1,37 @@ #include + +#include + +#include + +#include + namespace fc { struct openssl_scope { + static path _configurationFilePath; openssl_scope() { ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); - OPENSSL_config(NULL); + const boost::filesystem::path& boostPath = _configurationFilePath; + OPENSSL_config(boostPath.empty() ? nullptr : _configurationFilePath.to_native_ansi_path().c_str()); } + ~openssl_scope() { EVP_cleanup(); ERR_free_strings(); } }; + + path openssl_scope::_configurationFilePath; + + void store_configuration_path(const path& filePath) + { + openssl_scope::_configurationFilePath = filePath; + } int init_openssl() { diff --git a/src/crypto/rand.cpp b/src/crypto/rand.cpp index 313ba75..7235ab6 100644 --- a/src/crypto/rand.cpp +++ b/src/crypto/rand.cpp @@ -6,10 +6,10 @@ namespace fc { -static int init = init_openssl(); - void rand_bytes(char* buf, int count) { + static int init = init_openssl(); + int result = RAND_bytes((unsigned char*)buf, count); if (result != 1) FC_THROW("Error calling OpenSSL's RAND_bytes(): ${code}", ("code", (uint32_t)ERR_get_error())); @@ -17,6 +17,8 @@ void rand_bytes(char* buf, int count) void rand_pseudo_bytes(char* buf, int count) { + static int init = init_openssl(); + int result = RAND_pseudo_bytes((unsigned char*)buf, count); if (result == -1) FC_THROW("Error calling OpenSSL's RAND_pseudo_bytes(): ${code}", ("code", (uint32_t)ERR_get_error())); From 2251d0f2417cf716c6e0bea8e0a98909dbea2d59 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Mon, 2 Jun 2014 13:32:16 -0400 Subject: [PATCH 2/3] Fix bigint on conversions to and from 64-bit integers on 32-bit platforms Fixes BitShares/bitshares_toolkit#150 --- include/fc/crypto/bigint.hpp | 2 +- src/crypto/bigint.cpp | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/include/fc/crypto/bigint.hpp b/include/fc/crypto/bigint.hpp index e4fdd8b..debc869 100644 --- a/include/fc/crypto/bigint.hpp +++ b/include/fc/crypto/bigint.hpp @@ -11,7 +11,7 @@ namespace fc { public: bigint( const std::vector& bige ); bigint( const char* bige, uint32_t l ); - bigint( unsigned long i ); + bigint(uint64_t value); bigint( ); bigint( const bigint& c ); bigint( bigint&& c ); diff --git a/src/crypto/bigint.cpp b/src/crypto/bigint.cpp index 0682992..e26b2c9 100644 --- a/src/crypto/bigint.cpp +++ b/src/crypto/bigint.cpp @@ -6,6 +6,16 @@ #include +#ifdef _MSC_VER +# include +# define bswap_64(x) _byteswap_uint64(x) +#elif defined(__APPLE__) +# include +# define bswap_64(x) OSSwapInt64(x) +#else +# include +#endif + namespace fc { bigint::bigint( const char* bige, uint32_t l ) { n = BN_bin2bn( (const unsigned char*)bige, l, NULL ); @@ -28,9 +38,10 @@ namespace fc { return BN_dup( n ); } - bigint::bigint( unsigned long i ) - :n(BN_new()) { - BN_set_word( n, i ); + bigint::bigint(uint64_t value) + { + uint64_t big_endian_value = bswap_64(value); + n = BN_bin2bn((const unsigned char*)&big_endian_value, sizeof(big_endian_value), NULL); } bigint::bigint( const bigint& c ) { @@ -47,7 +58,15 @@ namespace fc { } bool bigint::is_negative()const { return BN_is_negative(n); } - int64_t bigint::to_int64()const { return BN_get_word(n); } + + int64_t bigint::to_int64() const + { + FC_ASSERT(BN_num_bits(n) <= 63); + size_t size = BN_num_bytes(n); + uint64_t abs_value = 0; + BN_bn2bin(n, (unsigned char*)&abs_value + (sizeof(uint64_t) - size)); + return BN_is_negative(n) ? -bswap_64(abs_value) : bswap_64(abs_value); + } int64_t bigint::log2()const { return BN_num_bits(n); } bool bigint::operator < ( const bigint& c )const { From 222092012681f1dd4e3290360afe41be30c427f1 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Mon, 2 Jun 2014 17:19:36 -0400 Subject: [PATCH 3/3] Fix signed bigint conversion (probably never used) --- src/crypto/bigint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/bigint.cpp b/src/crypto/bigint.cpp index e26b2c9..b76ba92 100644 --- a/src/crypto/bigint.cpp +++ b/src/crypto/bigint.cpp @@ -65,7 +65,7 @@ namespace fc { size_t size = BN_num_bytes(n); uint64_t abs_value = 0; BN_bn2bin(n, (unsigned char*)&abs_value + (sizeof(uint64_t) - size)); - return BN_is_negative(n) ? -bswap_64(abs_value) : bswap_64(abs_value); + return BN_is_negative(n) ? -(int64_t)bswap_64(abs_value) : bswap_64(abs_value); } int64_t bigint::log2()const { return BN_num_bits(n); }