Example #1
0
    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')
Example #2
0
    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}')