Skip to content

Commit 0954142

Browse files
committed
Support AEAD responses in repeater/room/sensor
1 parent 4ed0db4 commit 0954142

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
@@ -623,6 +623,31 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
623623
}
624624
}
625625

626+
uint8_t MyMesh::getPeerFlags(int peer_idx) {
627+
int i = matching_peer_indexes[peer_idx];
628+
if (i >= 0 && i < acl.getNumClients())
629+
return acl.getClientByIdx(i)->flags;
630+
return 0;
631+
}
632+
633+
uint16_t MyMesh::getPeerNextAeadNonce(int peer_idx) {
634+
int i = matching_peer_indexes[peer_idx];
635+
if (i >= 0 && i < acl.getNumClients())
636+
return acl.getClientByIdx(i)->nextAeadNonce();
637+
return 0;
638+
}
639+
640+
void MyMesh::onPeerAeadDetected(int peer_idx) {
641+
int i = matching_peer_indexes[peer_idx];
642+
if (i >= 0 && i < acl.getNumClients()) {
643+
auto c = acl.getClientByIdx(i);
644+
if (!(c->flags & CONTACT_FLAG_AEAD)) {
645+
c->flags |= CONTACT_FLAG_AEAD;
646+
getRNG()->random((uint8_t*)&c->aead_nonce, sizeof(c->aead_nonce));
647+
}
648+
}
649+
}
650+
626651
static bool isShare(const mesh::Packet *packet) {
627652
if (packet->hasTransportCodes()) {
628653
return packet->transport_codes[0] == 0 && packet->transport_codes[1] == 0; // codes { 0, 0 } means 'send to nowhere'
@@ -666,11 +691,11 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
666691
if (packet->isRouteFlood()) {
667692
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
668693
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
669-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
694+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->nextAeadNonce());
670695
if (path) sendFloodReply(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
671696
} else {
672697
mesh::Packet *reply =
673-
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
698+
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->nextAeadNonce());
674699
if (reply) {
675700
if (client->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
676701
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
@@ -731,7 +756,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
731756
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
732757
temp[4] = (TXT_TYPE_CLI_DATA << 2); // NOTE: legacy was: TXT_TYPE_PLAIN
733758

734-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
759+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->nextAeadNonce());
735760
if (reply) {
736761
if (client->out_path_len == OUT_PATH_UNKNOWN) {
737762
sendFloodReply(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
@@ -168,6 +168,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
168168
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
169169
int searchPeersByHash(const uint8_t* hash) override;
170170
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
171+
uint8_t getPeerFlags(int peer_idx) override;
172+
uint16_t getPeerNextAeadNonce(int peer_idx) override;
173+
void onPeerAeadDetected(int peer_idx) override;
171174
void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len);
172175
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
173176
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;
@@ -412,6 +412,31 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
412412
}
413413
}
414414

415+
uint8_t MyMesh::getPeerFlags(int peer_idx) {
416+
int i = matching_peer_indexes[peer_idx];
417+
if (i >= 0 && i < acl.getNumClients())
418+
return acl.getClientByIdx(i)->flags;
419+
return 0;
420+
}
421+
422+
uint16_t MyMesh::getPeerNextAeadNonce(int peer_idx) {
423+
int i = matching_peer_indexes[peer_idx];
424+
if (i >= 0 && i < acl.getNumClients())
425+
return acl.getClientByIdx(i)->nextAeadNonce();
426+
return 0;
427+
}
428+
429+
void MyMesh::onPeerAeadDetected(int peer_idx) {
430+
int i = matching_peer_indexes[peer_idx];
431+
if (i >= 0 && i < acl.getNumClients()) {
432+
auto c = acl.getClientByIdx(i);
433+
if (!(c->flags & CONTACT_FLAG_AEAD)) {
434+
c->flags |= CONTACT_FLAG_AEAD;
435+
getRNG()->random((uint8_t*)&c->aead_nonce, sizeof(c->aead_nonce));
436+
}
437+
}
438+
}
439+
415440
void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx, const uint8_t *secret,
416441
uint8_t *data, size_t len) {
417442
int i = matching_peer_indexes[sender_idx];
@@ -505,7 +530,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
505530
// mesh::Utils::sha256((uint8_t *)&expected_ack_crc, 4, temp, 5 + text_len, self_id.pub_key,
506531
// PUB_KEY_SIZE);
507532

508-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
533+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->nextAeadNonce());
509534
if (reply) {
510535
if (client->out_path_len == OUT_PATH_UNKNOWN) {
511536
sendFloodReply(reply, delay_millis + SERVER_RESPONSE_DELAY, packet->getPathHashSize());
@@ -562,10 +587,10 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
562587
if (packet->isRouteFlood()) {
563588
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
564589
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
565-
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
590+
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->nextAeadNonce());
566591
if (path) sendFloodReply(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
567592
} else {
568-
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
593+
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->nextAeadNonce());
569594
if (reply) {
570595
if (client->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
571596
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
@@ -157,6 +157,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
157157
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
158158
int searchPeersByHash(const uint8_t* hash) override ;
159159
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
160+
uint8_t getPeerFlags(int peer_idx) override;
161+
uint16_t getPeerNextAeadNonce(int peer_idx) override;
162+
void onPeerAeadDetected(int peer_idx) override;
160163
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
161164
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;
162165
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
@@ -124,6 +124,9 @@ class SensorMesh : public mesh::Mesh, public CommonCLICallbacks {
124124
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
125125
int searchPeersByHash(const uint8_t* hash) override;
126126
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
127+
uint8_t getPeerFlags(int peer_idx) override;
128+
uint16_t getPeerNextAeadNonce(int peer_idx) override;
129+
void onPeerAeadDetected(int peer_idx) override;
127130
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
128131
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;
129132
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)