Skip to content

Commit 7637e64

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 6526793 commit 7637e64

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
@@ -156,16 +156,23 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
156156

157157
// Try-both decode: AEAD-first for peers known to support it (avoids 1/65536
158158
// ECB false-positive on AEAD packets), ECB-first for unknown/legacy peers.
159-
uint8_t assoc[3] = { pkt->header, dest_hash, src_hash };
159+
// Mask out route type bits — they are set after encryption and vary per hop.
160+
uint8_t assoc[3] = { (uint8_t)(pkt->header & ~PH_ROUTE_MASK), dest_hash, src_hash };
160161
int len;
162+
bool decoded_aead = false;
161163
if (getPeerFlags(j) & CONTACT_FLAG_AEAD) {
162164
len = Utils::aeadDecrypt(secret, data, macAndData, macAndDataLen, assoc, 3, dest_hash, src_hash);
163-
if (len <= 0) len = Utils::MACThenDecrypt(secret, data, macAndData, macAndDataLen);
165+
if (len > 0) decoded_aead = true;
166+
else len = Utils::MACThenDecrypt(secret, data, macAndData, macAndDataLen);
164167
} else {
165168
len = Utils::MACThenDecrypt(secret, data, macAndData, macAndDataLen);
166-
if (len <= 0) len = Utils::aeadDecrypt(secret, data, macAndData, macAndDataLen, assoc, 3, dest_hash, src_hash);
169+
if (len <= 0) {
170+
len = Utils::aeadDecrypt(secret, data, macAndData, macAndDataLen, assoc, 3, dest_hash, src_hash);
171+
if (len > 0) decoded_aead = true;
172+
}
167173
}
168174
if (len > 0) { // success!
175+
if (decoded_aead) onPeerAeadDetected(j);
169176
if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH) {
170177
int k = 0;
171178
uint8_t path_len = data[k++];
@@ -219,7 +226,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
219226
// Phase 2 MUST swap to AEAD-first (see peer message comment above).
220227
int len = Utils::MACThenDecrypt(secret, data, macAndData, macAndDataLen);
221228
if (len <= 0) {
222-
uint8_t assoc[2] = { pkt->header, dest_hash };
229+
uint8_t assoc[2] = { (uint8_t)(pkt->header & ~PH_ROUTE_MASK), dest_hash };
223230
len = Utils::aeadDecrypt(secret, data, macAndData, macAndDataLen, assoc, 2, dest_hash, 0);
224231
}
225232
if (len > 0) { // success!
@@ -255,7 +262,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
255262
// worthwhile for public/hashtag channels where the PSK is already widely known.
256263
int len = Utils::MACThenDecrypt(channels[j].secret, data, macAndData, macAndDataLen);
257264
if (len <= 0) {
258-
uint8_t assoc[2] = { pkt->header, channel_hash };
265+
uint8_t assoc[2] = { (uint8_t)(pkt->header & ~PH_ROUTE_MASK), channel_hash };
259266
len = Utils::aeadDecrypt(channels[j].secret, data, macAndData, macAndDataLen, assoc, 2, channel_hash, 0);
260267
}
261268
if (len > 0) { // success!
@@ -498,7 +505,7 @@ Packet* Mesh::createPathReturn(const uint8_t* dest_hash, const uint8_t* secret,
498505
if (aead_nonce) {
499506
uint8_t dh = packet->payload[0];
500507
uint8_t sh = packet->payload[1];
501-
uint8_t assoc[3] = { packet->header, dh, sh };
508+
uint8_t assoc[3] = { (uint8_t)(packet->header & ~PH_ROUTE_MASK), dh, sh };
502509
len += Utils::aeadEncrypt(secret, &packet->payload[len], data, data_len, assoc, 3, aead_nonce, dh, sh);
503510
} else {
504511
len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len);
@@ -533,7 +540,7 @@ Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t*
533540
if (aead_nonce) {
534541
uint8_t dest_hash = packet->payload[0];
535542
uint8_t src_hash = packet->payload[1];
536-
uint8_t assoc[3] = { packet->header, dest_hash, src_hash };
543+
uint8_t assoc[3] = { (uint8_t)(packet->header & ~PH_ROUTE_MASK), dest_hash, src_hash };
537544
len += Utils::aeadEncrypt(secret, &packet->payload[len], data, data_len, assoc, 3, aead_nonce, dest_hash, src_hash);
538545
} else {
539546
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)