Skip to content

Commit f969ba8

Browse files
committed
sneaky mode refactor - hide in payload v1, don't use v2
repeater first login chacha sensing
1 parent d189d8a commit f969ba8

12 files changed

Lines changed: 289 additions & 182 deletions

File tree

examples/simple_repeater/MyMesh.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ bool MyMesh::filterRecvFloodPacket(mesh::Packet* pkt) {
506506
}
507507

508508
void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const mesh::Identity &sender,
509-
uint8_t *data, size_t len) {
509+
uint8_t *data, size_t len, bool decrypted_with_chacha) {
510510
if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin
511511
// client (unknown at this stage)
512512
uint32_t timestamp;
@@ -530,17 +530,20 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
530530

531531
if (reply_len == 0) return; // invalid request
532532

533-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
533+
// Mark peer as ChaCha-capable if we decoded their packet with ChaCha
534+
if (decrypted_with_chacha) setPeerSupportsCHACHA(&sender, -1);
535+
536+
bool use_chacha = peerSupportsCHACHA(sender);
534537
if (packet->isRouteFlood()) {
535538
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
536539
mesh::Packet* path = createPathReturn(sender, secret, packet->path, packet->path_len,
537-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_v2);
540+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_chacha);
538541
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
539542
} else if (reply_path_len < 0) {
540-
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, use_v2);
543+
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, use_chacha);
541544
if (reply) sendFlood(reply, SERVER_RESPONSE_DELAY);
542545
} else {
543-
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, use_v2);
546+
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, use_chacha);
544547
if (reply) sendDirect(reply, reply_path, reply_path_len, SERVER_RESPONSE_DELAY);
545548
}
546549
}
@@ -572,10 +575,24 @@ bool MyMesh::peerSupportsCHACHA(const mesh::Identity& dest) {
572575
if (client) {
573576
return client->supports_chacha;
574577
}
575-
// Unknown peer - default to v1 (safe fallback)
578+
// Unknown peer - default to AES (safe fallback)
576579
return false;
577580
}
578581

582+
void MyMesh::setPeerSupportsCHACHA(const mesh::Identity* id, int peer_idx) {
583+
if (peer_idx >= 0) {
584+
int i = matching_peer_indexes[peer_idx];
585+
if (i >= 0 && i < acl.getNumClients()) {
586+
acl.getClientByIdx(i)->supports_chacha = true;
587+
}
588+
} else if (id != nullptr) {
589+
ClientInfo* client = acl.getClient(id->pub_key, PUB_KEY_SIZE);
590+
if (client) {
591+
client->supports_chacha = true;
592+
}
593+
}
594+
}
595+
579596
static bool isShare(const mesh::Packet *packet) {
580597
if (packet->hasTransportCodes()) {
581598
return packet->transport_codes[0] == 0 && packet->transport_codes[1] == 0; // codes { 0, 0 } means 'send to nowhere'
@@ -624,15 +641,15 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
624641
client->last_timestamp = timestamp;
625642
client->last_activity = getRTCClock()->getCurrentTime();
626643

627-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
644+
bool use_chacha = client->supports_chacha;
628645
if (packet->isRouteFlood()) {
629646
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
630647
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
631-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_v2);
648+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_chacha);
632649
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
633650
} else {
634651
mesh::Packet *reply =
635-
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, use_v2);
652+
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, use_chacha);
636653
if (reply) {
637654
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
638655
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
@@ -693,8 +710,8 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
693710
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
694711
temp[4] = (TXT_TYPE_CLI_DATA << 2); // NOTE: legacy was: TXT_TYPE_PLAIN
695712

696-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
697-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, use_v2);
713+
bool use_chacha = client->supports_chacha;
714+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, use_chacha);
698715
if (reply) {
699716
if (client->out_path_len < 0) {
700717
sendFlood(reply, CLI_REPLY_DELAY_MILLIS);

examples/simple_repeater/MyMesh.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,11 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
159159

160160
bool filterRecvFloodPacket(mesh::Packet* pkt) override;
161161

162-
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
162+
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len, bool decrypted_with_chacha = false) override;
163163
int searchPeersByHash(const uint8_t* hash) override;
164164
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
165165
bool peerSupportsCHACHA(const mesh::Identity& dest) override;
166+
void setPeerSupportsCHACHA(const mesh::Identity* id, int peer_idx) override;
166167
void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len) override;
167168
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
168169
bool 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;

examples/simple_room_server/MyMesh.cpp

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ void MyMesh::pushPostToClient(ClientInfo *client, PostInfo &post) {
7171
mesh::Utils::sha256((uint8_t *)&client->extra.room.pending_ack, 4, reply_data, len, client->id.pub_key, PUB_KEY_SIZE);
7272
client->extra.room.push_post_timestamp = post.post_timestamp;
7373

74-
bool use_v2 = client->supports_chacha;
75-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, client->shared_secret, reply_data, len, use_v2);
74+
bool use_chacha = client->supports_chacha;
75+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, client->shared_secret, reply_data, len, use_chacha);
7676
if (reply) {
7777
if (client->out_path_len < 0) {
7878
sendFlood(reply);
@@ -280,7 +280,7 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
280280
}
281281

282282
void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const mesh::Identity &sender,
283-
uint8_t *data, size_t len) {
283+
uint8_t *data, size_t len, bool decrypted_with_chacha) {
284284
if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin
285285
// client (unknown at this stage)
286286
uint32_t sender_timestamp, sender_sync_since;
@@ -350,14 +350,17 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
350350

351351
next_push = futureMillis(PUSH_NOTIFY_DELAY_MILLIS); // delay next push, give RESPONSE packet time to arrive first
352352

353-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
353+
// Mark peer as ChaCha-capable if we decoded their packet with ChaCha
354+
if (decrypted_with_chacha) client->supports_chacha = true;
355+
356+
bool use_chacha = client->supports_chacha;
354357
if (packet->isRouteFlood()) {
355358
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
356359
mesh::Packet *path = createPathReturn(sender, client->shared_secret, packet->path, packet->path_len,
357-
PAYLOAD_TYPE_RESPONSE, reply_data, 13, use_v2);
360+
PAYLOAD_TYPE_RESPONSE, reply_data, 13, use_chacha);
358361
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
359362
} else {
360-
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, client->shared_secret, reply_data, 13, use_v2);
363+
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, client->shared_secret, reply_data, 13, use_chacha);
361364
if (reply) {
362365
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
363366
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
@@ -395,10 +398,24 @@ bool MyMesh::peerSupportsCHACHA(const mesh::Identity& dest) {
395398
if (client) {
396399
return client->supports_chacha;
397400
}
398-
// Unknown peer - default to v1 (safe fallback)
401+
// Unknown peer - default to AES (safe fallback)
399402
return false;
400403
}
401404

405+
void MyMesh::setPeerSupportsCHACHA(const mesh::Identity* id, int peer_idx) {
406+
if (peer_idx >= 0) {
407+
int i = matching_peer_indexes[peer_idx];
408+
if (i >= 0 && i < acl.getNumClients()) {
409+
acl.getClientByIdx(i)->supports_chacha = true;
410+
}
411+
} else if (id != nullptr) {
412+
ClientInfo* client = acl.getClient(id->pub_key, PUB_KEY_SIZE);
413+
if (client) {
414+
client->supports_chacha = true;
415+
}
416+
}
417+
}
418+
402419
void MyMesh::onAdvertRecv(mesh::Packet *packet, const mesh::Identity &id, uint32_t timestamp,
403420
const uint8_t *app_data, size_t app_data_len) {
404421
mesh::Mesh::onAdvertRecv(packet, id, timestamp, app_data, app_data_len); // chain to super impl
@@ -506,8 +523,8 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
506523
// mesh::Utils::sha256((uint8_t *)&expected_ack_crc, 4, temp, 5 + text_len, self_id.pub_key,
507524
// PUB_KEY_SIZE);
508525

509-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
510-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, use_v2);
526+
bool use_chacha = client->supports_chacha;
527+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, use_chacha);
511528
if (reply) {
512529
if (client->out_path_len < 0) {
513530
sendFlood(reply, delay_millis + SERVER_RESPONSE_DELAY);
@@ -561,14 +578,14 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
561578
} else {
562579
int reply_len = handleRequest(client, sender_timestamp, &data[4], len - 4);
563580
if (reply_len > 0) { // valid command
564-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
581+
bool use_chacha = client->supports_chacha;
565582
if (packet->isRouteFlood()) {
566583
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
567584
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
568-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_v2);
585+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_chacha);
569586
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
570587
} else {
571-
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, use_v2);
588+
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, use_chacha);
572589
if (reply) {
573590
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
574591
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);

examples/simple_room_server/MyMesh.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,11 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
145145
}
146146

147147
bool allowPacketForward(const mesh::Packet* packet) override;
148-
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
148+
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len, bool decrypted_with_chacha = false) override;
149149
int searchPeersByHash(const uint8_t* hash) override ;
150150
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
151151
bool peerSupportsCHACHA(const mesh::Identity& dest) override;
152+
void setPeerSupportsCHACHA(const mesh::Identity* id, int peer_idx) override;
152153
void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len) override;
153154
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
154155
bool 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;

examples/simple_sensor/SensorMesh.cpp

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ void SensorMesh::sendAlert(const ClientInfo* c, Trigger* t) {
256256
mesh::Utils::sha256((uint8_t *)&t->expected_acks[t->attempt], 4, data, 5 + text_len, self_id.pub_key, PUB_KEY_SIZE);
257257
t->attempt++;
258258

259-
bool use_v2 = c->supports_chacha;
260-
auto pkt = createDatagram(PAYLOAD_TYPE_TXT_MSG, c->id, c->shared_secret, data, 5 + text_len, use_v2);
259+
bool use_chacha = c->supports_chacha;
260+
auto pkt = createDatagram(PAYLOAD_TYPE_TXT_MSG, c->id, c->shared_secret, data, 5 + text_len, use_chacha);
261261
if (pkt) {
262262
if (c->out_path_len >= 0) { // we have an out_path, so send DIRECT
263263
sendDirect(pkt, c->out_path, c->out_path_len);
@@ -448,7 +448,7 @@ void SensorMesh::handleCommand(uint32_t sender_timestamp, char* command, char* r
448448
}
449449
}
450450

451-
void SensorMesh::onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) {
451+
void SensorMesh::onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len, bool decrypted_with_chacha) {
452452
if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin client (unknown at this stage)
453453
uint32_t timestamp;
454454
memcpy(&timestamp, data, 4);
@@ -465,14 +465,17 @@ void SensorMesh::onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, con
465465

466466
if (reply_len == 0) return; // invalid request
467467

468-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
468+
// Mark peer as ChaCha-capable if we decoded their packet with ChaCha
469+
if (decrypted_with_chacha) setPeerSupportsCHACHA(&sender, -1);
470+
471+
bool use_chacha = peerSupportsCHACHA(sender);
469472
if (packet->isRouteFlood()) {
470473
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
471474
mesh::Packet* path = createPathReturn(sender, secret, packet->path, packet->path_len,
472-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_v2);
475+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_chacha);
473476
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
474477
} else {
475-
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, use_v2);
478+
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, use_chacha);
476479
if (reply) sendFlood(reply, SERVER_RESPONSE_DELAY);
477480
}
478481
}
@@ -504,10 +507,24 @@ bool SensorMesh::peerSupportsCHACHA(const mesh::Identity& dest) {
504507
if (client) {
505508
return client->supports_chacha;
506509
}
507-
// Unknown peer - default to v1 (safe fallback)
510+
// Unknown peer - default to AES (safe fallback)
508511
return false;
509512
}
510513

514+
void SensorMesh::setPeerSupportsCHACHA(const mesh::Identity* id, int peer_idx) {
515+
if (peer_idx >= 0) {
516+
int i = matching_peer_indexes[peer_idx];
517+
if (i >= 0 && i < acl.getNumClients()) {
518+
acl.getClientByIdx(i)->supports_chacha = true;
519+
}
520+
} else if (id != nullptr) {
521+
ClientInfo* client = acl.getClient(id->pub_key, PUB_KEY_SIZE);
522+
if (client) {
523+
client->supports_chacha = true;
524+
}
525+
}
526+
}
527+
511528
void SensorMesh::onAdvertRecv(mesh::Packet *packet, const mesh::Identity &id, uint32_t timestamp,
512529
const uint8_t *app_data, size_t app_data_len) {
513530
mesh::Mesh::onAdvertRecv(packet, id, timestamp, app_data, app_data_len); // chain to super impl
@@ -559,14 +576,14 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
559576
from->last_timestamp = timestamp;
560577
from->last_activity = getRTCClock()->getCurrentTime();
561578

562-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
579+
bool use_chacha = from->supports_chacha;
563580
if (packet->isRouteFlood()) {
564581
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
565582
mesh::Packet* path = createPathReturn(from->id, secret, packet->path, packet->path_len,
566-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_v2);
583+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_chacha);
567584
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
568585
} else {
569-
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, from->id, secret, reply_data, reply_len, use_v2);
586+
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, from->id, secret, reply_data, reply_len, use_chacha);
570587
if (reply) {
571588
if (from->out_path_len >= 0) { // we have an out_path, so send DIRECT
572589
sendDirect(reply, from->out_path, from->out_path_len, SERVER_RESPONSE_DELAY);
@@ -592,9 +609,9 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
592609

593610
if (packet->isRouteFlood()) {
594611
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK
595-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
612+
bool use_chacha = from->supports_chacha;
596613
mesh::Packet* path = createPathReturn(from->id, secret, packet->path, packet->path_len,
597-
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4, use_v2);
614+
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4, use_chacha);
598615
if (path) sendFlood(path, TXT_ACK_DELAY);
599616
} else {
600617
sendAckTo(*from, ack_hash);
@@ -622,8 +639,8 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
622639
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
623640
temp[4] = (TXT_TYPE_CLI_DATA << 2);
624641

625-
bool use_v2 = (packet->getPayloadVer() == PAYLOAD_VER_2);
626-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from->id, secret, temp, 5 + text_len, use_v2);
642+
bool use_chacha = from->supports_chacha;
643+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from->id, secret, temp, 5 + text_len, use_chacha);
627644
if (reply) {
628645
if (from->out_path_len < 0) {
629646
sendFlood(reply, CLI_REPLY_DELAY_MILLIS);

0 commit comments

Comments
 (0)