Coverage Report

Created: 2025-02-15 06:25

/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
 */