Coverage Report

Created: 2025-08-04 07:15

/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
19.4k
#define CBOR_TYPE_USIGNED_INT   0
92
5.97k
#define CBOR_TYPE_NEGATIVE_INT  1
93
1.31k
#define CBOR_TYPE_BYTE_STRING   2
94
2.62k
#define CBOR_TYPE_TEXT_STRING   3
95
5.42k
#define CBOR_TYPE_ARRAY   4
96
3.92k
#define CBOR_TYPE_MAP   5
97
4.95k
#define CBOR_TYPE_TAGGED  6
98
8.63k
#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
19.4k
{
208
19.4k
  uint64_t value = 0;
209
19.4k
  proto_item *item;
210
19.4k
  proto_tree *subtree;
211
212
19.4k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_unsigned_integer, tvb, *offset, -1, ENC_NA);
213
19.4k
  subtree = proto_item_add_subtree(item, ett_cbor_unsigned_integer);
214
215
19.4k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
216
19.4k
  if (type_minor <= 0x17) {
217
19.0k
    proto_tree_add_item(subtree, hf_cbor_type_uint5, tvb, *offset, 1, ENC_BIG_ENDIAN);
218
19.0k
    value = type_minor;
219
19.0k
  } else {
220
428
    proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
221
428
  }
222
19.4k
  *offset += 1;
223
224
19.4k
  switch (type_minor) {
225
282
  case 0x18:
226
282
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 1, ENC_BIG_ENDIAN, &value);
227
282
    *offset += 1;
228
282
    break;
229
58
  case 0x19:
230
58
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 2, ENC_BIG_ENDIAN, &value);
231
58
    *offset += 2;
232
58
    break;
233
42
  case 0x1a:
234
42
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 4, ENC_BIG_ENDIAN, &value);
235
42
    *offset += 4;
236
42
    break;
237
26
  case 0x1b:
238
26
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 8, ENC_BIG_ENDIAN, &value);
239
26
    *offset += 8;
240
26
    break;
241
19.0k
  default:
242
19.0k
    if (type_minor > 0x17) {
243
20
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
244
20
          "invalid minor type %i in unsigned integer", type_minor);
245
20
      return false;
246
20
    }
247
19.0k
    break;
248
19.4k
  }
249
250
19.4k
  proto_item_append_text(item, ": %" PRIu64, value);
251
19.4k
  proto_item_set_end(item, tvb, *offset);
252
253
19.4k
  return true;
254
19.4k
}
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
5.97k
{
259
5.97k
  int64_t value = 0;
260
5.97k
  proto_item *item;
261
5.97k
  proto_tree *subtree;
262
263
5.97k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_negative_integer, tvb, *offset, -1, ENC_NA);
264
5.97k
  subtree = proto_item_add_subtree(item, ett_cbor_negative_integer);
265
266
5.97k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
267
5.97k
  if (type_minor <= 0x17) {
268
4.28k
    value = (int64_t)-1 - type_minor;
269
    /* Keep correct bit representation with a modified value. */
270
4.28k
    proto_tree_add_int64_bits_format_value(subtree, hf_cbor_type_nint, tvb, 3, 5, type_minor, ENC_BIG_ENDIAN, "%" PRId64, value);
271
4.28k
  } else {
272
1.68k
    proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
273
1.68k
  }
274
5.97k
  *offset += 1;
275
276
5.97k
  switch (type_minor) {
277
877
  case 0x18:
278
877
    value = (int64_t)-1 - tvb_get_uint8(tvb, *offset);
279
877
    proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 1, value);
280
877
    *offset += 1;
281
877
    break;
282
201
  case 0x19:
283
201
    value = (int64_t)-1 - tvb_get_ntohs(tvb, *offset);
284
201
    proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 2, value);
285
201
    *offset += 2;
286
201
    break;
287
401
  case 0x1a:
288
401
    value = (int64_t)-1 - tvb_get_ntohl(tvb, *offset);
289
401
    proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 4, value);
290
401
    *offset += 4;
291
401
    break;
292
181
  case 0x1b:
293
    /* TODO: an overflow could happen here, for negative int < INT64_MIN */
294
181
    value = (int64_t)-1 - tvb_get_ntoh64(tvb, *offset);
295
181
    if (value > -1) {
296
48
      expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length,
297
48
        "The value is too small, Wireshark can not display it correctly");
298
48
    }
299
181
    proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 8, value);
300
181
    *offset += 8;
301
181
    break;
302
4.31k
  default:
303
4.31k
    if (type_minor > 0x17) {
304
22
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
305
22
          "invalid minor type %i in negative integer", type_minor);
306
22
      return false;
307
22
    }
308
4.28k
    break;
309
5.97k
  }
310
311
5.94k
  proto_item_append_text(item, ": %" PRId64, value);
312
5.94k
  proto_item_set_end(item, tvb, *offset);
313
314
5.94k
  return true;
315
5.97k
}
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
1.29k
{
321
1.29k
  uint64_t length;
322
1.29k
  int      eof_type;
323
1.29k
  proto_tree *subtree;
324
1.29k
  proto_item *item;
325
326
1.29k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_byte_string, tvb, *offset, -1, ENC_NA);
327
1.29k
  subtree = proto_item_add_subtree(item, ett_cbor_byte_string);
328
329
1.29k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
330
1.29k
  if (type_minor <= 0x17) {
331
988
    proto_tree_add_item(subtree, hf_cbor_item_length5, tvb, *offset, 1, ENC_BIG_ENDIAN);
332
988
    length = type_minor;
333
988
  } else {
334
305
    proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
335
305
  }
336
1.29k
  *offset += 1;
337
338
1.29k
  switch (type_minor) {
339
36
  case 0x18:
340
36
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 1, ENC_BIG_ENDIAN, &length);
341
36
    *offset += 1;
342
36
    break;
343
14
  case 0x19:
344
14
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 2, ENC_BIG_ENDIAN, &length);
345
14
    *offset += 2;
346
14
    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
12
  case 0x1b:
352
12
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 8, ENC_BIG_ENDIAN, &length);
353
12
    *offset += 8;
354
12
    break;
355
228
  case 0x1f:
356
228
    proto_item_append_text(item, ": (indefinite length)");
357
228
    item = proto_tree_add_item(subtree, hf_cbor_type_byte_string_indef, tvb, *offset, 1, ENC_NA);
358
228
    subtree = proto_item_add_subtree(item, ett_cbor_byte_string_indef);
359
271
    while (1) {
360
255
      eof_type = tvb_get_uint8(tvb, *offset);
361
255
      if (eof_type == 0xff) {
362
30
        dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f);
363
30
        proto_item_set_end(item, tvb, *offset);
364
30
        return true;
365
30
      }
366
367
225
      if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_BYTE_STRING) {
368
15
        expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_element,
369
15
          "invalid element %i, expected byte string", (eof_type & 0xe0) >> 5);
370
15
        return false;
371
15
      }
372
373
210
      unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor);
374
210
      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
210
      p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1);
379
380
210
      bool recursed = dissect_cbor_byte_string(tvb, pinfo, subtree, offset, eof_type & 0x1f);
381
210
      p_set_proto_depth(pinfo, proto_cbor, recursion_depth);
382
383
210
      if (!recursed) {
384
167
        return false;
385
167
      }
386
210
    }
387
16
    DISSECTOR_ASSERT_NOT_REACHED();
388
16
    return false;
389
999
  default:
390
999
    if (type_minor > 0x17) {
391
11
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
392
11
          "invalid minor type %i in byte string", type_minor);
393
11
      return false;
394
11
    }
395
988
    break;
396
1.29k
  }
397
398
1.05k
  if (length > INT32_MAX || *offset + (int)length < *offset) {
399
10
    expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length,
400
10
      "the length (%" PRIu64 ") of the byte string too long", length);
401
10
    return false;
402
10
  }
403
404
1.04k
  proto_item *item_data = proto_tree_add_item(subtree, hf_cbor_type_byte_string, tvb, *offset, (int)length, ENC_NA);
405
1.04k
  *offset += (int)length;
406
407
1.04k
  proto_item_append_text(item, ": (%" PRIu64 " byte%s)", length, plurality(length, "", "s"));
408
1.04k
  proto_item_set_end(item, tvb, *offset);
409
410
1.04k
  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
1.04k
  return true;
419
1.05k
}
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
2.57k
{
425
2.57k
  const uint8_t *value = NULL;
426
2.57k
  uint64_t length = 0;
427
2.57k
  int      eof_type;
428
2.57k
  proto_tree *subtree;
429
2.57k
  proto_item *item;
430
431
2.57k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_text_string, tvb, *offset, -1, ENC_NA);
432
2.57k
  subtree = proto_item_add_subtree(item, ett_cbor_text_string);
433
434
2.57k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
435
2.57k
  if (type_minor <= 0x17) {
436
1.68k
    proto_tree_add_item(subtree, hf_cbor_item_length5, tvb, *offset, 1, ENC_BIG_ENDIAN);
437
1.68k
    length = type_minor;
438
1.68k
  } else {
439
889
    proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
440
889
  }
441
2.57k
  *offset += 1;
442
443
2.57k
  switch (type_minor) {
444
43
  case 0x18:
445
43
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 1, ENC_BIG_ENDIAN, &length);
446
43
    *offset += 1;
447
43
    break;
448
11
  case 0x19:
449
11
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 2, ENC_BIG_ENDIAN, &length);
450
11
    *offset += 2;
451
11
    break;
452
16
  case 0x1a:
453
16
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 4, ENC_BIG_ENDIAN, &length);
454
16
    *offset += 4;
455
16
    break;
456
13
  case 0x1b:
457
13
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 8, ENC_BIG_ENDIAN, &length);
458
13
    *offset += 8;
459
13
    break;
460
795
  case 0x1f:
461
795
    proto_item_append_text(item, ": (indefinite length)");
462
795
    item = proto_tree_add_item(subtree, hf_cbor_type_text_string_indef, tvb, *offset, 1, ENC_NA);
463
795
    subtree = proto_item_add_subtree(item, ett_cbor_text_string_indef);
464
1.18k
    while (1) {
465
1.13k
      eof_type = tvb_get_uint8(tvb, *offset);
466
1.13k
      if (eof_type == 0xff) {
467
308
        dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f);
468
308
        proto_item_set_end(item, tvb, *offset);
469
308
        return true;
470
308
      }
471
472
828
      if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_TEXT_STRING) {
473
22
        expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_element,
474
22
          "invalid element %i, expected text string", (eof_type & 0xe0) >> 5);
475
22
        return false;
476
22
      }
477
478
806
      unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor);
479
806
      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
806
      p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1);
484
485
806
      bool recursed = dissect_cbor_text_string(tvb, pinfo, subtree, offset, eof_type & 0x1f);
486
806
      p_set_proto_depth(pinfo, proto_cbor, recursion_depth);
487
488
806
      if (!recursed) {
489
421
        return false;
490
421
      }
491
806
    }
492
44
    DISSECTOR_ASSERT_NOT_REACHED();
493
44
    return false;
494
1.69k
  default:
495
1.69k
    if (type_minor > 0x17) {
496
11
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
497
11
          "invalid minor type %i in text string", type_minor);
498
11
      return false;
499
11
    }
500
1.68k
    break;
501
2.57k
  }
502
503
1.76k
  if (length > INT32_MAX || *offset + (int)length < *offset) {
504
12
    expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length,
505
12
      "the length (%" PRIu64 ") of the text string too long", length);
506
12
    return false;
507
12
  }
508
509
1.75k
  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
1.75k
  *offset += (int)length;
511
512
1.75k
  proto_item_append_text(item, ": %s", value);
513
1.75k
  proto_item_set_end(item, tvb, *offset);
514
515
1.75k
  return true;
516
1.76k
}
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
5.42k
{
522
5.42k
  uint64_t length = 0;
523
5.42k
  proto_tree *subtree;
524
5.42k
  proto_item *item;
525
5.42k
  bool        indefinite = false;
526
527
5.42k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_array, tvb, *offset, -1, ENC_NA);
528
5.42k
  subtree = proto_item_add_subtree(item, ett_cbor_array);
529
530
5.42k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
531
532
5.42k
  if (type_minor <= 0x17) {
533
3.66k
    proto_tree_add_item(subtree, hf_cbor_item_items5, tvb, *offset, 1, ENC_BIG_ENDIAN);
534
3.66k
    length = type_minor;
535
3.66k
  } else {
536
1.75k
    proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
537
1.75k
  }
538
5.42k
  *offset += 1;
539
540
5.42k
  switch (type_minor) {
541
234
  case 0x18:
542
234
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 1, ENC_BIG_ENDIAN, &length);
543
234
    *offset += 1;
544
234
    break;
545
175
  case 0x19:
546
175
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 2, ENC_BIG_ENDIAN, &length);
547
175
    *offset += 2;
548
175
    break;
549
127
  case 0x1a:
550
127
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 4, ENC_BIG_ENDIAN, &length);
551
127
    *offset += 4;
552
127
    break;
553
112
  case 0x1b:
554
112
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 8, ENC_BIG_ENDIAN, &length);
555
112
    *offset += 8;
556
112
    break;
557
1.10k
  case 0x1f:
558
1.10k
    length = INT_MAX;
559
1.10k
    indefinite = true;
560
1.10k
    break;
561
3.66k
  default:
562
3.66k
    if (type_minor > 0x17) {
563
4
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
564
4
          "invalid minor type %i in array", type_minor);
565
4
      return false;
566
4
    }
567
3.66k
    break;
568
5.42k
  }
569
570
19.4k
  for (uint64_t i = 0; i < length; i++) {
571
15.7k
    if (indefinite) {
572
2.51k
      int value = tvb_get_uint8(tvb, *offset);
573
2.51k
      if (value == 0xff) {
574
311
        dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f);
575
311
        break;
576
311
      }
577
2.51k
    }
578
579
15.4k
    if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset)) {
580
1.43k
      return false;
581
1.43k
    }
582
15.4k
  }
583
584
3.97k
  if (indefinite) {
585
311
    proto_item_append_text(item, ": (indefinite length)");
586
3.66k
  } else {
587
3.66k
    proto_item_append_text(item, ": (%" PRIu64 " item%s)", length, plurality(length, "", "s"));
588
3.66k
  }
589
3.97k
  proto_item_set_end(item, tvb, *offset);
590
591
3.97k
  return true;
592
5.41k
}
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
3.92k
{
598
3.92k
  uint64_t    length = 0;
599
3.92k
  proto_tree *subtree;
600
3.92k
  proto_item *item;
601
3.92k
  bool        indefinite = false;
602
603
3.92k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_map, tvb, *offset, -1, ENC_NA);
604
3.92k
  subtree = proto_item_add_subtree(item, ett_cbor_map);
605
606
3.92k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
607
608
3.92k
  if (type_minor <= 0x17) {
609
2.48k
    proto_tree_add_item(subtree, hf_cbor_item_pairs5, tvb, *offset, 1, ENC_BIG_ENDIAN);
610
2.48k
    length = type_minor;
611
2.48k
  } else {
612
1.44k
    proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
613
1.44k
  }
614
3.92k
  *offset += 1;
615
616
3.92k
  switch (type_minor) {
617
339
  case 0x18:
618
339
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 1, ENC_BIG_ENDIAN, &length);
619
339
    *offset += 1;
620
339
    break;
621
165
  case 0x19:
622
165
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 2, ENC_BIG_ENDIAN, &length);
623
165
    *offset += 2;
624
165
    break;
625
113
  case 0x1a:
626
113
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 4, ENC_BIG_ENDIAN, &length);
627
113
    *offset += 4;
628
113
    break;
629
200
  case 0x1b:
630
200
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 8, ENC_BIG_ENDIAN, &length);
631
200
    *offset += 8;
632
200
    break;
633
616
  case 0x1f:
634
616
    length = INT_MAX;
635
616
    indefinite = true;
636
616
    break;
637
2.49k
  default:
638
2.49k
    if (type_minor > 0x17) {
639
7
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
640
7
          "invalid minor type %i in map", type_minor);
641
7
      return false;
642
7
    }
643
2.48k
    break;
644
3.92k
  }
645
646
10.2k
  for (uint64_t i = 0; i < length; i++) {
647
7.84k
    if (indefinite) {
648
1.65k
      int value = tvb_get_uint8(tvb, *offset);
649
1.65k
      if (value == 0xff) {
650
166
        dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f);
651
166
        break;
652
166
      }
653
1.65k
    }
654
655
7.67k
    if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset)) {
656
1.21k
      return false;
657
1.21k
    }
658
659
6.46k
    if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset)) {
660
134
      return false;
661
134
    }
662
6.46k
  }
663
664
2.56k
  if (indefinite) {
665
166
    proto_item_append_text(item, ": (indefinite length)");
666
2.40k
  } else {
667
2.40k
    proto_item_append_text(item, ": (%" PRIu64 " pair%s)", length, plurality(length, "", "s"));
668
2.40k
  }
669
2.56k
  proto_item_set_end(item, tvb, *offset);
670
671
2.56k
  return true;
672
3.91k
}
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
4.95k
{
678
4.95k
  uint64_t         tag = 0;
679
4.95k
  proto_item      *item;
680
4.95k
  proto_tree      *subtree;
681
682
4.95k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_tag, tvb, *offset, -1, ENC_NA);
683
4.95k
  subtree = proto_item_add_subtree(item, ett_cbor_tag);
684
685
4.95k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
686
687
4.95k
  if (type_minor <= 0x17) {
688
4.41k
    tag = type_minor;
689
4.41k
    proto_tree_add_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 1, tag);
690
4.41k
  } else {
691
536
    proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
692
536
  }
693
4.95k
  *offset += 1;
694
695
4.95k
  switch (type_minor) {
696
293
  case 0x18:
697
293
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 1, ENC_BIG_ENDIAN, &tag);
698
293
    *offset += 1;
699
293
    break;
700
79
  case 0x19:
701
79
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 2, ENC_BIG_ENDIAN, &tag);
702
79
    *offset += 2;
703
79
    break;
704
116
  case 0x1a:
705
116
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 4, ENC_BIG_ENDIAN, &tag);
706
116
    *offset += 4;
707
116
    break;
708
34
  case 0x1b:
709
34
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 8, ENC_BIG_ENDIAN, &tag);
710
34
    *offset += 8;
711
34
    break;
712
4.43k
  default:
713
4.43k
    if (type_minor > 0x17) {
714
14
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
715
14
          "invalid minor type %i in tag", type_minor);
716
14
      return false;
717
14
    }
718
4.41k
    break;
719
4.95k
  }
720
721
4.93k
  if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset)) {
722
304
    return false;
723
304
  }
724
725
4.63k
  proto_item_append_text(item, ": %s (%" PRIu64 ")", val64_to_str_wmem(pinfo->pool, tag, tag64_vals, "Unknown"), tag);
726
4.63k
  proto_item_set_end(item, tvb, *offset);
727
728
4.63k
  return true;
729
4.93k
}
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
351
{
735
351
  char value[6];
736
351
  int half, exponent, mantissa;
737
351
  float val = 0;
738
739
351
  half = tvb_get_ntohs(tvb, *offset);
740
351
  exponent = (half >> 10) & 0x1f;
741
351
  mantissa = half & 0x3ff;
742
743
351
  if (exponent == 0) {
744
66
    val = ldexpf((float)mantissa, -24);
745
66
    if (half & 0x8000) {
746
12
      val = -val;
747
12
    }
748
66
    proto_tree_add_float(tree, hfindex, tvb, *offset, 2, val);
749
66
    proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", val);
750
285
  } else if (exponent != 31) {
751
271
    val = ldexpf((float)(mantissa + 1024), exponent - 25);
752
271
    if (half & 0x8000) {
753
232
      val = -val;
754
232
    }
755
271
    proto_tree_add_float(tree, hfindex, tvb, *offset, 2, val);
756
271
    proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", val);
757
271
  } else {
758
14
    snprintf(value, sizeof(value), "%s%s", half & 0x8000 ? "-" : "", mantissa == 0 ? "inf" : "nan");
759
14
    proto_tree_add_float_format_value(tree, hfindex, tvb, *offset, 2, 0, "%s", value);
760
14
    proto_item_set_text(item, "Float: %s", value);
761
14
  }
762
351
}
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
9.45k
{
767
9.45k
  uint32_t         simple;
768
9.45k
  float            f_value;
769
9.45k
  double           d_value;
770
9.45k
  proto_item      *item;
771
9.45k
  proto_tree      *subtree;
772
773
9.45k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_float_simple, tvb, *offset, -1, ENC_NA);
774
9.45k
  subtree = proto_item_add_subtree(item, ett_cbor_float_simple);
775
776
9.45k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
777
778
9.45k
  if (type_minor <= 0x17) {
779
2.90k
    proto_tree_add_item_ret_uint(subtree, hf_cbor_type_simple_data5, tvb, *offset, 1, ENC_BIG_ENDIAN, &simple);
780
2.90k
    proto_item_set_text(item, "Simple: %s (%u)", val_to_str_const(simple, vals_simple_data, "Unknown"), simple);
781
6.54k
  } else {
782
6.54k
    proto_tree_add_item(subtree, hf_cbor_item_float_simple_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
783
6.54k
  }
784
9.45k
  *offset += 1;
785
786
9.45k
  switch (type_minor) {
787
303
  case 0x18:
788
303
    proto_tree_add_item_ret_uint(subtree, hf_cbor_type_simple_data8, tvb, *offset, 1, ENC_BIG_ENDIAN, &simple);
789
303
    proto_item_set_text(item, "Simple: %s (%u)", val_to_str_const(simple, vals_simple_data, "Unknown"), simple);
790
303
    *offset += 1;
791
303
    break;
792
351
  case 0x19:
793
351
    decode_half(tvb, subtree, item, offset, hf_cbor_type_float16);
794
351
    *offset += 2;
795
351
    break;
796
187
  case 0x1a:
797
187
    f_value = tvb_get_ntohieee_float(tvb, *offset);
798
187
    proto_tree_add_item(subtree, hf_cbor_type_float32, tvb, *offset, 4, ENC_BIG_ENDIAN);
799
187
    proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", f_value);
800
187
    *offset += 4;
801
187
    break;
802
121
  case 0x1b:
803
121
    d_value = tvb_get_ntohieee_double(tvb, *offset);
804
121
    proto_tree_add_item(subtree, hf_cbor_type_float64, tvb, *offset, 8, ENC_BIG_ENDIAN);
805
121
    proto_item_set_text(item, "Float: %." G_STRINGIFY(DBL_DIG) "g", d_value);
806
121
    *offset += 8;
807
121
    break;
808
5.56k
  case 0x1f:
809
5.56k
    proto_item_set_text(item, "Break indefinite length (%u)", type_minor);
810
5.56k
    break;
811
2.92k
  default:
812
2.92k
    if (type_minor > 0x17) {
813
14
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
814
14
          "invalid minor type %i in simple data and float", type_minor);
815
14
      return false;
816
14
    }
817
2.90k
    break;
818
9.45k
  }
819
820
9.43k
  proto_item_set_end(item, tvb, *offset);
821
822
9.43k
  return true;
823
9.45k
}
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
51.3k
{
830
51.3k
  uint8_t     type;
831
51.3k
  uint8_t     type_major;
832
51.3k
  uint8_t     type_minor;
833
834
51.3k
  type = tvb_get_uint8(tvb, *offset);
835
836
51.3k
  type_major = (type & 0xe0) >> 5;
837
51.3k
  type_minor = (type & 0x1f);
838
839
51.3k
  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
51.3k
  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
51.3k
  p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1);
848
849
51.3k
  bool valid = false;
850
51.3k
  switch (type_major) {
851
19.4k
  case CBOR_TYPE_USIGNED_INT:
852
19.4k
    valid = dissect_cbor_unsigned_integer(tvb, pinfo, cbor_tree, offset, type_minor);
853
19.4k
    break;
854
5.97k
  case CBOR_TYPE_NEGATIVE_INT:
855
5.97k
    valid = dissect_cbor_negative_integer(tvb, pinfo, cbor_tree, offset, type_minor);
856
5.97k
    break;
857
1.08k
  case CBOR_TYPE_BYTE_STRING:
858
1.08k
    valid = dissect_cbor_byte_string(tvb, pinfo, cbor_tree, offset, type_minor);
859
1.08k
    break;
860
1.79k
  case CBOR_TYPE_TEXT_STRING:
861
1.79k
    valid = dissect_cbor_text_string(tvb, pinfo, cbor_tree, offset, type_minor);
862
1.79k
    break;
863
5.42k
  case CBOR_TYPE_ARRAY:
864
5.42k
    valid = dissect_cbor_array(tvb, pinfo, cbor_tree, offset, type_minor);
865
5.42k
    break;
866
3.92k
  case CBOR_TYPE_MAP:
867
3.92k
    valid = dissect_cbor_map(tvb, pinfo, cbor_tree, offset, type_minor);
868
3.92k
    break;
869
4.95k
  case CBOR_TYPE_TAGGED:
870
4.95k
    valid = dissect_cbor_tag(tvb, pinfo, cbor_tree, offset, type_minor);
871
4.95k
    break;
872
8.63k
  case CBOR_TYPE_FLOAT:
873
8.63k
    valid = dissect_cbor_float_simple_data(tvb, pinfo, cbor_tree, offset, type_minor);
874
8.63k
    break;
875
0
  default:
876
0
    DISSECTOR_ASSERT_NOT_REACHED();
877
51.3k
  }
878
879
47.6k
  p_set_proto_depth(pinfo, proto_cbor, recursion_depth);
880
47.6k
  return valid;
881
51.3k
}
882
883
static int
884
dissect_cbor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
885
10.3k
{
886
10.3k
  int         offset = 0;
887
10.3k
  proto_item *cbor_root;
888
10.3k
  proto_tree *cbor_tree;
889
890
10.3k
  cbor_root = proto_tree_add_item(parent_tree, proto_cbor, tvb, offset, -1, ENC_NA);
891
10.3k
  cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor);
892
10.3k
  dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset);
893
894
10.3k
  proto_item_set_len(cbor_root, offset);
895
10.3k
  return offset;
896
10.3k
}
897
898
static int
899
dissect_cborseq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
900
237
{
901
237
  int         offset = 0;
902
237
  proto_item *cbor_root;
903
237
  proto_tree *cbor_tree;
904
905
237
  cbor_root = proto_tree_add_item(parent_tree, proto_cbor, tvb, offset, -1, ENC_NA);
906
237
  proto_item_append_text(cbor_root, " Sequence");
907
237
  cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor);
908
7.83k
  while ((unsigned)offset < tvb_reported_length(tvb)) {
909
7.72k
    if (!dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset)) {
910
122
      break;
911
122
    }
912
7.72k
  }
913
914
237
  return offset;
915
237
}
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
            // A failure in any one item is a failure of the heuristic
930
0
            count = 0;
931
0
            break;
932
0
        }
933
0
        ++count;
934
0
    }
935
936
    // Anything went wrong with any part of the data
937
0
    if ((count == 0) || ((unsigned)offset != tvb_reported_length(tvb))) {
938
0
        return false;
939
0
    }
940
941
0
    if (count == 1) {
942
0
        call_dissector(cbor_handle, tvb, pinfo, tree);
943
0
    }
944
0
    else {
945
0
        call_dissector(cborseq_handle, tvb, pinfo, tree);
946
0
    }
947
0
    return true;
948
0
}
949
950
void
951
proto_register_cbor(void)
952
14
{
953
14
  static hf_register_info hf[] = {
954
14
    { &hf_cbor_item_major_type,
955
14
      { "Major Type", "cbor.item.major_type",
956
14
        FT_UINT8, BASE_DEC, VALS(major_type_vals), 0xe0,
957
14
        NULL, HFILL }
958
14
    },
959
14
    { &hf_cbor_item_integer_size,
960
14
      { "Size", "cbor.item.size",
961
14
        FT_UINT8, BASE_DEC, VALS(integer_size_vals), 0x1f,
962
14
        NULL, HFILL }
963
14
    },
964
14
    { &hf_cbor_item_length_size,
965
14
      { "Size", "cbor.item.size",
966
14
        FT_UINT8, BASE_DEC, VALS(length_size_vals), 0x1f,
967
14
        NULL, HFILL }
968
14
    },
969
14
    { &hf_cbor_item_length5,
970
14
      { "Length", "cbor.item.length5",
971
14
        FT_UINT8, BASE_DEC, NULL, 0x1f,
972
14
        NULL, HFILL }
973
14
    },
974
14
    { &hf_cbor_item_length,
975
14
      { "Length", "cbor.item.length",
976
14
        FT_UINT64, BASE_DEC, NULL, 0x00,
977
14
        NULL, HFILL }
978
14
    },
979
14
    { &hf_cbor_item_items5,
980
14
      { "Items", "cbor.item.items5",
981
14
        FT_UINT8, BASE_DEC, NULL, 0x1f,
982
14
        NULL, HFILL }
983
14
    },
984
14
    { &hf_cbor_item_items,
985
14
      { "Items", "cbor.item.items",
986
14
        FT_UINT64, BASE_DEC, NULL, 0x00,
987
14
        NULL, HFILL }
988
14
    },
989
14
    { &hf_cbor_item_pairs5,
990
14
      { "Pairs", "cbor.item.pairs",
991
14
        FT_UINT8, BASE_DEC, NULL, 0x1f,
992
14
        NULL, HFILL }
993
14
    },
994
14
    { &hf_cbor_item_pairs,
995
14
      { "Pairs", "cbor.item.pairs",
996
14
        FT_UINT64, BASE_DEC, NULL, 0x00,
997
14
        NULL, HFILL }
998
14
    },
999
14
    { &hf_cbor_item_float_simple_type,
1000
14
      { "Type", "cbor.item.float_simple_type",
1001
14
        FT_UINT8, BASE_DEC, VALS(float_simple_type_vals), 0x1f,
1002
14
        NULL, HFILL }
1003
14
    },
1004
14
    { &hf_cbor_item_unsigned_integer,
1005
14
      { "Unsigned Integer", "cbor.item.unsigned_integer",
1006
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1007
14
        NULL, HFILL }
1008
14
    },
1009
14
    { &hf_cbor_item_negative_integer,
1010
14
      { "Negative Integer", "cbor.item.negative_integer",
1011
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1012
14
        NULL, HFILL }
1013
14
    },
1014
14
    { &hf_cbor_item_text_string,
1015
14
      { "Text String", "cbor.item.textstring",
1016
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1017
14
        NULL, HFILL }
1018
14
    },
1019
14
    { &hf_cbor_item_byte_string,
1020
14
      { "Byte String", "cbor.item.bytestring",
1021
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1022
14
        NULL, HFILL }
1023
14
    },
1024
14
    { &hf_cbor_item_array,
1025
14
      { "Array", "cbor.item.array",
1026
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1027
14
        NULL, HFILL }
1028
14
    },
1029
14
    { &hf_cbor_item_map,
1030
14
      { "Map", "cbor.item.map",
1031
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1032
14
        NULL, HFILL }
1033
14
    },
1034
14
    { &hf_cbor_item_tag,
1035
14
      { "Tag", "cbor.item.tag",
1036
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1037
14
        NULL, HFILL }
1038
14
    },
1039
14
    { &hf_cbor_item_float_simple,
1040
14
      { "Floating-point or Simple", "cbor.item.float_or_simple",
1041
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1042
14
        NULL, HFILL }
1043
14
    },
1044
14
    { &hf_cbor_type_uint5,
1045
14
      { "Unsigned Integer", "cbor.type.uint",
1046
14
        FT_UINT8, BASE_DEC, NULL, 0x1f,
1047
14
        NULL, HFILL }
1048
14
    },
1049
14
    { &hf_cbor_type_uint,
1050
14
      { "Unsigned Integer", "cbor.type.uint",
1051
14
        FT_UINT64, BASE_DEC, NULL, 0x00,
1052
14
        NULL, HFILL }
1053
14
    },
1054
14
    { &hf_cbor_type_nint,
1055
14
      { "Negative Integer", "cbor.type.nint",
1056
14
        FT_INT64, BASE_DEC, NULL, 0x00,
1057
14
        NULL, HFILL }
1058
14
    },
1059
14
    { &hf_cbor_type_byte_string,
1060
14
      { "Byte String", "cbor.type.bytestring",
1061
14
        FT_BYTES, BASE_NONE, NULL, 0x00,
1062
14
        NULL, HFILL }
1063
14
    },
1064
14
    { &hf_cbor_type_byte_string_indef,
1065
14
      { "Byte String (indefinite length)", "cbor.type.bytestring.indef",
1066
14
        FT_NONE, BASE_NONE, NULL, 0x0,
1067
14
        NULL, HFILL }
1068
14
    },
1069
14
    { &hf_cbor_type_text_string,
1070
14
      { "Text String", "cbor.type.textstring",
1071
14
        FT_STRING, BASE_NONE, NULL, 0x00,
1072
14
        NULL, HFILL }
1073
14
    },
1074
14
    { &hf_cbor_type_text_string_indef,
1075
14
      { "Text String (indefinite length)", "cbor.type.textstring.indef",
1076
14
        FT_NONE, BASE_NONE, NULL, 0x0,
1077
14
        NULL, HFILL }
1078
14
    },
1079
14
    { &hf_cbor_type_tag,
1080
14
      { "Tag", "cbor.type.tag",
1081
14
        FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(tag64_vals), 0x00,
1082
14
        NULL, HFILL }
1083
14
    },
1084
14
    { &hf_cbor_type_simple_data5,
1085
14
      { "Simple data", "cbor.type.simple_data",
1086
14
        FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x1f,
1087
14
        NULL, HFILL }
1088
14
    },
1089
14
    { &hf_cbor_type_simple_data8,
1090
14
      { "Simple data", "cbor.type.simple_data",
1091
14
        FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x00,
1092
14
        NULL, HFILL }
1093
14
    },
1094
14
    { &hf_cbor_type_float16,
1095
14
      { "Float 16 Bit", "cbor.type.float16",
1096
14
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1097
14
        NULL, HFILL }
1098
14
    },
1099
14
    { &hf_cbor_type_float32,
1100
14
      { "Float 32 Bit", "cbor.type.float32",
1101
14
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1102
14
        NULL, HFILL }
1103
14
    },
1104
14
    { &hf_cbor_type_float64,
1105
14
      { "Float 64 Bit", "cbor.type.float64",
1106
14
        FT_DOUBLE, BASE_NONE, NULL, 0x00,
1107
14
        NULL, HFILL }
1108
14
    },
1109
14
  };
1110
1111
14
  static int *ett[] = {
1112
14
    &ett_cbor,
1113
14
    &ett_cbor_type,
1114
14
    &ett_cbor_unsigned_integer,
1115
14
    &ett_cbor_negative_integer,
1116
14
    &ett_cbor_byte_string,
1117
14
    &ett_cbor_byte_string_indef,
1118
14
    &ett_cbor_text_string,
1119
14
    &ett_cbor_text_string_indef,
1120
14
    &ett_cbor_array,
1121
14
    &ett_cbor_map,
1122
14
    &ett_cbor_tag,
1123
14
    &ett_cbor_float_simple
1124
14
  };
1125
1126
14
  static ei_register_info ei[] = {
1127
14
    { &ei_cbor_invalid_minor_type,
1128
14
      { "cbor.invalid_minor_type", PI_MALFORMED, PI_WARN, "Invalid minor type", EXPFILL }},
1129
14
    { &ei_cbor_invalid_element,
1130
14
      { "cbor.invalid_element", PI_MALFORMED, PI_WARN, "Invalid element", EXPFILL }},
1131
14
    { &ei_cbor_too_long_length,
1132
14
      { "cbor.too_long_length", PI_MALFORMED, PI_WARN, "Too long length", EXPFILL }},
1133
14
    { &ei_cbor_max_recursion_depth_reached,
1134
14
      { "cbor.max_recursion_depth_reached", PI_PROTOCOL, PI_WARN, "Maximum allowed recursion depth reached. Dissection stopped.", EXPFILL }},
1135
14
    { &ei_cbor_embedded_bstr,
1136
14
      { "cbor.embedded_bstr", PI_COMMENTS_GROUP, PI_COMMENT, "Heuristic dissection of CBOR embedded in a byte string", EXPFILL }},
1137
14
  };
1138
1139
14
  expert_module_t *expert_cbor;
1140
1141
14
  proto_cbor = proto_register_protocol("Concise Binary Object Representation", "CBOR", "cbor");
1142
14
  proto_register_field_array(proto_cbor, hf, array_length(hf));
1143
14
  proto_register_subtree_array(ett, array_length(ett));
1144
14
  expert_cbor = expert_register_protocol(proto_cbor);
1145
14
  expert_register_field_array(expert_cbor, ei, array_length(ei));
1146
1147
14
  cbor_handle = register_dissector("cbor", dissect_cbor, proto_cbor);
1148
14
  cborseq_handle = register_dissector_with_description("cborseq", "CBOR Sequence", dissect_cborseq, proto_cbor);
1149
1150
14
  module_t *module_cbor = prefs_register_protocol(proto_cbor, NULL);
1151
14
  prefs_register_bool_preference(
1152
14
      module_cbor,
1153
14
      "dissect_embeded_bstr",  /* mispelt but best leave */
1154
14
      "Dissect bstr-embedded CBOR",
1155
14
      "If enabled, a heuristic dissection of byte strings as embedded "
1156
14
      "CBOR/sequence is performed.",
1157
14
      &cbor_dissect_embeded_bstr
1158
14
  );
1159
1160
14
}
1161
1162
void
1163
proto_reg_handoff_cbor(void)
1164
14
{
1165
14
  dissector_add_string("media_type", "application/cbor", cbor_handle); /* RFC 8949 */
1166
14
  dissector_add_string("media_type", "application/cwt", cbor_handle); /* RFC 8392 */
1167
14
  dissector_add_string("media_type", "application/cbor-seq", cborseq_handle); /* RFC 8742 */
1168
1169
14
  dissector_add_string("media_type.suffix", "cbor", cbor_handle); /* RFC 8949 */
1170
14
  dissector_add_string("media_type.suffix", "cbor-seq", cborseq_handle); /* RFC 8742 */
1171
14
}
1172
1173
/*
1174
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1175
 *
1176
 * Local variables:
1177
 * c-basic-offset: 8
1178
 * tab-width: 8
1179
 * indent-tabs-mode: t
1180
 * End:
1181
 *
1182
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1183
 * :indentSize=8:tabSize=8:noTabs=false:
1184
 */