diff --git a/include/libtorrent/pe_crypto.hpp b/include/libtorrent/pe_crypto.hpp index dd1260497..05ee08ea1 100644 --- a/include/libtorrent/pe_crypto.hpp +++ b/include/libtorrent/pe_crypto.hpp @@ -58,7 +58,9 @@ namespace libtorrent // m_dh_secret. int compute_secret(const char* remote_pubkey); - const char* get_secret() const; + char const* get_secret() const { return m_dh_secret; } + + sha1_hash const& get_hash_xor_mask() const { return m_xor_mask; } private: int get_local_key_size() const @@ -71,6 +73,7 @@ namespace libtorrent char m_dh_local_key[96]; char m_dh_secret[96]; + sha1_hash m_xor_mask; }; class RC4_handler // Non copyable diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index d6a0f9dd3..c812aed33 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -132,6 +132,14 @@ namespace libtorrent void parse_resume_data(std::vector* resume_data); +#ifndef TORRENT_DISABLE_ENCRYPTION + sha1_hash const& obfuscated_hash() const + { return m_obfuscated_hash; } +#endif + + sha1_hash const& info_hash() const + { return m_torrent_file->info_hash(); } + // starts the announce timer void start(); @@ -821,6 +829,11 @@ namespace libtorrent // longer be used and will be reset boost::scoped_ptr m_name; +#ifndef TORRENT_DISABLE_ENCRYPTION + // this is SHA1("req2" + info-hash), used for + // encrypted hand shakes + sha1_hash m_obfuscated_hash; +#endif session_settings const& m_settings; storage_constructor_type m_storage_constructor; diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index c68640d79..7e9fd43ce 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -1841,7 +1841,8 @@ namespace libtorrent return; } - cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+20) - m_sync_bytes_read)); + cut_receive_buffer(bytes_processed, (std::min)(packet_size() + , (512+20) - m_sync_bytes_read)); TORRENT_ASSERT(!packet_finished()); return; @@ -1872,51 +1873,32 @@ namespace libtorrent recv_buffer = receive_buffer(); - // only calls info_hash() on the torrent_handle's, which - // never throws. - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - std::vector active_torrents = m_ses.get_torrents(); - std::vector::const_iterator i; - hasher h; - sha1_hash skey_hash, obfs_hash; + aux::session_impl::torrent_map::const_iterator i; - for (i = active_torrents.begin(); i != active_torrents.end(); ++i) + for (i = m_ses.m_torrents.begin(); i != m_ses.m_torrents.end(); ++i) { - torrent_handle const& t_h = *i; // TODO possible errors - sha1_hash const& info_hash = t_h.info_hash(); - // TODO Does info_hash need to be checked for validity? - - h.reset(); - h.update("req2", 4); - h.update((char*)info_hash.begin(), 20); - - skey_hash = h.final(); - - h.reset(); - h.update("req3", 4); - h.update(m_dh_key_exchange->get_secret(), dh_key_len); - - obfs_hash = h.final(); + torrent const& ti = *i->second; + sha1_hash const& skey_hash = ti.obfuscated_hash(); + sha1_hash obfs_hash = m_dh_key_exchange->get_hash_xor_mask(); obfs_hash ^= skey_hash; - if (std::equal (recv_buffer.begin, recv_buffer.begin + 20, - (char*)obfs_hash.begin())) + if (std::equal(recv_buffer.begin, recv_buffer.begin + 20, + (char*)&obfs_hash[0])) { if (!t) { - attach_to_torrent(info_hash); + attach_to_torrent(ti.info_hash()); if (is_disconnecting()) return; t = associated_torrent().lock(); TORRENT_ASSERT(t); } - init_pe_RC4_handler(m_dh_key_exchange->get_secret(), info_hash); + init_pe_RC4_handler(m_dh_key_exchange->get_secret(), ti.info_hash()); #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << " stream key found, torrent located.\n"; #endif - continue; // TODO Check flow control with multiple torrents + break; } } diff --git a/src/pe_crypto.cpp b/src/pe_crypto.cpp index f20535610..fe6ab6c81 100644 --- a/src/pe_crypto.cpp +++ b/src/pe_crypto.cpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include "libtorrent/pe_crypto.hpp" +#include "libtorrent/hasher.hpp" #include "libtorrent/assert.hpp" namespace libtorrent @@ -144,12 +145,14 @@ namespace libtorrent } std::copy(dh_secret, dh_secret + secret_size, m_dh_secret + 96 - secret_size); BN_free(bn_remote_pubkey); - return 0; - } - char const* dh_key_exchange::get_secret() const - { - return m_dh_secret; + // calculate the xor mask for the obfuscated hash + hasher h; + h.update("req3", 4); + h.update(m_dh_secret, 96); + m_xor_mask = h.final(); + + return 0; } } // namespace libtorrent diff --git a/src/torrent.cpp b/src/torrent.cpp index e116d1d40..555d48561 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -206,6 +206,13 @@ namespace libtorrent , m_complete_sent(false) { parse_resume_data(resume_data); + +#ifndef TORRENT_DISABLE_ENCRYPTION + hasher h; + h.update("req2", 4); + h.update((char*)&tf->info_hash()[0], 20); + m_obfuscated_hash = h.final(); +#endif } torrent::torrent( @@ -280,6 +287,14 @@ namespace libtorrent , m_complete_sent(false) { parse_resume_data(resume_data); + +#ifndef TORRENT_DISABLE_ENCRYPTION + hasher h; + h.update("req2", 4); + h.update((char*)&info_hash[0], 20); + m_obfuscated_hash = h.final(); +#endif + #ifndef NDEBUG m_files_checked = false; #endif