diff --git a/libtransmission/crypto.cc b/libtransmission/crypto.cc index 1ff1b4eb8..cb11d1e42 100644 --- a/libtransmission/crypto.cc +++ b/libtransmission/crypto.cc @@ -13,14 +13,34 @@ #include "tr-assert.h" #include "utils.h" -/** -*** -**/ +/// -static auto constexpr PrimeLen = size_t{ 96 }; -static auto constexpr DhPrivkeyLen = size_t{ 20 }; +tr_crypto::tr_crypto(tr_sha1_digest_t const* torrent_hash, bool is_incoming) + : is_incoming_{ is_incoming } +{ + if (torrent_hash != nullptr) + { + this->torrent_hash_ = *torrent_hash; + } +} -static uint8_t constexpr dh_P[PrimeLen] = { +tr_crypto::~tr_crypto() +{ + tr_dh_secret_free(my_secret_); + tr_dh_free(dh_); + tr_free(enc_key_); + tr_free(dec_key_); +} + +/// + +namespace +{ + +auto constexpr PrimeLen = size_t{ 96 }; +auto constexpr DhPrivkeyLen = size_t{ 20 }; + +uint8_t constexpr dh_P[PrimeLen] = { 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, // @@ -31,76 +51,20 @@ static uint8_t constexpr dh_P[PrimeLen] = { 0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63, // }; -static uint8_t constexpr dh_G[] = { 2 }; +uint8_t constexpr dh_G[] = { 2 }; -/** -*** -**/ - -static void ensureKeyExists(tr_crypto* crypto) +void init_rc4(tr_crypto const* crypto, struct arc4_context** setme, std::string_view key) { - if (crypto->dh == nullptr) - { - size_t public_key_length = KEY_LEN; - crypto->dh = tr_dh_new(dh_P, sizeof(dh_P), dh_G, sizeof(dh_G)); - tr_dh_make_key(crypto->dh, DhPrivkeyLen, crypto->myPublicKey, &public_key_length); - - TR_ASSERT(public_key_length == KEY_LEN); - } -} - -tr_crypto::tr_crypto(tr_sha1_digest_t const* torrent_hash_in, bool is_incoming_in) - : is_incoming{ is_incoming_in } -{ - if (torrent_hash_in != nullptr) - { - this->torrent_hash = *torrent_hash_in; - } -} - -tr_crypto::~tr_crypto() -{ - tr_dh_secret_free(this->mySecret); - tr_dh_free(this->dh); - tr_free(this->enc_key); - tr_free(this->dec_key); -} - -/** -*** -**/ - -bool tr_cryptoComputeSecret(tr_crypto* crypto, uint8_t const* peerPublicKey) -{ - ensureKeyExists(crypto); - crypto->mySecret = tr_dh_agree(crypto->dh, peerPublicKey, KEY_LEN); - return crypto->mySecret != nullptr; -} - -uint8_t const* tr_cryptoGetMyPublicKey(tr_crypto const* crypto, int* setme_len) -{ - ensureKeyExists(const_cast(crypto)); - *setme_len = KEY_LEN; - return crypto->myPublicKey; -} - -/** -*** -**/ - -static void init_rc4(tr_crypto const* crypto, struct arc4_context** setme, char const* key) -{ - TR_ASSERT(crypto->torrent_hash); + TR_ASSERT(crypto->torrentHash()); if (*setme == nullptr) { *setme = tr_new0(struct arc4_context, 1); } - auto const buf = crypto->torrent_hash ? - tr_cryptoSecretKeySha1(crypto, key, 4, std::data(*crypto->torrent_hash), std::size(*crypto->torrent_hash)) : - std::nullopt; - + auto const hash = crypto->torrentHash(); + auto const buf = hash ? crypto->secretKeySha1(std::data(key), std::size(key), std::data(*hash), std::size(*hash)) : + std::nullopt; if (buf) { arc4_init(*setme, std::data(*buf), std::size(*buf)); @@ -108,7 +72,7 @@ static void init_rc4(tr_crypto const* crypto, struct arc4_context** setme, char } } -static void crypt_rc4(struct arc4_context* key, size_t buf_len, void const* buf_in, void* buf_out) +void crypt_rc4(struct arc4_context* key, size_t buf_len, void const* buf_in, void* buf_out) { if (key == nullptr) { @@ -123,51 +87,62 @@ static void crypt_rc4(struct arc4_context* key, size_t buf_len, void const* buf_ arc4_process(key, buf_in, buf_out, buf_len); } -void tr_cryptoDecryptInit(tr_crypto* crypto) +} // namespace + +/// + +bool tr_crypto::computeSecret(void const* peer_public_key, size_t len) { - init_rc4(crypto, &crypto->dec_key, crypto->is_incoming ? "keyA" : "keyB"); // lgtm[cpp/weak-cryptographic-algorithm] + ensureKeyExists(); + my_secret_ = tr_dh_agree(dh_, static_cast(peer_public_key), len); + return my_secret_ != nullptr; } -void tr_cryptoDecrypt(tr_crypto* crypto, size_t buf_len, void const* buf_in, void* buf_out) +void tr_crypto::ensureKeyExists() { - crypt_rc4(crypto->dec_key, buf_len, buf_in, buf_out); // lgtm[cpp/weak-cryptographic-algorithm] + if (dh_ == nullptr) + { + size_t public_key_length = KEY_LEN; + dh_ = tr_dh_new(dh_P, sizeof(dh_P), dh_G, sizeof(dh_G)); + tr_dh_make_key(dh_, DhPrivkeyLen, my_public_key_, &public_key_length); + + TR_ASSERT(public_key_length == KEY_LEN); + } +} +void tr_crypto::decryptInit() +{ + init_rc4(this, &dec_key_, is_incoming_ ? "keyA" : "keyB"); // lgtm[cpp/weak-cryptographic-algorithm] } -void tr_cryptoEncryptInit(tr_crypto* crypto) +void tr_crypto::decrypt(size_t buf_len, void const* buf_in, void* buf_out) { - init_rc4(crypto, &crypto->enc_key, crypto->is_incoming ? "keyB" : "keyA"); // lgtm[cpp/weak-cryptographic-algorithm] + crypt_rc4(dec_key_, buf_len, buf_in, buf_out); // lgtm[cpp/weak-cryptographic-algorithm] } -void tr_cryptoEncrypt(tr_crypto* crypto, size_t buf_len, void const* buf_in, void* buf_out) +void tr_crypto::encryptInit() { - crypt_rc4(crypto->enc_key, buf_len, buf_in, buf_out); // lgtm[cpp/weak-cryptographic-algorithm] + init_rc4(this, &enc_key_, is_incoming_ ? "keyB" : "keyA"); // lgtm[cpp/weak-cryptographic-algorithm] } -std::optional tr_cryptoSecretKeySha1( - tr_crypto const* crypto, - void const* prepend_data, - size_t prepend_data_size, - void const* append_data, - size_t append_data_size) +void tr_crypto::encrypt(size_t buf_len, void const* buf_in, void* buf_out) { - TR_ASSERT(crypto != nullptr); - TR_ASSERT(crypto->mySecret != nullptr); - - return tr_dh_secret_derive(crypto->mySecret, prepend_data, prepend_data_size, append_data, append_data_size); + crypt_rc4(enc_key_, buf_len, buf_in, buf_out); // lgtm[cpp/weak-cryptographic-algorithm] } -/** -*** -**/ - -void tr_cryptoSetTorrentHash(tr_crypto* crypto, tr_sha1_digest_t const& hash) +std::optional tr_crypto::secretKeySha1( + void const* prepend, + size_t prepend_len, + void const* append, + size_t append_len) const { - crypto->torrent_hash = hash; + return tr_dh_secret_derive(my_secret_, prepend, prepend_len, append, append_len); } -std::optional tr_cryptoGetTorrentHash(tr_crypto const* crypto) +std::vector tr_crypto::pad(size_t maxlen) const { - TR_ASSERT(crypto != nullptr); - - return crypto->torrent_hash; + auto const len = tr_rand_int(maxlen); + auto ret = std::vector{}; + ret.resize(len); + tr_rand_buffer(std::data(ret), len); + return ret; } diff --git a/libtransmission/crypto.h b/libtransmission/crypto.h index 7ff90a13f..32707b8f6 100644 --- a/libtransmission/crypto.h +++ b/libtransmission/crypto.h @@ -14,15 +14,12 @@ #include // size_t #include // uint8_t #include +#include +#include #include "crypto-utils.h" #include "tr-macros.h" -/** -*** @addtogroup peers -*** @{ -**/ - enum { KEY_LEN = 96 @@ -34,38 +31,57 @@ struct tr_crypto tr_crypto(tr_sha1_digest_t const* torrent_hash = nullptr, bool is_incoming = true); ~tr_crypto(); - std::optional torrent_hash = {}; - struct arc4_context* dec_key = nullptr; - struct arc4_context* enc_key = nullptr; - tr_dh_ctx_t dh = {}; - uint8_t myPublicKey[KEY_LEN] = {}; - tr_dh_secret_t mySecret = {}; - bool is_incoming = false; + tr_crypto& operator=(tr_crypto const&) = delete; + tr_crypto& operator=(tr_crypto&&) = delete; + tr_crypto(tr_crypto const&) = delete; + tr_crypto(tr_crypto&&) = delete; + + void setTorrentHash(tr_sha1_digest_t hash) noexcept + { + torrent_hash_ = hash; + } + + [[nodiscard]] constexpr auto const& torrentHash() const noexcept + { + return torrent_hash_; + } + + [[nodiscard]] std::string_view myPublicKey() + { + ensureKeyExists(); + return { reinterpret_cast(my_public_key_), KEY_LEN }; + } + + [[nodiscard]] bool computeSecret(void const* peer_public_key, size_t len); + + [[nodiscard]] std::optional secretKeySha1( + void const* prepend, + size_t prepend_len, + void const* append, + size_t append_len) const; + + [[nodiscard]] constexpr auto isIncoming() const noexcept + { + return is_incoming_; + } + + [[nodiscard]] virtual std::vector pad(size_t maxlen) const; + + void decryptInit(); + void decrypt(size_t buflen, void const* buf_in, void* buf_out); + void encryptInit(); + void encrypt(size_t buflen, void const* buf_in, void* buf_out); + +private: + void ensureKeyExists(); + + std::optional torrent_hash_; + struct arc4_context* dec_key_ = nullptr; + struct arc4_context* enc_key_ = nullptr; + tr_dh_ctx_t dh_ = {}; + tr_dh_secret_t my_secret_ = {}; + uint8_t my_public_key_[KEY_LEN] = {}; + bool const is_incoming_; }; -void tr_cryptoSetTorrentHash(tr_crypto* crypto, tr_sha1_digest_t const& torrent_hash); - -std::optional tr_cryptoGetTorrentHash(tr_crypto const* crypto); - -bool tr_cryptoComputeSecret(tr_crypto* crypto, uint8_t const* peerPublicKey); - -uint8_t const* tr_cryptoGetMyPublicKey(tr_crypto const* crypto, int* setme_len); - -void tr_cryptoDecryptInit(tr_crypto* crypto); - -void tr_cryptoDecrypt(tr_crypto* crypto, size_t buflen, void const* buf_in, void* buf_out); - -void tr_cryptoEncryptInit(tr_crypto* crypto); - -void tr_cryptoEncrypt(tr_crypto* crypto, size_t buflen, void const* buf_in, void* buf_out); - -std::optional tr_cryptoSecretKeySha1( - tr_crypto const* crypto, - void const* prepend_data, - size_t prepend_data_size, - void const* append_data, - size_t append_data_size); - -/* @} */ - #endif // TR_ENCRYPTION_H diff --git a/libtransmission/handshake.cc b/libtransmission/handshake.cc index c4a7bd87a..183ec70fd 100644 --- a/libtransmission/handshake.cc +++ b/libtransmission/handshake.cc @@ -173,7 +173,7 @@ static void setReadState(tr_handshake* handshake, handshake_state_t state) static bool buildHandshakeMessage(tr_handshake* handshake, uint8_t* buf) { - auto const torrent_hash = tr_cryptoGetTorrentHash(handshake->crypto); + auto const torrent_hash = handshake->crypto->torrentHash(); auto* const tor = torrent_hash ? handshake->session->torrents().get(*torrent_hash) : nullptr; bool const success = tor != nullptr; @@ -242,7 +242,7 @@ static handshake_parse_err_t parseHandshake(tr_handshake* handshake, struct evbu /* torrent hash */ auto hash = tr_sha1_digest_t{}; tr_peerIoReadBytes(handshake->io, inbuf, std::data(hash), std::size(hash)); - if (auto const torrent_hash = tr_peerIoGetTorrentHash(handshake->io); !torrent_hash || *torrent_hash != hash) + if (auto const torrent_hash = handshake->io->torrentHash(); !torrent_hash || *torrent_hash != hash) { tr_logAddTraceHand(handshake, "peer returned the wrong hash. wtf?"); return HANDSHAKE_BAD_TORRENT; @@ -285,19 +285,16 @@ static void sendYa(tr_handshake* handshake) { /* add our public key (Ya) */ - int len = 0; - uint8_t const* const public_key = tr_cryptoGetMyPublicKey(handshake->crypto, &len); - TR_ASSERT(len == KEY_LEN); - TR_ASSERT(public_key != nullptr); + auto const public_key = handshake->crypto->myPublicKey(); + TR_ASSERT(std::size(public_key) == KEY_LEN); char outbuf[KEY_LEN + PadA_MAXLEN]; char* walk = outbuf; - walk = std::copy_n(public_key, len, walk); + walk = std::copy(std::begin(public_key), std::end(public_key), walk); - /* add some bullshit padding */ - len = tr_rand_int(PadA_MAXLEN); - tr_rand_buffer(walk, len); - walk += len; + // add some random padding + auto const pad_a = handshake->crypto->pad(PadA_MAXLEN); + walk = std::copy(std::begin(pad_a), std::end(pad_a), walk); /* send it */ setReadState(handshake, AWAITING_YB); @@ -358,7 +355,7 @@ static uint32_t getCryptoSelect(tr_handshake const* handshake, uint32_t crypto_p static auto computeRequestHash(tr_handshake const* handshake, std::string_view name) { - return tr_cryptoSecretKeySha1(handshake->crypto, std::data(name), std::size(name), "", 0); + return handshake->crypto->secretKeySha1(std::data(name), std::size(name), "", 0); } static ReadState readYb(tr_handshake* handshake, struct evbuffer* inbuf) @@ -398,7 +395,7 @@ static ReadState readYb(tr_handshake* handshake, struct evbuffer* inbuf) /* compute the secret */ evbuffer_remove(inbuf, yb, KEY_LEN); - if (!tr_cryptoComputeSecret(handshake->crypto, yb)) + if (!handshake->crypto->computeSecret(yb, KEY_LEN)) { return tr_handshakeDone(handshake, false); } @@ -420,7 +417,7 @@ static ReadState readYb(tr_handshake* handshake, struct evbuffer* inbuf) /* HASH('req2', SKEY) xor HASH('req3', S) */ { - auto const hash = tr_cryptoGetTorrentHash(handshake->crypto); + auto const hash = handshake->crypto->torrentHash(); if (!hash) { tr_logAddTraceHand(handshake, "error while computing req2/req3 hash after Yb"); @@ -451,7 +448,7 @@ static ReadState readYb(tr_handshake* handshake, struct evbuffer* inbuf) uint8_t vc[VC_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0 }; tr_peerIoWriteBuf(handshake->io, outbuf, false); - tr_cryptoEncryptInit(handshake->crypto); + handshake->crypto->encryptInit(); tr_peerIoSetEncryption(handshake->io, PEER_ENCRYPTION_RC4); evbuffer_add(outbuf, vc, VC_LENGTH); @@ -475,7 +472,7 @@ static ReadState readYb(tr_handshake* handshake, struct evbuffer* inbuf) } /* send it */ - tr_cryptoDecryptInit(handshake->crypto); + handshake->crypto->decryptInit(); setReadState(handshake, AWAITING_VC); tr_peerIoWriteBuf(handshake->io, outbuf, false); @@ -502,8 +499,8 @@ static ReadState readVC(tr_handshake* handshake, struct evbuffer* inbuf) } memcpy(tmp, evbuffer_pullup(inbuf, key_len), key_len); - tr_cryptoDecryptInit(handshake->crypto); - tr_cryptoDecrypt(handshake->crypto, key_len, tmp, tmp); + handshake->crypto->decryptInit(); + handshake->crypto->decrypt(key_len, tmp, tmp); if (memcmp(tmp, key, key_len) == 0) { @@ -614,7 +611,7 @@ static ReadState readHandshake(tr_handshake* handshake, struct evbuffer* inbuf) return READ_NOW; } - tr_cryptoDecrypt(handshake->crypto, 1, &pstrlen, &pstrlen); + handshake->crypto->decrypt(1, &pstrlen, &pstrlen); if (pstrlen != 19) { @@ -660,11 +657,12 @@ static ReadState readHandshake(tr_handshake* handshake, struct evbuffer* inbuf) return tr_handshakeDone(handshake, false); } - tr_peerIoSetTorrentHash(handshake->io, hash); + handshake->io->setTorrentHash(hash); } else /* outgoing */ { - auto const torrent_hash = tr_peerIoGetTorrentHash(handshake->io); + auto const torrent_hash = handshake->io->torrentHash(); + if (!torrent_hash || *torrent_hash != hash) { tr_logAddTraceHand(handshake, "peer returned the wrong hash. wtf?"); @@ -709,7 +707,7 @@ static ReadState readPeerId(tr_handshake* handshake, struct evbuffer* inbuf) tr_logAddTraceHand(handshake, fmt::format("peer-id is '{}' ... isIncoming is {}", client, handshake->isIncoming())); // if we've somehow connected to ourselves, don't keep the connection - auto const hash = tr_peerIoGetTorrentHash(handshake->io); + auto const hash = handshake->io->torrentHash(); auto* const tor = hash ? handshake->session->torrents().get(*hash) : nullptr; bool const connected_to_self = tor != nullptr && peer_id == tr_torrentGetPeerId(tor); @@ -729,7 +727,7 @@ static ReadState readYa(tr_handshake* handshake, struct evbuffer* inbuf) uint8_t ya[KEY_LEN]; evbuffer_remove(inbuf, ya, KEY_LEN); - if (!tr_cryptoComputeSecret(handshake->crypto, ya)) + if (!handshake->crypto->computeSecret(ya, KEY_LEN)) { return tr_handshakeDone(handshake, false); } @@ -746,12 +744,10 @@ static ReadState readYa(tr_handshake* handshake, struct evbuffer* inbuf) tr_logAddTraceHand(handshake, "sending B->A: Diffie Hellman Yb, PadB"); uint8_t outbuf[KEY_LEN + PadB_MAXLEN]; uint8_t* walk = outbuf; - int len = 0; - uint8_t const* const myKey = tr_cryptoGetMyPublicKey(handshake->crypto, &len); - walk = std::copy_n(myKey, len, walk); - len = tr_rand_int(PadB_MAXLEN); - tr_rand_buffer(walk, len); - walk += len; + auto const public_key = handshake->crypto->myPublicKey(); + walk = std::copy(std::begin(public_key), std::end(public_key), walk); + auto const pad_b = handshake->crypto->pad(PadB_MAXLEN); + walk = std::copy(std::begin(pad_b), std::end(pad_b), walk); setReadState(handshake, AWAITING_PAD_A); tr_peerIoWriteBytes(handshake->io, outbuf, walk - outbuf, false); @@ -829,7 +825,7 @@ static ReadState readCryptoProvide(tr_handshake* handshake, struct evbuffer* inb tr_logAddTraceHand( handshake, fmt::format("got INCOMING connection's encrypted handshake for torrent [{}]", tor->name())); - tr_peerIoSetTorrentHash(handshake->io, tor->infoHash()); + handshake->io->setTorrentHash(tor->infoHash()); if (clientIsSeed && peerIsSeed) { @@ -845,7 +841,7 @@ static ReadState readCryptoProvide(tr_handshake* handshake, struct evbuffer* inb /* next part: ENCRYPT(VC, crypto_provide, len(PadC), */ - tr_cryptoDecryptInit(handshake->crypto); + handshake->crypto->decryptInit(); tr_peerIoReadBytes(handshake->io, inbuf, vc_in, VC_LENGTH); @@ -897,7 +893,7 @@ static ReadState readIA(tr_handshake* handshake, struct evbuffer const* inbuf) *** B->A: ENCRYPT(VC, crypto_select, len(padD), padD), ENCRYPT2(Payload Stream) **/ - tr_cryptoEncryptInit(handshake->crypto); + handshake->crypto->encryptInit(); evbuffer* const outbuf = evbuffer_new(); { @@ -1144,7 +1140,7 @@ static void gotError(tr_peerIo* io, short what, void* vhandshake) { /* This peer probably doesn't speak uTP. */ - auto const hash = tr_peerIoGetTorrentHash(io); + auto const hash = io->torrentHash(); auto* const tor = hash ? handshake->session->torrents().get(*hash) : nullptr; /* Don't mark a peer as non-uTP unless it's really a connect failure. */ diff --git a/libtransmission/peer-io.cc b/libtransmission/peer-io.cc index 7312ac804..595820eb2 100644 --- a/libtransmission/peer-io.cc +++ b/libtransmission/peer-io.cc @@ -861,24 +861,6 @@ int tr_peerIoReconnect(tr_peerIo* io) *** **/ -void tr_peerIoSetTorrentHash(tr_peerIo* io, tr_sha1_digest_t const& info_hash) -{ - TR_ASSERT(tr_isPeerIo(io)); - - tr_cryptoSetTorrentHash(&io->crypto, info_hash); -} - -std::optional tr_peerIoGetTorrentHash(tr_peerIo const* io) -{ - TR_ASSERT(tr_isPeerIo(io)); - - return tr_cryptoGetTorrentHash(&io->crypto); -} - -/** -*** -**/ - static unsigned int getDesiredOutputBufferSize(tr_peerIo const* io, uint64_t now) { /* this is all kind of arbitrary, but what seems to work well is @@ -922,12 +904,7 @@ void tr_peerIoSetEncryption(tr_peerIo* io, tr_encryption_type encryption_type) *** **/ -static inline void processBuffer( - tr_crypto* crypto, - struct evbuffer* buffer, - size_t offset, - size_t size, - void (*callback)(tr_crypto*, size_t, void const*, void*)) +static inline void processBuffer(tr_crypto& crypto, evbuffer* buffer, size_t offset, size_t size) { struct evbuffer_ptr pos; struct evbuffer_iovec iovec; @@ -941,7 +918,7 @@ static inline void processBuffer( break; } - callback(crypto, iovec.iov_len, iovec.iov_base, iovec.iov_base); + crypto.encrypt(iovec.iov_len, iovec.iov_base, iovec.iov_base); TR_ASSERT(size >= iovec.iov_len); size -= iovec.iov_len; @@ -950,18 +927,15 @@ static inline void processBuffer( TR_ASSERT(size == 0); } -static inline void maybeEncryptBuffer(tr_peerIo* io, struct evbuffer* buf, size_t offset, size_t size) -{ - if (io->encryption_type == PEER_ENCRYPTION_RC4) - { - processBuffer(&io->crypto, buf, offset, size, &tr_cryptoEncrypt); - } -} - void tr_peerIoWriteBuf(tr_peerIo* io, struct evbuffer* buf, bool isPieceData) { size_t const byteCount = evbuffer_get_length(buf); - maybeEncryptBuffer(io, buf, 0, byteCount); + + if (io->encryption_type == PEER_ENCRYPTION_RC4) + { + processBuffer(io->crypto, buf, 0, byteCount); + } + evbuffer_add_buffer(io->outbuf.get(), buf); io->outbuf_info.emplace_back(byteCount, isPieceData); } @@ -975,7 +949,7 @@ void tr_peerIoWriteBytes(tr_peerIo* io, void const* bytes, size_t byteCount, boo if (io->encryption_type == PEER_ENCRYPTION_RC4) { - tr_cryptoEncrypt(&io->crypto, iovec.iov_len, bytes, iovec.iov_base); + io->crypto.encrypt(iovec.iov_len, bytes, iovec.iov_base); } else { @@ -1031,7 +1005,7 @@ void tr_peerIoReadBytes(tr_peerIo* io, struct evbuffer* inbuf, void* bytes, size case PEER_ENCRYPTION_RC4: evbuffer_remove(inbuf, bytes, byteCount); - tr_cryptoDecrypt(&io->crypto, byteCount, bytes, bytes); + io->crypto.decrypt(byteCount, bytes, bytes); break; default: diff --git a/libtransmission/peer-io.h b/libtransmission/peer-io.h index 3b1f177b4..76beb067a 100644 --- a/libtransmission/peer-io.h +++ b/libtransmission/peer-io.h @@ -107,11 +107,6 @@ public: std::string addrStr() const; - [[nodiscard]] constexpr bool isIncoming() noexcept - { - return crypto.is_incoming; - } - [[nodiscard]] auto getReadBuffer() noexcept { return inbuf.get(); @@ -184,6 +179,21 @@ public: tr_crypto crypto; + [[nodiscard]] constexpr auto isIncoming() noexcept + { + return crypto.isIncoming(); + } + + void setTorrentHash(tr_sha1_digest_t hash) noexcept + { + crypto.setTorrentHash(hash); + } + + [[nodiscard]] constexpr auto const& torrentHash() const noexcept + { + return crypto.torrentHash(); + } + // TODO(ckerr): yikes, unlike other class' magic_numbers it looks // like this one isn't being used just for assertions, but also in // didWriteWrapper() to see if the tr_peerIo got freed during the @@ -285,10 +295,6 @@ constexpr tr_session* tr_peerIoGetSession(tr_peerIo* io) return io->session; } -std::optional tr_peerIoGetTorrentHash(tr_peerIo const* io); - -void tr_peerIoSetTorrentHash(tr_peerIo* io, tr_sha1_digest_t const& info_hash); - int tr_peerIoReconnect(tr_peerIo* io); /** diff --git a/libtransmission/peer-mgr.cc b/libtransmission/peer-mgr.cc index ddf0152e6..8b18be6e5 100644 --- a/libtransmission/peer-mgr.cc +++ b/libtransmission/peer-mgr.cc @@ -1084,7 +1084,7 @@ static bool on_handshake_done(tr_handshake_result const& result) bool success = false; auto* manager = static_cast(result.userData); - auto const hash = tr_peerIoGetTorrentHash(result.io); + auto const hash = result.io->torrentHash(); tr_swarm* const s = hash ? getExistingSwarm(manager, *hash) : nullptr; auto const [addr, port] = result.io->socketAddress(); @@ -2771,7 +2771,7 @@ void initiateConnection(tr_peerMgr* mgr, tr_swarm* s, peer_atom& atom) { tr_handshake* handshake = tr_handshakeNew(io, mgr->session->encryptionMode, on_handshake_done, mgr); - TR_ASSERT(tr_peerIoGetTorrentHash(io)); + TR_ASSERT(io->torrentHash()); tr_peerIoUnref(io); /* balanced by the initial ref in tr_peerIoNewOutgoing() */ diff --git a/tests/libtransmission/crypto-test-ref.h b/tests/libtransmission/crypto-test-ref.h index 7db1d9397..8f94e931d 100644 --- a/tests/libtransmission/crypto-test-ref.h +++ b/tests/libtransmission/crypto-test-ref.h @@ -19,18 +19,6 @@ #define tr_x509_store_t tr_x509_store_t_ #define tr_x509_cert_t tr_x509_cert_t_ #define tr_crypto tr_crypto_ -#define tr_cryptoConstruct tr_cryptoConstruct_ -#define tr_cryptoDestruct tr_cryptoDestruct_ -#define tr_cryptoSetTorrentHash tr_cryptoSetTorrentHash_ -#define tr_cryptoGetTorrentHash tr_cryptoGetTorrentHash_ -#define tr_cryptoHasTorrentHash tr_cryptoHasTorrentHash_ -#define tr_cryptoComputeSecret tr_cryptoComputeSecret_ -#define tr_cryptoGetMyPublicKey tr_cryptoGetMyPublicKey_ -#define tr_cryptoDecryptInit tr_cryptoDecryptInit_ -#define tr_cryptoDecrypt tr_cryptoDecrypt_ -#define tr_cryptoEncryptInit tr_cryptoEncryptInit_ -#define tr_cryptoEncrypt tr_cryptoEncrypt_ -#define tr_cryptoSecretKeySha1 tr_cryptoSecretKeySha1_ #define tr_sha1 tr_sha1_ #define tr_sha1_init tr_sha1_init_ #define tr_sha1_update tr_sha1_update_ @@ -84,18 +72,6 @@ #undef tr_x509_store_t #undef tr_x509_cert_t #undef tr_crypto -#undef tr_cryptoConstruct -#undef tr_cryptoDestruct -#undef tr_cryptoSetTorrentHash -#undef tr_cryptoGetTorrentHash -#undef tr_cryptoHasTorrentHash -#undef tr_cryptoComputeSecret -#undef tr_cryptoGetMyPublicKey -#undef tr_cryptoDecryptInit -#undef tr_cryptoDecrypt -#undef tr_cryptoEncryptInit -#undef tr_cryptoEncrypt -#undef tr_cryptoSecretKeySha1 #undef tr_sha1 #undef tr_sha1_init #undef tr_sha1_update @@ -142,18 +118,6 @@ #define tr_x509_store_t_ tr_x509_store_t #define tr_x509_cert_t_ tr_x509_cert_t #define tr_crypto_ tr_crypto -#define tr_cryptoConstruct_ tr_cryptoConstruct -#define tr_cryptoDestruct_ tr_cryptoDestruct -#define tr_cryptoSetTorrentHash_ tr_cryptoSetTorrentHash -#define tr_cryptoGetTorrentHash_ tr_cryptoGetTorrentHash -#define tr_cryptoHasTorrentHash_ tr_cryptoHasTorrentHash -#define tr_cryptoComputeSecret_ tr_cryptoComputeSecret -#define tr_cryptoGetMyPublicKey_ tr_cryptoGetMyPublicKey -#define tr_cryptoDecryptInit_ tr_cryptoDecryptInit -#define tr_cryptoDecrypt_ tr_cryptoDecrypt -#define tr_cryptoEncryptInit_ tr_cryptoEncryptInit -#define tr_cryptoEncrypt_ tr_cryptoEncrypt -#define tr_cryptoSecretKeySha1_ tr_cryptoSecretKeySha1 #define tr_sha1_ tr_sha1 #define tr_sha1_init_ tr_sha1_init #define tr_sha1_update_ tr_sha1_update diff --git a/tests/libtransmission/crypto-test.cc b/tests/libtransmission/crypto-test.cc index d0c219ffa..387e55b87 100644 --- a/tests/libtransmission/crypto-test.cc +++ b/tests/libtransmission/crypto-test.cc @@ -37,15 +37,15 @@ TEST(Crypto, torrentHash) { auto a = tr_crypto{}; - EXPECT_FALSE(tr_cryptoGetTorrentHash(&a)); + EXPECT_FALSE(a.torrentHash()); - tr_cryptoSetTorrentHash(&a, SomeHash); - EXPECT_TRUE(tr_cryptoGetTorrentHash(&a)); - EXPECT_EQ(SomeHash, *tr_cryptoGetTorrentHash(&a)); + a.setTorrentHash(SomeHash); + EXPECT_TRUE(a.torrentHash()); + EXPECT_EQ(SomeHash, *a.torrentHash()); - a = tr_crypto{ &SomeHash, false }; - EXPECT_TRUE(tr_cryptoGetTorrentHash(&a)); - EXPECT_EQ(SomeHash, *tr_cryptoGetTorrentHash(&a)); + auto b = tr_crypto{ &SomeHash, false }; + EXPECT_TRUE(b.torrentHash()); + EXPECT_EQ(SomeHash, *b.torrentHash()); } TEST(Crypto, encryptDecrypt) @@ -53,29 +53,30 @@ TEST(Crypto, encryptDecrypt) auto a = tr_crypto{ &SomeHash, false }; auto b = tr_crypto_{ &SomeHash, true }; - auto public_key_length = int{}; - EXPECT_TRUE(tr_cryptoComputeSecret(&a, tr_cryptoGetMyPublicKey_(&b, &public_key_length))); - EXPECT_TRUE(tr_cryptoComputeSecret_(&b, tr_cryptoGetMyPublicKey(&a, &public_key_length))); + auto public_key = b.myPublicKey(); + EXPECT_TRUE(a.computeSecret(std::data(public_key), std::size(public_key))); + public_key = a.myPublicKey(); + EXPECT_TRUE(b.computeSecret(std::data(public_key), std::size(public_key))); - auto const input1 = std::string{ "test1" }; + auto constexpr Input1 = "test1"sv; auto encrypted1 = std::array{}; auto decrypted1 = std::array{}; - tr_cryptoEncryptInit(&a); - tr_cryptoEncrypt(&a, input1.size(), input1.data(), encrypted1.data()); - tr_cryptoDecryptInit_(&b); - tr_cryptoDecrypt_(&b, input1.size(), encrypted1.data(), decrypted1.data()); - EXPECT_EQ(input1, std::string(decrypted1.data(), input1.size())); + a.encryptInit(); + a.encrypt(std::size(Input1), std::data(Input1), std::data(encrypted1)); + b.decryptInit(); + b.decrypt(std::size(Input1), std::data(encrypted1), std::data(decrypted1)); + EXPECT_EQ(Input1, std::data(decrypted1)); - auto const input2 = std::string{ "@#)C$@)#(*%bvkdjfhwbc039bc4603756VB3)" }; + auto constexpr Input2 = "@#)C$@)#(*%bvkdjfhwbc039bc4603756VB3)"sv; auto encrypted2 = std::array{}; auto decrypted2 = std::array{}; - tr_cryptoEncryptInit_(&b); - tr_cryptoEncrypt_(&b, input2.size(), input2.data(), encrypted2.data()); - tr_cryptoDecryptInit(&a); - tr_cryptoDecrypt(&a, input2.size(), encrypted2.data(), decrypted2.data()); - EXPECT_EQ(input2, std::string(decrypted2.data(), input2.size())); + b.encryptInit(); + b.encrypt(std::size(Input2), std::data(Input2), std::data(encrypted2)); + a.decryptInit(); + a.decrypt(std::size(Input2), std::data(encrypted2), std::data(decrypted2)); + EXPECT_EQ(Input2, std::data(decrypted2)); } TEST(Crypto, sha1)