remove dependency on libtommath and use boost.multiprecision instead

remove dependency on libtommath and use boost.multiprecision instead
This commit is contained in:
Arvid Norberg 2016-05-30 14:33:24 -04:00
parent 7795b2ff6c
commit 0583394af7
17 changed files with 409 additions and 12180 deletions

View File

@ -206,7 +206,7 @@ if (libiconv)
endif (libiconv)
if (encryption)
list(APPEND sources mpi pe_crypto)
list(APPEND sources pe_crypto)
if(NOT DEFINED OPENSSL_INCLUDE_DIR OR NOT DEFINED OPENSSL_LIBRARIES)
FIND_PACKAGE(OpenSSL REQUIRED)
endif()

View File

@ -319,7 +319,6 @@ rule building ( properties * )
if <encryption>on in $(properties)
{
result += <source>src/mpi.c ;
result += <source>src/pe_crypto.cpp ;
}

View File

@ -149,11 +149,6 @@ nobase_include_HEADERS = \
web_peer_connection.hpp \
xml_parse.hpp \
\
tommath.h \
tommath_class.h \
tommath_superclass.h \
tommath_private.h \
\
aux_/array_view.hpp \
aux_/allocating_handler.hpp \
aux_/bind_to_device.hpp \
@ -173,6 +168,7 @@ nobase_include_HEADERS = \
aux_/file_progress.hpp \
aux_/openssl.hpp \
aux_/byteswap.hpp \
aux_/cppint_import_export.hpp \
\
extensions/lt_trackers.hpp \
extensions/metadata_transfer.hpp \

View File

@ -0,0 +1,252 @@
///////////////////////////////////////////////////////////////
// Copyright 2015 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
#ifndef BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP
#define BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP
namespace boost {
namespace multiprecision {
namespace detail {
template <class Backend, class Unsigned>
void assign_bits(Backend& val, Unsigned bits, unsigned bit_location, unsigned chunk_bits, const mpl::false_& tag)
{
unsigned limb = bit_location / (sizeof(limb_type) * CHAR_BIT);
unsigned shift = bit_location % (sizeof(limb_type) * CHAR_BIT);
limb_type mask = chunk_bits >= sizeof(limb_type) * CHAR_BIT ? ~static_cast<limb_type>(0u) : (static_cast<limb_type>(1u) << chunk_bits) - 1;
limb_type value = (static_cast<limb_type>(bits) & mask) << shift;
if(value)
{
if(val.size() == limb)
{
val.resize(limb + 1, limb + 1);
if(val.size() > limb)
val.limbs()[limb] = value;
}
else if(val.size() > limb)
val.limbs()[limb] |= value;
}
if(chunk_bits > sizeof(limb_type) * CHAR_BIT - shift)
{
shift = sizeof(limb_type) * CHAR_BIT - shift;
chunk_bits -= shift;
bit_location += shift;
bits >>= shift;
if(bits)
assign_bits(val, bits, bit_location, chunk_bits, tag);
}
}
template <class Backend, class Unsigned>
void assign_bits(Backend& val, Unsigned bits, unsigned bit_location, unsigned chunk_bits, const mpl::true_&)
{
typedef typename Backend::local_limb_type local_limb_type;
//
// Check for possible overflow, this may trigger an exception, or have no effect
// depending on whether this is a checked integer or not:
//
if((bit_location >= sizeof(local_limb_type) * CHAR_BIT) && bits)
val.resize(2, 2);
else
{
local_limb_type mask = chunk_bits >= sizeof(local_limb_type) * CHAR_BIT ? ~static_cast<local_limb_type>(0u) : (static_cast<local_limb_type>(1u) << chunk_bits) - 1;
local_limb_type value = (static_cast<local_limb_type>(bits) & mask) << bit_location;
*val.limbs() |= value;
//
// Check for overflow bits:
//
bit_location = sizeof(local_limb_type) * CHAR_BIT - bit_location;
bits >>= bit_location;
if(bits)
val.resize(2, 2); // May throw!
}
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
inline void resize_to_bit_size(cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& newval, unsigned bits, const mpl::false_&)
{
unsigned limb_count = static_cast<unsigned>(bits / (sizeof(limb_type) * CHAR_BIT));
if(bits % (sizeof(limb_type) * CHAR_BIT))
++limb_count;
static const unsigned max_limbs = MaxBits ? MaxBits / (CHAR_BIT * sizeof(limb_type)) + ((MaxBits % (CHAR_BIT * sizeof(limb_type))) ? 1 : 0) : (std::numeric_limits<unsigned>::max)();
if(limb_count > max_limbs)
limb_count = max_limbs;
newval.resize(limb_count, limb_count);
std::memset(newval.limbs(), 0, newval.size() * sizeof(limb_type));
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
inline void resize_to_bit_size(cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& newval, unsigned, const mpl::true_&)
{
*newval.limbs() = 0;
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
import_bits_generic(
number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
{
typename number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>::backend_type newval;
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::make_unsigned<value_type>::type unsigned_value_type;
typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
typedef typename boost::make_unsigned<difference_type>::type size_type;
typedef typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::trivial_tag tag_type;
if(!chunk_size)
chunk_size = std::numeric_limits<value_type>::digits;
size_type limbs = std::distance(i, j);
size_type bits = limbs * chunk_size;
detail::resize_to_bit_size(newval, static_cast<unsigned>(bits), tag_type());
difference_type bit_location = msv_first ? bits - chunk_size : 0;
difference_type bit_location_change = msv_first ? -static_cast<difference_type>(chunk_size) : chunk_size;
while(i != j)
{
detail::assign_bits(newval, static_cast<unsigned_value_type>(*i), static_cast<unsigned>(bit_location), chunk_size, tag_type());
++i;
bit_location += bit_location_change;
}
newval.normalize();
val.backend().swap(newval);
return val;
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
inline typename boost::disable_if_c<boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
import_bits_fast(
number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0)
{
std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i));
std::size_t limb_len = byte_len / sizeof(limb_type);
if(byte_len % sizeof(limb_type))
++limb_len;
cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data!
result.limbs()[result.size() - 1] = 0u;
std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(limb_type)));
result.normalize(); // In case data has leading zeros.
return val;
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
inline typename boost::enable_if_c<boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
import_bits_fast(
number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0)
{
cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i));
std::size_t limb_len = byte_len / sizeof(result.limbs()[0]);
if(byte_len % sizeof(result.limbs()[0]))
++limb_len;
result.limbs()[0] = 0u;
result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data!
std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(result.limbs()[0])));
result.normalize(); // In case data has leading zeros.
return val;
}
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
import_bits(
number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
{
return detail::import_bits_generic(val, i, j, chunk_size, msv_first);
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
import_bits(
number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0, bool msv_first = true)
{
#ifdef BOOST_LITTLE_ENDIAN
if(((chunk_size % CHAR_BIT) == 0) && !msv_first)
return detail::import_bits_fast(val, i, j, chunk_size);
#endif
return detail::import_bits_generic(val, i, j, chunk_size, msv_first);
}
namespace detail {
template <class Backend>
boost::uintmax_t extract_bits(const Backend& val, unsigned location, unsigned count, const mpl::false_& tag)
{
unsigned limb = location / (sizeof(limb_type) * CHAR_BIT);
unsigned shift = location % (sizeof(limb_type) * CHAR_BIT);
boost::uintmax_t result = 0;
boost::uintmax_t mask = count == std::numeric_limits<boost::uintmax_t>::digits ? ~static_cast<boost::uintmax_t>(0) : (static_cast<boost::uintmax_t>(1u) << count) - 1;
if(count > (sizeof(limb_type) * CHAR_BIT - shift))
{
result = extract_bits(val, location + sizeof(limb_type) * CHAR_BIT - shift, count - sizeof(limb_type) * CHAR_BIT + shift, tag);
result <<= sizeof(limb_type) * CHAR_BIT - shift;
}
if(limb < val.size())
result |= (val.limbs()[limb] >> shift) & mask;
return result;
}
template <class Backend>
inline boost::uintmax_t extract_bits(const Backend& val, unsigned location, unsigned count, const mpl::true_&)
{
boost::uintmax_t result = *val.limbs();
boost::uintmax_t mask = count == std::numeric_limits<boost::uintmax_t>::digits ? ~static_cast<boost::uintmax_t>(0) : (static_cast<boost::uintmax_t>(1u) << count) - 1;
return (result >> location) & mask;
}
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class OutputIterator>
OutputIterator export_bits(
const number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, OutputIterator out, unsigned chunk_size, bool msv_first = true)
{
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4244)
#endif
typedef typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::trivial_tag tag_type;
if(!val)
{
*out = 0;
++out;
return out;
}
unsigned bitcount = msb(val) + 1;
unsigned chunks = bitcount / chunk_size;
if(bitcount % chunk_size)
++chunks;
int bit_location = msv_first ? bitcount - chunk_size : 0;
int bit_step = msv_first ? -static_cast<int>(chunk_size) : chunk_size;
while(bit_location % bit_step) ++bit_location;
do
{
*out = detail::extract_bits(val.backend(), bit_location, chunk_size, tag_type());
++out;
bit_location += bit_step;
} while((bit_location >= 0) && (bit_location < (int)bitcount));
return out;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
}
}
#endif // BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP

View File

@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
#ifdef __clang__
@ -70,6 +71,9 @@ POSSIBILITY OF SUCH DAMAGE.
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wreserved-id-macro"
#pragma clang diagnostic ignored "-Wunused-local-typedef"
#pragma clang diagnostic ignored "-Wgnu-folding-constant"
#pragma clang diagnostic ignored "-Wdouble-promotion"
#pragma clang diagnostic ignored "-Wfloat-equal"
#endif
#ifdef _MSC_VER

View File

@ -278,11 +278,6 @@ namespace libtorrent
void write_pe_vc_cryptofield(char* write_buf, int len
, int crypto_field, int pad_size);
// stream key (info hash of attached torrent)
// secret is the DH shared secret
// initializes m_enc_handler
void init_pe_rc4_handler(char const* secret, sha1_hash const& stream_key);
// Returns offset at which bytestream (src, src + src_size)
// matches bytestream(target, target + target_size).
// If no sync found, return -1

View File

@ -37,42 +37,51 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
// RC4 state from libtomcrypt
struct rc4 {
int x, y;
unsigned char buf[256];
};
void TORRENT_EXTRA_EXPORT rc4_init(const unsigned char* in, unsigned long len, rc4 *state);
unsigned long TORRENT_EXTRA_EXPORT rc4_encrypt(unsigned char *out, unsigned long outlen, rc4 *state);
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/asio/buffer.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
#include "libtorrent/receive_buffer.hpp"
#include "libtorrent/peer_id.hpp" // For sha1_hash
#include "libtorrent/sha1_hash.hpp"
#include "libtorrent/extensions.hpp"
#include "libtorrent/assert.hpp"
#include <list>
#include <array>
#include <cstdint>
namespace libtorrent
{
namespace mp = boost::multiprecision;
using key_t = mp::number<mp::cpp_int_backend<768, 768, mp::unsigned_magnitude, mp::unchecked, void> >;
// RC4 state from libtomcrypt
struct rc4 {
int x, y;
std::array<std::uint8_t, 256> buf;
};
void TORRENT_EXTRA_EXPORT rc4_init(const unsigned char* in, unsigned long len, rc4 *state);
unsigned long TORRENT_EXTRA_EXPORT rc4_encrypt(unsigned char *out, unsigned long outlen, rc4 *state);
// TODO: 3 dh_key_exchange should probably move into its own file
class TORRENT_EXTRA_EXPORT dh_key_exchange
{
public:
dh_key_exchange();
bool good() const { return true; }
// Get local public key, always 96 bytes
char const* get_local_key() const;
// Get local public key
key_t const& get_local_key() const { return m_dh_local_key; }
// read remote_pubkey, generate and store shared secret in
// m_dh_shared_secret.
int compute_secret(const char* remote_pubkey);
void compute_secret(boost::uint8_t const* remote_pubkey);
void compute_secret(key_t const& remote_pubkey);
char const* get_secret() const { return m_dh_shared_secret; }
key_t const& get_secret() const { return m_dh_shared_secret; }
sha1_hash const& get_hash_xor_mask() const { return m_xor_mask; }
@ -81,9 +90,9 @@ namespace libtorrent
int get_local_key_size() const
{ return sizeof(m_dh_local_key); }
char m_dh_local_key[96];
char m_dh_local_secret[96];
char m_dh_shared_secret[96];
key_t m_dh_local_key;
key_t m_dh_local_secret;
key_t m_dh_shared_secret;
sha1_hash m_xor_mask;
};
@ -127,6 +136,7 @@ namespace libtorrent
rc4_handler();
// Input keys must be 20 bytes
// TODO: 4 use uint768_t here instead of pointer + length
void set_incoming_key(unsigned char const* key, int len) override;
void set_outgoing_key(unsigned char const* key, int len) override;

View File

@ -1,575 +0,0 @@
/* LibTomMath, multiple-precision integer library -- Tom St Denis
*
* LibTomMath is a library that provides multiple-precision
* integer arithmetic as well as number theoretic functionality.
*
* The library was designed directly after the MPI library by
* Michael Fromberger but has been written from scratch with
* additional optimizations in place.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tstdenis82@gmail.com, http://math.libtomcrypt.com
*/
#ifndef BN_H_
#define BN_H_
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "libtorrent/export.hpp"
#ifdef _MSC_VER
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#include "libtorrent/tommath_class.h"
#ifdef __cplusplus
extern "C" {
#endif
/* detect 64-bit mode if possible */
#if defined(__x86_64__)
#if !(defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT))
#define MP_64BIT
#endif
#endif
/* some default configurations.
*
* A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
* A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
*
* At the very least a mp_digit must be able to hold 7 bits
* [any size beyond that is ok provided it doesn't overflow the data type]
*/
#ifdef MP_8BIT
typedef uint8_t mp_digit;
typedef uint16_t mp_word;
#define MP_SIZEOF_MP_DIGIT 1
#ifdef DIGIT_BIT
#error You must not define DIGIT_BIT when using MP_8BIT
#endif
#elif defined(MP_16BIT)
typedef uint16_t mp_digit;
typedef uint32_t mp_word;
#define MP_SIZEOF_MP_DIGIT 2
#ifdef DIGIT_BIT
#error You must not define DIGIT_BIT when using MP_16BIT
#endif
#elif defined(MP_64BIT)
/* for GCC only on supported platforms */
typedef uint64_t mp_digit;
#if defined(_WIN32)
typedef unsigned __int128 mp_word;
#elif defined(__GNUC__)
typedef unsigned long mp_word __attribute__ ((mode(TI)));
#else
/* it seems you have a problem
* but we assume you can somewhere define your own uint128_t */
typedef uint128_t mp_word;
#endif
#define DIGIT_BIT 60
#else
/* this is the default case, 28-bit digits */
/* this is to make porting into LibTomCrypt easier :-) */
typedef uint32_t mp_digit;
typedef uint64_t mp_word;
#ifdef MP_31BIT
/* this is an extension that uses 31-bit digits */
#define DIGIT_BIT 31
#else
/* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
#define DIGIT_BIT 28
#define MP_28BIT
#endif
#endif
/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
#ifndef DIGIT_BIT
#define DIGIT_BIT (((CHAR_BIT * MP_SIZEOF_MP_DIGIT) - 1)) /* bits per digit */
typedef uint_least32_t mp_min_u32;
#else
typedef mp_digit mp_min_u32;
#endif
/* platforms that can use a better rand function */
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#define MP_USE_ALT_RAND 1
#endif
/* use arc4random on platforms that support it */
#ifdef MP_USE_ALT_RAND
#define MP_GEN_RANDOM() arc4random()
#else
#define MP_GEN_RANDOM() rand()
#endif
#define MP_DIGIT_BIT DIGIT_BIT
#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX MP_MASK
/* equalities */
#define MP_LT -1 /* less than */
#define MP_EQ 0 /* equal to */
#define MP_GT 1 /* greater than */
#define MP_ZPOS 0 /* positive integer */
#define MP_NEG 1 /* negative */
#define MP_OKAY 0 /* ok result */
#define MP_MEM -2 /* out of mem */
#define MP_VAL -3 /* invalid input */
#define MP_RANGE MP_VAL
#define MP_YES 1 /* yes response */
#define MP_NO 0 /* no response */
/* Primality generation flags */
#define LTM_PRIME_BBS 0x0001 /* BBS style prime */
#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */
#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */
typedef int mp_err;
/* you'll have to tune these... */
extern int KARATSUBA_MUL_CUTOFF,
KARATSUBA_SQR_CUTOFF,
TOOM_MUL_CUTOFF,
TOOM_SQR_CUTOFF;
/* define this to use lower memory usage routines (exptmods mostly) */
/* #define MP_LOW_MEM */
/* default precision */
#ifndef MP_PREC
#ifndef MP_LOW_MEM
#define MP_PREC 32 /* default digits of precision */
#else
#define MP_PREC 8 /* default digits of precision */
#endif
#endif
/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY (1 << (((sizeof(mp_word) * CHAR_BIT) - (2 * DIGIT_BIT)) + 1))
/* the infamous mp_int structure */
typedef struct {
int used, alloc, sign;
mp_digit *dp;
} mp_int;
/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
#define USED(m) ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m) ((m)->sign)
/* error code to char* string */
const char *mp_error_to_string(int code);
/* ---> init and deinit bignum functions <--- */
/* init a bignum */
TORRENT_EXTRA_EXPORT int mp_init(mp_int *a);
/* free a bignum */
TORRENT_EXTRA_EXPORT void mp_clear(mp_int *a);
/* init a null terminated series of arguments */
int mp_init_multi(mp_int *mp, ...);
/* clear a null terminated series of arguments */
void mp_clear_multi(mp_int *mp, ...);
/* exchange two ints */
void mp_exch(mp_int *a, mp_int *b);
/* shrink ram required for a bignum */
int mp_shrink(mp_int *a);
/* grow an int to a given size */
int mp_grow(mp_int *a, int size);
/* init to a given number of digits */
int mp_init_size(mp_int *a, int size);
/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) ((((a)->used > 0) && (((a)->dp[0] & 1u) == 0u)) ? MP_YES : MP_NO)
#define mp_isodd(a) ((((a)->used > 0) && (((a)->dp[0] & 1u) == 1u)) ? MP_YES : MP_NO)
#define mp_isneg(a) (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO)
/* set to zero */
void mp_zero(mp_int *a);
/* set to a digit */
void mp_set(mp_int *a, mp_digit b);
/* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned long b);
/* set a platform dependent unsigned long value */
int mp_set_long(mp_int *a, unsigned long b);
/* set a platform dependent unsigned long long value */
int mp_set_long_long(mp_int *a, unsigned long long b);
/* get a 32-bit value */
unsigned long mp_get_int(mp_int * a);
/* get a platform dependent unsigned long value */
unsigned long mp_get_long(mp_int * a);
/* get a platform dependent unsigned long long value */
unsigned long long mp_get_long_long(mp_int * a);
/* initialize and set a digit */
int mp_init_set (mp_int * a, mp_digit b);
/* initialize and set 32-bit value */
int mp_init_set_int (mp_int * a, unsigned long b);
/* copy, b = a */
int mp_copy(mp_int *a, mp_int *b);
/* inits and copies, a = b */
int mp_init_copy(mp_int *a, mp_int *b);
/* trim unused digits */
void mp_clamp(mp_int *a);
/* import binary data */
int mp_import(mp_int* rop, size_t count, int order, size_t size, int endian, size_t nails, const void* op);
/* export binary data */
int mp_export(void* rop, size_t* countp, int order, size_t size, int endian, size_t nails, mp_int* op);
/* ---> digit manipulation <--- */
/* right shift by "b" digits */
void mp_rshd(mp_int *a, int b);
/* left shift by "b" digits */
int mp_lshd(mp_int *a, int b);
/* c = a / 2**b, implemented as c = a >> b */
int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
/* b = a/2 */
int mp_div_2(mp_int *a, mp_int *b);
/* c = a * 2**b, implemented as c = a << b */
int mp_mul_2d(mp_int *a, int b, mp_int *c);
/* b = a*2 */
int mp_mul_2(mp_int *a, mp_int *b);
/* c = a mod 2**b */
int mp_mod_2d(mp_int *a, int b, mp_int *c);
/* computes a = 2**b */
int mp_2expt(mp_int *a, int b);
/* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(mp_int *a);
/* I Love Earth! */
/* makes a pseudo-random int of a given size */
int mp_rand(mp_int *a, int digits);
/* ---> binary operations <--- */
/* c = a XOR b */
int mp_xor(mp_int *a, mp_int *b, mp_int *c);
/* c = a OR b */
int mp_or(mp_int *a, mp_int *b, mp_int *c);
/* c = a AND b */
int mp_and(mp_int *a, mp_int *b, mp_int *c);
/* ---> Basic arithmetic <--- */
/* b = -a */
int mp_neg(mp_int *a, mp_int *b);
/* b = |a| */
int mp_abs(mp_int *a, mp_int *b);
/* compare a to b */
int mp_cmp(mp_int *a, mp_int *b);
/* compare |a| to |b| */
int mp_cmp_mag(mp_int *a, mp_int *b);
/* c = a + b */
int mp_add(mp_int *a, mp_int *b, mp_int *c);
/* c = a - b */
int mp_sub(mp_int *a, mp_int *b, mp_int *c);
/* c = a * b */
int mp_mul(mp_int *a, mp_int *b, mp_int *c);
/* b = a*a */
int mp_sqr(mp_int *a, mp_int *b);
/* a/b => cb + d == a */
int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* c = a mod b, 0 <= c < b */
int mp_mod(mp_int *a, mp_int *b, mp_int *c);
/* ---> single digit functions <--- */
/* compare against a single digit */
int mp_cmp_d(mp_int *a, mp_digit b);
/* c = a + b */
int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
/* c = a - b */
int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
/* c = a * b */
int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
/* a/b => cb + d == a */
int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
/* a/3 => 3c + d == a */
int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
/* c = a**b */
int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
int mp_expt_d_ex (mp_int * a, mp_digit b, mp_int * c, int fast);
/* c = a mod b, 0 <= c < b */
int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
/* ---> number theory <--- */
/* d = a + b (mod c) */
int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* d = a - b (mod c) */
int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* d = a * b (mod c) */
int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* c = a * a (mod b) */
int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
/* c = 1/a (mod b) */
int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
/* c = (a, b) */
int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
/* produces value such that U1*a + U2*b = U3 */
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
/* c = [a, b] or (a*b)/(a, b) */
int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
/* finds one of the b'th root of a, such that |c|**b <= |a|
*
* returns error if a < 0 and b is even
*/
int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
int mp_n_root_ex (mp_int * a, mp_digit b, mp_int * c, int fast);
/* special sqrt algo */
int mp_sqrt(mp_int *arg, mp_int *ret);
/* special sqrt (mod prime) */
int mp_sqrtmod_prime(mp_int *arg, mp_int *prime, mp_int *ret);
/* is number a square? */
int mp_is_square(mp_int *arg, int *ret);
/* computes the jacobi c = (a | n) (or Legendre if b is prime) */
int mp_jacobi(mp_int *a, mp_int *n, int *c);
/* used to setup the Barrett reduction for a given modulus b */
int mp_reduce_setup(mp_int *a, mp_int *b);
/* Barrett Reduction, computes a (mod b) with a precomputed value c
*
* Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
* compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
*/
int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
/* setups the montgomery reduction */
int mp_montgomery_setup(mp_int *a, mp_digit *mp);
/* computes a = B**n mod b without division or multiplication useful for
* normalizing numbers in a Montgomery system.
*/
int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
/* computes x/R == x (mod N) via Montgomery Reduction */
int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
/* returns 1 if a is a valid DR modulus */
int mp_dr_is_modulus(mp_int *a);
/* sets the value of "d" required for mp_dr_reduce */
void mp_dr_setup(mp_int *a, mp_digit *d);
/* reduces a modulo b using the Diminished Radix method */
int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
/* returns true if a can be reduced with mp_reduce_2k */
int mp_reduce_is_2k(mp_int *a);
/* determines k value for 2k reduction */
int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
/* returns true if a can be reduced with mp_reduce_2k_l */
int mp_reduce_is_2k_l(mp_int *a);
/* determines k value for 2k reduction */
int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
/* d = a**b (mod c) */
int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* ---> Primes <--- */
/* number of primes */
#ifdef MP_8BIT
#define PRIME_SIZE 31
#else
#define PRIME_SIZE 256
#endif
/* table of first PRIME_SIZE primes */
extern const mp_digit ltm_prime_tab[PRIME_SIZE];
/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
int mp_prime_is_divisible(mp_int *a, int *result);
/* performs one Fermat test of "a" using base "b".
* Sets result to 0 if composite or 1 if probable prime
*/
int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
/* performs one Miller-Rabin test of "a" using base "b".
* Sets result to 0 if composite or 1 if probable prime
*/
int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
/* This gives [for a given bit size] the number of trials required
* such that Miller-Rabin gives a prob of failure lower than 2^-96
*/
int mp_prime_rabin_miller_trials(int size);
/* performs t rounds of Miller-Rabin on "a" using the first
* t prime bases. Also performs an initial sieve of trial
* division. Determines if "a" is prime with probability
* of error no more than (1/4)**t.
*
* Sets result to 1 if probably prime, 0 otherwise
*/
int mp_prime_is_prime(mp_int *a, int t, int *result);
/* finds the next prime after the number "a" using "t" trials
* of Miller-Rabin.
*
* bbs_style = 1 means the prime must be congruent to 3 mod 4
*/
int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
/* makes a truly random prime of a given size (bytes),
* call with bbs = 1 if you want it to be congruent to 3 mod 4
*
* You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
* have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
* so it can be NULL
*
* The prime generated will be larger than 2^(8*size).
*/
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
/* makes a truly random prime of a given size (bits),
*
* Flags are as follows:
*
* LTM_PRIME_BBS - make prime congruent to 3 mod 4
* LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
* LTM_PRIME_2MSB_ON - make the 2nd highest bit one
*
* You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
* have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
* so it can be NULL
*
*/
int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
/* ---> radix conversion <--- */
int mp_count_bits(mp_int *a);
TORRENT_EXTRA_EXPORT int mp_unsigned_bin_size(mp_int *a);
TORRENT_EXTRA_EXPORT int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
int mp_signed_bin_size(mp_int *a);
int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
int mp_to_signed_bin(mp_int *a, unsigned char *b);
int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
int mp_read_radix(mp_int *a, const char *str, int radix);
int mp_toradix(mp_int *a, char *str, int radix);
int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
int mp_radix_size(mp_int *a, int radix, int *size);
#ifndef LTM_NO_FILE
int mp_fread(mp_int *a, int radix, FILE *stream);
int mp_fwrite(mp_int *a, int radix, FILE *stream);
#endif
#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp) mp_signed_bin_size(mp)
#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp) mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str))
#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
#define mp_tohex(M, S) mp_toradix((M), (S), 16)
#ifdef __cplusplus
}
#endif
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

File diff suppressed because it is too large Load Diff

View File

@ -1,119 +0,0 @@
/* LibTomMath, multiple-precision integer library -- Tom St Denis
*
* LibTomMath is a library that provides multiple-precision
* integer arithmetic as well as number theoretic functionality.
*
* The library was designed directly after the MPI library by
* Michael Fromberger but has been written from scratch with
* additional optimizations in place.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tstdenis82@gmail.com, http://math.libtomcrypt.com
*/
#ifndef TOMMATH_PRIV_H_
#define TOMMATH_PRIV_H_
#include "libtorrent/tommath.h"
#include <ctype.h>
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#ifdef __cplusplus
extern "C" {
/* C++ compilers don't like assigning void * to mp_digit * */
#define OPT_CAST(x) (x *)
#else
/* C on the other hand doesn't care */
#define OPT_CAST(x)
#endif
/* define heap macros */
#ifndef XMALLOC
/* default to libc stuff */
#define XMALLOC malloc
#define XFREE free
#define XREALLOC realloc
#define XCALLOC calloc
#else
/* prototypes for our heap functions */
extern void *XMALLOC(size_t n);
extern void *XREALLOC(void *p, size_t n);
extern void *XCALLOC(size_t n, size_t s);
extern void XFREE(void *p);
#endif
/* lowlevel functions, do not call! */
int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
int fast_s_mp_sqr(mp_int *a, mp_int *b);
int s_mp_sqr(mp_int *a, mp_int *b);
int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
int mp_karatsuba_sqr(mp_int *a, mp_int *b);
int mp_toom_sqr(mp_int *a, mp_int *b);
int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
int fast_mp_montgomery_reduce(mp_int *x, mp_int *n, mp_digit rho);
int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int redmode);
int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
void bn_reverse(unsigned char *s, int len);
extern const char *mp_s_rmap;
/* Fancy macro to set an MPI from another type.
* There are several things assumed:
* x is the counter and unsigned
* a is the pointer to the MPI
* b is the original value that should be set in the MPI.
*/
#define MP_SET_XLONG(func_name, type) \
int func_name (mp_int * a, type b) \
{ \
unsigned int x; \
int res; \
\
mp_zero (a); \
\
/* set four bits at a time */ \
for (x = 0; x < (sizeof(type) * 2u); x++) { \
/* shift the number up four bits */ \
if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { \
return res; \
} \
\
/* OR in the top four bits of the source */ \
a->dp[0] |= (b >> ((sizeof(type) * 8u) - 4u)) & 15u; \
\
/* shift the source up to the next four bits */ \
b <<= 4; \
\
/* ensure that digits are not clamped off */ \
a->used += 1; \
} \
mp_clamp (a); \
return MP_OKAY; \
}
#ifdef __cplusplus
}
#endif
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -1,76 +0,0 @@
/* super class file for PK algos */
/* default ... include all MPI */
#define LTM_ALL
/* RSA only (does not support DH/DSA/ECC) */
/* #define SC_RSA_1 */
/* For reference.... On an Athlon64 optimizing for speed...
LTM's mpi.o with all functions [striped] is 142KiB in size.
*/
/* Works for RSA only, mpi.o is 68KiB */
#ifdef SC_RSA_1
#define BN_MP_SHRINK_C
#define BN_MP_LCM_C
#define BN_MP_PRIME_RANDOM_EX_C
#define BN_MP_INVMOD_C
#define BN_MP_GCD_C
#define BN_MP_MOD_C
#define BN_MP_MULMOD_C
#define BN_MP_ADDMOD_C
#define BN_MP_EXPTMOD_C
#define BN_MP_SET_INT_C
#define BN_MP_INIT_MULTI_C
#define BN_MP_CLEAR_MULTI_C
#define BN_MP_UNSIGNED_BIN_SIZE_C
#define BN_MP_TO_UNSIGNED_BIN_C
#define BN_MP_MOD_D_C
#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
#define BN_REVERSE_C
#define BN_PRIME_TAB_C
/* other modifiers */
#define BN_MP_DIV_SMALL /* Slower division, not critical */
/* here we are on the last pass so we turn things off. The functions classes are still there
* but we remove them specifically from the build. This also invokes tweaks in functions
* like removing support for even moduli, etc...
*/
#ifdef LTM_LAST
#undef BN_MP_TOOM_MUL_C
#undef BN_MP_TOOM_SQR_C
#undef BN_MP_KARATSUBA_MUL_C
#undef BN_MP_KARATSUBA_SQR_C
#undef BN_MP_REDUCE_C
#undef BN_MP_REDUCE_SETUP_C
#undef BN_MP_DR_IS_MODULUS_C
#undef BN_MP_DR_SETUP_C
#undef BN_MP_DR_REDUCE_C
#undef BN_MP_REDUCE_IS_2K_C
#undef BN_MP_REDUCE_2K_SETUP_C
#undef BN_MP_REDUCE_2K_C
#undef BN_S_MP_EXPTMOD_C
#undef BN_MP_DIV_3_C
#undef BN_S_MP_MUL_HIGH_DIGS_C
#undef BN_FAST_S_MP_MUL_HIGH_DIGS_C
#undef BN_FAST_MP_INVMOD_C
/* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
* which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines]
* which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
* trouble.
*/
#undef BN_S_MP_MUL_DIGS_C
#undef BN_S_MP_SQR_C
#undef BN_MP_MONTGOMERY_REDUCE_C
#endif
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -86,7 +86,6 @@ libtorrent_rasterbar_la_SOURCES = \
magnet_uri.cpp \
merkle.cpp \
metadata_transfer.cpp \
mpi.c \
natpmp.cpp \
parse_url.cpp \
part_file.cpp \

View File

@ -33,14 +33,18 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <memory> // unique_ptr
#include <vector>
#include <boost/limits.hpp>
#include <functional>
#ifdef TORRENT_USE_OPENSSL
#include <memory> // autp_ptr
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/integer.hpp>
// for backwards compatibility with boost < 1.60 which was before export_bits
// and import_bits were introduced
#if BOOST_VERSION < 106000
#include "libtorrent/aux_/cppint_import_export.hpp"
#endif
#include "libtorrent/aux_/disable_warnings_pop.hpp"
@ -78,6 +82,56 @@ using boost::shared_ptr;
namespace libtorrent
{
namespace mp = boost::multiprecision;
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
namespace {
// stream key (info hash of attached torrent)
// secret is the DH shared secret
// initializes m_enc_handler
boost::shared_ptr<rc4_handler> init_pe_rc4_handler(key_t const& secret
, sha1_hash const& stream_key, bool const outgoing)
{
hasher h;
static const char keyA[] = "keyA";
static const char keyB[] = "keyB";
// encryption rc4 longkeys
// outgoing connection : hash ('keyA',S,SKEY)
// incoming connection : hash ('keyB',S,SKEY)
std::array<boost::uint8_t, 96> secret_buf;
mp::export_bits(secret, secret_buf.begin(), 8);
if (outgoing) h.update(keyA, 4); else h.update(keyB, 4);
h.update(reinterpret_cast<char const*>(secret_buf.data()), secret_buf.size());
h.update(stream_key.data(), 20);
const sha1_hash local_key = h.final();
h.reset();
// decryption rc4 longkeys
// outgoing connection : hash ('keyB',S,SKEY)
// incoming connection : hash ('keyA',S,SKEY)
if (outgoing) h.update(keyB, 4); else h.update(keyA, 4);
h.update(reinterpret_cast<char const*>(secret_buf.data())
, secret_buf.size());
h.update(stream_key.data(), 20);
const sha1_hash remote_key = h.final();
boost::shared_ptr<rc4_handler> ret = boost::make_shared<rc4_handler>();
ret->set_incoming_key(&remote_key[0], 20);
ret->set_outgoing_key(&local_key[0], 20);
return ret;
}
} // anonymous namespace
#endif
const bt_peer_connection::message_handler
bt_peer_connection::m_message_handler[] =
{
@ -485,7 +539,8 @@ namespace libtorrent
char* ptr = msg;
int buf_size = dh_key_len + pad_size;
memcpy(ptr, m_dh_key_exchange->get_local_key(), dh_key_len);
mp::export_bits(m_dh_key_exchange->get_local_key()
, reinterpret_cast<std::uint8_t*>(ptr), 8);
ptr += dh_key_len;
std::generate(ptr, ptr + pad_size, random_byte);
@ -510,7 +565,9 @@ namespace libtorrent
hasher h;
sha1_hash const& info_hash = t->torrent_file().info_hash();
char const* const secret = m_dh_key_exchange->get_secret();
key_t const secret_key = m_dh_key_exchange->get_secret();
std::array<boost::uint8_t, 96> secret;
mp::export_bits(secret_key, secret.begin(), 8);
int pad_size = random() % 512;
@ -521,7 +578,8 @@ namespace libtorrent
// sync hash (hash('req1',S))
h.reset();
h.update("req1",4);
h.update(secret, dh_key_len);
h.update(reinterpret_cast<char const*>(secret.data())
, secret.size());
sha1_hash sync_hash = h.final();
memcpy(ptr, &sync_hash[0], 20);
@ -535,7 +593,8 @@ namespace libtorrent
h.reset();
h.update("req3",4);
h.update(secret, dh_key_len);
h.update(reinterpret_cast<char const*>(secret.data())
, secret.size());
sha1_hash obfsc_hash = h.final();
obfsc_hash ^= streamkey_hash;
@ -543,7 +602,10 @@ namespace libtorrent
ptr += 20;
// Discard DH key exchange data, setup RC4 keys
init_pe_rc4_handler(secret, info_hash);
m_rc4 = init_pe_rc4_handler(secret_key, info_hash, is_outgoing());
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION", "computed RC4 keys");
#endif
m_dh_key_exchange.reset(); // secret should be invalid at this point
// write the verification constant and crypto field
@ -634,54 +696,6 @@ namespace libtorrent
detail::write_uint16(handshake_len, write_buf); // len(IA)
}
void bt_peer_connection::init_pe_rc4_handler(char const* secret
, sha1_hash const& stream_key)
{
INVARIANT_CHECK;
TORRENT_ASSERT(secret);
hasher h;
static const char keyA[] = "keyA";
static const char keyB[] = "keyB";
// encryption rc4 longkeys
// outgoing connection : hash ('keyA',S,SKEY)
// incoming connection : hash ('keyB',S,SKEY)
if (is_outgoing()) h.update(keyA, 4); else h.update(keyB, 4);
h.update(secret, dh_key_len);
h.update(stream_key.data(), 20);
const sha1_hash local_key = h.final();
h.reset();
// decryption rc4 longkeys
// outgoing connection : hash ('keyB',S,SKEY)
// incoming connection : hash ('keyA',S,SKEY)
if (is_outgoing()) h.update(keyB, 4); else h.update(keyA, 4);
h.update(secret, dh_key_len);
h.update(stream_key.data(), 20);
const sha1_hash remote_key = h.final();
TORRENT_ASSERT(!m_rc4.get());
m_rc4 = boost::make_shared<rc4_handler>();
if (!m_rc4)
{
disconnect(errors::no_memory, op_encryption);
return;
}
m_rc4->set_incoming_key(&remote_key[0], 20);
m_rc4->set_outgoing_key(&local_key[0], 20);
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION", "computed RC4 keys");
#endif
}
int bt_peer_connection::get_syncoffset(char const* src, int src_size,
char const* target, int target_size) const
{
@ -2682,11 +2696,8 @@ namespace libtorrent
if (is_disconnecting()) return;
// read dh key, generate shared secret
if (m_dh_key_exchange->compute_secret(recv_buffer.begin) != 0)
{
disconnect(errors::no_memory, op_encryption);
return;
}
m_dh_key_exchange->compute_secret(
reinterpret_cast<boost::uint8_t const*>(recv_buffer.begin));
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION", "received DH key");
@ -2749,8 +2760,10 @@ namespace libtorrent
hasher h;
// compute synchash (hash('req1',S))
std::array<boost::uint8_t, 96> buffer;
mp::export_bits(m_dh_key_exchange->get_secret(), buffer.begin(), 8);
h.update("req1", 4);
h.update(m_dh_key_exchange->get_secret(), dh_key_len);
h.update(reinterpret_cast<char const*>(buffer.data()), buffer.size());
m_sync_hash.reset(new (std::nothrow) sha1_hash(h.final()));
if (!m_sync_hash)
@ -2836,8 +2849,10 @@ namespace libtorrent
TORRENT_ASSERT(t);
}
init_pe_rc4_handler(m_dh_key_exchange->get_secret(), ti->info_hash());
m_rc4 = init_pe_rc4_handler(m_dh_key_exchange->get_secret()
, ti->info_hash(), is_outgoing());
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION", "computed RC4 keys");
peer_log(peer_log_alert::info, "ENCRYPTION", "stream key found, torrent located");
#endif
}

10098
src/mpi.c

File diff suppressed because it is too large Load Diff

View File

@ -35,14 +35,20 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/cstdint.hpp>
#include <algorithm>
#include <boost/multiprecision/integer.hpp>
#include <boost/multiprecision/cpp_int.hpp>
extern "C" {
#include "libtorrent/tommath.h"
}
// for backwards compatibility with boost < 1.60 which was before export_bits
// and import_bits were introduced
#if BOOST_VERSION < 106000
#include "libtorrent/aux_/cppint_import_export.hpp"
#endif
#include "libtorrent/aux_/disable_warnings_pop.hpp"
#include <algorithm>
#include <random>
#include "libtorrent/random.hpp"
#include "libtorrent/pe_crypto.hpp"
#include "libtorrent/hasher.hpp"
@ -50,137 +56,49 @@ extern "C" {
namespace libtorrent
{
namespace
{
const unsigned char dh_prime[96] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63
};
}
namespace mp = boost::multiprecision;
struct mp_bigint
{
mp_bigint()
{ mp_init(&v); }
mp_int* operator&() { return &v; }
~mp_bigint() { mp_clear(&v); }
private:
// non-copyable
mp_bigint(mp_bigint const&);
mp_bigint const& operator=(mp_bigint const&);
mp_int v;
};
namespace {
// TODO: it would be nice to get the literal working
key_t const dh_prime
("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563");
}
// Set the prime P and the generator, generate local public key
dh_key_exchange::dh_key_exchange()
{
// create local key
for (int i = 0; i < int(sizeof(m_dh_local_secret)); ++i)
m_dh_local_secret[i] = random() & 0xff;
std::array<std::uint8_t, 96> random_key;
for (auto& i : random_key) i = random();
mp_bigint prime;
mp_bigint secret;
mp_bigint key;
// create local key (random)
mp::import_bits(m_dh_local_secret, random_key.begin(), random_key.end());
// TODO 2: use exceptions for error reporting here
if (mp_read_unsigned_bin(&prime, dh_prime, sizeof(dh_prime)))
{
TORRENT_ASSERT_FAIL();
return;
}
if (mp_read_unsigned_bin(&secret
, reinterpret_cast<unsigned char*>(m_dh_local_secret)
, sizeof(m_dh_local_secret)))
{
TORRENT_ASSERT_FAIL();
return;
}
// generator is 2
mp_set_int(&key, 2);
// key = (2 ^ secret) % prime
if (mp_exptmod(&key, &secret, &prime, &key))
{
TORRENT_ASSERT_FAIL();
return;
}
// key is now our local key
int const size = mp_unsigned_bin_size(&key);
TORRENT_ASSERT(size >= 0);
TORRENT_ASSERT(size <= sizeof(m_dh_local_key));
if (size < 0 || size > sizeof(m_dh_local_key)) return;
std::memset(m_dh_local_key, 0, sizeof(m_dh_local_key) - size);
mp_to_unsigned_bin(&key
, reinterpret_cast<unsigned char*>(m_dh_local_key)
+ sizeof(m_dh_local_key) - size);
}
char const* dh_key_exchange::get_local_key() const
{
return m_dh_local_key;
m_dh_local_key = mp::powm(key_t(2), m_dh_local_secret, dh_prime);
}
// compute shared secret given remote public key
int dh_key_exchange::compute_secret(char const* remote_pubkey)
void dh_key_exchange::compute_secret(boost::uint8_t const* remote_pubkey)
{
TORRENT_ASSERT(remote_pubkey);
mp_bigint prime;
mp_bigint secret;
mp_bigint remote_key;
// TODO 2: use exceptions for error reporting here
if (mp_read_unsigned_bin(&prime, dh_prime, sizeof(dh_prime)))
{
TORRENT_ASSERT_FAIL();
return -1;
}
if (mp_read_unsigned_bin(&secret
, reinterpret_cast<unsigned char*>(m_dh_local_secret)
, sizeof(m_dh_local_secret)))
{
TORRENT_ASSERT_FAIL();
return -1;
}
if (mp_read_unsigned_bin(&remote_key
, reinterpret_cast<const unsigned char*>(remote_pubkey), 96))
{
TORRENT_ASSERT_FAIL();
return -1;
key_t key;
mp::import_bits(key, remote_pubkey, remote_pubkey + 96);
compute_secret(key);
}
if (mp_exptmod(&remote_key, &secret, &prime, &remote_key))
void dh_key_exchange::compute_secret(key_t const& remote_pubkey)
{
TORRENT_ASSERT_FAIL();
return -1;
}
// shared_secret = (remote_pubkey ^ local_secret) % prime
m_dh_shared_secret = mp::powm(remote_pubkey, m_dh_local_secret, dh_prime);
// remote_key is now the shared secret
int const size = mp_unsigned_bin_size(&remote_key);
TORRENT_ASSERT(size >= 0);
TORRENT_ASSERT(size <= sizeof(m_dh_shared_secret));
if (size < 0 || size > sizeof(m_dh_shared_secret))
{
return -1;
}
std::memset(m_dh_shared_secret, 0, sizeof(m_dh_shared_secret) - size);
mp_to_unsigned_bin(&remote_key
, reinterpret_cast<unsigned char*>(m_dh_shared_secret)
+ sizeof(m_dh_shared_secret) - size);
std::array<boost::uint8_t, 96> buffer;
mp::export_bits(m_dh_shared_secret, buffer.begin(), 8);
// calculate the xor mask for the obfuscated hash
hasher h;
h.update("req3", 4);
h.update(m_dh_shared_secret, sizeof(m_dh_shared_secret));
h.update(reinterpret_cast<char const*>(buffer.data()), buffer.size());
m_xor_mask = h.final();
return 0;
}
int encryption_handler::encrypt(std::vector<boost::asio::mutable_buffer>& iovec)
@ -399,8 +317,6 @@ namespace libtorrent
produce = bytes_processed;
}
} // namespace libtorrent
// All this code is based on libTomCrypt (http://www.libtomcrypt.com/)
// this library is public domain and has been specially
// tailored for libtorrent by Arvid Norberg
@ -421,7 +337,7 @@ void rc4_init(const unsigned char* in, unsigned long len, rc4 *state)
}
/* extract the key */
s = state->buf;
s = state->buf.data();
std::memcpy(key, s, key_size);
keylen = state->x;
@ -452,7 +368,7 @@ unsigned long rc4_encrypt(unsigned char *out, unsigned long outlen, rc4 *state)
n = outlen;
x = state->x;
y = state->y;
s = state->buf;
s = state->buf.data();
while (outlen--) {
x = (x + 1) & 255;
y = (y + s[x]) & 255;
@ -465,5 +381,7 @@ unsigned long rc4_encrypt(unsigned char *out, unsigned long outlen, rc4 *state)
return n;
}
} // namespace libtorrent
#endif // #if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)

View File

@ -41,10 +41,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "setup_transfer.hpp"
#include "test.hpp"
extern "C" {
#include "libtorrent/tommath.h"
}
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
void test_enc_handler(libtorrent::crypto_plugin* a, libtorrent::crypto_plugin* b)
@ -93,15 +89,6 @@ void test_enc_handler(libtorrent::crypto_plugin* a, libtorrent::crypto_plugin* b
}
}
void print_key(char const* key)
{
for (int i = 0;i < 96; ++i)
{
std::printf("%02x ", unsigned(key[i]));
}
std::printf("\n");
}
TORRENT_TEST(diffie_hellman)
{
using namespace libtorrent;
@ -115,20 +102,20 @@ TORRENT_TEST(diffie_hellman)
DH1.compute_secret(DH2.get_local_key());
DH2.compute_secret(DH1.get_local_key());
TEST_CHECK(std::equal(DH1.get_secret(), DH1.get_secret() + 96, DH2.get_secret()));
if (!std::equal(DH1.get_secret(), DH1.get_secret() + 96, DH2.get_secret()))
TEST_EQUAL(DH1.get_secret(), DH2.get_secret());
if (!DH1.get_secret() != DH2.get_secret())
{
std::printf("DH1 local: ");
print_key(DH1.get_local_key());
std::cout << DH1.get_local_key() << std::endl;
std::printf("DH2 local: ");
print_key(DH2.get_local_key());
std::cout << DH2.get_local_key() << std::endl;
std::printf("DH1 shared_secret: ");
print_key(DH1.get_secret());
std::cout << DH1.get_secret() << std::endl;
std::printf("DH2 shared_secret: ");
print_key(DH2.get_secret());
std::cout << DH2.get_secret() << std::endl;
}
}
}
@ -150,28 +137,6 @@ TORRENT_TEST(rc4)
test_enc_handler(&rc41, &rc42);
}
TORRENT_TEST(tommath)
{
const unsigned char key[96] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63
};
mp_int bigint;
mp_init(&bigint);
TEST_CHECK(mp_read_unsigned_bin(&bigint, key, sizeof(key)) == 0);
TEST_EQUAL(mp_unsigned_bin_size(&bigint), sizeof(key));
mp_clear(&bigint);
}
#else
TORRENT_TEST(disabled)
{

View File

@ -39,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <fstream>
#include <iostream>
#include <boost/tuple/tuple.hpp>
using namespace libtorrent;