adafruit / Adafruit_CircuitPython_TinyLoRa

Adafruit Tiny LoRa
MIT License
44 stars 45 forks source link

TTN: Payload is not forwarded to the Application when the payload has more than seven bytes #19

Closed roamingthings closed 5 years ago

roamingthings commented 5 years ago

Seems as if only up to 16 bytes are encrypted: https://github.com/adafruit/Adafruit_CircuitPython_TinyLoRa/blob/980955ce263cfb2554e5e2bd9ed9afa0ebdb7995/adafruit_tinylora/adafruit_tinylora_encryption.py#L86

If the payload is more than 7 bytes which together wit the 9 bytes header is 16 bytes the payload is received by the TTN network but not forwarded to the application.

I will post some more details later.

ladyada commented 5 years ago

not surprising - we've only use mini payloads. if you have a fix we'd super appreciate a PR, we cobbled this together from tinylora and it kinda works but is missing a lot :)

jerryneedell commented 5 years ago

FYI - I have confirmed this -- payload of 10 bytes fails -- I tried this fix, but it did not work:

diff --git a/adafruit_tinylora/adafruit_tinylora_encryption.py b/adafruit_tinylora/adafruit_tinylora_encryption.py
index 357c623..37de395 100755
--- a/adafruit_tinylora/adafruit_tinylora_encryption.py
+++ b/adafruit_tinylora/adafruit_tinylora_encryption.py
@@ -83,7 +83,7 @@ class AES():
         # k = data ptr
         k = 0
         i = 1
-        while i <= 1:
+        while i <= num_blocks:
             block_a[0] = 0x01
             block_a[1] = 0x00
             block_a[2] = 0x00
jerryneedell commented 5 years ago

Was tinylora ever tested with packets > 16 bytes either?

roamingthings commented 5 years ago

Some additional information:

I've attached a simple application that can be used for test purposes (you have to insert your keys, id and region). There are also two screenshots to illustrate whats getting to the gateway and what gets to the application at TTN.

What makes me wonder is that the data becomes "invalid" when the the full LoRa packet reaches 16bytes (two blocks mic). So I think it may have something to do with the encryption or calculation of the mic. application gateway

roamingthings commented 5 years ago
"""Simple program to demonstrate the issue with payloads larger than 7 bytes..
"""
import time
import busio
import digitalio
import board
from adafruit_tinylora.adafruit_tinylora import TTN, TinyLoRa

# Create library object using our bus SPI port for radio
spi = busio.SPI(board.SCK, MISO=board.MISO, MOSI=board.MOSI)

# RFM9x Breakout Pinouts (They are swapped compared to the original application since the tutorial had the pins swapped when it comes to soldering)
cs = digitalio.DigitalInOut(board.D6)
irq = digitalio.DigitalInOut(board.D5)

# TTN Device Address, 4 Bytes, MSB
devaddr = bytearray([0x00, 0x00, 0x00, 0x00])

# TTN Network Key, 16 Bytes, MSB
nwkey = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])

# TTN Application Key, 16 Bytess, MSB
app = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])

ttn_config = TTN(devaddr, nwkey, app, country='EU')
lora = TinyLoRa(spi, cs, irq, ttn_config)

# Data Packet to send to TTN
# 7 bytes of Payload are working
shortPayload = bytearray(7)
# 8 bytes and more won't
longPayload = bytearray(8)

while True:
        print('Sending short packet...')
        lora.send_data(shortPayload, len(shortPayload), lora.frame_counter)
        lora.frame_counter += 1
        print('Sending long packet...')
        lora.send_data(longPayload, len(longPayload), lora.frame_counter)
        lora.frame_counter += 1
        time.sleep(5)
ladyada commented 5 years ago

nope we only tested with very small packets - so this is probably a real bug

jerryneedell commented 5 years ago

OK -- I think I found the problem -- made these fixes

index 357c623..af8e388 100755
--- a/adafruit_tinylora/adafruit_tinylora_encryption.py
+++ b/adafruit_tinylora/adafruit_tinylora_encryption.py
@@ -83,7 +83,7 @@ class AES():
         # k = data ptr
         k = 0
         i = 1
-        while i <= 1:
+        while i <= num_blocks:
             block_a[0] = 0x01
             block_a[1] = 0x00
             block_a[2] = 0x00
@@ -272,11 +272,12 @@ class AES():
             old_data[i] = block_b[i]
         block_counter = 1
         # calculate until n-1 packet blocks
+        k = 0  # ptr
         while block_counter < num_blocks:
+#            k = 0  # ptr
             # copy data into array
-            k = 0  # ptr
             for i in range(16):
-                new_data[k] = lora_packet[i]
+                new_data[i] = lora_packet[k]
                 k += 1
             # XOR new_data with old_data
             self._xor_data(new_data, old_data)
@@ -290,7 +291,8 @@ class AES():
         # perform calculation on last block
         if incomplete_block_size == 0:
             for i in range(16):
-                new_data[i] = lora_packet[i]
+                new_data[i] = lora_packet[k]
+                k += 1
             # xor with key 1
             self._xor_data(new_data, key_k1)
             # xor with old data
@@ -299,10 +301,10 @@ class AES():
             self._aes_encrypt(new_data, self._network_key)
         else:
             # copy the remaining data
-            k = 0  # ptr
+ #           k = 0  # ptr
             for i in range(16):
                 if i < incomplete_block_size:
-                    new_data[k] = lora_packet[i]
+                    new_data[i] = lora_packet[k]
                     k += 1
                 if i == incomplete_block_size:
                     new_data[i] = 0x80

and my 10 byte payload is now getting to my appiicatiion

jerryneedell commented 5 years ago

I'll do a little more testing for larger packets then put in a PR

roamingthings commented 5 years ago

I can confirm that this patch works with a 15 byte payload

Great job @jerryneedell

roamingthings commented 5 years ago

Successfully tested with 32bytes payload

jerryneedell commented 5 years ago

Great -- I also tested with a 30 byte payload and verified that it still works with a 6 byte payload. I'll create a PR later this evening or tomorrow.

ladyada commented 5 years ago

amazing! !!! thank you so much :)