From ec92bfa6b18076f65eeb30500e03d86c2be7fb38 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 15 Jan 2025 20:52:13 +1100 Subject: [PATCH] * Refactor: Mesh::onPeer ... methods added 'secret' param. (is whatever getPeerSharedSecret() returned) --- examples/ping_client/main.cpp | 29 ++++++++++++++++------------ examples/ping_server/main.cpp | 4 ++-- examples/simple_repeater/main.cpp | 10 +++++----- examples/simple_secure_chat/main.cpp | 10 +++++----- examples/test_admin/main.cpp | 29 ++++++++++++++++------------ src/Mesh.cpp | 8 ++++---- src/Mesh.h | 6 ++++-- 7 files changed, 54 insertions(+), 42 deletions(-) diff --git a/examples/ping_client/main.cpp b/examples/ping_client/main.cpp index e77ce9b1..f48bd475 100644 --- a/examples/ping_client/main.cpp +++ b/examples/ping_client/main.cpp @@ -18,7 +18,7 @@ #define LORA_BW 125 #endif #ifndef LORA_SF - #define LORA_SF 10 + #define LORA_SF 9 #endif #ifndef LORA_CR #define LORA_CR 5 @@ -42,13 +42,6 @@ class MyMesh : public mesh::Mesh { bool got_adv = false; protected: - int searchPeersByHash(const uint8_t* hash) override { - if (got_adv && server_id.isHashMatch(hash)) { - return 1; - } - return 0; // not found - } - void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len) override { if (memcmp(app_data, "PING", 4) == 0) { Serial.println("Received advertisement from a PING server"); @@ -64,19 +57,31 @@ protected: } } - void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, uint8_t* data, size_t len) override { + int searchPeersByHash(const uint8_t* hash) override { + if (got_adv && server_id.isHashMatch(hash)) { + return 1; + } + return 0; // not found + } + + void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override { + // lookup pre-calculated shared_secret + memcpy(dest_secret, server_secret, PUB_KEY_SIZE); + } + + void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override { if (type == PAYLOAD_TYPE_RESPONSE) { Serial.println("Received PING Reply!"); if (packet->isRouteFlood()) { // let server know path TO here, so they can use sendDirect() for future ping responses - mesh::Packet* path = createPathReturn(server_id, server_secret, packet->path, packet->path_len, 0, NULL, 0); + mesh::Packet* path = createPathReturn(server_id, secret, packet->path, packet->path_len, 0, NULL, 0); if (path) sendFlood(path); } } } - void onPeerPathRecv(mesh::Packet* packet, int sender_idx, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { + void onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { // must be from server_id Serial.printf("PATH to server, path_len=%d\n", (uint32_t) path_len); @@ -84,7 +89,7 @@ protected: if (packet->isRouteFlood()) { // send a reciprocal return path to sender, but send DIRECTLY! - mesh::Packet* rpath = createPathReturn(server_id, server_secret, packet->path, packet->path_len, 0, NULL, 0); + mesh::Packet* rpath = createPathReturn(server_id, secret, packet->path, packet->path_len, 0, NULL, 0); if (rpath) sendDirect(rpath, path, path_len); } diff --git a/examples/ping_server/main.cpp b/examples/ping_server/main.cpp index 8b7eee97..f2111a5e 100644 --- a/examples/ping_server/main.cpp +++ b/examples/ping_server/main.cpp @@ -18,7 +18,7 @@ #define LORA_BW 125 #endif #ifndef LORA_SF - #define LORA_SF 10 + #define LORA_SF 9 #endif #ifndef LORA_CR #define LORA_CR 5 @@ -118,7 +118,7 @@ protected: } } - void onPeerPathRecv(mesh::Packet* packet, int sender_idx, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { + void onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { if (sender_idx >= 0 && sender_idx < MAX_CLIENTS) { Serial.printf("PATH to client, path_len=%d\n", (uint32_t) path_len); diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 3d8145c1..58cf95a6 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -19,7 +19,7 @@ #define LORA_BW 125 #endif #ifndef LORA_SF - #define LORA_SF 10 + #define LORA_SF 9 #endif #ifndef LORA_CR #define LORA_CR 5 @@ -218,7 +218,7 @@ protected: } } - void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, uint8_t* data, size_t len) override { + void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override { if (type == PAYLOAD_TYPE_REQ) { // request (from a Known admin client!) int i = matching_peer_indexes[sender_idx]; @@ -236,11 +236,11 @@ protected: if (packet->isRouteFlood()) { // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response - mesh::Packet* path = createPathReturn(client->id, client->secret, packet->path, packet->path_len, + mesh::Packet* path = createPathReturn(client->id, secret, packet->path, packet->path_len, PAYLOAD_TYPE_RESPONSE, reply_data, reply_len); if (path) sendFlood(path); } else { - mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, client->secret, reply_data, reply_len); + mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len); if (reply) { if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT sendDirect(reply, client->out_path, client->out_path_len); @@ -256,7 +256,7 @@ protected: } } - void onPeerPathRecv(mesh::Packet* packet, int sender_idx, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { + void onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { // TODO: prevent replay attacks int i = matching_peer_indexes[sender_idx]; diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index 352c8961..8250478f 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -18,7 +18,7 @@ #define LORA_BW 125 #endif #ifndef LORA_SF - #define LORA_SF 10 + #define LORA_SF 9 #endif #ifndef LORA_CR #define LORA_CR 5 @@ -119,7 +119,7 @@ protected: } } - void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, uint8_t* data, size_t len) override { + void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override { if (type == PAYLOAD_TYPE_TXT_MSG && len > 5) { int i = matching_peer_indexes[sender_idx]; if (i < 0 || i >= num_contacts) { @@ -146,7 +146,7 @@ protected: if (packet->isRouteFlood()) { // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK - mesh::Packet* path = createPathReturn(from.id, from.shared_secret, packet->path, packet->path_len, + mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len, PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4); if (path) sendFlood(path); } else { @@ -162,7 +162,7 @@ protected: } } - void onPeerPathRecv(mesh::Packet* packet, int sender_idx, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { + void onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { int i = matching_peer_indexes[sender_idx]; if (i < 0 || i >= num_contacts) { MESH_DEBUG_PRINTLN("onPeerPathRecv: Invalid sender idx: %d", i); @@ -178,7 +178,7 @@ protected: if (packet->isRouteFlood()) { // send a reciprocal return path to sender, but send DIRECTLY! - mesh::Packet* rpath = createPathReturn(from.id, from.shared_secret, packet->path, packet->path_len, 0, NULL, 0); + mesh::Packet* rpath = createPathReturn(from.id, secret, packet->path, packet->path_len, 0, NULL, 0); if (rpath) sendDirect(rpath, path, path_len); } diff --git a/examples/test_admin/main.cpp b/examples/test_admin/main.cpp index 827def95..08032276 100644 --- a/examples/test_admin/main.cpp +++ b/examples/test_admin/main.cpp @@ -18,7 +18,7 @@ #define LORA_BW 125 #endif #ifndef LORA_SF - #define LORA_SF 10 + #define LORA_SF 9 #endif #ifndef LORA_CR #define LORA_CR 5 @@ -62,13 +62,6 @@ class MyMesh : public mesh::Mesh { bool got_adv = false; protected: - int searchPeersByHash(const uint8_t* hash) override { - if (got_adv && server_id.isHashMatch(hash)) { - return 1; - } - return 0; // not found - } - void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len) override { if (memcmp(app_data, "repeater:", 9) == 0) { Serial.println("Received advertisement from a repeater!"); @@ -115,19 +108,31 @@ protected: } } - void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, uint8_t* data, size_t len) override { + int searchPeersByHash(const uint8_t* hash) override { + if (got_adv && server_id.isHashMatch(hash)) { + return 1; + } + return 0; // not found + } + + void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override { + // lookup pre-calculated shared_secret + memcpy(dest_secret, server_secret, PUB_KEY_SIZE); + } + + void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override { if (type == PAYLOAD_TYPE_RESPONSE) { handleResponse(data, len); if (packet->isRouteFlood()) { // let server know path TO here, so they can use sendDirect() for future ping responses - mesh::Packet* path = createPathReturn(server_id, server_secret, packet->path, packet->path_len, 0, NULL, 0); + mesh::Packet* path = createPathReturn(server_id, secret, packet->path, packet->path_len, 0, NULL, 0); if (path) sendFlood(path); } } } - void onPeerPathRecv(mesh::Packet* packet, int sender_idx, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { + void onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override { // must be from server_id Serial.printf("PATH to repeater, path_len=%d\n", (uint32_t) path_len); @@ -135,7 +140,7 @@ protected: if (packet->isRouteFlood()) { // send a reciprocal return path to sender, but send DIRECTLY! - mesh::Packet* rpath = createPathReturn(server_id, server_secret, packet->path, packet->path_len, 0, NULL, 0); + mesh::Packet* rpath = createPathReturn(server_id, secret, packet->path, packet->path_len, 0, NULL, 0); if (rpath) sendDirect(rpath, path, path_len); } diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 0e7414e2..bbc42b2b 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -97,9 +97,9 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { uint8_t extra_type = data[k++]; uint8_t* extra = &data[k]; uint8_t extra_len = len - k; // remainder of packet (may be padded with zeroes!) - onPeerPathRecv(pkt, j, path, path_len, extra_type, extra, extra_len); + onPeerPathRecv(pkt, j, secret, path, path_len, extra_type, extra, extra_len); } else { - onPeerDataRecv(pkt, pkt->getPayloadType(), j, data, len); + onPeerDataRecv(pkt, pkt->getPayloadType(), j, secret, data, len); } found = true; break; @@ -172,7 +172,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { uint32_t timestamp; memcpy(×tamp, &pkt->payload[i], 4); i += 4; - uint8_t* signature = &pkt->payload[i]; i += SIGNATURE_SIZE; + const uint8_t* signature = &pkt->payload[i]; i += SIGNATURE_SIZE; if (i > pkt->payload_len) { MESH_DEBUG_PRINTLN("Mesh::onRecvPacket(): incomplete advertisement packet"); @@ -197,7 +197,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { onAdvertRecv(pkt, id, timestamp, app_data, app_data_len); action = routeRecvPacket(pkt); } else { - MESH_DEBUG_PRINTLN("Mesh::onRecvPacket(): received advertisement with forged signature!"); + MESH_DEBUG_PRINTLN("Mesh::onRecvPacket(): received advertisement with forged signature! (app_data_len=%d)", app_data_len); } } break; diff --git a/src/Mesh.h b/src/Mesh.h index 06a47790..bc51be73 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -80,15 +80,17 @@ protected: * NOTE: these can be received multiple times (per sender/msg-id), via different routes * \param type one of: PAYLOAD_TYPE_TXT_MSG, PAYLOAD_TYPE_REQ, PAYLOAD_TYPE_RESPONSE * \param sender_idx index of peer, [0..n) where n is what searchPeersByHash() returned + * \param secret the pre-calculated shared-secret (handy for sending response packet) */ - virtual void onPeerDataRecv(Packet* packet, uint8_t type, int sender_idx, uint8_t* data, size_t len) { } + virtual void onPeerDataRecv(Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) { } /** * \brief A path TO peer (sender_idx) has been received. (also with optional 'extra' data encoded) * NOTE: these can be received multiple times (per sender), via differen routes * \param sender_idx index of peer, [0..n) where n is what searchPeersByHash() returned + * \param secret the pre-calculated shared-secret (handy for sending response packet) */ - virtual void onPeerPathRecv(Packet* packet, int sender_idx, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) { } + virtual void onPeerPathRecv(Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) { } virtual int searchChannelsByHash(const uint8_t* hash, GroupChannel channels[], int max_matches);