Workaround LoRa link delivery truncation for large LXMF messages

Link delivery adds ~64 bytes of overhead (dest_hash + Token IV/HMAC/padding)
which can push encrypted payloads past the 255-byte LoRa MTU. SX1262::write()
silently truncates, corrupting the HMAC and failing decryption on the receiver.

Band-aid: cap link delivery plaintext at 180 bytes, falling back to
opportunistic delivery for larger messages. Long-term fix needed: negotiate
link MTU based on interface HW_MTU, or implement Resource-based multi-packet
transfer for oversized payloads.
This commit is contained in:
DeFiDude
2026-03-21 14:00:12 -06:00
parent 6f8e53c060
commit 4a7b1935d5
2 changed files with 14 additions and 1 deletions
+3
View File
@@ -367,6 +367,9 @@ size_t SX1262::write(uint8_t byte) { return write(&byte, 1); }
size_t SX1262::write(const uint8_t* buffer, size_t size) {
if ((_payloadLength + size) > MAX_PACKET_SIZE) {
Serial.printf("[SX1262] WARNING: write() truncating %d->%d bytes (payload=%d max=%d)\n",
(int)size, (int)(MAX_PACKET_SIZE - _payloadLength),
(int)_payloadLength, (int)MAX_PACKET_SIZE);
size = MAX_PACKET_SIZE - _payloadLength;
}
writeBuffer(buffer, size);
+11 -1
View File
@@ -152,12 +152,22 @@ bool LXMFManager::sendDirect(LXMFMessage& msg) {
linkPayload.insert(linkPayload.end(), msg.destHash.data(), msg.destHash.data() + 16);
linkPayload.insert(linkPayload.end(), payload.begin(), payload.end());
RNS::Bytes linkBytes(linkPayload.data(), linkPayload.size());
if (linkBytes.size() <= RNS::Type::Reticulum::MDU) {
// Token encryption adds ~48 bytes (IV:16 + HMAC:32 + AES padding).
// LoRa packets are max 255 bytes (1 header + 19 Reticulum H1 + encrypted).
// If the plaintext is too large, Token output exceeds LoRa MTU and
// SX1262::write() silently truncates, corrupting the HMAC.
// Cap link delivery to 180 bytes to stay safely under the limit.
// Larger messages fall through to opportunistic delivery.
static constexpr size_t LORA_SAFE_LINK_PAYLOAD = 180;
if (linkBytes.size() <= LORA_SAFE_LINK_PAYLOAD) {
Serial.printf("[LXMF] sending via link: %d bytes to %s\n",
(int)linkBytes.size(), msg.destHash.toHex().substr(0, 8).c_str());
RNS::Packet packet(_outLink, linkBytes);
RNS::PacketReceipt receipt = packet.send();
if (receipt) { sent = true; }
} else {
Serial.printf("[LXMF] link payload too large for LoRa (%d > %d), using opportunistic\n",
(int)linkBytes.size(), (int)LORA_SAFE_LINK_PAYLOAD);
}
}