Skip to content

Commit e51ac5f

Browse files
committed
Enable Ascon encryption across all firmware variants
1 parent 46a87c3 commit e51ac5f

12 files changed

Lines changed: 204 additions & 62 deletions

File tree

examples/companion_radio/DataStore.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,17 @@ File file = openRead(_getContactsChannelsFS(), "/contacts3");
274274
bool full = false;
275275
while (!full) {
276276
ContactInfo c;
277+
memset(&c, 0, sizeof(c)); // Zero-initialize to prevent garbage in new fields
278+
c.shared_secret_valid = false;
279+
c.supports_ascon = false;
277280
uint8_t pub_key[32];
278-
uint8_t unused;
281+
uint8_t crypto_flags; // was 'unused'; bit 0 = supports_ascon
279282

280283
bool success = (file.read(pub_key, 32) == 32);
281284
success = success && (file.read((uint8_t *)&c.name, 32) == 32);
282285
success = success && (file.read(&c.type, 1) == 1);
283286
success = success && (file.read(&c.flags, 1) == 1);
284-
success = success && (file.read(&unused, 1) == 1);
287+
success = success && (file.read(&crypto_flags, 1) == 1);
285288
success = success && (file.read((uint8_t *)&c.sync_since, 4) == 4); // was 'reserved'
286289
success = success && (file.read((uint8_t *)&c.out_path_len, 1) == 1);
287290
success = success && (file.read((uint8_t *)&c.last_advert_timestamp, 4) == 4);
@@ -292,6 +295,7 @@ File file = openRead(_getContactsChannelsFS(), "/contacts3");
292295

293296
if (!success) break; // EOF
294297

298+
c.supports_ascon = (crypto_flags & 0x01) != 0; // bit 0; old files have 0 here (backwards compatible)
295299
c.id = mesh::Identity(pub_key);
296300
if (!host->onContactLoaded(c)) full = true;
297301
}
@@ -304,14 +308,14 @@ void DataStore::saveContacts(DataStoreHost* host) {
304308
if (file) {
305309
uint32_t idx = 0;
306310
ContactInfo c;
307-
uint8_t unused = 0;
308311

309312
while (host->getContactForSave(idx, c)) {
313+
uint8_t crypto_flags = c.supports_ascon ? 0x01 : 0x00; // bit 0 = supports_ascon
310314
bool success = (file.write(c.id.pub_key, 32) == 32);
311315
success = success && (file.write((uint8_t *)&c.name, 32) == 32);
312316
success = success && (file.write(&c.type, 1) == 1);
313317
success = success && (file.write(&c.flags, 1) == 1);
314-
success = success && (file.write(&unused, 1) == 1);
318+
success = success && (file.write(&crypto_flags, 1) == 1);
315319
success = success && (file.write((uint8_t *)&c.sync_since, 4) == 4);
316320
success = success && (file.write((uint8_t *)&c.out_path_len, 1) == 1);
317321
success = success && (file.write((uint8_t *)&c.last_advert_timestamp, 4) == 4);
@@ -335,14 +339,18 @@ void DataStore::loadChannels(DataStoreHost* host) {
335339
uint8_t channel_idx = 0;
336340
while (!full) {
337341
ChannelDetails ch;
338-
uint8_t unused[4];
342+
uint8_t flags_and_unused[4];
339343

340-
bool success = (file.read(unused, 4) == 4);
344+
bool success = (file.read(flags_and_unused, 4) == 4);
341345
success = success && (file.read((uint8_t *)ch.name, 32) == 32);
342346
success = success && (file.read((uint8_t *)ch.channel.secret, 32) == 32);
343347

344348
if (!success) break; // EOF
345349

350+
// First byte stores channel flags (v2 support, etc), rest unused
351+
// Old files have all zeros here, which means v1 (backward compatible)
352+
ch.channel.flags = flags_and_unused[0];
353+
346354
if (host->onChannelLoaded(channel_idx, ch)) {
347355
channel_idx++;
348356
} else {
@@ -358,11 +366,14 @@ void DataStore::saveChannels(DataStoreHost* host) {
358366
if (file) {
359367
uint8_t channel_idx = 0;
360368
ChannelDetails ch;
361-
uint8_t unused[4];
362-
memset(unused, 0, 4);
369+
uint8_t flags_and_unused[4];
363370

364371
while (host->getChannelForSave(channel_idx, ch)) {
365-
bool success = (file.write(unused, 4) == 4);
372+
// First byte stores channel flags (v2 support, etc), rest unused
373+
memset(flags_and_unused, 0, 4);
374+
flags_and_unused[0] = ch.channel.flags;
375+
376+
bool success = (file.write(flags_and_unused, 4) == 4);
366377
success = success && (file.write((uint8_t *)ch.name, 32) == 32);
367378
success = success && (file.write((uint8_t *)ch.channel.secret, 32) == 32);
368379

examples/companion_radio/MyMesh.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#define CMD_SEND_ANON_REQ 57
5757
#define CMD_SET_AUTOADD_CONFIG 58
5858
#define CMD_GET_AUTOADD_CONFIG 59
59+
#define CMD_GET_CHANNEL_V2 60 // returns 51 bytes (includes flags)
5960

6061
// Stats sub-types for CMD_GET_STATS
6162
#define STATS_TYPE_CORE 0
@@ -88,6 +89,7 @@
8889
#define RESP_CODE_TUNING_PARAMS 23
8990
#define RESP_CODE_STATS 24 // v8+, second byte is stats type
9091
#define RESP_CODE_AUTOADD_CONFIG 25
92+
#define RESP_CODE_CHANNEL_INFO_V2 26 // reply to CMD_GET_CHANNEL_V2 (51 bytes)
9193

9294
#define SEND_TIMEOUT_BASE_MILLIS 500
9395
#define FLOOD_SEND_TIMEOUT_FACTOR 16.0f
@@ -1500,6 +1502,23 @@ void MyMesh::handleCmdFrame(size_t len) {
15001502
i += 32;
15011503
memcpy(&out_frame[i], channel.channel.secret, 16);
15021504
i += 16; // NOTE: only 128-bit supported
1505+
// flags byte NOT included - old apps expect exactly 50 bytes
1506+
_serial->writeFrame(out_frame, i);
1507+
} else {
1508+
writeErrFrame(ERR_CODE_NOT_FOUND);
1509+
}
1510+
} else if (cmd_frame[0] == CMD_GET_CHANNEL_V2 && len >= 2) {
1511+
uint8_t channel_idx = cmd_frame[1];
1512+
ChannelDetails channel;
1513+
if (getChannel(channel_idx, channel)) {
1514+
int i = 0;
1515+
out_frame[i++] = RESP_CODE_CHANNEL_INFO_V2;
1516+
out_frame[i++] = channel_idx;
1517+
strcpy((char *)&out_frame[i], channel.name);
1518+
i += 32;
1519+
memcpy(&out_frame[i], channel.channel.secret, 16);
1520+
i += 16; // NOTE: only 128-bit supported
1521+
out_frame[i++] = channel.channel.flags; // V2: includes flags byte (51 bytes total)
15031522
_serial->writeFrame(out_frame, i);
15041523
} else {
15051524
writeErrFrame(ERR_CODE_NOT_FOUND);
@@ -1509,9 +1528,13 @@ void MyMesh::handleCmdFrame(size_t len) {
15091528
} else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 2 + 32 + 16) {
15101529
uint8_t channel_idx = cmd_frame[1];
15111530
ChannelDetails channel;
1531+
memset(&channel, 0, sizeof(channel));
15121532
StrHelper::strncpy(channel.name, (char *)&cmd_frame[2], 32);
1513-
memset(channel.channel.secret, 0, sizeof(channel.channel.secret));
15141533
memcpy(channel.channel.secret, &cmd_frame[2 + 32], 16); // NOTE: only 128-bit supported
1534+
// Optional flags byte: old apps don't send it (flags defaults to 0 = AES)
1535+
if (len >= 2 + 32 + 16 + 1) {
1536+
channel.channel.flags = cmd_frame[2 + 32 + 16];
1537+
}
15151538
if (setChannel(channel_idx, channel)) {
15161539
saveChannels();
15171540
writeOKFrame();

examples/simple_repeater/MyMesh.cpp

Lines changed: 32 additions & 12 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 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,16 +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+
// Reply with same encryption the sender used
533534
if (packet->isRouteFlood()) {
534535
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
535536
mesh::Packet* path = createPathReturn(sender, secret, packet->path, packet->path_len,
536-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
537+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, was_ascon);
537538
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
538539
} else if (reply_path_len < 0) {
539-
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
540+
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, was_ascon);
540541
if (reply) sendFlood(reply, SERVER_RESPONSE_DELAY);
541542
} else {
542-
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
543+
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len, was_ascon);
543544
if (reply) sendDirect(reply, reply_path, reply_path_len, SERVER_RESPONSE_DELAY);
544545
}
545546
}
@@ -565,6 +566,17 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
565566
}
566567
}
567568

569+
void MyMesh::onPeerAsconCapabilityDetected(int peer_idx, bool supports_ascon) {
570+
int i = matching_peer_indexes[peer_idx];
571+
if (i >= 0 && i < acl.getNumClients()) {
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);
576+
}
577+
}
578+
}
579+
568580
static bool isShare(const mesh::Packet *packet) {
569581
if (packet->hasTransportCodes()) {
570582
return packet->transport_codes[0] == 0 && packet->transport_codes[1] == 0; // codes { 0, 0 } means 'send to nowhere'
@@ -576,11 +588,19 @@ void MyMesh::onAdvertRecv(mesh::Packet *packet, const mesh::Identity &id, uint32
576588
const uint8_t *app_data, size_t app_data_len) {
577589
mesh::Mesh::onAdvertRecv(packet, id, timestamp, app_data, app_data_len); // chain to super impl
578590

579-
// if this a zero hop advert (and not via 'Share'), add it to neighbours
580-
if (packet->path_len == 0 && !isShare(packet)) {
581-
AdvertDataParser parser(app_data, app_data_len);
582-
if (parser.isValid() && parser.getType() == ADV_TYPE_REPEATER) { // just keep neigbouring Repeaters
583-
putNeighbour(id, timestamp, packet->getSNR());
591+
AdvertDataParser parser(app_data, app_data_len);
592+
if (parser.isValid()) {
593+
// Update Ascon encryption capability for known clients (chat nodes that are in our ACL)
594+
ClientInfo* client = acl.getClient(id.pub_key, PUB_KEY_SIZE);
595+
if (client) {
596+
client->supports_ascon = (parser.getFeat1() & ADV_FEAT1_ASCON_CAPABLE) != 0;
597+
}
598+
599+
// if this a zero hop advert (and not via 'Share'), add it to neighbours
600+
if (packet->path_len == 0 && !isShare(packet)) {
601+
if (parser.getType() == ADV_TYPE_REPEATER) { // just keep neigbouring Repeaters
602+
putNeighbour(id, timestamp, packet->getSNR());
603+
}
584604
}
585605
}
586606
}
@@ -608,11 +628,11 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
608628
if (packet->isRouteFlood()) {
609629
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
610630
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
611-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
631+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->supports_ascon);
612632
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
613633
} else {
614634
mesh::Packet *reply =
615-
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
635+
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->supports_ascon);
616636
if (reply) {
617637
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
618638
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
@@ -673,7 +693,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
673693
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
674694
temp[4] = (TXT_TYPE_CLI_DATA << 2); // NOTE: legacy was: TXT_TYPE_PLAIN
675695

676-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
696+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->supports_ascon);
677697
if (reply) {
678698
if (client->out_path_len < 0) {
679699
sendFlood(reply, CLI_REPLY_DELAY_MILLIS);

examples/simple_repeater/MyMesh.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,11 @@ 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) 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-
void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len);
166+
void onPeerAsconCapabilityDetected(int peer_idx, bool supports_ascon) override;
167+
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;
169170
void onControlDataRecv(mesh::Packet* packet) override;

examples/simple_room_server/MyMesh.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +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-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, client->shared_secret, reply_data, len);
74+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, client->shared_secret, reply_data, len, client->supports_ascon);
7575
if (reply) {
7676
if (client->out_path_len < 0) {
7777
sendFlood(reply);
@@ -279,7 +279,7 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
279279
}
280280

281281
void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const mesh::Identity &sender,
282-
uint8_t *data, size_t len) {
282+
uint8_t *data, size_t len, bool was_ascon) {
283283
if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin
284284
// client (unknown at this stage)
285285
uint32_t sender_timestamp, sender_sync_since;
@@ -352,10 +352,10 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
352352
if (packet->isRouteFlood()) {
353353
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
354354
mesh::Packet *path = createPathReturn(sender, client->shared_secret, packet->path, packet->path_len,
355-
PAYLOAD_TYPE_RESPONSE, reply_data, 13);
355+
PAYLOAD_TYPE_RESPONSE, reply_data, 13, client->supports_ascon);
356356
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
357357
} else {
358-
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, client->shared_secret, reply_data, 13);
358+
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, client->shared_secret, reply_data, 13, client->supports_ascon);
359359
if (reply) {
360360
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
361361
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
@@ -387,6 +387,31 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
387387
}
388388
}
389389

390+
void MyMesh::onPeerAsconCapabilityDetected(int peer_idx, bool supports_ascon) {
391+
int i = matching_peer_indexes[peer_idx];
392+
if (i >= 0 && i < acl.getNumClients()) {
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);
397+
}
398+
}
399+
}
400+
401+
void MyMesh::onAdvertRecv(mesh::Packet *packet, const mesh::Identity &id, uint32_t timestamp,
402+
const uint8_t *app_data, size_t app_data_len) {
403+
mesh::Mesh::onAdvertRecv(packet, id, timestamp, app_data, app_data_len); // chain to super impl
404+
405+
// Update Ascon encryption capability for known clients
406+
AdvertDataParser parser(app_data, app_data_len);
407+
if (parser.isValid()) {
408+
ClientInfo* client = acl.getClient(id.pub_key, PUB_KEY_SIZE);
409+
if (client) {
410+
client->supports_ascon = (parser.getFeat1() & ADV_FEAT1_ASCON_CAPABLE) != 0;
411+
}
412+
}
413+
}
414+
390415
void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx, const uint8_t *secret,
391416
uint8_t *data, size_t len) {
392417
int i = matching_peer_indexes[sender_idx];
@@ -480,7 +505,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
480505
// mesh::Utils::sha256((uint8_t *)&expected_ack_crc, 4, temp, 5 + text_len, self_id.pub_key,
481506
// PUB_KEY_SIZE);
482507

483-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
508+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->supports_ascon);
484509
if (reply) {
485510
if (client->out_path_len < 0) {
486511
sendFlood(reply, delay_millis + SERVER_RESPONSE_DELAY);
@@ -537,10 +562,10 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
537562
if (packet->isRouteFlood()) {
538563
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
539564
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
540-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
565+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->supports_ascon);
541566
if (path) sendFlood(path, SERVER_RESPONSE_DELAY);
542567
} else {
543-
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
568+
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->supports_ascon);
544569
if (reply) {
545570
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
546571
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);

examples/simple_room_server/MyMesh.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,9 +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 was_ascon) override;
149149
int searchPeersByHash(const uint8_t* hash) override ;
150150
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
151+
void onPeerAsconCapabilityDetected(int peer_idx, bool supports_ascon) override;
152+
void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len) override;
151153
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
152154
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;
153155
void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) 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)