Skip to content

Commit 4ed0db4

Browse files
committed
Fix AEAD-4 assoc data mismatch — route type bits set after encryption
The header's route type bits (PH_ROUTE_MASK) are zero when createDatagram/createPathReturn encrypt with AEAD, but get changed to ROUTE_TYPE_FLOOD (1) or ROUTE_TYPE_DIRECT (2) by sendFlood/sendDirect afterwards. The receiver builds assoc from the received header (with route bits set), so the tag check always fails and every AEAD packet is silently dropped. Mask out route type bits in assoc data on all 5 encrypt/decrypt sites. Also track AEAD decode success to enable peer capability auto-detection.
1 parent f3849b6 commit 4ed0db4

2 files changed

Lines changed: 15 additions & 7 deletions

File tree

src/Mesh.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,23 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
151151

152152
// Try-both decode: AEAD-first for peers known to support it (avoids 1/65536
153153
// ECB false-positive on AEAD packets), ECB-first for unknown/legacy peers.
154-
uint8_t assoc[3] = { pkt->header, dest_hash, src_hash };
154+
// Mask out route type bits — they are set after encryption and vary per hop.
155+
uint8_t assoc[3] = { (uint8_t)(pkt->header & ~PH_ROUTE_MASK), dest_hash, src_hash };
155156
int len;
157+
bool decoded_aead = false;
156158
if (getPeerFlags(j) & CONTACT_FLAG_AEAD) {
157159
len = Utils::aeadDecrypt(secret, data, macAndData, macAndDataLen, assoc, 3, dest_hash, src_hash);
158-
if (len <= 0) len = Utils::MACThenDecrypt(secret, data, macAndData, macAndDataLen);
160+
if (len > 0) decoded_aead = true;
161+
else len = Utils::MACThenDecrypt(secret, data, macAndData, macAndDataLen);
159162
} else {
160163
len = Utils::MACThenDecrypt(secret, data, macAndData, macAndDataLen);
161-
if (len <= 0) len = Utils::aeadDecrypt(secret, data, macAndData, macAndDataLen, assoc, 3, dest_hash, src_hash);
164+
if (len <= 0) {
165+
len = Utils::aeadDecrypt(secret, data, macAndData, macAndDataLen, assoc, 3, dest_hash, src_hash);
166+
if (len > 0) decoded_aead = true;
167+
}
162168
}
163169
if (len > 0) { // success!
170+
if (decoded_aead) onPeerAeadDetected(j);
164171
if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH) {
165172
int k = 0;
166173
uint8_t path_len = data[k++];
@@ -216,7 +223,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
216223
// Phase 2 MUST swap to AEAD-first (see peer message comment above).
217224
int len = Utils::MACThenDecrypt(secret, data, macAndData, macAndDataLen);
218225
if (len <= 0) {
219-
uint8_t assoc[2] = { pkt->header, dest_hash };
226+
uint8_t assoc[2] = { (uint8_t)(pkt->header & ~PH_ROUTE_MASK), dest_hash };
220227
len = Utils::aeadDecrypt(secret, data, macAndData, macAndDataLen, assoc, 2, dest_hash, 0);
221228
}
222229
if (len > 0) { // success!
@@ -252,7 +259,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
252259
// worthwhile for public/hashtag channels where the PSK is already widely known.
253260
int len = Utils::MACThenDecrypt(channels[j].secret, data, macAndData, macAndDataLen);
254261
if (len <= 0) {
255-
uint8_t assoc[2] = { pkt->header, channel_hash };
262+
uint8_t assoc[2] = { (uint8_t)(pkt->header & ~PH_ROUTE_MASK), channel_hash };
256263
len = Utils::aeadDecrypt(channels[j].secret, data, macAndData, macAndDataLen, assoc, 2, channel_hash, 0);
257264
}
258265
if (len > 0) { // success!
@@ -491,7 +498,7 @@ Packet* Mesh::createPathReturn(const uint8_t* dest_hash, const uint8_t* secret,
491498
if (aead_nonce) {
492499
uint8_t dh = packet->payload[0];
493500
uint8_t sh = packet->payload[1];
494-
uint8_t assoc[3] = { packet->header, dh, sh };
501+
uint8_t assoc[3] = { (uint8_t)(packet->header & ~PH_ROUTE_MASK), dh, sh };
495502
len += Utils::aeadEncrypt(secret, &packet->payload[len], data, data_len, assoc, 3, aead_nonce, dh, sh);
496503
} else {
497504
len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len);
@@ -526,7 +533,7 @@ Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t*
526533
if (aead_nonce) {
527534
uint8_t dest_hash = packet->payload[0];
528535
uint8_t src_hash = packet->payload[1];
529-
uint8_t assoc[3] = { packet->header, dest_hash, src_hash };
536+
uint8_t assoc[3] = { (uint8_t)(packet->header & ~PH_ROUTE_MASK), dest_hash, src_hash };
530537
len += Utils::aeadEncrypt(secret, &packet->payload[len], data, data_len, assoc, 3, aead_nonce, dest_hash, src_hash);
531538
} else {
532539
len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len);

src/Mesh.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class Mesh : public Dispatcher {
8484
virtual void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) { }
8585
virtual uint8_t getPeerFlags(int peer_idx) { return 0; }
8686
virtual uint16_t getPeerNextAeadNonce(int peer_idx) { return 0; }
87+
virtual void onPeerAeadDetected(int peer_idx) { }
8788

8889
/**
8990
* \brief A (now decrypted) data packet has been received (by a known peer).

0 commit comments

Comments
 (0)