LoRa-Workshop/micropython/uLoRaWAN/JoinAcceptPayload.py

101 lines
2.7 KiB
Python

#
# frm_payload: appnonce(3) netid(3) devaddr(4) dlsettings(1) rxdelay(1) cflist(0..16)
#
from .MalformedPacketException import MalformedPacketException
from .AES_CMAC import AES_CMAC
import ucryptolib
MODE_ECB = 1
class JoinAcceptPayload:
def read(self, payload):
if len(payload) < 12:
raise MalformedPacketException("Invalid join accept")
self.encrypted_payload = payload
def create(self, args):
pass
def length(self):
return len(self.encrypted_payload)
def to_raw(self):
return self.encrypted_payload
def to_clear_raw(self):
return self.payload
def get_appnonce(self):
return self.appnonce
def get_netid(self):
return self.netid
def get_devaddr(self):
return list(map(int, reversed(self.devaddr)))
def get_dlsettings(self):
return self.dlsettings
def get_rxdelay(self):
return self.rxdelay
def get_cflist(self):
return self.cflist
def compute_mic(self, key, direction, mhdr):
mic = []
mic += [mhdr.to_raw()]
mic += self.to_clear_raw()
cmac = AES_CMAC()
computed_mic = cmac.encode(bytes(key), bytes(mic))[:4]
return list(map(int, computed_mic))
def decrypt_payload(self, key, direction, mic):
a = []
a += self.encrypted_payload
a += mic
cipher = ucryptolib.aes(bytearray(key), MODE_ECB)
self.payload = cipher.encrypt(bytes(a))[:-4]
self.appnonce = self.payload[:3]
self.netid = self.payload[3:6]
self.devaddr = self.payload[6:10]
self.dlsettings = self.payload[10]
self.rxdelay = self.payload[11]
self.cflist = None
if self.payload[12:]:
self.cflist = self.payload[12:]
return list(map(int, self.payload))
def encrypt_payload(self, key, direction, mhdr):
a = []
a += self.to_clear_raw()
a += self.compute_mic(key, direction, mhdr)
cipher = ucryptolib.aes(bytearray(key), MODE_ECB)
return list(map(int, cipher.decrypt(bytes(a))))
def derive_nwskey(self, key, devnonce):
a = [0x01]
a += self.get_appnonce()
a += self.get_netid()
a += devnonce
a += [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
cipher = ucryptolib.aes(bytearray(key), MODE_ECB)
return list(map(int, cipher.encrypt(bytes(a))))
def derive_appskey(self, key, devnonce):
a = [0x02]
a += self.get_appnonce()
a += self.get_netid()
a += devnonce
a += [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
cipher = ucryptolib.aes(bytearray(key), MODE_ECB)
return list(map(int, cipher.encrypt(bytes(a))))