diff --git a/src/solanaceae/tox_p2prng/tox_p2prng.cpp b/src/solanaceae/tox_p2prng/tox_p2prng.cpp index 4de7476..3d8ddb9 100644 --- a/src/solanaceae/tox_p2prng/tox_p2prng.cpp +++ b/src/solanaceae/tox_p2prng/tox_p2prng.cpp @@ -1,8 +1,11 @@ #include "./tox_p2prng.hpp" +#include #include +#include #include +#include // packets: // @@ -25,6 +28,8 @@ // secret_request // - id +#define TOX_PKG_ID_FRIEND 0xB1 +#define TOX_PKG_ID_GROUP 0xa6 void ToxP2PRNG::RngState::fillInitalStatePreamble(const ByteSpan id) { // id @@ -105,6 +110,30 @@ void ToxP2PRNG::RngState::genFinalResult(void) { // we done } +P2PRNG::State ToxP2PRNG::RngState::getState(void) const { + //DONE, // rng is done, event contains full rng + if (!final_result.empty()) { + return P2PRNG::DONE; + } + + //SECRET, // got a secret (phase start will be denoted by own, secrets received before we have all hmacs get queued up) + if (hmacs.size() == contacts.size()) { + return P2PRNG::SECRET; + } + + //HMAC, // got a hmac (phase start will be denoted by the initiators hmac) + if (!hmacs.empty()) { + return P2PRNG::HMAC; + } + + //INIT, // inital params (incoming or outgoing?) + if (!inital_state.empty() && !inital_state_preamble.empty()) { + return P2PRNG::INIT; + } + + return P2PRNG::UNKNOWN; +} + ToxP2PRNG::ToxP2PRNG( ToxI& t, ToxEventProviderI& tep, @@ -137,32 +166,31 @@ ByteSpan ToxP2PRNG::getResult(const ByteSpan id) { bool ToxP2PRNG::handlePacket( Contact3Handle c, PKG pkg_type, - const uint8_t* data, - const size_t data_size + ByteSpan data ) { - if (data_size < 1) { + if (data.size < 1) { return false; // waht } // rn all are prefixed with ID, so here we go - if (data_size < 32) { + if (data.size < 32) { std::cerr << "TP2PRNG error: packet without id\n"; return false; } - ByteSpan id{data, 32}; + ByteSpan id{data.ptr, 32}; switch (pkg_type) { case PKG::INIT_WITH_HMAC: - return handle_init_with_hmac(c, id, data+32, data_size-(32)); + return handle_init_with_hmac(c, id, {data.ptr+32, data.size-(32)}); case PKG::HMAC: - return handle_hmac(c, id, data+32, data_size-(32)); + return handle_hmac(c, id, {data.ptr+32, data.size-(32)}); case PKG::HMAC_REQUEST: - return handle_hmac_request(c, id, data+32, data_size-(32)); + return handle_hmac_request(c, id, {data.ptr+32, data.size-(32)}); case PKG::SECRET: - return handle_secret(c, id, data+32, data_size-(32)); + return handle_secret(c, id, {data.ptr+32, data.size-(32)}); case PKG::SECRET_REQUEST: - return handle_secret_request(c, id, data+32, data_size-(32)); + return handle_secret_request(c, id, {data.ptr+32, data.size-(32)}); default: return false; } @@ -172,15 +200,14 @@ bool ToxP2PRNG::handlePacket( bool ToxP2PRNG::handleFriendPacket( const uint32_t friend_number, - const uint8_t* data, - const size_t data_size + ByteSpan data ) { // packet id + packet id + id - if (data_size < 1+1+32) { + if (data.size < 1+1+32) { return false; } - if (data[0] != 0xB1) { // 177 + if (data[0] != TOX_PKG_ID_FRIEND) { return false; } @@ -191,22 +218,21 @@ bool ToxP2PRNG::handleFriendPacket( return false; } - return handlePacket(c, tpr_pkg_type, data+2, data_size-2); + return handlePacket(c, tpr_pkg_type, {data.ptr+2, data.size-2}); } bool ToxP2PRNG::handleGroupPacket( const uint32_t group_number, const uint32_t peer_number, - const uint8_t* data, - const size_t data_size, + ByteSpan data, const bool /*_private*/ ) { // packet id + packet id + id - if (data_size < 1+1+32) { + if (data.size < 1+1+32) { return false; } - if (data[0] != (0x80 | 38u)) { // 0xa6 / 166 + if (data[0] != TOX_PKG_ID_GROUP) { return false; } @@ -217,50 +243,185 @@ bool ToxP2PRNG::handleGroupPacket( return false; } - return handlePacket(c, tpr_pkg_type, data+2, data_size-2); + return handlePacket(c, tpr_pkg_type, {data.ptr+2, data.size-2}); } -bool ToxP2PRNG::handle_init_with_hmac(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size) { +bool ToxP2PRNG::handle_init_with_hmac(Contact3Handle c, ByteSpan id, ByteSpan data) { std::cerr << "TP2PRNG: got packet INIT_WITH_HMAC\n"; size_t curser = 0; return false; } -bool ToxP2PRNG::handle_hmac(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size) { +bool ToxP2PRNG::handle_hmac(Contact3Handle c, ByteSpan id, ByteSpan data) { std::cerr << "TP2PRNG: got packet HMAC\n"; size_t curser = 0; return false; } -bool ToxP2PRNG::handle_hmac_request(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size) { +bool ToxP2PRNG::handle_hmac_request(Contact3Handle c, ByteSpan id, ByteSpan data) { std::cerr << "TP2PRNG: got packet HMAC_REQUEST\n"; - if (data_size > 0) { + if (!data.empty()) { std::cerr << "TP2PRNG warning: HMAC_REQUEST pkg has extra data!\n"; } + const auto* rng_state = getRngSate(c, id); + if (rng_state == nullptr) { + return false; + } + return false; } -bool ToxP2PRNG::handle_secret(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size) { +bool ToxP2PRNG::handle_secret(Contact3Handle c, ByteSpan id, ByteSpan data) { std::cerr << "TP2PRNG: got packet SECRET\n"; size_t curser = 0; return false; } -bool ToxP2PRNG::handle_secret_request(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size) { +bool ToxP2PRNG::handle_secret_request(Contact3Handle c, ByteSpan id, ByteSpan data) { std::cerr << "TP2PRNG: got packet SECRET_REQUEST\n"; - if (data_size > 0) { + if (!data.empty()) { std::cerr << "TP2PRNG warning: SECRET_REQUEST pkg has extra data!\n"; } + const auto* rng_state = getRngSate(c, id); + if (rng_state == nullptr) { + return false; + } + + // can only request secret if secret or done state + if (const auto current_state = rng_state->getState(); !(current_state == P2PRNG::SECRET || current_state == P2PRNG::DONE)) { + return false; + } + + // find self contact + // TODO: accel + // TODO: do TagSelfStrong over contacts instead?? probably. maybe additionally + Contact3Handle self; + if (c.all_of()) { + self = Contact3Handle{*c.registry(), c.get().self}; + } else if (c.all_of()) { + Contact3Handle parent = {*c.registry(), c.get().parent}; + if (static_cast(parent) && parent.all_of()) { + self = Contact3Handle{*c.registry(), parent.get().self}; + } + } + + if (!static_cast(self)) { + std::cerr << "TP2PRNG error: failed to look up self\n"; + return false; + } + + auto self_secret_it = rng_state->secrets.find(self); + if (self_secret_it == rng_state->secrets.cend()) { + // hmmmmmmmmmm this bad + std::cerr << "hmmmmmmmmmm this bad\n"; + return false; + } + + // TODO: queue these instead + // SEND secret to c + send_secret(c, id, ByteSpan{self_secret_it->second}); + + return true; +} + +static std::tuple, const Contact::Components::ToxFriendEphemeral*, const Contact::Components::ToxGroupPeerEphemeral*> prepSendPkgWithID(Contact3Handle c, ToxP2PRNG::PKG pkg_type, ByteSpan id) { + std::vector pkg; + + // determine friend or group (meh) + const auto* tfe = c.try_get(); + const auto* tgpe = c.try_get(); + if (tfe != nullptr) { + pkg.push_back(TOX_PKG_ID_FRIEND); + } else if (tgpe != nullptr) { + pkg.push_back(TOX_PKG_ID_GROUP); + } else { + return {}; + } + pkg.push_back(static_cast(pkg_type)); + + // pack packet + // - id + pkg.insert(pkg.cend(), id.cbegin(), id.cend()); + + return {pkg, tfe, tgpe}; +} + +static bool sendToxPrivatePacket( + ToxI& t, + const Contact::Components::ToxFriendEphemeral* tfe, + const Contact::Components::ToxGroupPeerEphemeral* tgpe, + const std::vector& pkg +) { + // send to friend or group peer + if (tfe != nullptr) { + return + t.toxFriendSendLosslessPacket( + tfe->friend_number, + pkg + ) == TOX_ERR_FRIEND_CUSTOM_PACKET_OK + ; + } else if (tgpe != nullptr) { + return + t.toxGroupSendCustomPrivatePacket( + tgpe->group_number, tgpe->peer_number, + true, + pkg + ) == TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK + ; + } + return false; } +bool ToxP2PRNG::send_hmac(Contact3Handle c, ByteSpan id, const ByteSpan hmac) { + auto [pkg, tfe, tgpe] = prepSendPkgWithID(c, PKG::HMAC, id); + if (pkg.empty()) { + return false; + } + + // - hmac + pkg.insert(pkg.cend(), hmac.cbegin(), hmac.cend()); + + return false; +} + +bool ToxP2PRNG::send_hmac_request(Contact3Handle c, ByteSpan id) { + auto [pkg, tfe, tgpe] = prepSendPkgWithID(c, PKG::HMAC_REQUEST, id); + if (pkg.empty()) { + return false; + } + + return sendToxPrivatePacket(_t, tfe, tgpe, pkg); +} + +bool ToxP2PRNG::send_secret(Contact3Handle c, ByteSpan id, const ByteSpan secret) { + auto [pkg, tfe, tgpe] = prepSendPkgWithID(c, PKG::SECRET, id); + if (pkg.empty()) { + return false; + } + + // - secret (msg+k) + pkg.insert(pkg.cend(), secret.cbegin(), secret.cend()); + + return sendToxPrivatePacket(_t, tfe, tgpe, pkg); +} + +bool ToxP2PRNG::send_secret_request(Contact3Handle c, ByteSpan id) { + auto [pkg, tfe, tgpe] = prepSendPkgWithID(c, PKG::SECRET_REQUEST, id); + if (pkg.empty()) { + return false; + } + + return sendToxPrivatePacket(_t, tfe, tgpe, pkg); +} + ToxP2PRNG::RngState* ToxP2PRNG::getRngSate(Contact3Handle c, ByteSpan id_bytes) { if (id_bytes.size != ID{}.size()) { return nullptr; @@ -268,7 +429,7 @@ ToxP2PRNG::RngState* ToxP2PRNG::getRngSate(Contact3Handle c, ByteSpan id_bytes) ID r_id{}; { // building the id is very annoying, should have not used array? - // TODO: provide custom comperator ? + // TODO: provide custom comperator ? for (size_t i = 0; i < r_id.size(); i++) { r_id[i] = id_bytes[i]; } @@ -293,7 +454,7 @@ bool ToxP2PRNG::onToxEvent(const Tox_Event_Friend_Lossless_Packet* e) { const uint8_t* data = tox_event_friend_lossless_packet_get_data(e); const auto data_length = tox_event_friend_lossless_packet_get_data_length(e); - return handleFriendPacket(friend_number, data, data_length); + return handleFriendPacket(friend_number, {data, data_length}); } bool ToxP2PRNG::onToxEvent(const Tox_Event_Group_Custom_Packet* e) { @@ -302,7 +463,7 @@ bool ToxP2PRNG::onToxEvent(const Tox_Event_Group_Custom_Packet* e) { const uint8_t* data = tox_event_group_custom_packet_get_data(e); const auto data_length = tox_event_group_custom_packet_get_data_length(e); - return handleGroupPacket(group_number, peer_number, data, data_length, false); + return handleGroupPacket(group_number, peer_number, {data, data_length}, false); } bool ToxP2PRNG::onToxEvent(const Tox_Event_Group_Custom_Private_Packet* e) { @@ -311,6 +472,6 @@ bool ToxP2PRNG::onToxEvent(const Tox_Event_Group_Custom_Private_Packet* e) { const uint8_t* data = tox_event_group_custom_private_packet_get_data(e); const auto data_length = tox_event_group_custom_private_packet_get_data_length(e); - return handleGroupPacket(group_number, peer_number, data, data_length, true); + return handleGroupPacket(group_number, peer_number, {data, data_length}, true); } diff --git a/src/solanaceae/tox_p2prng/tox_p2prng.hpp b/src/solanaceae/tox_p2prng/tox_p2prng.hpp index 632c6f7..c10d97b 100644 --- a/src/solanaceae/tox_p2prng/tox_p2prng.hpp +++ b/src/solanaceae/tox_p2prng/tox_p2prng.hpp @@ -19,42 +19,46 @@ class ToxP2PRNG : public P2PRNGI, public ToxEventI { ToxEventProviderI& _tep; ToxContactModel2& _tcm; - enum class PKG : uint8_t { - INVALID = 0u, + public: + enum class PKG : uint8_t { + INVALID = 0u, - INIT_WITH_HMAC, - HMAC, - HMAC_REQUEST, - SECRET, - SECRET_REQUEST, - }; + INIT_WITH_HMAC, + HMAC, + HMAC_REQUEST, + SECRET, + SECRET_REQUEST, + }; - using ID = std::array; - struct IDHash {size_t operator()(const ID& a) const {return (a[0] | a[1] << 1*8 | a[2] << 1*16 | a[3] << 1*24) ^ (a[31] | a[30] << 1*8);}}; + using ID = std::array; + struct IDHash {size_t operator()(const ID& a) const {return (a[0] | a[1] << 1*8 | a[2] << 1*16 | a[3] << 1*24) ^ (a[31] | a[30] << 1*8);}}; - struct RngState { - // all contacts participating, including self - std::vector contacts; + private: + struct RngState { + // all contacts participating, including self + std::vector contacts; - // app given - std::vector inital_state; + // app given + std::vector inital_state; - // the other stuff needed for full IS (preamble+IS) - // - ID - // - list of public keys of contacts (same order as later used to calc res) - std::vector inital_state_preamble; - void fillInitalStatePreamble(const ByteSpan id); + // the other stuff needed for full IS (preamble+IS) + // - ID + // - list of public keys of contacts (same order as later used to calc res) + std::vector inital_state_preamble; + void fillInitalStatePreamble(const ByteSpan id); - // use contacts instead? - entt::dense_map> hmacs; - entt::dense_map> secrets; - entt::dense_map secrets_valid; + // use contacts instead? + entt::dense_map> hmacs; + entt::dense_map> secrets; + entt::dense_map secrets_valid; - void genFinalResult(void); + void genFinalResult(void); - std::vector final_result; // cached - }; - entt::dense_map _global_map; + std::vector final_result; // cached + + P2PRNG::State getState(void) const; + }; + entt::dense_map _global_map; public: ToxP2PRNG( @@ -75,28 +79,31 @@ class ToxP2PRNG : public P2PRNGI, public ToxEventI { bool handlePacket( Contact3Handle c, PKG pkg_type, - const uint8_t* data, - const size_t data_size + ByteSpan data ); bool handleFriendPacket( const uint32_t friend_number, - const uint8_t* data, - const size_t data_size + ByteSpan data ); bool handleGroupPacket( const uint32_t group_number, const uint32_t peer_number, - const uint8_t* data, - const size_t data_size, + ByteSpan data, const bool _private ); - bool handle_init_with_hmac(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size); - bool handle_hmac(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size); - bool handle_hmac_request(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size); - bool handle_secret(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size); - bool handle_secret_request(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size); + bool handle_init_with_hmac(Contact3Handle c, ByteSpan id, ByteSpan data); + bool handle_hmac(Contact3Handle c, ByteSpan id, ByteSpan data); + bool handle_hmac_request(Contact3Handle c, ByteSpan id, ByteSpan data); + bool handle_secret(Contact3Handle c, ByteSpan id, ByteSpan data); + bool handle_secret_request(Contact3Handle c, ByteSpan id, ByteSpan data); + + //bool send_init_with_hmac(Contact3Handle c, ByteSpan id, const uint8_t* data, size_t data_size); + bool send_hmac(Contact3Handle c, ByteSpan id, const ByteSpan hmac); + bool send_hmac_request(Contact3Handle c, ByteSpan id); + bool send_secret(Contact3Handle c, ByteSpan id, const ByteSpan secret); + bool send_secret_request(Contact3Handle c, ByteSpan id); RngState* getRngSate(Contact3Handle c, ByteSpan id);