1#!/usr/bin/env python3
2#
3#  Copyright (c) 2016, The OpenThread Authors.
4#  All rights reserved.
5#
6#  Redistribution and use in source and binary forms, with or without
7#  modification, are permitted provided that the following conditions are met:
8#  1. Redistributions of source code must retain the above copyright
9#     notice, this list of conditions and the following disclaimer.
10#  2. Redistributions in binary form must reproduce the above copyright
11#     notice, this list of conditions and the following disclaimer in the
12#     documentation and/or other materials provided with the distribution.
13#  3. Neither the name of the copyright holder nor the
14#     names of its contributors may be used to endorse or promote products
15#     derived from this software without specific prior written permission.
16#
17#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27#  POSSIBILITY OF SUCH DAMAGE.
28#
29
30import io
31import unittest
32
33from common import MacAddress, MacAddressType
34import mac802154
35
36longaddrs = bytearray([0x61, 0xcc, 0x00, 0xce, 0xfa])
37shortaddrs = bytearray([0x61, 0x88, 0x00, 0xce, 0xfa])
38longshortaddrs = bytearray([0x61, 0xc8, 0x00, 0xce, 0xfa])
39shortlongaddrs = bytearray([0x61, 0x8c, 0x00, 0xce, 0xfa])
40
41
42class TestMacParser(unittest.TestCase):
43
44    def test_should_parse_ack_frame(self):
45        frame = mac802154.MacFrame()
46        frame.parse(io.BytesIO(bytearray([0x12, 0x00, 0x12, 0x34, 0x56])))
47
48        self.assertEqual(mac802154.MacHeader.FrameType.ACK, frame.header.frame_type)
49        self.assertEqual(True, frame.header.frame_pending)
50        self.assertEqual(False, frame.header.ack_request)
51        self.assertEqual(0, frame.header.frame_version)
52        self.assertEqual(0x12, frame.header.seq)
53        self.assertEqual(bytearray([0x34, 0x56]), frame.header.fcs)
54        self.assertEqual(None, frame.payload)
55
56    def test_should_parse_data_frame_with_short_addresses(self):
57        frame = mac802154.MacFrame()
58        frame.parse(
59            io.BytesIO(bytearray([0x61, 0x88, 0x34, 0xce, 0xfa, 0xad, 0xde, 0xef, 0xbe, 0x12, 0x34, 0xfe, 0xdc])))
60
61        self.assertEqual(mac802154.MacHeader.FrameType.DATA, frame.header.frame_type)
62        self.assertEqual(False, frame.header.frame_pending)
63        self.assertEqual(True, frame.header.ack_request)
64        self.assertEqual(0, frame.header.frame_version)
65        self.assertEqual(0x34, frame.header.seq)
66        self.assertEqual(bytearray([0xfe, 0xdc]), frame.header.fcs)
67        self.assertEqual(0xface, frame.header.dest_pan_id)
68        self.assertEqual(0xdead, frame.header.dest_address.rloc)
69        self.assertEqual(0xface, frame.header.src_pan_id)
70        self.assertEqual(0xbeef, frame.header.src_address.rloc)
71
72        self.assertEqual(bytearray([0x12, 0x34]), frame.payload.data)
73
74    def test_should_parse_data_frame_with_extended_addresses(self):
75        frame = mac802154.MacFrame()
76        frame.parse(
77            io.BytesIO(
78                bytearray([
79                    0x61, 0xcc, 0x56, 0xce, 0xfa, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0x0b, 0xad, 0xf0,
80                    0x0d, 0xba, 0xd0, 0xd0, 0x0d, 0x12, 0x34, 0xfe, 0xdc
81                ])))
82
83        self.assertEqual(mac802154.MacHeader.FrameType.DATA, frame.header.frame_type)
84        self.assertEqual(False, frame.header.frame_pending)
85        self.assertEqual(True, frame.header.ack_request)
86        self.assertEqual(0, frame.header.frame_version)
87        self.assertEqual(0x56, frame.header.seq)
88        self.assertEqual(bytearray([0xfe, 0xdc]), frame.header.fcs)
89        self.assertEqual(0xface, frame.header.dest_pan_id)
90        self.assertEqual(bytearray(reversed([0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef])),
91                         frame.header.dest_address.mac_address)
92        self.assertEqual(0xface, frame.header.src_pan_id)
93        self.assertEqual(bytearray(reversed([0x0b, 0xad, 0xf0, 0x0d, 0xba, 0xd0, 0xd0, 0x0d])),
94                         frame.header.src_address.mac_address)
95
96        self.assertEqual(bytearray([0x12, 0x34]), frame.payload.data)
97
98    def test_should_parse_data_frame_with_short_and_extended_addresses(self):
99        frame = mac802154.MacFrame()
100        frame.parse(
101            io.BytesIO(
102                bytearray([
103                    0x61, 0xc8, 0x56, 0xce, 0xfa, 0xad, 0xde, 0x0b, 0xad, 0xf0, 0x0d, 0xba, 0xd0, 0xd0, 0x0d, 0x12,
104                    0x34, 0xfe, 0xdc
105                ])))
106
107        self.assertEqual(mac802154.MacHeader.FrameType.DATA, frame.header.frame_type)
108        self.assertEqual(False, frame.header.frame_pending)
109        self.assertEqual(True, frame.header.ack_request)
110        self.assertEqual(0, frame.header.frame_version)
111        self.assertEqual(0x56, frame.header.seq)
112        self.assertEqual(bytearray([0xfe, 0xdc]), frame.header.fcs)
113        self.assertEqual(0xface, frame.header.dest_pan_id)
114        self.assertEqual(0xdead, frame.header.dest_address.rloc)
115        self.assertEqual(0xface, frame.header.src_pan_id)
116        self.assertEqual(bytearray(reversed([0x0b, 0xad, 0xf0, 0x0d, 0xba, 0xd0, 0xd0, 0x0d])),
117                         frame.header.src_address.mac_address)
118
119        self.assertEqual(bytearray([0x12, 0x34]), frame.payload.data)
120
121    def test_should_parse_data_frame_with_extended_and_short_addresses(self):
122        frame = mac802154.MacFrame()
123        frame.parse(
124            io.BytesIO(
125                bytearray([
126                    0x61, 0x8c, 0x56, 0xce, 0xfa, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0x0d, 0xf0, 0x12,
127                    0x34, 0xfe, 0xdc
128                ])))
129
130        self.assertEqual(mac802154.MacHeader.FrameType.DATA, frame.header.frame_type)
131        self.assertEqual(False, frame.header.frame_pending)
132        self.assertEqual(True, frame.header.ack_request)
133        self.assertEqual(0, frame.header.frame_version)
134        self.assertEqual(0x56, frame.header.seq)
135        self.assertEqual(bytearray([0xfe, 0xdc]), frame.header.fcs)
136        self.assertEqual(0xface, frame.header.dest_pan_id)
137        self.assertEqual(bytearray(reversed([0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef])),
138                         frame.header.dest_address.mac_address)
139        self.assertEqual(0xface, frame.header.src_pan_id)
140        self.assertEqual(0xf00d, frame.header.src_address.rloc)
141
142        self.assertEqual(bytearray([0x12, 0x34]), frame.payload.data)
143
144    def test_should_parse_data_request_command(self):
145        frame = mac802154.MacFrame()
146        frame.parse(io.BytesIO(bytearray([0x63, 0x88, 0x78, 0xce, 0xfa, 0xad, 0xde, 0x0d, 0xf0, 0x04, 0xfe, 0xdc])))
147
148        self.assertEqual(mac802154.MacHeader.FrameType.COMMAND, frame.header.frame_type)
149        self.assertEqual(False, frame.header.frame_pending)
150        self.assertEqual(True, frame.header.ack_request)
151        self.assertEqual(0, frame.header.frame_version)
152        self.assertEqual(0x78, frame.header.seq)
153        self.assertEqual(bytearray([0xfe, 0xdc]), frame.header.fcs)
154        self.assertEqual(0xface, frame.header.dest_pan_id)
155        self.assertEqual(0xdead, frame.header.dest_address.rloc)
156        self.assertEqual(0xface, frame.header.src_pan_id)
157        self.assertEqual(0xf00d, frame.header.src_address.rloc)
158
159        self.assertEqual(bytearray([0x4]), frame.payload.data)
160
161    def test_should_decrypt_data_frame(self):
162
163        mac802154.DeviceDescriptors.add(
164            0x2001, MacAddress(bytearray([0x16, 0x6e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x07]), MacAddressType.LONG))
165
166        frame = mac802154.MacFrame()
167        frame.parse(
168            io.BytesIO(
169                bytearray([
170                    0x69,
171                    0x98,
172                    0x68,  # FC, seq
173                    0xce,
174                    0xfa,  # Pan Id
175                    0x00,
176                    0x20,  # Dst addr
177                    0x01,
178                    0x20,  # Src addr
179                    0x0d,
180                    0x00,
181                    0x00,
182                    0x00,
183                    0x00,
184                    0x01,  # Aux Security Header
185                    0xb5,
186                    0x5a,
187                    0x0d,
188                    0x8e,
189                    0x18,
190                    0x5c,
191                    0xb1,
192                    0x06,  # Payload
193                    0xc4,
194                    0x6f,
195                    0x7d,
196                    0x6b,
197                    0xb5,
198                    0x4a,
199                    0x87,
200                    0x14,
201                    0xae,
202                    0xdd,
203                    0x8e,
204                    0xb7,
205                    0x37,
206                    0x62,
207                    0x27,
208                    0x48,
209                    0xc9,
210                    0x53,
211                    0x0c,
212                    0x44,
213                    0x31,
214                    0x59,
215                    0x8b,
216                    0xa2,
217                    0x83,
218                    0x59,
219                    0xa1,
220                    0x43,  # MIC (valid)
221                    0x74,
222                    0xe0,
223                    0x2a,
224                    0xf6,
225                    0x99,
226                    0xfc
227                ])))  # FCS (valid)
228
229        self.assertEqual(mac802154.MacHeader.FrameType.DATA, frame.header.frame_type)
230        self.assertEqual(False, frame.header.frame_pending)
231        self.assertEqual(True, frame.header.ack_request)
232        self.assertEqual(1, frame.header.frame_version)
233        self.assertEqual(0x68, frame.header.seq)
234        self.assertEqual(bytearray([0x99, 0xfc]), frame.header.fcs)
235        self.assertEqual(0xface, frame.header.dest_pan_id)
236        self.assertEqual(0x2000, frame.header.dest_address.rloc)
237        self.assertEqual(0xface, frame.header.src_pan_id)
238        self.assertEqual(0x2001, frame.header.src_address.rloc)
239
240        self.assertEqual(0, frame.header.aux_sec_header.frame_counter)
241        self.assertEqual(5, frame.header.aux_sec_header.security_level)
242
243        self.assertEqual(
244            bytes(
245                bytearray([
246                    0x7c, 0x77, 0x80, 0xf0, 0x4d, 0x4d, 0x4d, 0x4d, 0xe0, 0x04, 0x44, 0x02, 0x44, 0x66, 0x13, 0x5f,
247                    0x22, 0x80, 0xb1, 0x61, 0x02, 0x61, 0x73, 0x11, 0x2a, 0xff, 0x01, 0x08, 0x16, 0x6e, 0x0a, 0x00,
248                    0x00, 0x00, 0x00, 0x07
249                ])), frame.payload.data)
250
251    def test_should_decrypt_command_frame(self):
252        frame = mac802154.MacFrame()
253        frame.parse(
254            io.BytesIO(
255                bytearray([
256                    0x6b, 0xdc, 0xce, 0xce, 0xfa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x03, 0x00, 0x00,
257                    0x00, 0x00, 0x0a, 0x6e, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x2d, 0xbc, 0x12, 0xbe,
258                    0x0a, 0x4f
259                ])))
260
261        self.assertEqual(mac802154.MacHeader.FrameType.COMMAND, frame.header.frame_type)
262        self.assertEqual(False, frame.header.frame_pending)
263        self.assertEqual(True, frame.header.ack_request)
264        self.assertEqual(1, frame.header.frame_version)
265        self.assertEqual(206, frame.header.seq)
266        self.assertEqual(bytearray([0x0a, 0x4f]), frame.header.fcs)
267        self.assertEqual(0xface, frame.header.dest_pan_id)
268        self.assertEqual(bytearray([0x16, 0x6e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x02]),
269                         frame.header.dest_address.mac_address)
270        self.assertEqual(0xface, frame.header.src_pan_id)
271        self.assertEqual(bytearray([0x16, 0x6e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x03]),
272                         frame.header.src_address.mac_address)
273
274        self.assertEqual(0, frame.header.aux_sec_header.frame_counter)
275        self.assertEqual(5, frame.header.aux_sec_header.security_level)
276
277
278if __name__ == "__main__":
279    unittest.main()
280