/src/wireshark/epan/dissectors/packet-cbor.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-cbor.c |
2 | | * Routines for Concise Binary Object Representation (CBOR) (STD 94) dissection |
3 | | * References: |
4 | | * RFC 8949: https://tools.ietf.org/html/rfc8949 |
5 | | * RFC 8742: https://tools.ietf.org/html/rfc8742 |
6 | | * |
7 | | * Copyright 2015, Hauke Mehrtens <hauke@hauke-m.de> |
8 | | * Copyright 2022, Stig Bjorlykke <stig@bjorlykke.org> |
9 | | * |
10 | | * Wireshark - Network traffic analyzer |
11 | | * By Gerald Combs <gerald@wireshark.org> |
12 | | * Copyright 1998 Gerald Combs |
13 | | * |
14 | | * SPDX-License-Identifier: GPL-2.0-or-later |
15 | | */ |
16 | | |
17 | | #include "config.h" |
18 | | |
19 | | #include <math.h> |
20 | | |
21 | | #include "packet-cbor.h" |
22 | | #include <epan/packet.h> |
23 | | #include <epan/exceptions.h> |
24 | | #include <epan/expert.h> |
25 | | #include <epan/proto_data.h> |
26 | | #include <epan/wscbor.h> |
27 | | #include <wsutil/str_util.h> |
28 | | |
29 | | void proto_register_cbor(void); |
30 | | void proto_reg_handoff_cbor(void); |
31 | | |
32 | | // Protocol preferences and defaults |
33 | | static bool cbor_dissect_embeded_bstr = false; |
34 | | |
35 | | static int proto_cbor; |
36 | | |
37 | | static int hf_cbor_item_major_type; |
38 | | static int hf_cbor_item_integer_size; |
39 | | static int hf_cbor_item_length_size; |
40 | | static int hf_cbor_item_length5; |
41 | | static int hf_cbor_item_length; |
42 | | static int hf_cbor_item_items5; |
43 | | static int hf_cbor_item_items; |
44 | | static int hf_cbor_item_pairs5; |
45 | | static int hf_cbor_item_pairs; |
46 | | static int hf_cbor_item_float_simple_type; |
47 | | static int hf_cbor_item_unsigned_integer; |
48 | | static int hf_cbor_item_negative_integer; |
49 | | static int hf_cbor_item_text_string; |
50 | | static int hf_cbor_item_byte_string; |
51 | | static int hf_cbor_item_array; |
52 | | static int hf_cbor_item_map; |
53 | | static int hf_cbor_item_tag; |
54 | | static int hf_cbor_item_float_simple; |
55 | | static int hf_cbor_type_uint5; |
56 | | static int hf_cbor_type_uint; |
57 | | static int hf_cbor_type_nint; |
58 | | static int hf_cbor_type_byte_string; |
59 | | static int hf_cbor_type_byte_string_indef; |
60 | | static int hf_cbor_type_text_string; |
61 | | static int hf_cbor_type_text_string_indef; |
62 | | static int hf_cbor_type_tag; |
63 | | static int hf_cbor_type_simple_data5; |
64 | | static int hf_cbor_type_simple_data8; |
65 | | static int hf_cbor_type_float16; |
66 | | static int hf_cbor_type_float32; |
67 | | static int hf_cbor_type_float64; |
68 | | |
69 | | static int ett_cbor; |
70 | | static int ett_cbor_type; |
71 | | static int ett_cbor_unsigned_integer; |
72 | | static int ett_cbor_negative_integer; |
73 | | static int ett_cbor_byte_string; |
74 | | static int ett_cbor_byte_string_indef; |
75 | | static int ett_cbor_text_string; |
76 | | static int ett_cbor_text_string_indef; |
77 | | static int ett_cbor_array; |
78 | | static int ett_cbor_map; |
79 | | static int ett_cbor_tag; |
80 | | static int ett_cbor_float_simple; |
81 | | |
82 | | static expert_field ei_cbor_invalid_minor_type; |
83 | | static expert_field ei_cbor_invalid_element; |
84 | | static expert_field ei_cbor_too_long_length; |
85 | | static expert_field ei_cbor_max_recursion_depth_reached; |
86 | | static expert_field ei_cbor_embedded_bstr; |
87 | | |
88 | | static dissector_handle_t cbor_handle; |
89 | | static dissector_handle_t cborseq_handle; |
90 | | |
91 | 6.66k | #define CBOR_TYPE_USIGNED_INT 0 |
92 | 1.70k | #define CBOR_TYPE_NEGATIVE_INT 1 |
93 | 540 | #define CBOR_TYPE_BYTE_STRING 2 |
94 | 908 | #define CBOR_TYPE_TEXT_STRING 3 |
95 | 1.57k | #define CBOR_TYPE_ARRAY 4 |
96 | 1.03k | #define CBOR_TYPE_MAP 5 |
97 | 1.50k | #define CBOR_TYPE_TAGGED 6 |
98 | 3.69k | #define CBOR_TYPE_FLOAT 7 |
99 | | |
100 | | static const value_string major_type_vals[] = { |
101 | | { 0, "Unsigned Integer" }, |
102 | | { 1, "Negative Integer" }, |
103 | | { 2, "Byte String" }, |
104 | | { 3, "Text String" }, |
105 | | { 4, "Array" }, |
106 | | { 5, "Map" }, |
107 | | { 6, "Tagged" }, |
108 | | { 7, "Floating-Point or Simple" }, |
109 | | { 0, NULL } |
110 | | }; |
111 | | |
112 | | static const value_string integer_size_vals[] = { |
113 | | { 24, "1 byte" }, |
114 | | { 25, "2 bytes" }, |
115 | | { 26, "4 bytes" }, |
116 | | { 27, "8 bytes" }, |
117 | | { 28, "Reserved for future additions" }, |
118 | | { 29, "Reserved for future additions" }, |
119 | | { 30, "Reserved for future additions" }, |
120 | | { 31, "No argument value is derived" }, |
121 | | { 0, NULL } |
122 | | }; |
123 | | |
124 | | static const value_string length_size_vals[] = { |
125 | | { 24, "1 byte" }, |
126 | | { 25, "2 bytes" }, |
127 | | { 26, "4 bytes" }, |
128 | | { 27, "8 bytes" }, |
129 | | { 28, "Reserved for future additions" }, |
130 | | { 29, "Reserved for future additions" }, |
131 | | { 30, "Reserved for future additions" }, |
132 | | { 31, "Indefinite Length" }, |
133 | | { 0, NULL } |
134 | | }; |
135 | | |
136 | | static const value_string float_simple_type_vals[] = { |
137 | | { 24, "Simple value" }, |
138 | | { 25, "IEEE 754 Half-Precision Float" }, |
139 | | { 26, "IEEE 754 Single-Precision Float" }, |
140 | | { 27, "IEEE 754 Double-Precision Float" }, |
141 | | { 28, "Reserved for future additions" }, |
142 | | { 29, "Reserved for future additions" }, |
143 | | { 30, "Reserved for future additions" }, |
144 | | { 31, "Break indefinite length" }, |
145 | | { 0, NULL } |
146 | | }; |
147 | | |
148 | | /* see https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml#tags */ |
149 | | static const val64_string tag64_vals[] = { |
150 | | { 0, "Standard date/time string" }, |
151 | | { 1, "Epoch-based date/time" }, |
152 | | { 2, "Positive bignum" }, |
153 | | { 3, "Negative bignum" }, |
154 | | { 4, "Decimal fraction" }, |
155 | | { 5, "Bigfloat" }, |
156 | | { 16, "COSE Single Recipient Encrypted Data Object" }, |
157 | | { 17, "COSE Mac w/o Recipients Object" }, |
158 | | { 18, "COSE Single Signer Data Object" }, |
159 | | { 19, "COSE standalone V2 countersignature" }, |
160 | | { 21, "Expected conversion to base64url encoding" }, |
161 | | { 22, "Expected conversion to base64 encoding" }, |
162 | | { 23, "Expected conversion to base16 encoding" }, |
163 | | { 24, "Encoded CBOR data item" }, |
164 | | { 25, "reference the nth previously seen string" }, |
165 | | { 26, "Serialised Perl object with classname and constructor arguments" }, |
166 | | { 27, "Serialised language-independent object with type name and constructor arguments" }, |
167 | | { 28, "mark value as (potentially) shared" }, |
168 | | { 29, "reference nth marked value" }, |
169 | | { 30, "Rational number" }, |
170 | | { 32, "URI" }, |
171 | | { 33, "base64url" }, |
172 | | { 34, "base64" }, |
173 | | { 35, "Regular expression" }, |
174 | | { 36, "MIME message" }, |
175 | | { 37, "Binary UUID" }, |
176 | | { 38, "Language-tagged string" }, |
177 | | { 39, "Identifier" }, |
178 | | { 61, "CBOR Web Token (CWT)" }, |
179 | | { 63, "Encoded CBOR Sequence" }, |
180 | | { 100, "Number of days since the epoch date 1970-01-01" }, |
181 | | { 256, "mark value as having string references" }, |
182 | | { 257, "Binary MIME message" }, |
183 | | { 264, "Decimal fraction with arbitrary exponent" }, |
184 | | { 265, "Bigfloat with arbitrary exponent" }, |
185 | | { 1004, "RFC 3339 full-date string" }, |
186 | | { 22098, "hint that indicates an additional level of indirection" }, |
187 | | { 55799, "Self-describe CBOR" }, |
188 | | { 0, NULL }, |
189 | | }; |
190 | | |
191 | | static const value_string vals_simple_data[] = { |
192 | | { 20, "False" }, |
193 | | { 21, "True" }, |
194 | | { 22, "Null" }, |
195 | | { 23, "Undefined" }, |
196 | | { 0, NULL }, |
197 | | }; |
198 | | |
199 | | static bool |
200 | | dissect_cbor_main_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset); |
201 | | |
202 | | static bool |
203 | | dissect_cbor_float_simple_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor); |
204 | | |
205 | | static bool |
206 | | dissect_cbor_unsigned_integer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor) |
207 | 6.66k | { |
208 | 6.66k | uint64_t value = 0; |
209 | 6.66k | proto_item *item; |
210 | 6.66k | proto_tree *subtree; |
211 | | |
212 | 6.66k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_unsigned_integer, tvb, *offset, -1, ENC_NA); |
213 | 6.66k | subtree = proto_item_add_subtree(item, ett_cbor_unsigned_integer); |
214 | | |
215 | 6.66k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
216 | 6.66k | if (type_minor <= 0x17) { |
217 | 6.52k | proto_tree_add_item(subtree, hf_cbor_type_uint5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
218 | 6.52k | value = type_minor; |
219 | 6.52k | } else { |
220 | 136 | proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
221 | 136 | } |
222 | 6.66k | *offset += 1; |
223 | | |
224 | 6.66k | switch (type_minor) { |
225 | 28 | case 0x18: |
226 | 28 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 1, ENC_BIG_ENDIAN, &value); |
227 | 28 | *offset += 1; |
228 | 28 | break; |
229 | 59 | case 0x19: |
230 | 59 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 2, ENC_BIG_ENDIAN, &value); |
231 | 59 | *offset += 2; |
232 | 59 | break; |
233 | 19 | case 0x1a: |
234 | 19 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 4, ENC_BIG_ENDIAN, &value); |
235 | 19 | *offset += 4; |
236 | 19 | break; |
237 | 28 | case 0x1b: |
238 | 28 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 8, ENC_BIG_ENDIAN, &value); |
239 | 28 | *offset += 8; |
240 | 28 | break; |
241 | 6.53k | default: |
242 | 6.53k | if (type_minor > 0x17) { |
243 | 2 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
244 | 2 | "invalid minor type %i in unsigned integer", type_minor); |
245 | 2 | return false; |
246 | 2 | } |
247 | 6.52k | break; |
248 | 6.66k | } |
249 | | |
250 | 6.66k | proto_item_append_text(item, ": %" PRIu64, value); |
251 | 6.66k | proto_item_set_end(item, tvb, *offset); |
252 | | |
253 | 6.66k | return true; |
254 | 6.66k | } |
255 | | |
256 | | static bool |
257 | | dissect_cbor_negative_integer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor) |
258 | 1.70k | { |
259 | 1.70k | int64_t value = 0; |
260 | 1.70k | proto_item *item; |
261 | 1.70k | proto_tree *subtree; |
262 | | |
263 | 1.70k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_negative_integer, tvb, *offset, -1, ENC_NA); |
264 | 1.70k | subtree = proto_item_add_subtree(item, ett_cbor_negative_integer); |
265 | | |
266 | 1.70k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
267 | 1.70k | if (type_minor <= 0x17) { |
268 | 1.46k | value = (int64_t)-1 - type_minor; |
269 | | /* Keep correct bit representation with a modified value. */ |
270 | 1.46k | proto_tree_add_int64_bits_format_value(subtree, hf_cbor_type_nint, tvb, 3, 5, type_minor, ENC_BIG_ENDIAN, "%" PRId64, value); |
271 | 1.46k | } else { |
272 | 236 | proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
273 | 236 | } |
274 | 1.70k | *offset += 1; |
275 | | |
276 | 1.70k | switch (type_minor) { |
277 | 72 | case 0x18: |
278 | 72 | value = (int64_t)-1 - tvb_get_uint8(tvb, *offset); |
279 | 72 | proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 1, value); |
280 | 72 | *offset += 1; |
281 | 72 | break; |
282 | 56 | case 0x19: |
283 | 56 | value = (int64_t)-1 - tvb_get_ntohs(tvb, *offset); |
284 | 56 | proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 2, value); |
285 | 56 | *offset += 2; |
286 | 56 | break; |
287 | 52 | case 0x1a: |
288 | 52 | value = (int64_t)-1 - tvb_get_ntohl(tvb, *offset); |
289 | 52 | proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 4, value); |
290 | 52 | *offset += 4; |
291 | 52 | break; |
292 | 54 | case 0x1b: |
293 | | /* TODO: an overflow could happen here, for negative int < INT64_MIN */ |
294 | 54 | value = (int64_t)-1 - tvb_get_ntoh64(tvb, *offset); |
295 | 54 | if (value > -1) { |
296 | 25 | expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length, |
297 | 25 | "The value is too small, Wireshark can not display it correctly"); |
298 | 25 | } |
299 | 54 | proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 8, value); |
300 | 54 | *offset += 8; |
301 | 54 | break; |
302 | 1.46k | default: |
303 | 1.46k | if (type_minor > 0x17) { |
304 | 2 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
305 | 2 | "invalid minor type %i in negative integer", type_minor); |
306 | 2 | return false; |
307 | 2 | } |
308 | 1.46k | break; |
309 | 1.70k | } |
310 | | |
311 | 1.69k | proto_item_append_text(item, ": %" PRId64, value); |
312 | 1.69k | proto_item_set_end(item, tvb, *offset); |
313 | | |
314 | 1.69k | return true; |
315 | 1.70k | } |
316 | | |
317 | | static bool |
318 | | // NOLINTNEXTLINE(misc-no-recursion) |
319 | | dissect_cbor_byte_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor) |
320 | 536 | { |
321 | 536 | uint64_t length; |
322 | 536 | int eof_type; |
323 | 536 | proto_tree *subtree; |
324 | 536 | proto_item *item; |
325 | | |
326 | 536 | item = proto_tree_add_item(cbor_tree, hf_cbor_item_byte_string, tvb, *offset, -1, ENC_NA); |
327 | 536 | subtree = proto_item_add_subtree(item, ett_cbor_byte_string); |
328 | | |
329 | 536 | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
330 | 536 | if (type_minor <= 0x17) { |
331 | 494 | proto_tree_add_item(subtree, hf_cbor_item_length5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
332 | 494 | length = type_minor; |
333 | 494 | } else { |
334 | 42 | proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
335 | 42 | } |
336 | 536 | *offset += 1; |
337 | | |
338 | 536 | switch (type_minor) { |
339 | 18 | case 0x18: |
340 | 18 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 1, ENC_BIG_ENDIAN, &length); |
341 | 18 | *offset += 1; |
342 | 18 | break; |
343 | 2 | case 0x19: |
344 | 2 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 2, ENC_BIG_ENDIAN, &length); |
345 | 2 | *offset += 2; |
346 | 2 | break; |
347 | 4 | case 0x1a: |
348 | 4 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 4, ENC_BIG_ENDIAN, &length); |
349 | 4 | *offset += 4; |
350 | 4 | break; |
351 | 7 | case 0x1b: |
352 | 7 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 8, ENC_BIG_ENDIAN, &length); |
353 | 7 | *offset += 8; |
354 | 7 | break; |
355 | 8 | case 0x1f: |
356 | 8 | proto_item_append_text(item, ": (indefinite length)"); |
357 | 8 | item = proto_tree_add_item(subtree, hf_cbor_type_byte_string_indef, tvb, *offset, 1, ENC_NA); |
358 | 8 | subtree = proto_item_add_subtree(item, ett_cbor_byte_string_indef); |
359 | 10 | while (1) { |
360 | 10 | eof_type = tvb_get_uint8(tvb, *offset); |
361 | 10 | if (eof_type == 0xff) { |
362 | 2 | dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f); |
363 | 2 | proto_item_set_end(item, tvb, *offset); |
364 | 2 | return true; |
365 | 2 | } |
366 | | |
367 | 8 | if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_BYTE_STRING) { |
368 | 4 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_element, |
369 | 4 | "invalid element %i, expected byte string", (eof_type & 0xe0) >> 5); |
370 | 4 | return false; |
371 | 4 | } |
372 | | |
373 | 4 | unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor); |
374 | 4 | if (recursion_depth > prefs.gui_max_tree_depth) { |
375 | 0 | proto_tree_add_expert(subtree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0); |
376 | 0 | return false; |
377 | 0 | } |
378 | 4 | p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1); |
379 | | |
380 | 4 | bool recursed = dissect_cbor_byte_string(tvb, pinfo, subtree, offset, eof_type & 0x1f); |
381 | 4 | p_set_proto_depth(pinfo, proto_cbor, recursion_depth); |
382 | | |
383 | 4 | if (!recursed) { |
384 | 2 | return false; |
385 | 2 | } |
386 | 4 | } |
387 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
388 | 0 | return false; |
389 | 497 | default: |
390 | 497 | if (type_minor > 0x17) { |
391 | 3 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
392 | 3 | "invalid minor type %i in byte string", type_minor); |
393 | 3 | return false; |
394 | 3 | } |
395 | 494 | break; |
396 | 536 | } |
397 | | |
398 | 525 | if (length > INT32_MAX || *offset + (int)length < *offset) { |
399 | 3 | expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length, |
400 | 3 | "the length (%" PRIu64 ") of the byte string too long", length); |
401 | 3 | return false; |
402 | 3 | } |
403 | | |
404 | 522 | proto_item *item_data = proto_tree_add_item(subtree, hf_cbor_type_byte_string, tvb, *offset, (int)length, ENC_BIG_ENDIAN|ENC_NA); |
405 | 522 | *offset += (int)length; |
406 | | |
407 | 522 | proto_item_append_text(item, ": (%" PRIu64 " byte%s)", length, plurality(length, "", "s")); |
408 | 522 | proto_item_set_end(item, tvb, *offset); |
409 | | |
410 | 522 | if (cbor_dissect_embeded_bstr && length) { |
411 | 0 | tvbuff_t *sub_tvb = tvb_new_subset_length(tvb, *offset - (int)length, (int)length); |
412 | 0 | bool valid = cbor_heuristic(sub_tvb, pinfo, subtree, NULL); |
413 | 0 | if (valid) { |
414 | 0 | expert_add_info(pinfo, item_data, &ei_cbor_embedded_bstr); |
415 | 0 | } |
416 | 0 | } |
417 | | |
418 | 522 | return true; |
419 | 525 | } |
420 | | |
421 | | static bool |
422 | | // NOLINTNEXTLINE(misc-no-recursion) |
423 | | dissect_cbor_text_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor) |
424 | 903 | { |
425 | 903 | const uint8_t *value = NULL; |
426 | 903 | uint64_t length = 0; |
427 | 903 | int eof_type; |
428 | 903 | proto_tree *subtree; |
429 | 903 | proto_item *item; |
430 | | |
431 | 903 | item = proto_tree_add_item(cbor_tree, hf_cbor_item_text_string, tvb, *offset, -1, ENC_NA); |
432 | 903 | subtree = proto_item_add_subtree(item, ett_cbor_text_string); |
433 | | |
434 | 903 | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
435 | 903 | if (type_minor <= 0x17) { |
436 | 844 | proto_tree_add_item(subtree, hf_cbor_item_length5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
437 | 844 | length = type_minor; |
438 | 844 | } else { |
439 | 59 | proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
440 | 59 | } |
441 | 903 | *offset += 1; |
442 | | |
443 | 903 | switch (type_minor) { |
444 | 16 | case 0x18: |
445 | 16 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 1, ENC_BIG_ENDIAN, &length); |
446 | 16 | *offset += 1; |
447 | 16 | break; |
448 | 6 | case 0x19: |
449 | 6 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 2, ENC_BIG_ENDIAN, &length); |
450 | 6 | *offset += 2; |
451 | 6 | break; |
452 | 8 | case 0x1a: |
453 | 8 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 4, ENC_BIG_ENDIAN, &length); |
454 | 8 | *offset += 4; |
455 | 8 | break; |
456 | 5 | case 0x1b: |
457 | 5 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 8, ENC_BIG_ENDIAN, &length); |
458 | 5 | *offset += 8; |
459 | 5 | break; |
460 | 16 | case 0x1f: |
461 | 16 | proto_item_append_text(item, ": (indefinite length)"); |
462 | 16 | item = proto_tree_add_item(subtree, hf_cbor_type_text_string_indef, tvb, *offset, 1, ENC_NA); |
463 | 16 | subtree = proto_item_add_subtree(item, ett_cbor_text_string_indef); |
464 | 24 | while (1) { |
465 | 22 | eof_type = tvb_get_uint8(tvb, *offset); |
466 | 22 | if (eof_type == 0xff) { |
467 | 10 | dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f); |
468 | 10 | proto_item_set_end(item, tvb, *offset); |
469 | 10 | return true; |
470 | 10 | } |
471 | | |
472 | 12 | if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_TEXT_STRING) { |
473 | 4 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_element, |
474 | 4 | "invalid element %i, expected text string", (eof_type & 0xe0) >> 5); |
475 | 4 | return false; |
476 | 4 | } |
477 | | |
478 | 8 | unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor); |
479 | 8 | if (recursion_depth > prefs.gui_max_tree_depth) { |
480 | 0 | proto_tree_add_expert(subtree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0); |
481 | 0 | return false; |
482 | 0 | } |
483 | 8 | p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1); |
484 | | |
485 | 8 | bool recursed = dissect_cbor_text_string(tvb, pinfo, subtree, offset, eof_type & 0x1f); |
486 | 8 | p_set_proto_depth(pinfo, proto_cbor, recursion_depth); |
487 | | |
488 | 8 | if (!recursed) { |
489 | 0 | return false; |
490 | 0 | } |
491 | 8 | } |
492 | 2 | DISSECTOR_ASSERT_NOT_REACHED(); |
493 | 2 | return false; |
494 | 852 | default: |
495 | 852 | if (type_minor > 0x17) { |
496 | 8 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
497 | 8 | "invalid minor type %i in text string", type_minor); |
498 | 8 | return false; |
499 | 8 | } |
500 | 844 | break; |
501 | 903 | } |
502 | | |
503 | 878 | if (length > INT32_MAX || *offset + (int)length < *offset) { |
504 | 9 | expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length, |
505 | 9 | "the length (%" PRIu64 ") of the text string too long", length); |
506 | 9 | return false; |
507 | 9 | } |
508 | | |
509 | 869 | proto_tree_add_item_ret_string(subtree, hf_cbor_type_text_string, tvb, *offset, (int)length, ENC_BIG_ENDIAN|ENC_UTF_8, pinfo->pool, &value); |
510 | 869 | *offset += (int)length; |
511 | | |
512 | 869 | proto_item_append_text(item, ": %s", value); |
513 | 869 | proto_item_set_end(item, tvb, *offset); |
514 | | |
515 | 869 | return true; |
516 | 878 | } |
517 | | |
518 | | static bool |
519 | | // NOLINTNEXTLINE(misc-no-recursion) |
520 | | dissect_cbor_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor) |
521 | 1.57k | { |
522 | 1.57k | uint64_t length = 0; |
523 | 1.57k | proto_tree *subtree; |
524 | 1.57k | proto_item *item; |
525 | 1.57k | bool indefinite = false; |
526 | | |
527 | 1.57k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_array, tvb, *offset, -1, ENC_NA); |
528 | 1.57k | subtree = proto_item_add_subtree(item, ett_cbor_array); |
529 | | |
530 | 1.57k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
531 | | |
532 | 1.57k | if (type_minor <= 0x17) { |
533 | 1.06k | proto_tree_add_item(subtree, hf_cbor_item_items5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
534 | 1.06k | length = type_minor; |
535 | 1.06k | } else { |
536 | 518 | proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
537 | 518 | } |
538 | 1.57k | *offset += 1; |
539 | | |
540 | 1.57k | switch (type_minor) { |
541 | 360 | case 0x18: |
542 | 360 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 1, ENC_BIG_ENDIAN, &length); |
543 | 360 | *offset += 1; |
544 | 360 | break; |
545 | 26 | case 0x19: |
546 | 26 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 2, ENC_BIG_ENDIAN, &length); |
547 | 26 | *offset += 2; |
548 | 26 | break; |
549 | 35 | case 0x1a: |
550 | 35 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 4, ENC_BIG_ENDIAN, &length); |
551 | 35 | *offset += 4; |
552 | 35 | break; |
553 | 31 | case 0x1b: |
554 | 31 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 8, ENC_BIG_ENDIAN, &length); |
555 | 31 | *offset += 8; |
556 | 31 | break; |
557 | 66 | case 0x1f: |
558 | 66 | length = INT_MAX; |
559 | 66 | indefinite = true; |
560 | 66 | break; |
561 | 1.06k | default: |
562 | 1.06k | if (type_minor > 0x17) { |
563 | 0 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
564 | 0 | "invalid minor type %i in array", type_minor); |
565 | 0 | return false; |
566 | 0 | } |
567 | 1.06k | break; |
568 | 1.57k | } |
569 | | |
570 | 4.66k | for (uint64_t i = 0; i < length; i++) { |
571 | 3.58k | if (indefinite) { |
572 | 178 | int value = tvb_get_uint8(tvb, *offset); |
573 | 178 | if (value == 0xff) { |
574 | 16 | dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f); |
575 | 16 | break; |
576 | 16 | } |
577 | 178 | } |
578 | | |
579 | 3.56k | if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset)) { |
580 | 476 | return false; |
581 | 476 | } |
582 | 3.56k | } |
583 | | |
584 | 1.10k | if (indefinite) { |
585 | 16 | proto_item_append_text(item, ": (indefinite length)"); |
586 | 1.08k | } else { |
587 | 1.08k | proto_item_append_text(item, ": (%" PRIu64 " item%s)", length, plurality(length, "", "s")); |
588 | 1.08k | } |
589 | 1.10k | proto_item_set_end(item, tvb, *offset); |
590 | | |
591 | 1.10k | return true; |
592 | 1.57k | } |
593 | | |
594 | | static bool |
595 | | // NOLINTNEXTLINE(misc-no-recursion) |
596 | | dissect_cbor_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor) |
597 | 1.03k | { |
598 | 1.03k | uint64_t length = 0; |
599 | 1.03k | proto_tree *subtree; |
600 | 1.03k | proto_item *item; |
601 | 1.03k | bool indefinite = false; |
602 | | |
603 | 1.03k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_map, tvb, *offset, -1, ENC_NA); |
604 | 1.03k | subtree = proto_item_add_subtree(item, ett_cbor_map); |
605 | | |
606 | 1.03k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
607 | | |
608 | 1.03k | if (type_minor <= 0x17) { |
609 | 934 | proto_tree_add_item(subtree, hf_cbor_item_pairs5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
610 | 934 | length = type_minor; |
611 | 934 | } else { |
612 | 101 | proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
613 | 101 | } |
614 | 1.03k | *offset += 1; |
615 | | |
616 | 1.03k | switch (type_minor) { |
617 | 12 | case 0x18: |
618 | 12 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 1, ENC_BIG_ENDIAN, &length); |
619 | 12 | *offset += 1; |
620 | 12 | break; |
621 | 4 | case 0x19: |
622 | 4 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 2, ENC_BIG_ENDIAN, &length); |
623 | 4 | *offset += 2; |
624 | 4 | break; |
625 | 14 | case 0x1a: |
626 | 14 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 4, ENC_BIG_ENDIAN, &length); |
627 | 14 | *offset += 4; |
628 | 14 | break; |
629 | 35 | case 0x1b: |
630 | 35 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 8, ENC_BIG_ENDIAN, &length); |
631 | 35 | *offset += 8; |
632 | 35 | break; |
633 | 33 | case 0x1f: |
634 | 33 | length = INT_MAX; |
635 | 33 | indefinite = true; |
636 | 33 | break; |
637 | 937 | default: |
638 | 937 | if (type_minor > 0x17) { |
639 | 3 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
640 | 3 | "invalid minor type %i in map", type_minor); |
641 | 3 | return false; |
642 | 3 | } |
643 | 934 | break; |
644 | 1.03k | } |
645 | | |
646 | 3.32k | for (uint64_t i = 0; i < length; i++) { |
647 | 2.60k | if (indefinite) { |
648 | 181 | int value = tvb_get_uint8(tvb, *offset); |
649 | 181 | if (value == 0xff) { |
650 | 9 | dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f); |
651 | 9 | break; |
652 | 9 | } |
653 | 181 | } |
654 | | |
655 | 2.59k | if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset)) { |
656 | 262 | return false; |
657 | 262 | } |
658 | | |
659 | 2.33k | if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset)) { |
660 | 39 | return false; |
661 | 39 | } |
662 | 2.33k | } |
663 | | |
664 | 731 | if (indefinite) { |
665 | 9 | proto_item_append_text(item, ": (indefinite length)"); |
666 | 722 | } else { |
667 | 722 | proto_item_append_text(item, ": (%" PRIu64 " pair%s)", length, plurality(length, "", "s")); |
668 | 722 | } |
669 | 731 | proto_item_set_end(item, tvb, *offset); |
670 | | |
671 | 731 | return true; |
672 | 1.03k | } |
673 | | |
674 | | static bool |
675 | | // NOLINTNEXTLINE(misc-no-recursion) |
676 | | dissect_cbor_tag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor) |
677 | 1.50k | { |
678 | 1.50k | uint64_t tag = 0; |
679 | 1.50k | proto_item *item; |
680 | 1.50k | proto_tree *subtree; |
681 | | |
682 | 1.50k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_tag, tvb, *offset, -1, ENC_NA); |
683 | 1.50k | subtree = proto_item_add_subtree(item, ett_cbor_tag); |
684 | | |
685 | 1.50k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
686 | | |
687 | 1.50k | if (type_minor <= 0x17) { |
688 | 1.30k | tag = type_minor; |
689 | 1.30k | proto_tree_add_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 1, tag); |
690 | 1.30k | } else { |
691 | 201 | proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
692 | 201 | } |
693 | 1.50k | *offset += 1; |
694 | | |
695 | 1.50k | switch (type_minor) { |
696 | 106 | case 0x18: |
697 | 106 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 1, ENC_BIG_ENDIAN, &tag); |
698 | 106 | *offset += 1; |
699 | 106 | break; |
700 | 36 | case 0x19: |
701 | 36 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 2, ENC_BIG_ENDIAN, &tag); |
702 | 36 | *offset += 2; |
703 | 36 | break; |
704 | 37 | case 0x1a: |
705 | 37 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 4, ENC_BIG_ENDIAN, &tag); |
706 | 37 | *offset += 4; |
707 | 37 | break; |
708 | 15 | case 0x1b: |
709 | 15 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 8, ENC_BIG_ENDIAN, &tag); |
710 | 15 | *offset += 8; |
711 | 15 | break; |
712 | 1.30k | default: |
713 | 1.30k | if (type_minor > 0x17) { |
714 | 7 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
715 | 7 | "invalid minor type %i in tag", type_minor); |
716 | 7 | return false; |
717 | 7 | } |
718 | 1.30k | break; |
719 | 1.50k | } |
720 | | |
721 | 1.49k | if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset)) { |
722 | 93 | return false; |
723 | 93 | } |
724 | | |
725 | 1.40k | proto_item_append_text(item, ": %s (%" PRIu64 ")", val64_to_str(tag, tag64_vals, "Unknown"), tag); |
726 | 1.40k | proto_item_set_end(item, tvb, *offset); |
727 | | |
728 | 1.40k | return true; |
729 | 1.49k | } |
730 | | |
731 | | /* based on code from rfc7049 appendix-D */ |
732 | | static void |
733 | | decode_half(tvbuff_t *tvb, proto_tree *tree, proto_item *item, int *offset, int hfindex) |
734 | 96 | { |
735 | 96 | char value[6]; |
736 | 96 | int half, exponent, mantissa; |
737 | 96 | float val = 0; |
738 | | |
739 | 96 | half = tvb_get_ntohs(tvb, *offset); |
740 | 96 | exponent = (half >> 10) & 0x1f; |
741 | 96 | mantissa = half & 0x3ff; |
742 | | |
743 | 96 | if (exponent == 0) { |
744 | 21 | val = ldexpf((float)mantissa, -24); |
745 | 21 | if (half & 0x8000) { |
746 | 0 | val = -val; |
747 | 0 | } |
748 | 21 | proto_tree_add_float(tree, hfindex, tvb, *offset, 2, val); |
749 | 21 | proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", val); |
750 | 75 | } else if (exponent != 31) { |
751 | 62 | val = ldexpf((float)(mantissa + 1024), exponent - 25); |
752 | 62 | if (half & 0x8000) { |
753 | 55 | val = -val; |
754 | 55 | } |
755 | 62 | proto_tree_add_float(tree, hfindex, tvb, *offset, 2, val); |
756 | 62 | proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", val); |
757 | 62 | } else { |
758 | 13 | snprintf(value, sizeof(value), "%s%s", half & 0x8000 ? "-" : "", mantissa == 0 ? "inf" : "nan"); |
759 | 13 | proto_tree_add_float_format_value(tree, hfindex, tvb, *offset, 2, 0, "%s", value); |
760 | 13 | proto_item_set_text(item, "Float: %s", value); |
761 | 13 | } |
762 | 96 | } |
763 | | |
764 | | static bool |
765 | | dissect_cbor_float_simple_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor) |
766 | 3.73k | { |
767 | 3.73k | uint32_t simple; |
768 | 3.73k | float f_value; |
769 | 3.73k | double d_value; |
770 | 3.73k | proto_item *item; |
771 | 3.73k | proto_tree *subtree; |
772 | | |
773 | 3.73k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_float_simple, tvb, *offset, -1, ENC_NA); |
774 | 3.73k | subtree = proto_item_add_subtree(item, ett_cbor_float_simple); |
775 | | |
776 | 3.73k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
777 | | |
778 | 3.73k | if (type_minor <= 0x17) { |
779 | 1.26k | proto_tree_add_item_ret_uint(subtree, hf_cbor_type_simple_data5, tvb, *offset, 1, ENC_BIG_ENDIAN, &simple); |
780 | 1.26k | proto_item_set_text(item, "Simple: %s (%u)", val_to_str_const(simple, vals_simple_data, "Unknown"), simple); |
781 | 2.47k | } else { |
782 | 2.47k | proto_tree_add_item(subtree, hf_cbor_item_float_simple_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
783 | 2.47k | } |
784 | 3.73k | *offset += 1; |
785 | | |
786 | 3.73k | switch (type_minor) { |
787 | 172 | case 0x18: |
788 | 172 | proto_tree_add_item_ret_uint(subtree, hf_cbor_type_simple_data8, tvb, *offset, 1, ENC_BIG_ENDIAN, &simple); |
789 | 172 | proto_item_set_text(item, "Simple: %s (%u)", val_to_str_const(simple, vals_simple_data, "Unknown"), simple); |
790 | 172 | *offset += 1; |
791 | 172 | break; |
792 | 96 | case 0x19: |
793 | 96 | decode_half(tvb, subtree, item, offset, hf_cbor_type_float16); |
794 | 96 | *offset += 2; |
795 | 96 | break; |
796 | 11 | case 0x1a: |
797 | 11 | f_value = tvb_get_ntohieee_float(tvb, *offset); |
798 | 11 | proto_tree_add_item(subtree, hf_cbor_type_float32, tvb, *offset, 4, ENC_BIG_ENDIAN); |
799 | 11 | proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", f_value); |
800 | 11 | *offset += 4; |
801 | 11 | break; |
802 | 51 | case 0x1b: |
803 | 51 | d_value = tvb_get_ntohieee_double(tvb, *offset); |
804 | 51 | proto_tree_add_item(subtree, hf_cbor_type_float64, tvb, *offset, 8, ENC_BIG_ENDIAN); |
805 | 51 | proto_item_set_text(item, "Float: %." G_STRINGIFY(DBL_DIG) "g", d_value); |
806 | 51 | *offset += 8; |
807 | 51 | break; |
808 | 2.13k | case 0x1f: |
809 | 2.13k | proto_item_set_text(item, "Break indefinite length (%u)", type_minor); |
810 | 2.13k | break; |
811 | 1.26k | default: |
812 | 1.26k | if (type_minor > 0x17) { |
813 | 4 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
814 | 4 | "invalid minor type %i in simple data and float", type_minor); |
815 | 4 | return false; |
816 | 4 | } |
817 | 1.26k | break; |
818 | 3.73k | } |
819 | | |
820 | 3.72k | proto_item_set_end(item, tvb, *offset); |
821 | | |
822 | 3.72k | return true; |
823 | 3.73k | } |
824 | | |
825 | | |
826 | | static bool |
827 | | // NOLINTNEXTLINE(misc-no-recursion) |
828 | | dissect_cbor_main_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset) |
829 | 17.6k | { |
830 | 17.6k | uint8_t type; |
831 | 17.6k | uint8_t type_major; |
832 | 17.6k | uint8_t type_minor; |
833 | | |
834 | 17.6k | type = tvb_get_uint8(tvb, *offset); |
835 | | |
836 | 17.6k | type_major = (type & 0xe0) >> 5; |
837 | 17.6k | type_minor = (type & 0x1f); |
838 | | |
839 | 17.6k | unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor); |
840 | | |
841 | | /* dissect_cbor_main_type and dissect_cbor_tag/dissect_cbor_map can exhaust |
842 | | * the stack calling each other recursively on malformed packets otherwise */ |
843 | 17.6k | if (recursion_depth > prefs.gui_max_tree_depth) { |
844 | 0 | proto_tree_add_expert(cbor_tree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0); |
845 | 0 | return false; |
846 | 0 | } |
847 | 17.6k | p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1); |
848 | | |
849 | 17.6k | bool valid = false; |
850 | 17.6k | switch (type_major) { |
851 | 6.66k | case CBOR_TYPE_USIGNED_INT: |
852 | 6.66k | valid = dissect_cbor_unsigned_integer(tvb, pinfo, cbor_tree, offset, type_minor); |
853 | 6.66k | break; |
854 | 1.70k | case CBOR_TYPE_NEGATIVE_INT: |
855 | 1.70k | valid = dissect_cbor_negative_integer(tvb, pinfo, cbor_tree, offset, type_minor); |
856 | 1.70k | break; |
857 | 532 | case CBOR_TYPE_BYTE_STRING: |
858 | 532 | valid = dissect_cbor_byte_string(tvb, pinfo, cbor_tree, offset, type_minor); |
859 | 532 | break; |
860 | 896 | case CBOR_TYPE_TEXT_STRING: |
861 | 896 | valid = dissect_cbor_text_string(tvb, pinfo, cbor_tree, offset, type_minor); |
862 | 896 | break; |
863 | 1.57k | case CBOR_TYPE_ARRAY: |
864 | 1.57k | valid = dissect_cbor_array(tvb, pinfo, cbor_tree, offset, type_minor); |
865 | 1.57k | break; |
866 | 1.03k | case CBOR_TYPE_MAP: |
867 | 1.03k | valid = dissect_cbor_map(tvb, pinfo, cbor_tree, offset, type_minor); |
868 | 1.03k | break; |
869 | 1.50k | case CBOR_TYPE_TAGGED: |
870 | 1.50k | valid = dissect_cbor_tag(tvb, pinfo, cbor_tree, offset, type_minor); |
871 | 1.50k | break; |
872 | 3.69k | case CBOR_TYPE_FLOAT: |
873 | 3.69k | valid = dissect_cbor_float_simple_data(tvb, pinfo, cbor_tree, offset, type_minor); |
874 | 3.69k | break; |
875 | 0 | default: |
876 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
877 | 17.6k | } |
878 | | |
879 | 16.5k | p_set_proto_depth(pinfo, proto_cbor, recursion_depth); |
880 | 16.5k | return valid; |
881 | 17.6k | } |
882 | | |
883 | | static int |
884 | | dissect_cbor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_) |
885 | 5.70k | { |
886 | 5.70k | int offset = 0; |
887 | 5.70k | proto_item *cbor_root; |
888 | 5.70k | proto_tree *cbor_tree; |
889 | | |
890 | 5.70k | cbor_root = proto_tree_add_item(parent_tree, proto_cbor, tvb, offset, -1, ENC_NA); |
891 | 5.70k | cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor); |
892 | 5.70k | dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset); |
893 | | |
894 | 5.70k | proto_item_set_len(cbor_root, offset); |
895 | 5.70k | return offset; |
896 | 5.70k | } |
897 | | |
898 | | static int |
899 | | dissect_cborseq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_) |
900 | 84 | { |
901 | 84 | int offset = 0; |
902 | 84 | proto_item *cbor_root; |
903 | 84 | proto_tree *cbor_tree; |
904 | | |
905 | 84 | cbor_root = proto_tree_add_item(parent_tree, proto_cbor, tvb, offset, -1, ENC_NA); |
906 | 84 | proto_item_append_text(cbor_root, " Sequence"); |
907 | 84 | cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor); |
908 | 2.25k | while ((unsigned)offset < tvb_reported_length(tvb)) { |
909 | 2.21k | if (!dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset)) { |
910 | 46 | break; |
911 | 46 | } |
912 | 2.21k | } |
913 | | |
914 | 84 | return offset; |
915 | 84 | } |
916 | | |
917 | 0 | bool cbor_heuristic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
918 | 0 | int offset = 0; |
919 | 0 | volatile int count = 0; |
920 | |
|
921 | 0 | while ((unsigned)offset < tvb_reported_length(tvb)) { |
922 | 0 | volatile bool valid = false; |
923 | 0 | TRY { |
924 | 0 | valid = wscbor_skip_next_item(pinfo->pool, tvb, &offset); |
925 | 0 | } |
926 | 0 | CATCH_BOUNDS_AND_DISSECTOR_ERRORS {} |
927 | 0 | ENDTRY; |
928 | 0 | if (!valid) { |
929 | 0 | break; |
930 | 0 | } |
931 | 0 | ++count; |
932 | 0 | } |
933 | | |
934 | | // Anything went wrong with any part of the data |
935 | 0 | if ((count == 0) || ((unsigned)offset != tvb_reported_length(tvb))) { |
936 | 0 | return false; |
937 | 0 | } |
938 | | |
939 | 0 | if (count == 1) { |
940 | 0 | call_dissector(cbor_handle, tvb, pinfo, tree); |
941 | 0 | } |
942 | 0 | else { |
943 | 0 | call_dissector(cborseq_handle, tvb, pinfo, tree); |
944 | 0 | } |
945 | 0 | return true; |
946 | 0 | } |
947 | | |
948 | | void |
949 | | proto_register_cbor(void) |
950 | 14 | { |
951 | 14 | static hf_register_info hf[] = { |
952 | 14 | { &hf_cbor_item_major_type, |
953 | 14 | { "Major Type", "cbor.item.major_type", |
954 | 14 | FT_UINT8, BASE_DEC, VALS(major_type_vals), 0xe0, |
955 | 14 | NULL, HFILL } |
956 | 14 | }, |
957 | 14 | { &hf_cbor_item_integer_size, |
958 | 14 | { "Size", "cbor.item.size", |
959 | 14 | FT_UINT8, BASE_DEC, VALS(integer_size_vals), 0x1f, |
960 | 14 | NULL, HFILL } |
961 | 14 | }, |
962 | 14 | { &hf_cbor_item_length_size, |
963 | 14 | { "Size", "cbor.item.size", |
964 | 14 | FT_UINT8, BASE_DEC, VALS(length_size_vals), 0x1f, |
965 | 14 | NULL, HFILL } |
966 | 14 | }, |
967 | 14 | { &hf_cbor_item_length5, |
968 | 14 | { "Length", "cbor.item.length5", |
969 | 14 | FT_UINT8, BASE_DEC, NULL, 0x1f, |
970 | 14 | NULL, HFILL } |
971 | 14 | }, |
972 | 14 | { &hf_cbor_item_length, |
973 | 14 | { "Length", "cbor.item.length", |
974 | 14 | FT_UINT64, BASE_DEC, NULL, 0x00, |
975 | 14 | NULL, HFILL } |
976 | 14 | }, |
977 | 14 | { &hf_cbor_item_items5, |
978 | 14 | { "Items", "cbor.item.items5", |
979 | 14 | FT_UINT8, BASE_DEC, NULL, 0x1f, |
980 | 14 | NULL, HFILL } |
981 | 14 | }, |
982 | 14 | { &hf_cbor_item_items, |
983 | 14 | { "Items", "cbor.item.items", |
984 | 14 | FT_UINT64, BASE_DEC, NULL, 0x00, |
985 | 14 | NULL, HFILL } |
986 | 14 | }, |
987 | 14 | { &hf_cbor_item_pairs5, |
988 | 14 | { "Pairs", "cbor.item.pairs", |
989 | 14 | FT_UINT8, BASE_DEC, NULL, 0x1f, |
990 | 14 | NULL, HFILL } |
991 | 14 | }, |
992 | 14 | { &hf_cbor_item_pairs, |
993 | 14 | { "Pairs", "cbor.item.pairs", |
994 | 14 | FT_UINT64, BASE_DEC, NULL, 0x00, |
995 | 14 | NULL, HFILL } |
996 | 14 | }, |
997 | 14 | { &hf_cbor_item_float_simple_type, |
998 | 14 | { "Type", "cbor.item.float_simple_type", |
999 | 14 | FT_UINT8, BASE_DEC, VALS(float_simple_type_vals), 0x1f, |
1000 | 14 | NULL, HFILL } |
1001 | 14 | }, |
1002 | 14 | { &hf_cbor_item_unsigned_integer, |
1003 | 14 | { "Unsigned Integer", "cbor.item.unsigned_integer", |
1004 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
1005 | 14 | NULL, HFILL } |
1006 | 14 | }, |
1007 | 14 | { &hf_cbor_item_negative_integer, |
1008 | 14 | { "Negative Integer", "cbor.item.negative_integer", |
1009 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
1010 | 14 | NULL, HFILL } |
1011 | 14 | }, |
1012 | 14 | { &hf_cbor_item_text_string, |
1013 | 14 | { "Text String", "cbor.item.textstring", |
1014 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
1015 | 14 | NULL, HFILL } |
1016 | 14 | }, |
1017 | 14 | { &hf_cbor_item_byte_string, |
1018 | 14 | { "Byte String", "cbor.item.bytestring", |
1019 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
1020 | 14 | NULL, HFILL } |
1021 | 14 | }, |
1022 | 14 | { &hf_cbor_item_array, |
1023 | 14 | { "Array", "cbor.item.array", |
1024 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
1025 | 14 | NULL, HFILL } |
1026 | 14 | }, |
1027 | 14 | { &hf_cbor_item_map, |
1028 | 14 | { "Map", "cbor.item.map", |
1029 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
1030 | 14 | NULL, HFILL } |
1031 | 14 | }, |
1032 | 14 | { &hf_cbor_item_tag, |
1033 | 14 | { "Tag", "cbor.item.tag", |
1034 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
1035 | 14 | NULL, HFILL } |
1036 | 14 | }, |
1037 | 14 | { &hf_cbor_item_float_simple, |
1038 | 14 | { "Floating-point or Simple", "cbor.item.float_or_simple", |
1039 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
1040 | 14 | NULL, HFILL } |
1041 | 14 | }, |
1042 | 14 | { &hf_cbor_type_uint5, |
1043 | 14 | { "Unsigned Integer", "cbor.type.uint", |
1044 | 14 | FT_UINT8, BASE_DEC, NULL, 0x1f, |
1045 | 14 | NULL, HFILL } |
1046 | 14 | }, |
1047 | 14 | { &hf_cbor_type_uint, |
1048 | 14 | { "Unsigned Integer", "cbor.type.uint", |
1049 | 14 | FT_UINT64, BASE_DEC, NULL, 0x00, |
1050 | 14 | NULL, HFILL } |
1051 | 14 | }, |
1052 | 14 | { &hf_cbor_type_nint, |
1053 | 14 | { "Negative Integer", "cbor.type.nint", |
1054 | 14 | FT_INT64, BASE_DEC, NULL, 0x00, |
1055 | 14 | NULL, HFILL } |
1056 | 14 | }, |
1057 | 14 | { &hf_cbor_type_byte_string, |
1058 | 14 | { "Byte String", "cbor.type.bytestring", |
1059 | 14 | FT_BYTES, BASE_NONE, NULL, 0x00, |
1060 | 14 | NULL, HFILL } |
1061 | 14 | }, |
1062 | 14 | { &hf_cbor_type_byte_string_indef, |
1063 | 14 | { "Byte String (indefinite length)", "cbor.type.bytestring.indef", |
1064 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, |
1065 | 14 | NULL, HFILL } |
1066 | 14 | }, |
1067 | 14 | { &hf_cbor_type_text_string, |
1068 | 14 | { "Text String", "cbor.type.textstring", |
1069 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
1070 | 14 | NULL, HFILL } |
1071 | 14 | }, |
1072 | 14 | { &hf_cbor_type_text_string_indef, |
1073 | 14 | { "Text String (indefinite length)", "cbor.type.textstring.indef", |
1074 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, |
1075 | 14 | NULL, HFILL } |
1076 | 14 | }, |
1077 | 14 | { &hf_cbor_type_tag, |
1078 | 14 | { "Tag", "cbor.type.tag", |
1079 | 14 | FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(tag64_vals), 0x00, |
1080 | 14 | NULL, HFILL } |
1081 | 14 | }, |
1082 | 14 | { &hf_cbor_type_simple_data5, |
1083 | 14 | { "Simple data", "cbor.type.simple_data", |
1084 | 14 | FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x1f, |
1085 | 14 | NULL, HFILL } |
1086 | 14 | }, |
1087 | 14 | { &hf_cbor_type_simple_data8, |
1088 | 14 | { "Simple data", "cbor.type.simple_data", |
1089 | 14 | FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x00, |
1090 | 14 | NULL, HFILL } |
1091 | 14 | }, |
1092 | 14 | { &hf_cbor_type_float16, |
1093 | 14 | { "Float 16 Bit", "cbor.type.float16", |
1094 | 14 | FT_FLOAT, BASE_NONE, NULL, 0x00, |
1095 | 14 | NULL, HFILL } |
1096 | 14 | }, |
1097 | 14 | { &hf_cbor_type_float32, |
1098 | 14 | { "Float 32 Bit", "cbor.type.float32", |
1099 | 14 | FT_FLOAT, BASE_NONE, NULL, 0x00, |
1100 | 14 | NULL, HFILL } |
1101 | 14 | }, |
1102 | 14 | { &hf_cbor_type_float64, |
1103 | 14 | { "Float 64 Bit", "cbor.type.float64", |
1104 | 14 | FT_DOUBLE, BASE_NONE, NULL, 0x00, |
1105 | 14 | NULL, HFILL } |
1106 | 14 | }, |
1107 | 14 | }; |
1108 | | |
1109 | 14 | static int *ett[] = { |
1110 | 14 | &ett_cbor, |
1111 | 14 | &ett_cbor_type, |
1112 | 14 | &ett_cbor_unsigned_integer, |
1113 | 14 | &ett_cbor_negative_integer, |
1114 | 14 | &ett_cbor_byte_string, |
1115 | 14 | &ett_cbor_byte_string_indef, |
1116 | 14 | &ett_cbor_text_string, |
1117 | 14 | &ett_cbor_text_string_indef, |
1118 | 14 | &ett_cbor_array, |
1119 | 14 | &ett_cbor_map, |
1120 | 14 | &ett_cbor_tag, |
1121 | 14 | &ett_cbor_float_simple |
1122 | 14 | }; |
1123 | | |
1124 | 14 | static ei_register_info ei[] = { |
1125 | 14 | { &ei_cbor_invalid_minor_type, |
1126 | 14 | { "cbor.invalid_minor_type", PI_MALFORMED, PI_WARN, "Invalid minor type", EXPFILL }}, |
1127 | 14 | { &ei_cbor_invalid_element, |
1128 | 14 | { "cbor.invalid_element", PI_MALFORMED, PI_WARN, "Invalid element", EXPFILL }}, |
1129 | 14 | { &ei_cbor_too_long_length, |
1130 | 14 | { "cbor.too_long_length", PI_MALFORMED, PI_WARN, "Too long length", EXPFILL }}, |
1131 | 14 | { &ei_cbor_max_recursion_depth_reached, |
1132 | 14 | { "cbor.max_recursion_depth_reached", PI_PROTOCOL, PI_WARN, "Maximum allowed recursion depth reached. Dissection stopped.", EXPFILL }}, |
1133 | 14 | { &ei_cbor_embedded_bstr, |
1134 | 14 | { "cbor.embedded_bstr", PI_COMMENTS_GROUP, PI_COMMENT, "Heuristic dissection of CBOR embedded in a byte string", EXPFILL }}, |
1135 | 14 | }; |
1136 | | |
1137 | 14 | expert_module_t *expert_cbor; |
1138 | | |
1139 | 14 | proto_cbor = proto_register_protocol("Concise Binary Object Representation", "CBOR", "cbor"); |
1140 | 14 | proto_register_field_array(proto_cbor, hf, array_length(hf)); |
1141 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1142 | 14 | expert_cbor = expert_register_protocol(proto_cbor); |
1143 | 14 | expert_register_field_array(expert_cbor, ei, array_length(ei)); |
1144 | | |
1145 | 14 | cbor_handle = register_dissector("cbor", dissect_cbor, proto_cbor); |
1146 | 14 | cborseq_handle = register_dissector_with_description("cborseq", "CBOR Sequence", dissect_cborseq, proto_cbor); |
1147 | | |
1148 | 14 | module_t *module_cbor = prefs_register_protocol(proto_cbor, NULL); |
1149 | 14 | prefs_register_bool_preference( |
1150 | 14 | module_cbor, |
1151 | 14 | "dissect_embeded_bstr", /* mispelt but best leave */ |
1152 | 14 | "Dissect bstr-embedded CBOR", |
1153 | 14 | "If enabled, a heuristic dissection of byte strings as embedded " |
1154 | 14 | "CBOR/sequence is performed.", |
1155 | 14 | &cbor_dissect_embeded_bstr |
1156 | 14 | ); |
1157 | | |
1158 | 14 | } |
1159 | | |
1160 | | void |
1161 | | proto_reg_handoff_cbor(void) |
1162 | 14 | { |
1163 | 14 | dissector_add_string("media_type", "application/cbor", cbor_handle); /* RFC 8949 */ |
1164 | 14 | dissector_add_string("media_type", "application/cwt", cbor_handle); /* RFC 8392 */ |
1165 | 14 | dissector_add_string("media_type", "application/cbor-seq", cborseq_handle); /* RFC 8742 */ |
1166 | | |
1167 | 14 | dissector_add_string("media_type.suffix", "cbor", cbor_handle); /* RFC 8949 */ |
1168 | 14 | dissector_add_string("media_type.suffix", "cbor-seq", cborseq_handle); /* RFC 8742 */ |
1169 | 14 | } |
1170 | | |
1171 | | /* |
1172 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1173 | | * |
1174 | | * Local variables: |
1175 | | * c-basic-offset: 8 |
1176 | | * tab-width: 8 |
1177 | | * indent-tabs-mode: t |
1178 | | * End: |
1179 | | * |
1180 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
1181 | | * :indentSize=8:tabSize=8:noTabs=false: |
1182 | | */ |