def format_jacc(self, pdu: bytes, info: List[str]) -> None: n = len(pdu) if n != 17 and n != 33: info.append(f'-- invalid length {n}, expected 17 or 23') return if self.sm: for s in self.sm.all(): ppdu = bytes(pdu[0:1] + lc.crypto.encrypt(s['nwkkey'], pdu[1:])) mic = lm.get_mic(ppdu) cmic = lc.crypto.calcMicJoin(s['nwkkey'], ppdu) if mic == cmic: appnonce = struct.unpack_from("<I", ppdu, 1)[0] & 0xFFFFFF netid = struct.unpack_from("<I", ppdu, 1 + 3)[0] & 0xFFFFFF devaddr, dlset, rxdly = struct.unpack_from( "<iBB", ppdu, 1 + 3 + 3) cflist = None if n == 17 else ppdu[-20:-4] info.append(f'appnonce={appnonce}') info.append(f'netid={netid}') info.append(f'addr=0x{devaddr:08x}') dls = lm.DLSettings.unpack(dlset) info.append( f'dlset=RX1DRoff:{dls[0]},RX2DR:{dls[1]},OptNeg:{dls[2]}' ) info.append(f'rxdly={rxdly}') info.append(f'mic={mic}:ok') if cflist: info.append('cflist=' + self.format_cflist(cflist)) break else: info.append('-- unknown session')
def format_da(self, pdu: bytes, info: List[str]) -> None: n = len(pdu) if n < 8 + 4: info.append(f'-- invalid length {n}, expected at least 12') return mhdr, addr, fctrl, seqno = struct.unpack_from('<BiBH', pdu) dndir = int(bool(mhdr & lm.MHdr.DNFLAG)) info.append(f'addr=0x{addr:08x}') info.append('fctrl=' + self.format_fctrl(fctrl, not (mhdr & lm.MHdr.DNFLAG))) info.append(f'fcnt={seqno}') fol = fctrl & lm.FCtrl.OPTLEN if fol: if n < 8 + 4 + fol: info.append( f'-- invalid length {n}, expected at least {8+4+fol}') return info.append('fopts=' + self.format_opts(pdu[8:8 + fol], dndir)) pl = pdu[8 + fol:-4] mic = lm.get_mic(pdu) if pl: info.append(f'fport={pl[0]}') info.append(f'plen={len(pl)-1}') if self.sm: sessions = self.sm.get(addr) for s in sessions: fcnt = seqno # TODO - extend seqno to 32 bit from session context cmic = lc.crypto.calcMic(s['nwkskey'], addr, fcnt, dndir, pdu) if cmic == mic: micstatus = ':ok' if pl: ppl = lc.crypto.cipher( s['appskey'] if pl[0] else s['nwkskey'], addr, seqno, dndir, pl[1:]) info.append(f'data={ppl.hex()}') if pl[0] == 0: info.append(self.format_opts(ppl, dndir)) break else: micstatus = ':?' else: micstatus = '' info.append(f'mic={mic}{micstatus}')