mirror of
https://github.com/transmission/transmission
synced 2024-12-24 08:43:27 +00:00
refactor: migrate tr_crypto C functions to members (#3430)
This commit is contained in:
parent
5e4c7f9a1e
commit
0a39cb9302
8 changed files with 204 additions and 272 deletions
|
@ -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<tr_crypto*>(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<uint8_t const*>(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_sha1_digest_t> 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_sha1_digest_t> 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_sha1_digest_t> tr_cryptoGetTorrentHash(tr_crypto const* crypto)
|
||||
std::vector<uint8_t> 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<uint8_t>{};
|
||||
ret.resize(len);
|
||||
tr_rand_buffer(std::data(ret), len);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -14,15 +14,12 @@
|
|||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint8_t
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#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<tr_sha1_digest_t> 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<char const*>(my_public_key_), KEY_LEN };
|
||||
}
|
||||
|
||||
[[nodiscard]] bool computeSecret(void const* peer_public_key, size_t len);
|
||||
|
||||
[[nodiscard]] std::optional<tr_sha1_digest_t> 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<uint8_t> 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<tr_sha1_digest_t> 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_sha1_digest_t> 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_sha1_digest_t> 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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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_sha1_digest_t> 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:
|
||||
|
|
|
@ -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_sha1_digest_t> 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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -1084,7 +1084,7 @@ static bool on_handshake_done(tr_handshake_result const& result)
|
|||
bool success = false;
|
||||
auto* manager = static_cast<tr_peerMgr*>(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() */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<char, 128>{};
|
||||
auto decrypted1 = std::array<char, 128>{};
|
||||
|
||||
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<char, 128>{};
|
||||
auto decrypted2 = std::array<char, 128>{};
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue