1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-12 23:23:54 +00:00

refactor: save outgoing len(PadA), len(PadB) and len(IA) (#6973)

* refactor: save length of PadA and PadB sent

* refactor: log outgoing `len(PadA)` and `len(PadB)`

* refactor: set `ia_len_` as the MSE handshake initiator
This commit is contained in:
Yat Ho 2025-03-11 00:06:42 +08:00 committed by GitHub
parent 088232f69c
commit 40814a3195
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 22 additions and 24 deletions

View file

@ -40,8 +40,8 @@ using key_bigend_t = tr_message_stream_encryption::DH::key_bigend_t;
// 1 A->B: our public key (Ya) and some padding (PadA)
void tr_handshake::send_ya(tr_peerIo* io)
{
tr_logAddTraceHand(this, "sending MSE handshake (Ya)");
send_public_key_and_pad<PadaMaxlen>(io);
pad_a_len_ = send_public_key_and_pad<PadaMaxlen>(io);
tr_logAddTraceHand(this, fmt::format("sent MSE handshake (Ya)... len(PadA) = {}", pad_a_len_));
set_state(tr_handshake::State::AwaitingYb);
}
@ -77,12 +77,12 @@ ReadState tr_handshake::read_yb(tr_peerIo* peer_io)
// everything received so far is Yb+PadB; peer has not yet sent VC for resync.
// so throw away buffer, and do early exit check: we know it's not legit MSE if > max PadB
pad_b_recv_len_ = peer_io->read_buffer_size();
if (pad_b_recv_len_ > PadbMaxlen)
pad_b_len_ = peer_io->read_buffer_size();
if (pad_b_len_ > PadbMaxlen)
{
return done(false);
}
peer_io->read_buffer_discard(pad_b_recv_len_);
peer_io->read_buffer_discard(pad_b_len_);
/* now send these: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S),
* ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA) */
@ -119,6 +119,7 @@ ReadState tr_handshake::read_yb(tr_peerIo* peer_io)
outbuf.add_uint16(0);
/* ENCRYPT len(IA)), ENCRYPT(IA) */
ia_len_ = HandshakeSize;
outbuf.add_uint16(HandshakeSize);
if (build_handshake_message(peer_io, outbuf))
{
@ -155,14 +156,14 @@ ReadState tr_handshake::read_vc(tr_peerIo* peer_io)
filter.encrypt(std::data(VC), std::size(VC), std::data(*encrypted_vc_));
}
for (; pad_b_recv_len_ <= PadbMaxlen; ++pad_b_recv_len_)
for (; pad_b_len_ <= PadbMaxlen; ++pad_b_len_)
{
static auto constexpr Needlen = std::size(VC);
if (peer_io->read_buffer_size() < Needlen)
{
tr_logAddTraceHand(
this,
fmt::format("in read_vc... need {}, read {}, have {}", Needlen, pad_b_recv_len_, peer_io->read_buffer_size()));
fmt::format("in read_vc... need {}, read {}, have {}", Needlen, pad_b_len_, peer_io->read_buffer_size()));
return ReadState::Later;
}
@ -244,7 +245,7 @@ ReadState tr_handshake::read_handshake(tr_peerIo* peer_io)
return ReadState::Later;
}
if (ia_len_ > 0U)
if (is_incoming() && ia_len_ > 0U)
{
// do nothing, the check below won't work correctly
}
@ -382,16 +383,16 @@ ReadState tr_handshake::read_ya(tr_peerIo* peer_io)
// everything received so far is Ya+PadA; haven't sent Yb and peer has not yet sent HASH('req1').
// so throw away buffer, and do early exit check: we know it's not legit MSE if > max PadA
pad_a_recv_len_ = peer_io->read_buffer_size();
if (pad_a_recv_len_ > PadaMaxlen)
pad_a_len_ = peer_io->read_buffer_size();
if (pad_a_len_ > PadaMaxlen)
{
return done(false);
}
peer_io->read_buffer_discard(pad_a_recv_len_);
peer_io->read_buffer_discard(pad_a_len_);
// send our public key to the peer
tr_logAddTraceHand(this, "sending B->A: Diffie Hellman Yb, PadB");
send_public_key_and_pad<PadbMaxlen>(peer_io);
pad_b_len_ = send_public_key_and_pad<PadbMaxlen>(peer_io);
tr_logAddTraceHand(this, fmt::format("sent B->A: Diffie Hellman Yb, PadB... len(PadB) = {}", pad_b_len_));
set_state(State::AwaitingPadA);
// LATER, not NOW: recv buffer was just drained and peer was blocking
@ -403,18 +404,14 @@ ReadState tr_handshake::read_pad_a(tr_peerIo* peer_io)
// find the end of PadA by looking for HASH('req1', S)
auto const needle = tr_sha1::digest("req1"sv, get_dh().secret());
for (; pad_a_recv_len_ <= PadaMaxlen; ++pad_a_recv_len_)
for (; pad_a_len_ <= PadaMaxlen; ++pad_a_len_)
{
static auto constexpr Needlen = std::size(needle);
if (peer_io->read_buffer_size() < Needlen)
{
tr_logAddTraceHand(
this,
fmt::format(
"in read_pad_a... need {}, read {}, have {}",
Needlen,
pad_a_recv_len_,
peer_io->read_buffer_size()));
fmt::format("in read_pad_a... need {}, read {}, have {}", Needlen, pad_a_len_, peer_io->read_buffer_size()));
return ReadState::Later;
}

View file

@ -235,15 +235,17 @@ private:
bool send_handshake(tr_peerIo* io);
template<size_t PadMax>
void send_public_key_and_pad(tr_peerIo* io)
auto send_public_key_and_pad(tr_peerIo* io)
{
auto const public_key = get_dh().publicKey();
auto outbuf = std::array<std::byte, std::size(public_key) + PadMax>{};
auto const data = std::data(outbuf);
auto walk = data;
walk = std::copy(std::begin(public_key), std::end(public_key), walk);
walk += mediator_->pad(walk, PadMax);
auto const pad_len = mediator_->pad(walk, PadMax);
walk += pad_len;
io->write_bytes(data, walk - data, false);
return pad_len;
}
[[nodiscard]] uint32_t crypto_provide() const noexcept;
@ -334,13 +336,12 @@ private:
uint32_t crypto_select_ = {};
uint32_t crypto_provide_ = {};
uint16_t pad_a_len_ = {};
uint16_t pad_b_len_ = {};
uint16_t pad_c_len_ = {};
uint16_t pad_d_len_ = {};
uint16_t ia_len_ = {};
uint16_t pad_a_recv_len_ = {};
uint16_t pad_b_recv_len_ = {};
bool have_read_anything_from_peer_ = false;
bool have_sent_bittorrent_handshake_ = false;