Skip to content

Commit 10b4156

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 03ca9d5 commit 10b4156

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!
@@ -494,7 +501,7 @@ Packet* Mesh::createPathReturn(const uint8_t* dest_hash, const uint8_t* secret,
494501
if (aead_nonce) {
495502
uint8_t dh = packet->payload[0];
496503
uint8_t sh = packet->payload[1];
497-
uint8_t assoc[3] = { packet->header, dh, sh };
504+
uint8_t assoc[3] = { (uint8_t)(packet->header & ~PH_ROUTE_MASK), dh, sh };
498505
len += Utils::aeadEncrypt(secret, &packet->payload[len], data, data_len, assoc, 3, aead_nonce, dh, sh);
499506
} else {
500507
len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len);
@@ -529,7 +536,7 @@ Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t*
529536
if (aead_nonce) {
530537
uint8_t dest_hash = packet->payload[0];
531538
uint8_t src_hash = packet->payload[1];
532-
uint8_t assoc[3] = { packet->header, dest_hash, src_hash };
539+
uint8_t assoc[3] = { (uint8_t)(packet->header & ~PH_ROUTE_MASK), dest_hash, src_hash };
533540
len += Utils::aeadEncrypt(secret, &packet->payload[len], data, data_len, assoc, 3, aead_nonce, dest_hash, src_hash);
534541
} else {
535542
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)