Skip to content

Commit c54e08c

Browse files
committed
switch to ascon + refactor
1 parent 22072f3 commit c54e08c

27 files changed

Lines changed: 3608 additions & 564 deletions

examples/companion_radio/DataStore.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,9 @@ File file = openRead(_getContactsChannelsFS(), "/contacts3");
276276
ContactInfo c;
277277
memset(&c, 0, sizeof(c)); // Zero-initialize to prevent garbage in new fields
278278
c.shared_secret_valid = false;
279-
c.supports_chacha = false;
279+
c.supports_ascon = false;
280280
uint8_t pub_key[32];
281-
uint8_t crypto_flags; // was 'unused'; bit 0 = supports_chacha
281+
uint8_t crypto_flags; // was 'unused'; bit 0 = supports_ascon
282282

283283
bool success = (file.read(pub_key, 32) == 32);
284284
success = success && (file.read((uint8_t *)&c.name, 32) == 32);
@@ -295,7 +295,7 @@ File file = openRead(_getContactsChannelsFS(), "/contacts3");
295295

296296
if (!success) break; // EOF
297297

298-
c.supports_chacha = (crypto_flags & 0x01) != 0; // bit 0; old files have 0 here (backwards compatible)
298+
c.supports_ascon = (crypto_flags & 0x01) != 0; // bit 0; old files have 0 here (backwards compatible)
299299
c.id = mesh::Identity(pub_key);
300300
if (!host->onContactLoaded(c)) full = true;
301301
}
@@ -310,7 +310,7 @@ void DataStore::saveContacts(DataStoreHost* host) {
310310
ContactInfo c;
311311

312312
while (host->getContactForSave(idx, c)) {
313-
uint8_t crypto_flags = c.supports_chacha ? 0x01 : 0x00; // bit 0 = supports_chacha
313+
uint8_t crypto_flags = c.supports_ascon ? 0x01 : 0x00; // bit 0 = supports_ascon
314314
bool success = (file.write(c.id.pub_key, 32) == 32);
315315
success = success && (file.write((uint8_t *)&c.name, 32) == 32);
316316
success = success && (file.write(&c.type, 1) == 1);

examples/simple_repeater/MyMesh.cpp

Lines changed: 15 additions & 42 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, bool decrypted_with_chacha) {
509+
uint8_t *data, size_t len, bool was_ascon) {
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,20 +530,17 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
530530

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

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);
533+
// Reply with same encryption the sender used
537534
if (packet->isRouteFlood()) {
538535
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
539536
mesh::Packet* path = createPathReturn(sender, secret, packet->path, packet->path_len,
540-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_chacha);
537+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, was_ascon);
541538
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
542539
} else if (reply_path_len < 0) {
543-
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, use_chacha);
540+
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, was_ascon);
544541
if (reply) sendFlood(reply, SERVER_RESPONSE_DELAY);
545542
} else {
546-
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, use_chacha);
543+
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, was_ascon);
547544
if (reply) sendDirect(reply, reply_path, reply_path_len, SERVER_RESPONSE_DELAY);
548545
}
549546
}
@@ -569,35 +566,13 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
569566
}
570567
}
571568

572-
bool MyMesh::peerSupportsCHACHA(const mesh::Identity& dest) {
573-
// Look up client by public key
574-
ClientInfo* client = acl.getClient(dest.pub_key, PUB_KEY_SIZE);
575-
if (client) {
576-
return client->supports_chacha;
577-
}
578-
// Unknown peer - default to AES (safe fallback)
579-
return false;
580-
}
581-
582-
bool MyMesh::peerSupportsCHACHA(uint8_t src_hash, int peer_idx) {
583-
// Use the peer index from searchPeersByHash() - no re-lookup needed
569+
void MyMesh::onPeerAsconCapabilityDetected(int peer_idx, bool supports_ascon) {
584570
int i = matching_peer_indexes[peer_idx];
585571
if (i >= 0 && i < acl.getNumClients()) {
586-
return acl.getClientByIdx(i)->supports_chacha;
587-
}
588-
return false;
589-
}
590-
591-
void MyMesh::setPeerSupportsCHACHA(const mesh::Identity* id, int peer_idx) {
592-
if (peer_idx >= 0) {
593-
int i = matching_peer_indexes[peer_idx];
594-
if (i >= 0 && i < acl.getNumClients()) {
595-
acl.getClientByIdx(i)->supports_chacha = true;
596-
}
597-
} else if (id != nullptr) {
598-
ClientInfo* client = acl.getClient(id->pub_key, PUB_KEY_SIZE);
599-
if (client) {
600-
client->supports_chacha = true;
572+
auto client = acl.getClientByIdx(i);
573+
if (supports_ascon && !client->supports_ascon) {
574+
client->supports_ascon = true;
575+
MESH_DEBUG_PRINTLN("Auto-detected Ascon capability for client %d", i);
601576
}
602577
}
603578
}
@@ -615,10 +590,10 @@ void MyMesh::onAdvertRecv(mesh::Packet *packet, const mesh::Identity &id, uint32
615590

616591
AdvertDataParser parser(app_data, app_data_len);
617592
if (parser.isValid()) {
618-
// Update CHACHA capability for known clients (chat nodes that are in our ACL)
593+
// Update Ascon encryption capability for known clients (chat nodes that are in our ACL)
619594
ClientInfo* client = acl.getClient(id.pub_key, PUB_KEY_SIZE);
620595
if (client) {
621-
client->supports_chacha = (parser.getFeat1() & ADV_FEAT1_CHACHA_CAPABLE) != 0;
596+
client->supports_ascon = (parser.getFeat1() & ADV_FEAT1_ASCON_CAPABLE) != 0;
622597
}
623598

624599
// if this a zero hop advert (and not via 'Share'), add it to neighbours
@@ -650,15 +625,14 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
650625
client->last_timestamp = timestamp;
651626
client->last_activity = getRTCClock()->getCurrentTime();
652627

653-
bool use_chacha = client->supports_chacha;
654628
if (packet->isRouteFlood()) {
655629
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
656630
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
657-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_chacha);
631+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->supports_ascon);
658632
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
659633
} else {
660634
mesh::Packet *reply =
661-
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, use_chacha);
635+
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->supports_ascon);
662636
if (reply) {
663637
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
664638
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
@@ -719,8 +693,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
719693
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
720694
temp[4] = (TXT_TYPE_CLI_DATA << 2); // NOTE: legacy was: TXT_TYPE_PLAIN
721695

722-
bool use_chacha = client->supports_chacha;
723-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, use_chacha);
696+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->supports_ascon);
724697
if (reply) {
725698
if (client->out_path_len < 0) {
726699
sendFlood(reply, CLI_REPLY_DELAY_MILLIS);

examples/simple_repeater/MyMesh.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,10 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
160160

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

163-
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;
163+
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len, bool was_ascon) override;
164164
int searchPeersByHash(const uint8_t* hash) override;
165165
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
166-
bool peerSupportsCHACHA(const mesh::Identity& dest) override;
167-
bool peerSupportsCHACHA(uint8_t src_hash, int peer_idx) override;
168-
void setPeerSupportsCHACHA(const mesh::Identity* id, int peer_idx) override;
166+
void onPeerAsconCapabilityDetected(int peer_idx, bool supports_ascon) override;
169167
void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len) override;
170168
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
171169
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: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ 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_chacha = client->supports_chacha;
75-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, client->shared_secret, reply_data, len, use_chacha);
74+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, client->shared_secret, reply_data, len, client->supports_ascon);
7675
if (reply) {
7776
if (client->out_path_len < 0) {
7877
sendFlood(reply);
@@ -280,7 +279,7 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
280279
}
281280

282281
void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const mesh::Identity &sender,
283-
uint8_t *data, size_t len, bool decrypted_with_chacha) {
282+
uint8_t *data, size_t len, bool was_ascon) {
284283
if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin
285284
// client (unknown at this stage)
286285
uint32_t sender_timestamp, sender_sync_since;
@@ -350,17 +349,13 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
350349

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

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;
357352
if (packet->isRouteFlood()) {
358353
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
359354
mesh::Packet *path = createPathReturn(sender, client->shared_secret, packet->path, packet->path_len,
360-
PAYLOAD_TYPE_RESPONSE, reply_data, 13, use_chacha);
355+
PAYLOAD_TYPE_RESPONSE, reply_data, 13, client->supports_ascon);
361356
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
362357
} else {
363-
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, client->shared_secret, reply_data, 13, use_chacha);
358+
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, client->shared_secret, reply_data, 13, client->supports_ascon);
364359
if (reply) {
365360
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
366361
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
@@ -392,35 +387,13 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
392387
}
393388
}
394389

395-
bool MyMesh::peerSupportsCHACHA(const mesh::Identity& dest) {
396-
// Look up client by public key
397-
ClientInfo* client = acl.getClient(dest.pub_key, PUB_KEY_SIZE);
398-
if (client) {
399-
return client->supports_chacha;
400-
}
401-
// Unknown peer - default to AES (safe fallback)
402-
return false;
403-
}
404-
405-
bool MyMesh::peerSupportsCHACHA(uint8_t src_hash, int peer_idx) {
406-
// Use the peer index from searchPeersByHash() - no re-lookup needed
390+
void MyMesh::onPeerAsconCapabilityDetected(int peer_idx, bool supports_ascon) {
407391
int i = matching_peer_indexes[peer_idx];
408392
if (i >= 0 && i < acl.getNumClients()) {
409-
return acl.getClientByIdx(i)->supports_chacha;
410-
}
411-
return false;
412-
}
413-
414-
void MyMesh::setPeerSupportsCHACHA(const mesh::Identity* id, int peer_idx) {
415-
if (peer_idx >= 0) {
416-
int i = matching_peer_indexes[peer_idx];
417-
if (i >= 0 && i < acl.getNumClients()) {
418-
acl.getClientByIdx(i)->supports_chacha = true;
419-
}
420-
} else if (id != nullptr) {
421-
ClientInfo* client = acl.getClient(id->pub_key, PUB_KEY_SIZE);
422-
if (client) {
423-
client->supports_chacha = true;
393+
auto client = acl.getClientByIdx(i);
394+
if (supports_ascon && !client->supports_ascon) {
395+
client->supports_ascon = true;
396+
MESH_DEBUG_PRINTLN("Auto-detected Ascon capability for client %d", i);
424397
}
425398
}
426399
}
@@ -429,12 +402,12 @@ void MyMesh::onAdvertRecv(mesh::Packet *packet, const mesh::Identity &id, uint32
429402
const uint8_t *app_data, size_t app_data_len) {
430403
mesh::Mesh::onAdvertRecv(packet, id, timestamp, app_data, app_data_len); // chain to super impl
431404

432-
// Update CHACHA capability for known clients
405+
// Update Ascon encryption capability for known clients
433406
AdvertDataParser parser(app_data, app_data_len);
434407
if (parser.isValid()) {
435408
ClientInfo* client = acl.getClient(id.pub_key, PUB_KEY_SIZE);
436409
if (client) {
437-
client->supports_chacha = (parser.getFeat1() & ADV_FEAT1_CHACHA_CAPABLE) != 0;
410+
client->supports_ascon = (parser.getFeat1() & ADV_FEAT1_ASCON_CAPABLE) != 0;
438411
}
439412
}
440413
}
@@ -532,8 +505,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
532505
// mesh::Utils::sha256((uint8_t *)&expected_ack_crc, 4, temp, 5 + text_len, self_id.pub_key,
533506
// PUB_KEY_SIZE);
534507

535-
bool use_chacha = client->supports_chacha;
536-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, use_chacha);
508+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->supports_ascon);
537509
if (reply) {
538510
if (client->out_path_len < 0) {
539511
sendFlood(reply, delay_millis + SERVER_RESPONSE_DELAY);
@@ -587,14 +559,13 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
587559
} else {
588560
int reply_len = handleRequest(client, sender_timestamp, &data[4], len - 4);
589561
if (reply_len > 0) { // valid command
590-
bool use_chacha = client->supports_chacha;
591562
if (packet->isRouteFlood()) {
592563
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
593564
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
594-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, use_chacha);
565+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->supports_ascon);
595566
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
596567
} else {
597-
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, use_chacha);
568+
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->supports_ascon);
598569
if (reply) {
599570
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
600571
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);

examples/simple_room_server/MyMesh.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,10 @@ 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, bool decrypted_with_chacha = false) override;
148+
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len, bool was_ascon) override;
149149
int searchPeersByHash(const uint8_t* hash) override ;
150150
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
151-
bool peerSupportsCHACHA(const mesh::Identity& dest) override;
152-
bool peerSupportsCHACHA(uint8_t src_hash, int peer_idx) override;
153-
void setPeerSupportsCHACHA(const mesh::Identity* id, int peer_idx) override;
151+
void onPeerAsconCapabilityDetected(int peer_idx, bool supports_ascon) override;
154152
void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len) override;
155153
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
156154
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_secure_chat/main.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,9 @@ class MyMesh : public BaseChatMesh, ContactVisitor {
408408
temp[5 + MAX_TEXT_LEN] = 0; // truncate if too long
409409

410410
int len = strlen((char *) &temp[5]);
411-
auto pkt = createGroupDatagram(PAYLOAD_TYPE_GRP_TXT, _public->channel, temp, 5 + len);
411+
// Use Ascon if channel has the flag set, otherwise use legacy for backwards compatibility
412+
bool use_ascon = (_public->channel.flags & CHANNEL_FLAG_ASCON) != 0;
413+
auto pkt = createGroupDatagram(PAYLOAD_TYPE_GRP_TXT, _public->channel, temp, 5 + len, use_ascon);
412414
if (pkt) {
413415
sendFlood(pkt);
414416
Serial.println(" Sent.");

0 commit comments

Comments
 (0)