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 ;
|
||||
|
||||
# openssl libraries, if enabled
|
||||
if <openssl>sha-1 in $(properties)
|
||||
|| <openssl>pe in $(properties)
|
||||
if <encryption>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 <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)
|
||||
{
|
||||
result += <library>GeoIP ;
|
||||
|
@ -161,16 +171,13 @@ rule building ( properties * )
|
|||
result += <source>src/GeoIP.c ;
|
||||
}
|
||||
|
||||
if <openssl>off in $(properties)
|
||||
if <encryption>off in $(properties)
|
||||
{
|
||||
result += <source>src/sha1.cpp ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if <openssl>pe in $(properties)
|
||||
{
|
||||
result += <source>src/pe_crypto.cpp ;
|
||||
}
|
||||
result += <source>src/pe_crypto.cpp ;
|
||||
|
||||
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>logging : <define>TORRENT_DHT_VERBOSE_LOGGING ;
|
||||
|
||||
feature openssl : pe sha-1 off : composite propagated link-incompatible ;
|
||||
feature.compose <openssl>pe : <define>TORRENT_USE_OPENSSL ;
|
||||
feature.compose <openssl>sha-1 : <define>TORRENT_USE_OPENSSL <define>TORRENT_DISABLE_ENCRYPTION ;
|
||||
feature.compose <openssl>off : <define>TORRENT_DISABLE_ENCRYPTION ;
|
||||
feature encryption : off openssl gcrypt : composite propagated link-incompatible ;
|
||||
feature.compose <encryption>openssl : <define>TORRENT_USE_OPENSSL ;
|
||||
feature.compose <encryption>gcrypt : <define>TORRENT_USE_GCRYPT ;
|
||||
feature.compose <encryption>off : <define>TORRENT_DISABLE_ENCRYPTION ;
|
||||
|
||||
feature resolve-countries : on off : composite propagated link-incompatible ;
|
||||
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 ;
|
||||
|
||||
# openssl on linux/bsd/macos etc.
|
||||
lib gcrypt : : <name>gcrypt <link>shared <search>/opt/local/lib ;
|
||||
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
|
||||
lib librt : : <name>rt <link>shared ;
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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 <boost/config.hpp>
|
||||
#include <boost/version.hpp>
|
||||
#include <stdio.h> // for snprintf
|
||||
|
|
|
@ -40,7 +40,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/assert.hpp"
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#ifdef TORRENT_USE_GCRYPT
|
||||
#include <gcrypt.h>
|
||||
#elif defined TORRENT_USE_OPENSSL
|
||||
extern "C"
|
||||
{
|
||||
#include <openssl/sha.h>
|
||||
|
@ -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<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(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<unsigned char const*>(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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -35,9 +35,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
|
||||
#define TORRENT_PE_CRYPTO_HPP_INCLUDED
|
||||
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/engine.h>
|
||||
#ifdef TORRENT_USE_GCRYPT
|
||||
#include <gcrypt.h>
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <openssl/rc4.h>
|
||||
#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<unsigned char const*>(rc4_local_longkey.begin()));
|
||||
RC4_set_key(&m_remote_key, 20,
|
||||
reinterpret_cast<unsigned char const*>(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<unsigned char const*>(pos),
|
||||
reinterpret_cast<unsigned char*>(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<unsigned char const*>(pos),
|
||||
reinterpret_cast<unsigned char*>(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
|
||||
|
|
|
@ -34,8 +34,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/engine.h>
|
||||
#if defined TORRENT_USE_GCRYPT
|
||||
#include <gcrypt.h>
|
||||
#elif defined TORRENT_USE_OPENSSL
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rand.h>
|
||||
#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
|
||||
|
|
|
@ -92,7 +92,31 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <sys/resource.h>
|
||||
#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>
|
||||
|
||||
|
@ -106,7 +130,8 @@ namespace
|
|||
} openssl_global_destructor;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // TORRENT_USE_OPENSSL
|
||||
|
||||
#ifdef TORRENT_WINDOWS
|
||||
// for ERROR_SEM_TIMEOUT
|
||||
#include <winerror.h>
|
||||
|
|
Loading…
Reference in New Issue