added support for libgcrypt

This commit is contained in:
Arvid Norberg 2009-11-08 03:09:19 +00:00
parent e86ad4f0f7
commit e9e32235b4
7 changed files with 308 additions and 128 deletions

32
Jamfile
View File

@ -29,8 +29,7 @@ rule linking ( properties * )
local result ; local result ;
# openssl libraries, if enabled # openssl libraries, if enabled
if <openssl>sha-1 in $(properties) if <encryption>openssl in $(properties)
|| <openssl>pe in $(properties)
{ {
# exclude gcc from a regular windows build to make mingw # exclude gcc from a regular windows build to make mingw
# link against the regular unix library name # link against the regular unix library name
@ -55,6 +54,17 @@ rule linking ( properties * )
} }
} }
# gcrypt libraries, if enabled
if <encryption>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 += <library>gcrypt <include>/opt/local/include ;
}
if <geoip>shared in $(properties) if <geoip>shared in $(properties)
{ {
result += <library>GeoIP ; result += <library>GeoIP ;
@ -161,16 +171,13 @@ rule building ( properties * )
result += <source>src/GeoIP.c ; result += <source>src/GeoIP.c ;
} }
if <openssl>off in $(properties) if <encryption>off in $(properties)
{ {
result += <source>src/sha1.cpp ; result += <source>src/sha1.cpp ;
} }
else else
{ {
if <openssl>pe in $(properties) result += <source>src/pe_crypto.cpp ;
{
result += <source>src/pe_crypto.cpp ;
}
if <target-os>linux in $(properties) if <target-os>linux in $(properties)
{ {
@ -228,10 +235,10 @@ feature dht-support : on off logging : composite propagated link-incompatible ;
feature.compose <dht-support>off : <define>TORRENT_DISABLE_DHT ; feature.compose <dht-support>off : <define>TORRENT_DISABLE_DHT ;
feature.compose <dht-support>logging : <define>TORRENT_DHT_VERBOSE_LOGGING ; feature.compose <dht-support>logging : <define>TORRENT_DHT_VERBOSE_LOGGING ;
feature openssl : pe sha-1 off : composite propagated link-incompatible ; feature encryption : off openssl gcrypt : composite propagated link-incompatible ;
feature.compose <openssl>pe : <define>TORRENT_USE_OPENSSL ; feature.compose <encryption>openssl : <define>TORRENT_USE_OPENSSL ;
feature.compose <openssl>sha-1 : <define>TORRENT_USE_OPENSSL <define>TORRENT_DISABLE_ENCRYPTION ; feature.compose <encryption>gcrypt : <define>TORRENT_USE_GCRYPT ;
feature.compose <openssl>off : <define>TORRENT_DISABLE_ENCRYPTION ; feature.compose <encryption>off : <define>TORRENT_DISABLE_ENCRYPTION ;
feature resolve-countries : on off : composite propagated link-incompatible ; feature resolve-countries : on off : composite propagated link-incompatible ;
feature.compose <resolve-countries>off : <define>TORRENT_DISABLE_RESOLVE_COUNTRIES ; feature.compose <resolve-countries>off : <define>TORRENT_DISABLE_RESOLVE_COUNTRIES ;
@ -285,8 +292,9 @@ lib boost_system : : <target-os>darwin <name>boost_system-mt $(boost-library-sea
lib boost_system : : <name>boost_system ; lib boost_system : : <name>boost_system ;
# openssl on linux/bsd/macos etc. # openssl on linux/bsd/macos etc.
lib gcrypt : : <name>gcrypt <link>shared <search>/opt/local/lib ;
lib crypto : : <name>crypto <link>shared ; lib crypto : : <name>crypto <link>shared ;
lib ssl : : <name>ssl <link>shared ; lib ssl : : <name>ssl <link>shared <use>crypto ;
# time functions used on linux require librt # time functions used on linux require librt
lib librt : : <name>rt <link>shared ; lib librt : : <name>rt <link>shared ;

View File

@ -287,16 +287,14 @@ Build features:
| | * ``on`` - creates "upnp.log" with the messages | | | * ``on`` - creates "upnp.log" with the messages |
| | sent to and received from UPnP devices. | | | sent to and received from UPnP devices. |
+--------------------------+----------------------------------------------------+ +--------------------------+----------------------------------------------------+
| ``openssl`` | * ``pe`` - turns on support for encrypted | | ``encryption`` | * ``openssl`` - links against openssl and |
| | connections. requires openssl (libcrypto) | | | libcrypto to enable https and encrypted |
| | * ``sha-1`` - openssl will be used instead of the | | | bittorrent connections. |
| | public domain SHA-1 implementation shipped with | | | * ``gcrypt`` - links against libgcrypt to enable |
| | libtorrent. ``libcrypto.a`` will be required for | | | encrypted bittorrent connections. |
| | linking. Encryption support is still turned off. |
| | * ``off`` - turns off support for encrypted | | | * ``off`` - turns off support for encrypted |
| | connections. openssl is not linked in. The | | | connections. The shipped public domain SHA-1 |
| | shipped public domain SHA-1 implementation is | | | implementation is used. |
| | used. |
+--------------------------+----------------------------------------------------+ +--------------------------+----------------------------------------------------+
| ``pool-allocators`` | * ``on`` - default, uses pool allocators for send | | ``pool-allocators`` | * ``on`` - default, uses pool allocators for send |
| | buffers. | | | buffers. |
@ -573,15 +571,6 @@ defines you can use to control the build.
| | UTF-16 before they are passed to the file | | | UTF-16 before they are passed to the file |
| | operations. | | | 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_DISABLE_POOL_ALLOCATOR`` | Disables use of ``boost::pool<>``. |
+----------------------------------------+-------------------------------------------------+ +----------------------------------------+-------------------------------------------------+
| ``TORRENT_LINKING_SHARED`` | If this is defined when including the | | ``TORRENT_LINKING_SHARED`` | If this is defined when including the |
@ -608,10 +597,13 @@ defines you can use to control the build.
| | protocol traffic. | | | protocol traffic. |
+----------------------------------------+-------------------------------------------------+ +----------------------------------------+-------------------------------------------------+
| ``TORRENT_DISABLE_ENCRYPTION`` | This will disable any encryption support and | | ``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 | | | Encryption support is the peer connection |
| | encrypted supported by clients such as | | | encrypted supported by clients such as |
| | uTorrent, Azureus and KTorrent. | | | 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 | | ``_UNICODE`` | On windows, this will cause the file IO |
| | use wide character API, to properly support | | | use wide character API, to properly support |

View File

@ -33,6 +33,12 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_CONFIG_HPP_INCLUDED #ifndef TORRENT_CONFIG_HPP_INCLUDED
#define 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 <boost/config.hpp> #include <boost/config.hpp>
#include <boost/version.hpp> #include <boost/version.hpp>
#include <stdio.h> // for snprintf #include <stdio.h> // for snprintf

View File

@ -40,7 +40,9 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "zlib.h" #include "zlib.h"
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_GCRYPT
#include <gcrypt.h>
#elif defined TORRENT_USE_OPENSSL
extern "C" extern "C"
{ {
#include <openssl/sha.h> #include <openssl/sha.h>
@ -87,35 +89,88 @@ namespace libtorrent
{ {
public: 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) hasher(const char* data, int len)
{ {
SHA1_Init(&m_context);
TORRENT_ASSERT(data != 0); TORRENT_ASSERT(data != 0);
TORRENT_ASSERT(len > 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<unsigned char const*>(data), len); SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(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(std::string const& data) { update(&data[0], data.size()); }
void update(const char* data, int len) void update(const char* data, int len)
{ {
TORRENT_ASSERT(data != 0); TORRENT_ASSERT(data != 0);
TORRENT_ASSERT(len > 0); TORRENT_ASSERT(len > 0);
#ifdef TORRENT_USE_GCRYPT
gcry_md_write(m_context, data, len);
#else
SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len); SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#endif
} }
sha1_hash final() sha1_hash final()
{ {
sha1_hash digest; 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); SHA1_Final(digest.begin(), &m_context);
#endif
return digest; 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: private:
#ifdef TORRENT_USE_GCRYPT
gcry_md_hd_t m_context;
#else
SHA_CTX m_context; SHA_CTX m_context;
#endif
}; };
} }

View File

@ -35,9 +35,13 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED #ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
#define TORRENT_PE_CRYPTO_HPP_INCLUDED #define TORRENT_PE_CRYPTO_HPP_INCLUDED
#include <openssl/dh.h> #ifdef TORRENT_USE_GCRYPT
#include <openssl/engine.h> #include <gcrypt.h>
#endif
#ifdef TORRENT_USE_OPENSSL
#include <openssl/rc4.h> #include <openssl/rc4.h>
#endif
#include "libtorrent/peer_id.hpp" // For sha1_hash #include "libtorrent/peer_id.hpp" // For sha1_hash
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
@ -48,31 +52,27 @@ namespace libtorrent
{ {
public: public:
dh_key_exchange(); dh_key_exchange();
~dh_key_exchange(); bool good() const { return true; }
bool good() const { return m_dh; }
// Get local public key, always 96 bytes // Get local public key, always 96 bytes
char const* get_local_key() const; char const* get_local_key() const;
// read remote_pubkey, generate and store shared secret in // read remote_pubkey, generate and store shared secret in
// m_dh_secret. // m_dh_shared_secret.
int compute_secret(const char* remote_pubkey); 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; } sha1_hash const& get_hash_xor_mask() const { return m_xor_mask; }
private: 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_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; sha1_hash m_xor_mask;
}; };
@ -80,13 +80,18 @@ namespace libtorrent
{ {
public: public:
// Input longkeys must be 20 bytes // Input longkeys must be 20 bytes
RC4_handler(const sha1_hash& rc4_local_longkey, RC4_handler(sha1_hash const& rc4_local_longkey,
const sha1_hash& rc4_remote_longkey) sha1_hash const& rc4_remote_longkey)
{ {
RC4_set_key(&m_local_key, 20, #ifdef TORRENT_USE_GCRYPT
reinterpret_cast<unsigned char const*>(rc4_local_longkey.begin())); gcry_cipher_open(&m_rc4_incoming, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0);
RC4_set_key(&m_remote_key, 20, gcry_cipher_open(&m_rc4_outgoing, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0);
reinterpret_cast<unsigned char const*>(rc4_remote_longkey.begin())); 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 // Discard first 1024 bytes
char buf[1024]; char buf[1024];
@ -94,15 +99,24 @@ namespace libtorrent
decrypt(buf, 1024); 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) void encrypt(char* pos, int len)
{ {
TORRENT_ASSERT(len >= 0); TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos); TORRENT_ASSERT(pos);
RC4(&m_local_key, len, reinterpret_cast<unsigned char const*>(pos), #ifdef TORRENT_USE_GCRYPT
reinterpret_cast<unsigned char*>(pos)); 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) void decrypt(char* pos, int len)
@ -110,13 +124,21 @@ namespace libtorrent
TORRENT_ASSERT(len >= 0); TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos); TORRENT_ASSERT(pos);
RC4(&m_remote_key, len, reinterpret_cast<unsigned char const*>(pos), #ifdef TORRENT_USE_GCRYPT
reinterpret_cast<unsigned char*>(pos)); 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: 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_local_key; // Key to encrypt outgoing data
RC4_KEY m_remote_key; // Key to decrypt incoming data RC4_KEY m_remote_key; // Key to decrypt incoming data
#endif
}; };
} // namespace libtorrent } // namespace libtorrent

View File

@ -34,8 +34,12 @@ POSSIBILITY OF SUCH DAMAGE.
#include <algorithm> #include <algorithm>
#include <openssl/dh.h> #if defined TORRENT_USE_GCRYPT
#include <openssl/engine.h> #include <gcrypt.h>
#elif defined TORRENT_USE_OPENSSL
#include <openssl/bn.h>
#include <openssl/rand.h>
#endif
#include "libtorrent/pe_crypto.hpp" #include "libtorrent/pe_crypto.hpp"
#include "libtorrent/hasher.hpp" #include "libtorrent/hasher.hpp"
@ -55,69 +59,85 @@ namespace libtorrent
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63 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 // Set the prime P and the generator, generate local public key
dh_key_exchange::dh_key_exchange() dh_key_exchange::dh_key_exchange()
{ {
m_dh = DH_new(); #ifdef TORRENT_USE_GCRYPT
if (m_dh == 0) return; // 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); // build gcrypt big ints from the prime and the secret
m_dh->g = BN_bin2bn(dh_generator, sizeof(dh_generator), 0); gcry_mpi_t prime = 0;
if (m_dh->p == 0 || m_dh->g == 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); memmove(m_dh_local_key + (sizeof(m_dh_local_key) - written), m_dh_local_key, written);
m_dh = 0; memset(m_dh_local_key, 0, sizeof(m_dh_local_key) - written);
return;
} }
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)); #elif defined TORRENT_USE_OPENSSL
// create local key
if (DH_generate_key(m_dh) == 0 || m_dh->pub_key == 0) RAND_bytes((unsigned char*)m_dh_local_secret, sizeof(m_dh_local_secret));
{
DH_free(m_dh);
m_dh = 0;
return;
}
// DH can generate key sizes that are smaller than the size of BIGNUM* prime = 0;
// P with exponentially decreasing probability, in which case BIGNUM* secret = 0;
// the msb's of m_dh_local_key need to be zeroed BIGNUM* key = 0;
// appropriately. BN_CTX* ctx = 0;
int key_size = get_local_key_size(); int 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);
int pad_zero_size = len_dh - key_size; prime = BN_bin2bn(dh_prime, sizeof(dh_prime), 0);
std::fill(m_dh_local_key, m_dh_local_key + pad_zero_size, 0); if (prime == 0) goto get_out;
if (BN_bn2bin(m_dh->pub_key, (unsigned char*)m_dh_local_key + pad_zero_size) == 0) secret = BN_bin2bn((unsigned char*)m_dh_local_secret, sizeof(m_dh_local_secret), 0);
{ if (secret == 0) goto get_out;
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;
}
}
}
dh_key_exchange::~dh_key_exchange() key = BN_new();
{ if (key == 0) goto get_out;
if (m_dh) DH_free(m_dh); // 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 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) int dh_key_exchange::compute_secret(char const* remote_pubkey)
{ {
TORRENT_ASSERT(remote_pubkey); TORRENT_ASSERT(remote_pubkey);
BIGNUM* bn_remote_pubkey = BN_bin2bn ((unsigned char*)remote_pubkey, 96, NULL); int ret = 0;
if (bn_remote_pubkey == 0) return -1; #ifdef TORRENT_USE_GCRYPT
char dh_secret[96];
int secret_size = DH_compute_key((unsigned char*)dh_secret gcry_mpi_t prime = 0;
, bn_remote_pubkey, m_dh); gcry_mpi_t remote_key = 0;
if (secret_size < 0 || secret_size > 96) return -1; 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); memmove(m_dh_shared_secret, m_dh_shared_secret
std::fill(m_dh_secret, m_dh_secret + 96 - secret_size, 0); + (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 // calculate the xor mask for the obfuscated hash
hasher h; hasher h;
h.update("req3", 4); 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(); m_xor_mask = h.final();
return ret;
return 0;
} }
} // namespace libtorrent } // namespace libtorrent

View File

@ -92,7 +92,31 @@ POSSIBILITY OF SUCH DAMAGE.
#include <sys/resource.h> #include <sys/resource.h>
#endif #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 <openssl/crypto.h> #include <openssl/crypto.h>
@ -106,7 +130,8 @@ namespace
} openssl_global_destructor; } openssl_global_destructor;
} }
#endif #endif // TORRENT_USE_OPENSSL
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
// for ERROR_SEM_TIMEOUT // for ERROR_SEM_TIMEOUT
#include <winerror.h> #include <winerror.h>