Skip to content

Commit 90a5dda

Browse files
committed
Support AEAD responses in repeater/room/sensor
1 parent 10b4156 commit 90a5dda

7 files changed

Lines changed: 105 additions & 12 deletions

File tree

examples/simple_repeater/MyMesh.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,31 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
579579
}
580580
}
581581

582+
uint8_t MyMesh::getPeerFlags(int peer_idx) {
583+
int i = matching_peer_indexes[peer_idx];
584+
if (i >= 0 && i < acl.getNumClients())
585+
return acl.getClientByIdx(i)->flags;
586+
return 0;
587+
}
588+
589+
uint16_t MyMesh::getPeerNextAeadNonce(int peer_idx) {
590+
int i = matching_peer_indexes[peer_idx];
591+
if (i >= 0 && i < acl.getNumClients())
592+
return acl.getClientByIdx(i)->nextAeadNonce();
593+
return 0;
594+
}
595+
596+
void MyMesh::onPeerAeadDetected(int peer_idx) {
597+
int i = matching_peer_indexes[peer_idx];
598+
if (i >= 0 && i < acl.getNumClients()) {
599+
auto c = acl.getClientByIdx(i);
600+
if (!(c->flags & CONTACT_FLAG_AEAD)) {
601+
c->flags |= CONTACT_FLAG_AEAD;
602+
getRNG()->random((uint8_t*)&c->aead_nonce, sizeof(c->aead_nonce));
603+
}
604+
}
605+
}
606+
582607
static bool isShare(const mesh::Packet *packet) {
583608
if (packet->hasTransportCodes()) {
584609
return packet->transport_codes[0] == 0 && packet->transport_codes[1] == 0; // codes { 0, 0 } means 'send to nowhere'
@@ -622,11 +647,11 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
622647
if (packet->isRouteFlood()) {
623648
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
624649
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
625-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
650+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->nextAeadNonce());
626651
if (path) sendFlood(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
627652
} else {
628653
mesh::Packet *reply =
629-
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
654+
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->nextAeadNonce());
630655
if (reply) {
631656
if (client->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
632657
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
@@ -687,7 +712,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
687712
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
688713
temp[4] = (TXT_TYPE_CLI_DATA << 2); // NOTE: legacy was: TXT_TYPE_PLAIN
689714

690-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
715+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->nextAeadNonce());
691716
if (reply) {
692717
if (client->out_path_len == OUT_PATH_UNKNOWN) {
693718
sendFlood(reply, CLI_REPLY_DELAY_MILLIS, packet->getPathHashSize());

examples/simple_repeater/MyMesh.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
167167
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
168168
int searchPeersByHash(const uint8_t* hash) override;
169169
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
170+
uint8_t getPeerFlags(int peer_idx) override;
171+
uint16_t getPeerNextAeadNonce(int peer_idx) override;
172+
void onPeerAeadDetected(int peer_idx) override;
170173
void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len);
171174
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
172175
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 & 4 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->nextAeadNonce());
7575
if (reply) {
7676
if (client->out_path_len == OUT_PATH_UNKNOWN) {
7777
unsigned long delay_millis = 0;
@@ -389,6 +389,31 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
389389
}
390390
}
391391

392+
uint8_t MyMesh::getPeerFlags(int peer_idx) {
393+
int i = matching_peer_indexes[peer_idx];
394+
if (i >= 0 && i < acl.getNumClients())
395+
return acl.getClientByIdx(i)->flags;
396+
return 0;
397+
}
398+
399+
uint16_t MyMesh::getPeerNextAeadNonce(int peer_idx) {
400+
int i = matching_peer_indexes[peer_idx];
401+
if (i >= 0 && i < acl.getNumClients())
402+
return acl.getClientByIdx(i)->nextAeadNonce();
403+
return 0;
404+
}
405+
406+
void MyMesh::onPeerAeadDetected(int peer_idx) {
407+
int i = matching_peer_indexes[peer_idx];
408+
if (i >= 0 && i < acl.getNumClients()) {
409+
auto c = acl.getClientByIdx(i);
410+
if (!(c->flags & CONTACT_FLAG_AEAD)) {
411+
c->flags |= CONTACT_FLAG_AEAD;
412+
getRNG()->random((uint8_t*)&c->aead_nonce, sizeof(c->aead_nonce));
413+
}
414+
}
415+
}
416+
392417
void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx, const uint8_t *secret,
393418
uint8_t *data, size_t len) {
394419
int i = matching_peer_indexes[sender_idx];
@@ -482,7 +507,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
482507
// mesh::Utils::sha256((uint8_t *)&expected_ack_crc, 4, temp, 5 + text_len, self_id.pub_key,
483508
// PUB_KEY_SIZE);
484509

485-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
510+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->nextAeadNonce());
486511
if (reply) {
487512
if (client->out_path_len == OUT_PATH_UNKNOWN) {
488513
sendFlood(reply, delay_millis + SERVER_RESPONSE_DELAY, packet->getPathHashSize());
@@ -539,10 +564,10 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
539564
if (packet->isRouteFlood()) {
540565
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
541566
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
542-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
567+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->nextAeadNonce());
543568
if (path) sendFlood(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
544569
} else {
545-
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
570+
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->nextAeadNonce());
546571
if (reply) {
547572
if (client->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
548573
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);

examples/simple_room_server/MyMesh.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
148148
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
149149
int searchPeersByHash(const uint8_t* hash) override ;
150150
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
151+
uint8_t getPeerFlags(int peer_idx) override;
152+
uint16_t getPeerNextAeadNonce(int peer_idx) override;
153+
void onPeerAeadDetected(int peer_idx) override;
151154
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
152155
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;
153156
void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override;

examples/simple_sensor/SensorMesh.cpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ 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-
auto pkt = createDatagram(PAYLOAD_TYPE_TXT_MSG, c->id, c->shared_secret, data, 5 + text_len);
259+
auto pkt = createDatagram(PAYLOAD_TYPE_TXT_MSG, c->id, c->shared_secret, data, 5 + text_len, c->nextAeadNonce());
260260
if (pkt) {
261261
if (c->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
262262
sendDirect(pkt, c->out_path, c->out_path_len);
@@ -497,6 +497,31 @@ void SensorMesh::getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) {
497497
}
498498
}
499499

500+
uint8_t SensorMesh::getPeerFlags(int peer_idx) {
501+
int i = matching_peer_indexes[peer_idx];
502+
if (i >= 0 && i < acl.getNumClients())
503+
return acl.getClientByIdx(i)->flags;
504+
return 0;
505+
}
506+
507+
uint16_t SensorMesh::getPeerNextAeadNonce(int peer_idx) {
508+
int i = matching_peer_indexes[peer_idx];
509+
if (i >= 0 && i < acl.getNumClients())
510+
return acl.getClientByIdx(i)->nextAeadNonce();
511+
return 0;
512+
}
513+
514+
void SensorMesh::onPeerAeadDetected(int peer_idx) {
515+
int i = matching_peer_indexes[peer_idx];
516+
if (i >= 0 && i < acl.getNumClients()) {
517+
auto c = acl.getClientByIdx(i);
518+
if (!(c->flags & CONTACT_FLAG_AEAD)) {
519+
c->flags |= CONTACT_FLAG_AEAD;
520+
getRNG()->random((uint8_t*)&c->aead_nonce, sizeof(c->aead_nonce));
521+
}
522+
}
523+
}
524+
500525
void SensorMesh::sendAckTo(const ClientInfo& dest, uint32_t ack_hash, uint8_t path_hash_size) {
501526
if (dest.out_path_len == OUT_PATH_UNKNOWN) {
502527
mesh::Packet* ack = createAck(ack_hash);
@@ -537,10 +562,10 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
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(from->id, secret, packet->path, packet->path_len,
540-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
565+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, from->nextAeadNonce());
541566
if (path) sendFlood(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
542567
} else {
543-
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, from->id, secret, reply_data, reply_len);
568+
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, from->id, secret, reply_data, reply_len, from->nextAeadNonce());
544569
if (reply) {
545570
if (from->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
546571
sendDirect(reply, from->out_path, from->out_path_len, SERVER_RESPONSE_DELAY);
@@ -567,7 +592,7 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
567592
if (packet->isRouteFlood()) {
568593
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK
569594
mesh::Packet* path = createPathReturn(from->id, secret, packet->path, packet->path_len,
570-
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4);
595+
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4, from->nextAeadNonce());
571596
if (path) sendFlood(path, TXT_ACK_DELAY, packet->getPathHashSize());
572597
} else {
573598
sendAckTo(*from, ack_hash, packet->getPathHashSize());
@@ -595,7 +620,7 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
595620
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
596621
temp[4] = (TXT_TYPE_CLI_DATA << 2);
597622

598-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from->id, secret, temp, 5 + text_len);
623+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from->id, secret, temp, 5 + text_len, from->nextAeadNonce());
599624
if (reply) {
600625
if (from->out_path_len == OUT_PATH_UNKNOWN) {
601626
sendFlood(reply, CLI_REPLY_DELAY_MILLIS, packet->getPathHashSize());

examples/simple_sensor/SensorMesh.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ class SensorMesh : public mesh::Mesh, public CommonCLICallbacks {
123123
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
124124
int searchPeersByHash(const uint8_t* hash) override;
125125
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
126+
uint8_t getPeerFlags(int peer_idx) override;
127+
uint16_t getPeerNextAeadNonce(int peer_idx) override;
128+
void onPeerAeadDetected(int peer_idx) override;
126129
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
127130
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;
128131
void onControlDataRecv(mesh::Packet* packet) override;

src/helpers/ClientACL.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
struct ClientInfo {
1616
mesh::Identity id;
1717
uint8_t permissions;
18+
uint8_t flags; // transient — includes CONTACT_FLAG_AEAD
19+
mutable uint16_t aead_nonce; // transient — per-peer nonce counter
1820
uint8_t out_path_len;
1921
uint8_t out_path[MAX_PATH_SIZE];
2022
uint8_t shared_secret[PUB_KEY_SIZE];
@@ -30,6 +32,13 @@ struct ClientInfo {
3032
} room;
3133
} extra;
3234

35+
uint16_t nextAeadNonce() const {
36+
if (flags & CONTACT_FLAG_AEAD) {
37+
if (++aead_nonce == 0) ++aead_nonce; // skip 0 (means ECB)
38+
return aead_nonce;
39+
}
40+
return 0;
41+
}
3342
bool isAdmin() const { return (permissions & PERM_ACL_ROLE_MASK) == PERM_ACL_ADMIN; }
3443
};
3544

0 commit comments

Comments
 (0)