forked from premiere/premiere-libtorrent
added support for libgcrypt
This commit is contained in:
parent
e86ad4f0f7
commit
e9e32235b4
32
Jamfile
32
Jamfile
|
@ -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 ;
|
||||||
|
|
|
@ -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 |
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue