Browse Source

Support AEAD responses in repeater/room/sensor

pull/1677/head
Wessel Nieboer 6 months ago
parent
commit
dc2668c6d3
No known key found for this signature in database GPG Key ID: 929C8E45E33B5FD2
  1. 31
      examples/simple_repeater/MyMesh.cpp
  2. 3
      examples/simple_repeater/MyMesh.h
  3. 33
      examples/simple_room_server/MyMesh.cpp
  4. 3
      examples/simple_room_server/MyMesh.h
  5. 35
      examples/simple_sensor/SensorMesh.cpp
  6. 3
      examples/simple_sensor/SensorMesh.h
  7. 9
      src/helpers/ClientACL.h

31
examples/simple_repeater/MyMesh.cpp

@ -625,6 +625,31 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
}
}
uint8_t MyMesh::getPeerFlags(int peer_idx) {
int i = matching_peer_indexes[peer_idx];
if (i >= 0 && i < acl.getNumClients())
return acl.getClientByIdx(i)->flags;
return 0;
}
uint16_t MyMesh::getPeerNextAeadNonce(int peer_idx) {
int i = matching_peer_indexes[peer_idx];
if (i >= 0 && i < acl.getNumClients())
return acl.getClientByIdx(i)->nextAeadNonce();
return 0;
}
void MyMesh::onPeerAeadDetected(int peer_idx) {
int i = matching_peer_indexes[peer_idx];
if (i >= 0 && i < acl.getNumClients()) {
auto c = acl.getClientByIdx(i);
if (!(c->flags & CONTACT_FLAG_AEAD)) {
c->flags |= CONTACT_FLAG_AEAD;
getRNG()->random((uint8_t*)&c->aead_nonce, sizeof(c->aead_nonce));
}
}
}
static bool isShare(const mesh::Packet *packet) {
if (packet->hasTransportCodes()) {
return packet->transport_codes[0] == 0 && packet->transport_codes[1] == 0; // codes { 0, 0 } means 'send to nowhere'
@ -668,11 +693,11 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
if (packet->isRouteFlood()) {
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->nextAeadNonce());
if (path) sendFloodReply(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
} else {
mesh::Packet *reply =
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->nextAeadNonce());
if (reply) {
if (client->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
@ -733,7 +758,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
temp[4] = (TXT_TYPE_CLI_DATA << 2); // NOTE: legacy was: TXT_TYPE_PLAIN
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->nextAeadNonce());
if (reply) {
if (client->out_path_len == OUT_PATH_UNKNOWN) {
sendFloodReply(reply, CLI_REPLY_DELAY_MILLIS, packet->getPathHashSize());

3
examples/simple_repeater/MyMesh.h

@ -171,6 +171,9 @@ protected:
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
int searchPeersByHash(const uint8_t* hash) override;
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
uint8_t getPeerFlags(int peer_idx) override;
uint16_t getPeerNextAeadNonce(int peer_idx) override;
void onPeerAeadDetected(int peer_idx) override;
void onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len);
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
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;

33
examples/simple_room_server/MyMesh.cpp

@ -71,7 +71,7 @@ void MyMesh::pushPostToClient(ClientInfo *client, PostInfo &post) {
mesh::Utils::sha256((uint8_t *)&client->extra.room.pending_ack, 4, reply_data, len, client->id.pub_key, PUB_KEY_SIZE);
client->extra.room.push_post_timestamp = post.post_timestamp;
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, client->shared_secret, reply_data, len);
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, client->shared_secret, reply_data, len, client->nextAeadNonce());
if (reply) {
if (client->out_path_len == OUT_PATH_UNKNOWN) {
unsigned long delay_millis = 0;
@ -414,6 +414,31 @@ void MyMesh::getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) {
}
}
uint8_t MyMesh::getPeerFlags(int peer_idx) {
int i = matching_peer_indexes[peer_idx];
if (i >= 0 && i < acl.getNumClients())
return acl.getClientByIdx(i)->flags;
return 0;
}
uint16_t MyMesh::getPeerNextAeadNonce(int peer_idx) {
int i = matching_peer_indexes[peer_idx];
if (i >= 0 && i < acl.getNumClients())
return acl.getClientByIdx(i)->nextAeadNonce();
return 0;
}
void MyMesh::onPeerAeadDetected(int peer_idx) {
int i = matching_peer_indexes[peer_idx];
if (i >= 0 && i < acl.getNumClients()) {
auto c = acl.getClientByIdx(i);
if (!(c->flags & CONTACT_FLAG_AEAD)) {
c->flags |= CONTACT_FLAG_AEAD;
getRNG()->random((uint8_t*)&c->aead_nonce, sizeof(c->aead_nonce));
}
}
}
void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx, const uint8_t *secret,
uint8_t *data, size_t len) {
int i = matching_peer_indexes[sender_idx];
@ -507,7 +532,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
// mesh::Utils::sha256((uint8_t *)&expected_ack_crc, 4, temp, 5 + text_len, self_id.pub_key,
// PUB_KEY_SIZE);
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len, client->nextAeadNonce());
if (reply) {
if (client->out_path_len == OUT_PATH_UNKNOWN) {
sendFloodReply(reply, delay_millis + SERVER_RESPONSE_DELAY, packet->getPathHashSize());
@ -564,10 +589,10 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
if (packet->isRouteFlood()) {
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, client->nextAeadNonce());
if (path) sendFloodReply(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
} else {
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
mesh::Packet *reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len, client->nextAeadNonce());
if (reply) {
if (client->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);

3
examples/simple_room_server/MyMesh.h

@ -160,6 +160,9 @@ protected:
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
int searchPeersByHash(const uint8_t* hash) override ;
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
uint8_t getPeerFlags(int peer_idx) override;
uint16_t getPeerNextAeadNonce(int peer_idx) override;
void onPeerAeadDetected(int peer_idx) override;
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
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;
void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override;

35
examples/simple_sensor/SensorMesh.cpp

@ -256,7 +256,7 @@ void SensorMesh::sendAlert(const ClientInfo* c, Trigger* t) {
mesh::Utils::sha256((uint8_t *)&t->expected_acks[t->attempt], 4, data, 5 + text_len, self_id.pub_key, PUB_KEY_SIZE);
t->attempt++;
auto pkt = createDatagram(PAYLOAD_TYPE_TXT_MSG, c->id, c->shared_secret, data, 5 + text_len);
auto pkt = createDatagram(PAYLOAD_TYPE_TXT_MSG, c->id, c->shared_secret, data, 5 + text_len, c->nextAeadNonce());
if (pkt) {
if (c->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
sendDirect(pkt, c->out_path, c->out_path_len);
@ -500,6 +500,31 @@ void SensorMesh::getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) {
}
}
uint8_t SensorMesh::getPeerFlags(int peer_idx) {
int i = matching_peer_indexes[peer_idx];
if (i >= 0 && i < acl.getNumClients())
return acl.getClientByIdx(i)->flags;
return 0;
}
uint16_t SensorMesh::getPeerNextAeadNonce(int peer_idx) {
int i = matching_peer_indexes[peer_idx];
if (i >= 0 && i < acl.getNumClients())
return acl.getClientByIdx(i)->nextAeadNonce();
return 0;
}
void SensorMesh::onPeerAeadDetected(int peer_idx) {
int i = matching_peer_indexes[peer_idx];
if (i >= 0 && i < acl.getNumClients()) {
auto c = acl.getClientByIdx(i);
if (!(c->flags & CONTACT_FLAG_AEAD)) {
c->flags |= CONTACT_FLAG_AEAD;
getRNG()->random((uint8_t*)&c->aead_nonce, sizeof(c->aead_nonce));
}
}
}
void SensorMesh::sendAckTo(const ClientInfo& dest, uint32_t ack_hash, uint8_t path_hash_size) {
if (dest.out_path_len == OUT_PATH_UNKNOWN) {
mesh::Packet* ack = createAck(ack_hash);
@ -540,10 +565,10 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
if (packet->isRouteFlood()) {
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
mesh::Packet* path = createPathReturn(from->id, secret, packet->path, packet->path_len,
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len, from->nextAeadNonce());
if (path) sendFlood(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
} else {
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, from->id, secret, reply_data, reply_len);
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, from->id, secret, reply_data, reply_len, from->nextAeadNonce());
if (reply) {
if (from->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
sendDirect(reply, from->out_path, from->out_path_len, SERVER_RESPONSE_DELAY);
@ -570,7 +595,7 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
if (packet->isRouteFlood()) {
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK
mesh::Packet* path = createPathReturn(from->id, secret, packet->path, packet->path_len,
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4);
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4, from->nextAeadNonce());
if (path) sendFlood(path, TXT_ACK_DELAY, packet->getPathHashSize());
} else {
sendAckTo(*from, ack_hash, packet->getPathHashSize());
@ -598,7 +623,7 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
temp[4] = (TXT_TYPE_CLI_DATA << 2);
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from->id, secret, temp, 5 + text_len);
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from->id, secret, temp, 5 + text_len, from->nextAeadNonce());
if (reply) {
if (from->out_path_len == OUT_PATH_UNKNOWN) {
sendFlood(reply, CLI_REPLY_DELAY_MILLIS, packet->getPathHashSize());

3
examples/simple_sensor/SensorMesh.h

@ -125,6 +125,9 @@ protected:
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
int searchPeersByHash(const uint8_t* hash) override;
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
uint8_t getPeerFlags(int peer_idx) override;
uint16_t getPeerNextAeadNonce(int peer_idx) override;
void onPeerAeadDetected(int peer_idx) override;
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
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;
void onControlDataRecv(mesh::Packet* packet) override;

9
src/helpers/ClientACL.h

@ -15,6 +15,8 @@
struct ClientInfo {
mesh::Identity id;
uint8_t permissions;
uint8_t flags; // transient — includes CONTACT_FLAG_AEAD
mutable uint16_t aead_nonce; // transient — per-peer nonce counter
uint8_t out_path_len;
uint8_t out_path[MAX_PATH_SIZE];
uint8_t shared_secret[PUB_KEY_SIZE];
@ -30,6 +32,13 @@ struct ClientInfo {
} room;
} extra;
uint16_t nextAeadNonce() const {
if (flags & CONTACT_FLAG_AEAD) {
if (++aead_nonce == 0) ++aead_nonce; // skip 0 (means ECB)
return aead_nonce;
}
return 0;
}
bool isAdmin() const { return (permissions & PERM_ACL_ROLE_MASK) == PERM_ACL_ADMIN; }
};

Loading…
Cancel
Save