using span in crypto_plugin encrypt/decrypt (#934)

This commit is contained in:
Alden Torres 2016-07-23 18:54:39 -04:00 committed by Arvid Norberg
parent f57612b82d
commit ddb274751f
14 changed files with 69 additions and 82 deletions

View File

@ -161,8 +161,8 @@ namespace libtorrent
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
// next_barrier, buffers-to-prepend
virtual
std::tuple<int, span<boost::asio::const_buffer>>
hit_send_barrier(span<boost::asio::mutable_buffer> iovec) override;
std::tuple<int, span<aux::const_buffer>>
hit_send_barrier(span<aux::mutable_buffer> iovec) override;
#endif
virtual void get_specific_peer_info(peer_info& p) const override;

View File

@ -59,6 +59,13 @@ namespace libtorrent {
}
}
// TODO: eventually move this file to aux_ or create a new one
namespace aux
{
using mutable_buffer = span<char>;
using const_buffer = span<char const>;
}
// the buffer is allocated once and cannot be resized. The size() may be
// larger than requested, in case the underlying allocator over allocated. In
// order to "grow" an allocation, create a new buffer and initialize it by
@ -241,4 +248,3 @@ private:
}
#endif // BTORRENT_BUFFER_HPP_INCLUDED

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include "libtorrent/disk_io_job.hpp" // for block_cache_reference
#include "libtorrent/debug.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/aux_/disable_warnings_push.hpp"
@ -110,7 +111,7 @@ namespace libtorrent
void clear();
void build_mutable_iovec(int bytes, std::vector<boost::asio::mutable_buffer>& vec);
void build_mutable_iovec(int bytes, std::vector<aux::mutable_buffer>& vec);
~chained_buffer();
@ -142,4 +143,3 @@ namespace libtorrent
}
#endif

View File

@ -160,12 +160,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_DISABLE_EXTENSIONS
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/weak_ptr.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
#include <vector>
#include "libtorrent/config.hpp"
#include "libtorrent/buffer.hpp"
@ -509,8 +503,8 @@ namespace libtorrent
// send buffer, must be owned by the crypto plugin and guaranteed to stay
// alive until the crypto_plugin is destructed or this function is called
// again.
virtual std::tuple<int, span<boost::asio::const_buffer>>
encrypt(span<boost::asio::mutable_buffer> /*send_vec*/) = 0;
virtual std::tuple<int, span<span<char const>>>
encrypt(span<span<char>> /*send_vec*/) = 0;
// decrypt the provided buffers.
// consume is set to the number of bytes which should be trimmed from the
@ -521,7 +515,7 @@ namespace libtorrent
//
// packet_size is set to the minimum number of bytes which must be read to
// advance the next step of decryption. default is 0
virtual void decrypt(span<boost::asio::mutable_buffer> /*receive_vec*/
virtual void decrypt(span<span<char>> /*receive_vec*/
, int& /* consume */, int& /*produce*/, int& /*packet_size*/) = 0;
};
}
@ -529,4 +523,3 @@ namespace libtorrent
#endif
#endif // TORRENT_EXTENSIONS_HPP_INCLUDED

View File

@ -38,7 +38,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#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"
@ -47,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/extensions.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/span.hpp"
#include "libtorrent/buffer.hpp"
#include <list>
#include <array>
@ -56,7 +56,7 @@ namespace libtorrent
{
namespace mp = boost::multiprecision;
using key_t = mp::number<mp::cpp_int_backend<768, 768, mp::unsigned_magnitude, mp::unchecked, void> >;
using key_t = mp::number<mp::cpp_int_backend<768, 768, mp::unsigned_magnitude, mp::unchecked, void>>;
// RC4 state from libtomcrypt
struct rc4 {
@ -99,8 +99,8 @@ namespace libtorrent
struct encryption_handler
{
std::tuple<int, span<boost::asio::const_buffer>>
encrypt(span<boost::asio::mutable_buffer> iovec);
std::tuple<int, span<aux::const_buffer>>
encrypt(span<aux::mutable_buffer> iovec);
int decrypt(crypto_receive_buffer& recv_buffer
, std::size_t& bytes_transferred);
@ -144,10 +144,10 @@ namespace libtorrent
void set_incoming_key(unsigned char const* key, int len) override;
void set_outgoing_key(unsigned char const* key, int len) override;
std::tuple<int, span<boost::asio::const_buffer>>
encrypt(span<boost::asio::mutable_buffer> buf) override;
std::tuple<int, span<aux::const_buffer>>
encrypt(span<aux::mutable_buffer> buf) override;
void decrypt(span<boost::asio::mutable_buffer> buf
void decrypt(span<aux::mutable_buffer> buf
, int& consume
, int& produce
, int& packet_size) override;
@ -165,4 +165,3 @@ namespace libtorrent
#endif // TORRENT_PE_CRYPTO_HPP_INCLUDED
#endif // TORRENT_DISABLE_ENCRYPTION

View File

@ -749,11 +749,11 @@ namespace libtorrent
void send_piece_suggestions(int num);
virtual
std::tuple<int, span<boost::asio::const_buffer>>
hit_send_barrier(span<boost::asio::mutable_buffer> /* iovec */)
std::tuple<int, span<aux::const_buffer>>
hit_send_barrier(span<aux::mutable_buffer> /* iovec */)
{
return std::make_tuple(INT_MAX
, span<boost::asio::const_buffer>());
, span<aux::const_buffer>());
}
void attach_to_torrent(sha1_hash const& ih);

View File

@ -92,7 +92,7 @@ struct TORRENT_EXTRA_EXPORT receive_buffer
buffer::interval mutable_buffer();
// returns the last 'bytes' from the receive buffer
boost::asio::mutable_buffer mutable_buffer(int bytes);
aux::mutable_buffer mutable_buffer(int bytes);
#endif
// the purpose of this function is to free up and cut off all messages
@ -158,7 +158,7 @@ private:
// Wraps a receive_buffer to provide the ability to inject
// possibly authenticated crypto beneath the bittorrent protocol.
// When authenticated crypto is in use the wrapped receive_buffer
// holds the receive state of the crpyto layer while this class
// holds the receive state of the crypto layer while this class
// tracks the state of the bittorrent protocol.
struct crypto_receive_buffer
{
@ -200,7 +200,7 @@ struct crypto_receive_buffer
buffer::const_interval get() const;
boost::asio::mutable_buffer mutable_buffer(std::size_t bytes);
aux::mutable_buffer mutable_buffer(std::size_t bytes);
private:
// explicitly disallow assignment, to silence msvc warning
@ -215,4 +215,3 @@ private:
} // namespace libtorrent
#endif // #ifndef TORRENT_RECEIVE_BUFFER_HPP_INCLUDED

View File

@ -603,7 +603,7 @@ namespace libtorrent
#endif
write_pe_vc_cryptofield(ptr, encrypt_size, crypto_provide, pad_size);
boost::asio::mutable_buffer vec(ptr, encrypt_size);
aux::mutable_buffer vec(ptr, encrypt_size);
m_rc4->encrypt(vec);
send_buffer(msg, sizeof(msg) - 512 + pad_size);
}
@ -624,7 +624,7 @@ namespace libtorrent
char msg[512 + 8 + 4 + 2];
write_pe_vc_cryptofield(msg, sizeof(msg), crypto_select, pad_size);
boost::asio::mutable_buffer vec(msg, buf_size);
aux::mutable_buffer vec(msg, buf_size);
m_rc4->encrypt(vec);
send_buffer(msg, buf_size);
@ -702,7 +702,7 @@ namespace libtorrent
int consume = 0;
int produce = len;
int packet_size = 0;
boost::asio::mutable_buffer vec(pos, len);
aux::mutable_buffer vec(pos, len);
m_rc4->decrypt(vec, consume, produce, packet_size);
}
@ -3471,12 +3471,12 @@ namespace libtorrent
}
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
std::tuple<int, span<boost::asio::const_buffer>>
std::tuple<int, span<aux::const_buffer>>
bt_peer_connection::hit_send_barrier(
span<boost::asio::mutable_buffer> iovec)
span<aux::mutable_buffer> iovec)
{
int next_barrier;
span<boost::asio::const_buffer> out_iovec;
span<aux::const_buffer> out_iovec;
std::tie(next_barrier, out_iovec) = m_enc_handler.encrypt(iovec);
#ifndef TORRENT_DISABLE_LOGGING
if (next_barrier != 0)
@ -3576,4 +3576,3 @@ namespace libtorrent
#endif
}

View File

@ -151,7 +151,7 @@ namespace libtorrent
return m_tmp_vec;
}
void chained_buffer::build_mutable_iovec(int bytes, std::vector<boost::asio::mutable_buffer> &vec)
void chained_buffer::build_mutable_iovec(int bytes, std::vector<aux::mutable_buffer> &vec)
{
build_vec(bytes, vec);
}
@ -199,4 +199,3 @@ namespace libtorrent
}
}

View File

@ -103,38 +103,36 @@ namespace libtorrent
m_xor_mask = h.final();
}
std::tuple<int, span<boost::asio::const_buffer>>
std::tuple<int, span<aux::const_buffer>>
encryption_handler::encrypt(
span<boost::asio::mutable_buffer> iovec)
span<aux::mutable_buffer> iovec)
{
using namespace boost::asio;
TORRENT_ASSERT(!m_send_barriers.empty());
TORRENT_ASSERT(m_send_barriers.front().enc_handler);
int to_process = m_send_barriers.front().next;
boost::asio::mutable_buffer* bufs;
aux::mutable_buffer* bufs;
size_t num_bufs;
bool need_destruct = false;
if (to_process != INT_MAX)
{
bufs = TORRENT_ALLOCA(mutable_buffer, iovec.size());
bufs = TORRENT_ALLOCA(aux::mutable_buffer, iovec.size());
need_destruct = true;
num_bufs = 0;
for (int i = 0; to_process > 0 && i < iovec.size(); ++i)
{
++num_bufs;
int const size = buffer_size(iovec[i]);
int const size = int(iovec[i].size());
if (to_process < size)
{
new (&bufs[i]) mutable_buffer(
buffer_cast<void*>(iovec[i]), to_process);
new (&bufs[i]) aux::mutable_buffer(
iovec[i].data(), to_process);
to_process = 0;
}
else
{
new (&bufs[i]) mutable_buffer(iovec[i]);
new (&bufs[i]) aux::mutable_buffer(iovec[i]);
to_process -= size;
}
}
@ -146,7 +144,7 @@ namespace libtorrent
}
int next_barrier = 0;
span<const_buffer> out_iovec;
span<aux::const_buffer> out_iovec;
if (num_bufs != 0)
{
std::tie(next_barrier, out_iovec)
@ -179,18 +177,18 @@ namespace libtorrent
{
int payload = 0;
for (int i = 0; i < num_bufs; ++i)
payload += int(buffer_size(bufs[i]));
payload += int(bufs[i].size());
int overhead = 0;
for (auto buf : out_iovec)
overhead += int(buffer_size(buf));
overhead += int(buf.size());
TORRENT_ASSERT(overhead + payload == next_barrier);
}
#endif
if (need_destruct)
{
for (int i = 0; i < num_bufs; ++i)
bufs[i].~mutable_buffer();
bufs[i].~span<char>();
}
return std::make_tuple(next_barrier, out_iovec);
}
@ -202,7 +200,7 @@ namespace libtorrent
int consume = 0;
if (recv_buffer.crypto_packet_finished())
{
boost::asio::mutable_buffer wr_buf = recv_buffer.mutable_buffer(bytes_transferred);
aux::mutable_buffer wr_buf = recv_buffer.mutable_buffer(bytes_transferred);
int packet_size = 0;
int produce = int(bytes_transferred);
m_dec_handler->decrypt(wr_buf, consume, produce, packet_size);
@ -248,7 +246,7 @@ namespace libtorrent
{
int consume = 0;
int produce = 0;
std::vector<boost::asio::mutable_buffer> wr_buf;
std::vector<aux::mutable_buffer> wr_buf;
crypto->decrypt(wr_buf, consume, produce, packet_size);
TORRENT_ASSERT(wr_buf.empty());
TORRENT_ASSERT(consume == 0);
@ -276,7 +274,7 @@ namespace libtorrent
int produce = 0;
int packet_size = 0;
char buf[1024];
boost::asio::mutable_buffer vec(buf, sizeof(buf));
aux::mutable_buffer vec(buf, sizeof(buf));
decrypt(vec, consume, produce, packet_size);
}
@ -286,23 +284,22 @@ namespace libtorrent
rc4_init(key, len, &m_rc4_outgoing);
// Discard first 1024 bytes
char buf[1024];
boost::asio::mutable_buffer vec(buf, sizeof(buf));
aux::mutable_buffer vec(buf, sizeof(buf));
encrypt(vec);
}
std::tuple<int, span<boost::asio::const_buffer>>
rc4_handler::encrypt(span<boost::asio::mutable_buffer> bufs)
std::tuple<int, span<aux::const_buffer>>
rc4_handler::encrypt(span<aux::mutable_buffer> bufs)
{
using namespace boost::asio;
span<boost::asio::const_buffer> empty;
span<aux::const_buffer> empty;
if (!m_encrypt) return std::make_tuple(0, empty);
if (bufs.size() == 0) return std::make_tuple(0, empty);
int bytes_processed = 0;
for (auto& buf : bufs)
{
unsigned char* const pos = buffer_cast<unsigned char*>(buf);
int const len = int(buffer_size(buf));
unsigned char* const pos = reinterpret_cast<unsigned char*>(buf.data());
int const len = int(buf.size());
TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos);
@ -313,7 +310,7 @@ namespace libtorrent
return std::make_tuple(bytes_processed, empty);
}
void rc4_handler::decrypt(span<boost::asio::mutable_buffer> bufs
void rc4_handler::decrypt(span<aux::mutable_buffer> bufs
, int& consume
, int& produce
, int& packet_size)
@ -327,8 +324,8 @@ namespace libtorrent
int bytes_processed = 0;
for (auto& buf : bufs)
{
unsigned char* const pos = boost::asio::buffer_cast<unsigned char*>(buf);
int const len = int(boost::asio::buffer_size(buf));
unsigned char* const pos = reinterpret_cast<unsigned char*>(buf.data());
int const len = int(buf.size());
TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos);
@ -406,4 +403,3 @@ unsigned long rc4_encrypt(unsigned char *out, unsigned long outlen, rc4 *state)
} // namespace libtorrent
#endif // #if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)

View File

@ -5468,20 +5468,19 @@ namespace libtorrent
if (m_send_barrier == 0)
{
std::vector<boost::asio::mutable_buffer> vec;
std::vector<aux::mutable_buffer> vec;
// limit outgoing crypto messages to 1MB
int const send_bytes = (std::min)(m_send_buffer.size(), 1024*1024);
m_send_buffer.build_mutable_iovec(send_bytes, vec);
int next_barrier;
span<boost::asio::const_buffer> inject_vec;
span<aux::const_buffer> inject_vec;
std::tie(next_barrier, inject_vec) = hit_send_barrier(vec);
for (auto i = inject_vec.rbegin(); i != inject_vec.rend(); ++i)
{
int const size = boost::asio::buffer_size(*i);
int const size = int(i->size());
// this const_cast is a here because chained_buffer need to be
// fixed.
char* ptr = const_cast<char*>(
boost::asio::buffer_cast<char const*>(*i));
char* ptr = const_cast<char*>(i->data());
m_send_buffer.prepend_buffer(ptr
, size, size, &nop, nullptr);
}

View File

@ -157,17 +157,15 @@ buffer::interval receive_buffer::mutable_buffer()
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
}
boost::asio::mutable_buffer receive_buffer::mutable_buffer(int const bytes)
aux::mutable_buffer receive_buffer::mutable_buffer(int const bytes)
{
namespace asio = boost::asio;
// bytes is the number of bytes we just received, and m_recv_pos has
// already been adjusted for these bytes. The receive pos immediately
// before we received these bytes was (m_recv_pos - bytes)
int const last_recv_pos = m_recv_pos - bytes;
TORRENT_ASSERT(bytes <= m_recv_pos);
return asio::mutable_buffer(&m_recv_buffer[0] + m_recv_start
return aux::mutable_buffer(&m_recv_buffer[0] + m_recv_start
+ last_recv_pos, bytes);
}
#endif
@ -329,7 +327,7 @@ buffer::const_interval crypto_receive_buffer::get() const
return recv_buffer;
}
boost::asio::mutable_buffer crypto_receive_buffer::mutable_buffer(
aux::mutable_buffer crypto_receive_buffer::mutable_buffer(
std::size_t const bytes)
{
int const pending_decryption = (m_recv_pos != INT_MAX)

View File

@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/session.hpp"
#include "libtorrent/random.hpp"
#include "libtorrent/span.hpp"
#include "libtorrent/buffer.hpp"
#include "setup_transfer.hpp"
#include "test.hpp"
@ -58,7 +59,7 @@ void test_enc_handler(libtorrent::crypto_plugin& a, libtorrent::crypto_plugin& b
std::generate(buf.begin(), buf.end(), &std::rand);
std::copy(buf.begin(), buf.end(), cmp_buf.begin());
using namespace boost::asio;
using namespace libtorrent::aux;
{
mutable_buffer iovec(&buf[0], buf_len);
@ -158,4 +159,3 @@ TORRENT_TEST(disabled)
std::fprintf(stderr, "PE test not run because it's disabled\n");
}
#endif

View File

@ -229,7 +229,7 @@ TORRENT_TEST(recv_buffer_mutable_buffers)
b.cut(100, 1000); // packet size = 1000
packet_transferred = b.advance_pos(999);
TEST_EQUAL(packet_transferred, 999);
boost::asio::mutable_buffer vec = b.mutable_buffer(999);
aux::mutable_buffer vec = b.mutable_buffer(999);
// previous packet
// |
@ -242,8 +242,7 @@ TORRENT_TEST(recv_buffer_mutable_buffers)
// |----------------------| 1000 packet size
// |---------------------| 999 buffer
TEST_EQUAL(boost::asio::buffer_size(vec), 999);
TEST_EQUAL(vec.size(), 999);
}
#endif