• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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