From e9e32235b47cfa0b8eb5a27c4ce421848442bb1e Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 8 Nov 2009 03:09:19 +0000 Subject: [PATCH] added support for libgcrypt --- Jamfile | 32 +++-- docs/building.rst | 30 ++--- include/libtorrent/config.hpp | 6 + include/libtorrent/hasher.hpp | 65 +++++++++- include/libtorrent/pe_crypto.hpp | 70 +++++++---- src/pe_crypto.cpp | 204 +++++++++++++++++++++---------- src/session_impl.cpp | 29 ++++- 7 files changed, 308 insertions(+), 128 deletions(-) diff --git a/Jamfile b/Jamfile index 433b73b0d..83b9e43f3 100755 --- a/Jamfile +++ b/Jamfile @@ -29,8 +29,7 @@ rule linking ( properties * ) local result ; # openssl libraries, if enabled - if sha-1 in $(properties) - || pe in $(properties) + if openssl in $(properties) { # exclude gcc from a regular windows build to make mingw # link against the regular unix library name @@ -55,6 +54,17 @@ rule linking ( properties * ) } } + # gcrypt libraries, if enabled + if gcrypt in $(properties) + { + # on mac os x, adding the /opt/local/include path + # would include openssl headers incompatible with + # the system library. Only add this include path + # if we're not using openssl (which we're most + # likely not if we're using libgcrypt) + result += gcrypt /opt/local/include ; + } + if shared in $(properties) { result += GeoIP ; @@ -161,16 +171,13 @@ rule building ( properties * ) result += src/GeoIP.c ; } - if off in $(properties) + if off in $(properties) { result += src/sha1.cpp ; } else { - if pe in $(properties) - { - result += src/pe_crypto.cpp ; - } + result += src/pe_crypto.cpp ; if linux in $(properties) { @@ -228,10 +235,10 @@ feature dht-support : on off logging : composite propagated link-incompatible ; feature.compose off : TORRENT_DISABLE_DHT ; feature.compose logging : TORRENT_DHT_VERBOSE_LOGGING ; -feature openssl : pe sha-1 off : composite propagated link-incompatible ; -feature.compose pe : TORRENT_USE_OPENSSL ; -feature.compose sha-1 : TORRENT_USE_OPENSSL TORRENT_DISABLE_ENCRYPTION ; -feature.compose off : TORRENT_DISABLE_ENCRYPTION ; +feature encryption : off openssl gcrypt : composite propagated link-incompatible ; +feature.compose openssl : TORRENT_USE_OPENSSL ; +feature.compose gcrypt : TORRENT_USE_GCRYPT ; +feature.compose off : TORRENT_DISABLE_ENCRYPTION ; feature resolve-countries : on off : composite propagated link-incompatible ; feature.compose off : TORRENT_DISABLE_RESOLVE_COUNTRIES ; @@ -285,8 +292,9 @@ lib boost_system : : darwin boost_system-mt $(boost-library-sea lib boost_system : : boost_system ; # openssl on linux/bsd/macos etc. +lib gcrypt : : gcrypt shared /opt/local/lib ; lib crypto : : crypto shared ; -lib ssl : : ssl shared ; +lib ssl : : ssl shared crypto ; # time functions used on linux require librt lib librt : : rt shared ; diff --git a/docs/building.rst b/docs/building.rst index 562dc5c2b..a37d26734 100644 --- a/docs/building.rst +++ b/docs/building.rst @@ -287,16 +287,14 @@ Build features: | | * ``on`` - creates "upnp.log" with the messages | | | sent to and received from UPnP devices. | +--------------------------+----------------------------------------------------+ -| ``openssl`` | * ``pe`` - turns on support for encrypted | -| | connections. requires openssl (libcrypto) | -| | * ``sha-1`` - openssl will be used instead of the | -| | public domain SHA-1 implementation shipped with | -| | libtorrent. ``libcrypto.a`` will be required for | -| | linking. Encryption support is still turned off. | +| ``encryption`` | * ``openssl`` - links against openssl and | +| | libcrypto to enable https and encrypted | +| | bittorrent connections. | +| | * ``gcrypt`` - links against libgcrypt to enable | +| | encrypted bittorrent connections. | | | * ``off`` - turns off support for encrypted | -| | connections. openssl is not linked in. The | -| | shipped public domain SHA-1 implementation is | -| | used. | +| | connections. The shipped public domain SHA-1 | +| | implementation is used. | +--------------------------+----------------------------------------------------+ | ``pool-allocators`` | * ``on`` - default, uses pool allocators for send | | | buffers. | @@ -573,15 +571,6 @@ defines you can use to control the build. | | UTF-16 before they are passed to the file | | | operations. | +----------------------------------------+-------------------------------------------------+ -| ``LITTLE_ENDIAN`` | This will use the little endian version of the | -| | sha-1 code. If defined on a big-endian system | -| | the sha-1 hashes will be incorrect and fail. | -| | If it is not defined and ``__BIG_ENDIAN__`` | -| | isn't defined either (it is defined by Apple's | -| | GCC) both little-endian and big-endian versions | -| | will be built and the correct code will be | -| | chosen at run-time. | -+----------------------------------------+-------------------------------------------------+ | ``TORRENT_DISABLE_POOL_ALLOCATOR`` | Disables use of ``boost::pool<>``. | +----------------------------------------+-------------------------------------------------+ | ``TORRENT_LINKING_SHARED`` | If this is defined when including the | @@ -608,10 +597,13 @@ defines you can use to control the build. | | protocol traffic. | +----------------------------------------+-------------------------------------------------+ | ``TORRENT_DISABLE_ENCRYPTION`` | This will disable any encryption support and | -| | the openssl dependency that comes with it. | +| | the dependencies of a crypto library. | | | Encryption support is the peer connection | | | encrypted supported by clients such as | | | uTorrent, Azureus and KTorrent. | +| | If this is not defined, either | +| | ``TORRENT_USE_OPENSSL`` or | +| | ``TORRENT_USE_GCRYPT`` must be defined. | +----------------------------------------+-------------------------------------------------+ | ``_UNICODE`` | On windows, this will cause the file IO | | | use wide character API, to properly support | diff --git a/include/libtorrent/config.hpp b/include/libtorrent/config.hpp index e1549b335..d24062fb0 100644 --- a/include/libtorrent/config.hpp +++ b/include/libtorrent/config.hpp @@ -33,6 +33,12 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_CONFIG_HPP_INCLUDED #define TORRENT_CONFIG_HPP_INCLUDED +#if !defined TORRENT_USE_OPENSSL \ + && !defined TORRENT_USE_GCRYPT \ + && !defined TORRENT_DISABLE_ENCRYPTION +#error you need to either disable encryption or specify which library to use +#endif + #include #include #include // for snprintf diff --git a/include/libtorrent/hasher.hpp b/include/libtorrent/hasher.hpp index f4f0a6c0c..554daa13e 100644 --- a/include/libtorrent/hasher.hpp +++ b/include/libtorrent/hasher.hpp @@ -40,7 +40,9 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/assert.hpp" #include "zlib.h" -#ifdef TORRENT_USE_OPENSSL +#ifdef TORRENT_USE_GCRYPT +#include +#elif defined TORRENT_USE_OPENSSL extern "C" { #include @@ -87,35 +89,88 @@ namespace libtorrent { public: - hasher() { SHA1_Init(&m_context); } + hasher() + { +#ifdef TORRENT_USE_GCRYPT + gcry_md_open(&m_context, GCRY_MD_SHA1, 0); +#else + SHA1_Init(&m_context); +#endif + } hasher(const char* data, int len) { - SHA1_Init(&m_context); TORRENT_ASSERT(data != 0); TORRENT_ASSERT(len > 0); +#ifdef TORRENT_USE_GCRYPT + gcry_md_open(&m_context, GCRY_MD_SHA1, 0); + gcry_md_write(m_context, data, len); +#else + SHA1_Init(&m_context); SHA1_Update(&m_context, reinterpret_cast(data), len); +#endif } + +#ifdef TORRENT_USE_GCRYPT + hasher(hasher const& h) + { + gcry_md_copy(&m_context, h.m_context); + } + + hasher& operator=(hasher const& h) + { + gcry_md_close(m_context); + gcry_md_copy(&m_context, h.m_context); + return *this; + } +#endif + void update(std::string const& data) { update(&data[0], data.size()); } void update(const char* data, int len) { TORRENT_ASSERT(data != 0); TORRENT_ASSERT(len > 0); +#ifdef TORRENT_USE_GCRYPT + gcry_md_write(m_context, data, len); +#else SHA1_Update(&m_context, reinterpret_cast(data), len); +#endif } sha1_hash final() { sha1_hash digest; +#ifdef TORRENT_USE_GCRYPT + gcry_md_final(m_context); + digest.assign((const char*)gcry_md_read(m_context, 0)); +#else SHA1_Final(digest.begin(), &m_context); +#endif return digest; } - void reset() { SHA1_Init(&m_context); } + void reset() + { +#ifdef TORRENT_USE_GCRYPT + gcry_md_reset(m_context); +#else + SHA1_Init(&m_context); +#endif + } + +#ifdef TORRENT_USE_GCRYPT + ~hasher() + { + gcry_md_close(m_context); + } +#endif private: +#ifdef TORRENT_USE_GCRYPT + gcry_md_hd_t m_context; +#else SHA_CTX m_context; - +#endif }; } diff --git a/include/libtorrent/pe_crypto.hpp b/include/libtorrent/pe_crypto.hpp index c0c43e7fb..8d6bef188 100644 --- a/include/libtorrent/pe_crypto.hpp +++ b/include/libtorrent/pe_crypto.hpp @@ -35,9 +35,13 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED #define TORRENT_PE_CRYPTO_HPP_INCLUDED -#include -#include +#ifdef TORRENT_USE_GCRYPT +#include +#endif + +#ifdef TORRENT_USE_OPENSSL #include +#endif #include "libtorrent/peer_id.hpp" // For sha1_hash #include "libtorrent/assert.hpp" @@ -48,31 +52,27 @@ namespace libtorrent { public: dh_key_exchange(); - ~dh_key_exchange(); - bool good() const { return m_dh; } + bool good() const { return true; } // Get local public key, always 96 bytes char const* get_local_key() const; // read remote_pubkey, generate and store shared secret in - // m_dh_secret. + // m_dh_shared_secret. int compute_secret(const char* remote_pubkey); - char const* get_secret() const { return m_dh_secret; } + char const* get_secret() const { return m_dh_shared_secret; } sha1_hash const& get_hash_xor_mask() const { return m_xor_mask; } private: - int get_local_key_size() const - { - TORRENT_ASSERT(m_dh); - return BN_num_bytes(m_dh->pub_key); - } - DH* m_dh; + int get_local_key_size() const + { return sizeof(m_dh_local_key); } char m_dh_local_key[96]; - char m_dh_secret[96]; + char m_dh_local_secret[96]; + char m_dh_shared_secret[96]; sha1_hash m_xor_mask; }; @@ -80,13 +80,18 @@ namespace libtorrent { public: // Input longkeys must be 20 bytes - RC4_handler(const sha1_hash& rc4_local_longkey, - const sha1_hash& rc4_remote_longkey) + RC4_handler(sha1_hash const& rc4_local_longkey, + sha1_hash const& rc4_remote_longkey) { - RC4_set_key(&m_local_key, 20, - reinterpret_cast(rc4_local_longkey.begin())); - RC4_set_key(&m_remote_key, 20, - reinterpret_cast(rc4_remote_longkey.begin())); +#ifdef TORRENT_USE_GCRYPT + gcry_cipher_open(&m_rc4_incoming, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0); + gcry_cipher_open(&m_rc4_outgoing, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0); + gcry_cipher_setkey(m_rc4_incoming, &rc4_remote_longkey[0], 20); + gcry_cipher_setkey(m_rc4_outgoing, &rc4_local_longkey[0], 20); +#elif defined TORRENT_USE_OPENSSL + RC4_set_key(&m_local_key, 20, &rc4_local_longkey[0]); + RC4_set_key(&m_remote_key, 20, &rc4_remote_longkey[0]); +#endif // Discard first 1024 bytes char buf[1024]; @@ -94,15 +99,24 @@ namespace libtorrent decrypt(buf, 1024); }; - ~RC4_handler() {}; + ~RC4_handler() + { +#ifdef TORRENT_USE_GCRYPT + gcry_cipher_close(m_rc4_incoming); + gcry_cipher_close(m_rc4_outgoing); +#endif + }; void encrypt(char* pos, int len) { TORRENT_ASSERT(len >= 0); TORRENT_ASSERT(pos); - RC4(&m_local_key, len, reinterpret_cast(pos), - reinterpret_cast(pos)); +#ifdef TORRENT_USE_GCRYPT + gcry_cipher_encrypt(m_rc4_outgoing, pos, len, 0, 0); +#elif defined TORRENT_USE_OPENSSL + RC4(&m_local_key, len, (const unsigned char*)pos, (unsigned char*)pos); +#endif } void decrypt(char* pos, int len) @@ -110,13 +124,21 @@ namespace libtorrent TORRENT_ASSERT(len >= 0); TORRENT_ASSERT(pos); - RC4(&m_remote_key, len, reinterpret_cast(pos), - reinterpret_cast(pos)); +#ifdef TORRENT_USE_GCRYPT + gcry_cipher_decrypt(m_rc4_incoming, pos, len, 0, 0); +#elif defined TORRENT_USE_OPENSSL + RC4(&m_remote_key, len, (const unsigned char*)pos, (unsigned char*)pos); +#endif } private: +#ifdef TORRENT_USE_GCRYPT + gcry_cipher_hd_t m_rc4_incoming; + gcry_cipher_hd_t m_rc4_outgoing; +#elif defined TORRENT_USE_OPENSSL RC4_KEY m_local_key; // Key to encrypt outgoing data RC4_KEY m_remote_key; // Key to decrypt incoming data +#endif }; } // namespace libtorrent diff --git a/src/pe_crypto.cpp b/src/pe_crypto.cpp index fe6ab6c81..e102ab5a7 100644 --- a/src/pe_crypto.cpp +++ b/src/pe_crypto.cpp @@ -34,8 +34,12 @@ POSSIBILITY OF SUCH DAMAGE. #include -#include -#include +#if defined TORRENT_USE_GCRYPT +#include +#elif defined TORRENT_USE_OPENSSL +#include +#include +#endif #include "libtorrent/pe_crypto.hpp" #include "libtorrent/hasher.hpp" @@ -55,69 +59,85 @@ namespace libtorrent 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63 }; - - const unsigned char dh_generator[1] = { 2 }; } // Set the prime P and the generator, generate local public key dh_key_exchange::dh_key_exchange() { - m_dh = DH_new(); - if (m_dh == 0) return; +#ifdef TORRENT_USE_GCRYPT + // create local key + gcry_randomize(m_dh_local_secret, sizeof(m_dh_local_secret), GCRY_STRONG_RANDOM); - m_dh->p = BN_bin2bn(dh_prime, sizeof(dh_prime), 0); - m_dh->g = BN_bin2bn(dh_generator, sizeof(dh_generator), 0); - if (m_dh->p == 0 || m_dh->g == 0) + // build gcrypt big ints from the prime and the secret + gcry_mpi_t prime = 0; + gcry_mpi_t secret = 0; + gcry_mpi_t key = 0; + gcry_error_t e; + + e = gcry_mpi_scan(&prime, GCRYMPI_FMT_USG, dh_prime, sizeof(dh_prime), 0); + if (e) goto get_out; + e = gcry_mpi_scan(&secret, GCRYMPI_FMT_USG, m_dh_local_secret, sizeof(m_dh_local_secret), 0); + if (e) goto get_out; + + key = gcry_mpi_new(8); + + // generator is 2 + gcry_mpi_set_ui(key, 2); + // key = (2 ^ secret) % prime + gcry_mpi_powm(key, key, secret, prime); + + // key is now our local key + size_t written; + gcry_mpi_print(GCRYMPI_FMT_USG, (unsigned char*)m_dh_local_key + , sizeof(m_dh_local_key), &written, key); + if (written < 96) { - DH_free(m_dh); - m_dh = 0; - return; + memmove(m_dh_local_key + (sizeof(m_dh_local_key) - written), m_dh_local_key, written); + memset(m_dh_local_key, 0, sizeof(m_dh_local_key) - written); } - m_dh->length = 160l; +get_out: + if (key) gcry_mpi_release(key); + if (prime) gcry_mpi_release(prime); + if (secret) gcry_mpi_release(secret); - TORRENT_ASSERT(sizeof(dh_prime) == DH_size(m_dh)); - - if (DH_generate_key(m_dh) == 0 || m_dh->pub_key == 0) - { - DH_free(m_dh); - m_dh = 0; - return; - } +#elif defined TORRENT_USE_OPENSSL + // create local key + RAND_bytes((unsigned char*)m_dh_local_secret, sizeof(m_dh_local_secret)); - // DH can generate key sizes that are smaller than the size of - // P with exponentially decreasing probability, in which case - // the msb's of m_dh_local_key need to be zeroed - // appropriately. - int key_size = get_local_key_size(); - int len_dh = sizeof(dh_prime); // must equal DH_size(m_DH) - if (key_size != len_dh) - { - TORRENT_ASSERT(key_size > 0 && key_size < len_dh); + BIGNUM* prime = 0; + BIGNUM* secret = 0; + BIGNUM* key = 0; + BN_CTX* ctx = 0; + int size; - int pad_zero_size = len_dh - key_size; - std::fill(m_dh_local_key, m_dh_local_key + pad_zero_size, 0); - if (BN_bn2bin(m_dh->pub_key, (unsigned char*)m_dh_local_key + pad_zero_size) == 0) - { - DH_free(m_dh); - m_dh = 0; - return; - } - } - else - { - if (BN_bn2bin(m_dh->pub_key, (unsigned char*)m_dh_local_key) == 0) - { - DH_free(m_dh); - m_dh = 0; - return; - } - } - } + prime = BN_bin2bn(dh_prime, sizeof(dh_prime), 0); + if (prime == 0) goto get_out; + secret = BN_bin2bn((unsigned char*)m_dh_local_secret, sizeof(m_dh_local_secret), 0); + if (secret == 0) goto get_out; - dh_key_exchange::~dh_key_exchange() - { - if (m_dh) DH_free(m_dh); + key = BN_new(); + if (key == 0) goto get_out; + // generator is 2 + BN_set_word(key, 2); + + ctx = BN_CTX_new(); + if (ctx == 0) goto get_out; + BN_mod_exp(key, key, secret, prime, ctx); + BN_CTX_free(ctx); + + // print key to m_dh_local_key + size = BN_num_bytes(key); + memset(m_dh_local_key, 0, sizeof(m_dh_local_key) - size); + BN_bn2bin(key, (unsigned char*)m_dh_local_key + sizeof(m_dh_local_key) - size); + +get_out: + if (key) BN_free(key); + if (secret) BN_free(secret); + if (prime) BN_free(prime); +#else +#error you must define TORRENT_USE_OPENSSL or TORRENT_USE_GCRYPT +#endif } char const* dh_key_exchange::get_local_key() const @@ -130,29 +150,81 @@ namespace libtorrent int dh_key_exchange::compute_secret(char const* remote_pubkey) { TORRENT_ASSERT(remote_pubkey); - BIGNUM* bn_remote_pubkey = BN_bin2bn ((unsigned char*)remote_pubkey, 96, NULL); - if (bn_remote_pubkey == 0) return -1; - char dh_secret[96]; + int ret = 0; +#ifdef TORRENT_USE_GCRYPT - int secret_size = DH_compute_key((unsigned char*)dh_secret - , bn_remote_pubkey, m_dh); - if (secret_size < 0 || secret_size > 96) return -1; + gcry_mpi_t prime = 0; + gcry_mpi_t remote_key = 0; + gcry_mpi_t secret = 0; + size_t written; + gcry_error_t e; - if (secret_size != 96) + e = gcry_mpi_scan(&prime, GCRYMPI_FMT_USG, dh_prime, sizeof(dh_prime), 0); + if (e != 0) { ret = 1; goto get_out; } + e = gcry_mpi_scan(&remote_key, GCRYMPI_FMT_USG, remote_pubkey, 96, 0); + if (e != 0) { ret = 1; goto get_out; } + e = gcry_mpi_scan(&secret, GCRYMPI_FMT_USG, (unsigned char const*)m_dh_local_secret + , sizeof(m_dh_local_secret), 0); + if (e != 0) { ret = 1; goto get_out; } + + gcry_mpi_powm(remote_key, remote_key, secret, prime); + + // remote_key is now the shared secret + e = gcry_mpi_print(GCRYMPI_FMT_USG, (unsigned char*)m_dh_shared_secret + , sizeof(m_dh_shared_secret), &written, remote_key); + if (e != 0) { ret = 1; goto get_out; } + + if (written < 96) { - TORRENT_ASSERT(secret_size < 96 && secret_size > 0); - std::fill(m_dh_secret, m_dh_secret + 96 - secret_size, 0); + memmove(m_dh_shared_secret, m_dh_shared_secret + + (sizeof(m_dh_shared_secret) - written), written); + memset(m_dh_shared_secret, 0, sizeof(m_dh_shared_secret) - written); } - std::copy(dh_secret, dh_secret + secret_size, m_dh_secret + 96 - secret_size); - BN_free(bn_remote_pubkey); + +get_out: + if (prime) gcry_mpi_release(prime); + if (remote_key) gcry_mpi_release(remote_key); + if (secret) gcry_mpi_release(secret); + +#elif defined TORRENT_USE_OPENSSL + + BIGNUM* prime = 0; + BIGNUM* secret = 0; + BIGNUM* remote_key = 0; + BN_CTX* ctx = 0; + int size; + + prime = BN_bin2bn(dh_prime, sizeof(dh_prime), 0); + if (prime == 0) { ret = 1; goto get_out; } + secret = BN_bin2bn((unsigned char*)m_dh_local_secret, sizeof(m_dh_local_secret), 0); + if (secret == 0) { ret = 1; goto get_out; } + remote_key = BN_bin2bn((unsigned char*)remote_pubkey, 96, 0); + if (remote_key == 0) { ret = 1; goto get_out; } + + ctx = BN_CTX_new(); + if (ctx == 0) { ret = 1; goto get_out; } + BN_mod_exp(remote_key, remote_key, secret, prime, ctx); + BN_CTX_free(ctx); + + // remote_key is now the shared secret + size = BN_num_bytes(remote_key); + memset(m_dh_shared_secret, 0, sizeof(m_dh_shared_secret) - size); + BN_bn2bin(remote_key, (unsigned char*)m_dh_shared_secret + sizeof(m_dh_shared_secret) - size); + +get_out: + BN_free(remote_key); + BN_free(secret); + BN_free(prime); +#else +#error you must define TORRENT_USE_OPENSSL or TORRENT_USE_GCRYPT +#endif // calculate the xor mask for the obfuscated hash hasher h; h.update("req3", 4); - h.update(m_dh_secret, 96); + h.update(m_dh_shared_secret, sizeof(m_dh_shared_secret)); m_xor_mask = h.final(); - - return 0; + return ret; } } // namespace libtorrent diff --git a/src/session_impl.cpp b/src/session_impl.cpp index b09e5e64c..f6be81ebd 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -92,7 +92,31 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif -#ifndef TORRENT_DISABLE_ENCRYPTION +#ifdef TORRENT_USE_GCRYPT + +extern "C" { +GCRY_THREAD_OPTION_PTHREAD_IMPL; +} + +namespace +{ + // libgcrypt requires this to initialize the library + struct gcrypt_setup + { + gcrypt_setup() + { + gcry_check_version(0); + gcry_error_t e = gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + if (e != 0) fprintf(stderr, "libcrypt ERROR: %s\n", gcry_strerror(e)); + e = gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + if (e != 0) fprintf(stderr, "initialization finished error: %s\n", gcry_strerror(e)); + } + } gcrypt_global_constructor; +} + +#endif // TORRENT_USE_GCRYPT + +#ifdef TORRENT_USE_OPENSSL #include @@ -106,7 +130,8 @@ namespace } openssl_global_destructor; } -#endif +#endif // TORRENT_USE_OPENSSL + #ifdef TORRENT_WINDOWS // for ERROR_SEM_TIMEOUT #include