1% Regression tests for ISOTP packet definitions 2 3+ Configuration 4~ conf 5 6= Import isotp 7 8conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False} 9 10load_layer("can", globals_dict=globals()) 11load_contrib("isotp", globals_dict=globals()) 12from scapy.contrib.isotp.isotp_scanner import get_isotp_packet 13 14= Define helpers 15 16# hexadecimal to bytes convenience function 17dhex = bytes.fromhex 18 19 20+ ISOTP packet check 21 22= Creation of an empty ISOTP packet 23p = ISOTP() 24assert p.data == b"" 25assert p.tx_id is None and p.rx_id is None and p.ext_address is None and p.rx_ext_address is None 26assert bytes(p) == b"" 27 28= Creation of a simple ISOTP packet with tx_id 29p = ISOTP(b"eee", tx_id=0x241) 30assert p.tx_id == 0x241 31assert p.data == b"eee" 32assert bytes(p) == b"eee" 33 34= Creation of a simple ISOTP packet with ext_address 35p = ISOTP(b"eee", ext_address=0x41) 36assert p.ext_address == 0x41 37assert p.data == b"eee" 38assert bytes(p) == b"eee" 39 40= Creation of a simple ISOTP packet with rx_id 41p = ISOTP(b"eee", rx_id=0x241) 42assert p.rx_id == 0x241 43assert p.data == b"eee" 44assert bytes(p) == b"eee" 45 46= Creation of a simple ISOTP packet with rx_ext_address 47p = ISOTP(b"eee", rx_ext_address=0x41) 48assert p.rx_ext_address == 0x41 49assert p.data == b"eee" 50assert bytes(p) == b"eee" 51 52= Creation of a simple ISOTP packet with tx_id, rx_id, ext_address, rx_ext_address 53p = ISOTP(b"eee", tx_id=1, rx_id=2, ext_address=3, rx_ext_address=4) 54assert p.rx_id == 2 55assert p.rx_ext_address == 4 56assert p.tx_id == 1 57assert p.ext_address == 3 58assert p.data == b"eee" 59assert bytes(p) == b"eee" 60 61= ISOTP answers test 62p = ISOTP() 63r = ISOTP() 64assert p.data == b"" 65assert p.answers(r) 66assert not p.answers(Raw()) 67 68 69= Creation of a simple ISOTP packet with tx_id validation error 70ex = False 71try: 72 p = ISOTP(b"eee", tx_id=0x1000000000, rx_id=2, ext_address=3, rx_ext_address=4) 73except Scapy_Exception: 74 ex = True 75 76assert ex 77 78= Creation of a simple ISOTP packet with rx_id validation error 79ex = False 80try: 81 p = ISOTP(b"eee", tx_id=0x10, rx_id=0x20000000000, ext_address=3, rx_ext_address=4) 82except Scapy_Exception: 83 ex = True 84 85assert ex 86 87= Creation of a simple ISOTP packet with ext_address validation error 88ex = False 89try: 90 p = ISOTP(b"eee", tx_id=0x10, rx_id=2, ext_address=3000, rx_ext_address=4) 91except Scapy_Exception: 92 ex = True 93 94assert ex 95 96 97= Creation of a simple ISOTP packet with rx_ext_address validation error 98ex = False 99try: 100 p = ISOTP(b"eee", tx_id=0x10, rx_id=2, ext_address=30, rx_ext_address=400) 101except Scapy_Exception: 102 ex = True 103 104assert ex 105 106+ ISOTPFrame related checks 107 108= Build a packet with extended addressing 109pkt = CAN(identifier=0x123, data=b'\x42\x10\xff\xde\xea\xdd\xaa\xaa') 110isotpex = ISOTPHeaderEA(bytes(pkt)) 111assert isotpex.type == 1 112assert isotpex.message_size == 0xff 113assert isotpex.extended_address == 0x42 114assert isotpex.identifier == 0x123 115assert isotpex.length == 8 116 117= Build a packet with normal addressing 118pkt = CAN(identifier=0x123, data=b'\x10\xff\xde\xea\xdd\xaa\xaa') 119isotpno = ISOTPHeader(bytes(pkt)) 120assert isotpno.type == 1 121assert isotpno.message_size == 0xff 122assert isotpno.identifier == 0x123 123assert isotpno.length == 7 124 125= Compare both isotp payloads 126assert isotpno.data == isotpex.data 127assert isotpno.message_size == isotpex.message_size 128 129= Dissect multiple packets 130frames = \ 131 [b'\x00\x00\x00\x00\x08\x00\x00\x00\x10(\xde\xad\xbe\xef\xde\xad', 132 b'\x00\x00\x00\x00\x08\x00\x00\x00!\xbe\xef\xde\xad\xbe\xef\xde', 133 b'\x00\x00\x00\x00\x08\x00\x00\x00"\xad\xbe\xef\xde\xad\xbe\xef', 134 b'\x00\x00\x00\x00\x08\x00\x00\x00#\xde\xad\xbe\xef\xde\xad\xbe', 135 b'\x00\x00\x00\x00\x08\x00\x00\x00$\xef\xde\xad\xbe\xef\xde\xad', 136 b'\x00\x00\x00\x00\x07\x00\x00\x00%\xbe\xef\xde\xad\xbe\xef'] 137 138isotpframes = [ISOTPHeader(x) for x in frames] 139 140assert isotpframes[0].type == 1 141assert isotpframes[0].message_size == 40 142assert isotpframes[0].length == 8 143assert isotpframes[1].type == 2 144assert isotpframes[1].index == 1 145assert isotpframes[1].length == 8 146assert isotpframes[2].type == 2 147assert isotpframes[2].index == 2 148assert isotpframes[2].length == 8 149assert isotpframes[3].type == 2 150assert isotpframes[3].index == 3 151assert isotpframes[3].length == 8 152assert isotpframes[4].type == 2 153assert isotpframes[4].index == 4 154assert isotpframes[4].length == 8 155assert isotpframes[5].type == 2 156assert isotpframes[5].index == 5 157assert isotpframes[5].length == 7 158 159= Build SF frame with constructor, check for correct length assignments 160p = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_SF(data=b'\xad\xbe\xad\xff'))) 161assert p.length == 5 162assert p.message_size == 4 163assert len(p.data) == 4 164assert p.data == b'\xad\xbe\xad\xff' 165assert p.type == 0 166assert p.identifier == 0 167 168= Build SF frame EA with constructor, check for correct length assignments 169p = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_SF(data=b'\xad\xbe\xad\xff'))) 170assert p.extended_address == 0 171assert p.length == 6 172assert p.message_size == 4 173assert len(p.data) == 4 174assert p.data == b'\xad\xbe\xad\xff' 175assert p.type == 0 176assert p.identifier == 0 177 178= Build FF frame with constructor, check for correct length assignments 179p = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_FF(message_size=10, data=b'\xad\xbe\xad\xff'))) 180assert p.length == 6 181assert p.message_size == 10 182assert len(p.data) == 4 183assert p.data == b'\xad\xbe\xad\xff' 184assert p.type == 1 185assert p.identifier == 0 186 187= Build FF frame EA with constructor, check for correct length assignments 188p = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_FF(message_size=10, data=b'\xad\xbe\xad\xff'))) 189assert p.extended_address == 0 190assert p.length == 7 191assert p.message_size == 10 192assert len(p.data) == 4 193assert p.data == b'\xad\xbe\xad\xff' 194assert p.type == 1 195assert p.identifier == 0 196 197= Build FF frame EA, extended size, with constructor, check for correct length assignments 198p = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_FF_FD(message_size=2000, data=b'\xad'))) 199assert p.extended_address == 0 200assert p.length == 8 201assert p.message_size == 2000 202assert len(p.data) == 1 203assert p.data == b'\xad' 204assert p.type == 1 205assert p.identifier == 0 206 207= Build FF frame, extended size, with constructor, check for correct length assignments 208p = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_FF_FD(message_size=2000, data=b'\xad'))) 209assert p.length == 7 210assert p.message_size == 2000 211assert len(p.data) == 1 212assert p.data == b'\xad' 213assert p.type == 1 214assert p.identifier == 0 215 216= Build CF frame with constructor, check for correct length assignments 217p = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_CF(data=b'\xad'))) 218assert p.length == 2 219assert p.index == 0 220assert len(p.data) == 1 221assert p.data == b'\xad' 222assert p.type == 2 223assert p.identifier == 0 224 225= Build CF frame EA with constructor, check for correct length assignments 226p = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_CF(data=b'\xad'))) 227assert p.length == 3 228assert p.index == 0 229assert len(p.data) == 1 230assert p.data == b'\xad' 231assert p.type == 2 232assert p.identifier == 0 233 234= Build FC frame EA with constructor, check for correct length assignments 235p = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_FC())) 236assert p.length == 4 237assert p.block_size == 0 238assert p.separation_time == 0 239assert p.type == 3 240assert p.identifier == 0 241 242= Build FC frame with constructor, check for correct length assignments 243p = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_FC())) 244assert p.length == 3 245assert p.block_size == 0 246assert p.separation_time == 0 247assert p.type == 3 248assert p.identifier == 0 249 250= Construct some single frames 251p = ISOTPHeader(identifier=0x123, length=5)/ISOTP_SF(message_size=4, data=b'abcd') 252assert p.length == 5 253assert p.identifier == 0x123 254assert p.type == 0 255assert p.message_size == 4 256assert p.data == b'abcd' 257 258= Construct some single frames EA 259p = ISOTPHeaderEA(identifier=0x123, length=6, extended_address=42)/ISOTP_SF(message_size=4, data=b'abcd') 260assert p.length == 6 261assert p.extended_address == 42 262assert p.identifier == 0x123 263assert p.type == 0 264assert p.message_size == 4 265assert p.data == b'abcd' 266 267= Construct ISOTP_packet with extended can frame 268p = get_isotp_packet(identifier=0x1234, extended=False, extended_can_id=True) 269print(p) 270assert (p.identifier == 0x1234) 271assert (p.flags == "extended") 272 273= Construct ISOTPEA_Packet with extended can frame 274p = get_isotp_packet(identifier=0x1234, extended=True, extended_can_id=True) 275print(p) 276assert (p.identifier == 0x1234) 277assert (p.flags == "extended") 278 279+ ISOTP fragment and defragment checks 280 281= Fragment an empty ISOTP message 282fragments = ISOTP().fragment() 283assert len(fragments) == 1 284assert fragments[0].data == b"\0" 285 286= Fragment another empty ISOTP message 287fragments = ISOTP(b"").fragment() 288assert len(fragments) == 1 289assert fragments[0].data == b"\0" 290 291= Fragment a 4 bytes long ISOTP message 292fragments = ISOTP(b"data", tx_id=0x241).fragment() 293assert len(fragments) == 1 294assert isinstance(fragments[0], CAN) 295fragment = CAN(bytes(fragments[0])) 296assert fragment.data == b"\x04data" 297assert fragment.flags == 0 298assert fragment.length == 5 299assert fragment.reserved == 0 300 301= Fragment a 4 bytes long ISOTP message extended 302fragments = ISOTP(b"data", rx_id=0x1fff0000).fragment() 303assert len(fragments) == 1 304assert isinstance(fragments[0], CAN) 305fragment = CAN(bytes(fragments[0])) 306assert fragment.data == b"\x04data" 307assert fragment.length == 5 308assert fragment.reserved == 0 309assert fragment.flags == 4 310 311= Fragment a 8 bytes long ISOTP message extended 312fragments = ISOTP(b"datadata", rx_id=0x1fff0000).fragment() 313assert len(fragments) == 2 314assert isinstance(fragments[0], CAN) 315fragment = CAN(bytes(fragments[0])) 316assert fragment.data == b"\x10\x08datada" 317assert fragment.length == 8 318assert fragment.reserved == 0 319assert fragment.flags == 4 320fragment = CAN(bytes(fragments[1])) 321assert fragment.data == b"\x21ta" 322assert fragment.length == 3 323assert fragment.reserved == 0 324assert fragment.flags == 4 325 326= Fragment a 7 bytes long ISOTP message 327fragments = ISOTP(b"abcdefg").fragment() 328assert len(fragments) == 1 329assert fragments[0].data == b"\x07abcdefg" 330 331= Fragment a 8 bytes long ISOTP message 332fragments = ISOTP(b"abcdefgh").fragment() 333assert len(fragments) == 2 334assert fragments[0].data == b"\x10\x08abcdef" 335assert fragments[1].data == b"\x21gh" 336 337= Fragment an ISOTP message with extended addressing 338isotp = ISOTP(b"abcdef", rx_ext_address=ord('A')) 339fragments = isotp.fragment() 340assert len(fragments) == 1 341assert fragments[0].data == b"A\x06abcdef" 342 343= Fragment a 7 bytes ISOTP message with destination identifier 344isotp = ISOTP(b"abcdefg", rx_id=0x64f) 345fragments = isotp.fragment() 346assert len(fragments) == 1 347assert fragments[0].data == b"\x07abcdefg" 348assert fragments[0].identifier == 0x64f 349 350= Fragment a 16 bytes ISOTP message with extended addressing 351isotp = ISOTP(b"abcdefghijklmnop", rx_id=0x64f, rx_ext_address=ord('A')) 352fragments = isotp.fragment() 353assert len(fragments) == 3 354assert fragments[0].data == b"A\x10\x10abcde" 355assert fragments[1].data == b"A\x21fghijk" 356assert fragments[2].data == b"A\x22lmnop" 357assert fragments[0].identifier == 0x64f 358assert fragments[1].identifier == 0x64f 359assert fragments[2].identifier == 0x64f 360 361= Fragment a huge ISOTP message, 4997 bytes long 362data = b"T" * 4997 363isotp = ISOTP(b"T" * 4997, rx_id=0x345) 364fragments = isotp.fragment() 365assert len(fragments) == 715 366assert fragments[0].data == dhex("10 00 00 00 13 85") + b"TT" 367assert fragments[1].data == b"\x21TTTTTTT" 368assert fragments[-2].data == b"\x29TTTTTTT" 369assert fragments[-1].data == b"\x2ATTTT" 370 371= Defragment a single-frame ISOTP message 372fragments = [CAN(identifier=0x641, data=b"\x04test")] 373isotp = ISOTP.defragment(fragments) 374isotp.show() 375assert isotp.data == b"test" 376assert isotp.rx_id == 0x641 377 378= Defragment non ISOTP message 379fragments = [CAN(identifier=0x641, data=b"\xa4test")] 380isotp = ISOTP.defragment(fragments) 381assert isotp is None 382 383= Defragment ISOTP message with warning 384fragments = [CAN(identifier=0x641, data=b"\x04test"), CAN(identifier=0x642, data=b"\x04test")] 385isotp = ISOTP.defragment(fragments) 386assert isotp.data == b"test" 387assert isotp.rx_id == 0x641 388 389= Defragment exception 390fragments = [] 391ex = False 392try: 393 isotp = ISOTP.defragment(fragments) 394 isotp.show() 395except Scapy_Exception: 396 ex = True 397 398assert ex 399 400= Defragment an ISOTP message composed of multiple CAN frames 401fragments = [ 402 CAN(identifier=0x641, data=dhex("41 10 10 61 62 63 64 65")), 403 CAN(identifier=0x641, data=dhex("41 21 66 67 68 69 6A 6B")), 404 CAN(identifier=0x641, data=dhex("41 22 6C 6D 6E 6F 70 00")) 405] 406isotp = ISOTP.defragment(fragments) 407isotp.show() 408assert isotp.data == dhex("61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70") 409assert isotp.rx_id == 0x641 410assert isotp.rx_ext_address == 0x41 411 412= Check if fragmenting a message and defragmenting it back yields the original message 413isotp1 = ISOTP(b"abcdef", rx_ext_address=ord('A')) 414fragments = isotp1.fragment() 415isotp2 = ISOTP.defragment(fragments) 416isotp2.show() 417assert isotp1 == isotp2 418 419isotp1 = ISOTP(b"abcdefghijklmnop") 420fragments = isotp1.fragment() 421isotp2 = ISOTP.defragment(fragments) 422isotp2.show() 423assert isotp1 == isotp2 424 425isotp1 = ISOTP(b"abcdefghijklmnop", rx_ext_address=ord('A')) 426fragments = isotp1.fragment() 427isotp2 = ISOTP.defragment(fragments) 428isotp2.show() 429assert isotp1 == isotp2 430 431isotp1 = ISOTP(b"T"*5000, rx_ext_address=ord('A')) 432fragments = isotp1.fragment() 433isotp2 = ISOTP.defragment(fragments) 434isotp2.show() 435assert isotp1 == isotp2 436 437= Defragment an ambiguous CAN frame 438fragments = [CAN(identifier=0x641, data=dhex("02 01 AA"))] 439isotp = ISOTP.defragment(fragments, False) 440isotp.show() 441assert isotp.data == dhex("01 AA") 442assert isotp.rx_ext_address == None 443isotpex = ISOTP.defragment(fragments, True) 444isotpex.show() 445assert isotpex.data == dhex("AA") 446assert isotpex.rx_ext_address == 0x02 447 448= Build ISOTP_FF_FD 449 450pkt = ISOTP_FF_FD(message_size=0xffff0000) 451assert bytes(pkt) == bytes.fromhex("1000ffff0000") 452 453= Build ISOTP_SF_FD 454 455pkt = ISOTP_SF_FD(message_size=0xff) 456assert bytes(pkt) == bytes.fromhex("00ff") 457 458= Build ISOTP_FF_FD 2 459 460pkt = ISOTPHeaderEA_FD(identifier=0x7ff, extended_address=0xaf)/ISOTP_FF_FD(message_size=0xffff0000) 461assert bytes(pkt) == bytes.fromhex("000007ff 07 04 00 00 af 1000ffff0000") 462 463= Build ISOTP_SF_FD 2 464 465pkt = ISOTPHeaderEA_FD(identifier=0x7ff, extended_address=0xaf)/ISOTP_SF_FD(message_size=0xff) 466assert bytes(pkt) == bytes.fromhex("000007ff 03 04 00 00 af 00ff") 467 468= Build ISOTP_FF_FD 3 469 470pkt = ISOTPHeader_FD(identifier=0x7ff)/ISOTP_FF_FD(message_size=0xffff0000) 471assert bytes(pkt) == bytes.fromhex("000007ff 06 04 00 00 1000ffff0000") 472 473= Build ISOTP_SF_FD 3 474 475pkt = ISOTPHeader_FD(identifier=0x7ff)/ISOTP_SF_FD(message_size=0xff) 476assert bytes(pkt) == bytes.fromhex("000007ff 02 04 00 00 00ff") 477 478= Dissect ISOTPFD 1 479pkt = ISOTPHeaderEA_FD(bytes.fromhex("000007ff 07 04 00 00 af 1000ffff0000")) 480pkt.show() 481sub_pkt = pkt[ISOTP_FF_FD] 482assert pkt.identifier == 0x7ff 483assert pkt.length == 0x7 484assert pkt.fd_flags == 0x4 485assert pkt.extended_address == 0xaf 486assert sub_pkt.message_size == 0xffff0000 487 488= Dissect ISOTPFD 2 489pkt = ISOTPHeaderEA_FD(bytes.fromhex("000007ff 07 04 00 00 af 00ff00000000")) 490pkt.show() 491sub_pkt = pkt[ISOTP_SF_FD] 492assert pkt.identifier == 0x7ff 493assert pkt.length == 0x7 494assert pkt.fd_flags == 0x4 495assert pkt.extended_address == 0xaf 496assert sub_pkt.message_size == 0xff 497 498= Dissect ISOTPFD 3 499pkt = ISOTPHeader_FD(bytes.fromhex("000007ff 06 04 00 00 1000ffff0000")) 500pkt.show() 501sub_pkt = pkt[ISOTP_FF_FD] 502assert pkt.identifier == 0x7ff 503assert pkt.length == 0x6 504assert pkt.fd_flags == 0x4 505assert sub_pkt.message_size == 0xffff0000 506 507= Dissect ISOTPFD 4 508pkt = ISOTPHeader_FD(bytes.fromhex("000007ff 06 04 00 00 00ff00000000")) 509pkt.show() 510sub_pkt = pkt[ISOTP_SF_FD] 511assert pkt.identifier == 0x7ff 512assert pkt.length == 0x6 513assert pkt.fd_flags == 0x4 514assert sub_pkt.message_size == 0xff