2 * Routines for Bundle Protocol Version 7 Security (BPSec) dissection
4 * RFC 9172: https://www.rfc-editor.org/rfc/rfc9172.html
5 * RFC 9173: https://www.rfc-editor.org/rfc/rfc9173.html
7 * Copyright 2019-2021, Brian Sipos <brian.sipos@gmail.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: LGPL-2.1-or-later
18 #include "packet-bpsec.h"
19 #include "packet-bpv7.h"
20 #include <epan/packet.h>
21 #include <epan/prefs.h>
22 #include <epan/proto.h>
23 #include <epan/expert.h>
25 #include "epan/wscbor.h"
27 void proto_register_bpsec(void);
28 void proto_reg_handoff_bpsec(void);
30 /// Glib logging "domain" name
31 //static const char *LOG_DOMAIN = "bpsec";
34 static int proto_bpsec
;
36 /// Dissect opaque CBOR data
37 static dissector_handle_t handle_cbor
;
38 /// Extension sub-dissectors
39 static dissector_table_t secctx_dissectors
;
40 static dissector_table_t param_dissectors
;
41 static dissector_table_t result_dissectors
;
43 static const val64_string shavar_vals
[] = {
50 static const val64_string aesvar_vals
[] = {
58 static int hf_asb_target_list
;
59 static int hf_asb_target
;
60 static int hf_asb_ctxid
;
61 static int hf_asb_flags
;
62 static int hf_asb_flags_has_params
;
63 static int hf_asb_secsrc_nodeid
;
64 static int hf_asb_secsrc_uri
;
65 static int hf_asb_param_list
;
66 static int hf_asb_param_pair
;
67 static int hf_asb_param_id
;
68 static int hf_asb_result_all_list
;
69 static int hf_asb_result_tgt_list
;
70 static int hf_asb_result_tgt_ref
;
71 static int hf_asb_result_pair
;
72 static int hf_asb_result_id
;
74 static int hf_defaultsc_shavar
;
75 static int hf_defaultsc_wrapedkey
;
76 static int hf_defaultsc_scope
;
77 static int hf_defaultsc_scope_pri_block
;
78 static int hf_defaultsc_scope_tgt_head
;
79 static int hf_defaultsc_scope_sec_head
;
80 static int hf_defaultsc_hmac
;
81 static int hf_defaultsc_iv
;
82 static int hf_defaultsc_aesvar
;
83 static int hf_defaultsc_authtag
;
86 static hf_register_info fields
[] = {
87 {&hf_bib
, {"BPSec Block Integrity Block", "bpsec.bib", FT_PROTOCOL
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
88 {&hf_bcb
, {"BPSec Block Confidentiality Block", "bpsec.bcb", FT_PROTOCOL
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
89 {&hf_asb_target_list
, {"Security Targets, Count", "bpsec.asb.target_count", FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
90 {&hf_asb_target
, {"Target Block Number", "bpsec.asb.target", FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
91 {&hf_asb_ctxid
, {"Context ID", "bpsec.asb.ctxid", FT_INT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
92 {&hf_asb_flags
, {"Flags", "bpsec.asb.flags", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
93 {&hf_asb_flags_has_params
, {"Parameters Present", "bpsec.asb.flags.has_params", FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), BPSEC_ASB_HAS_PARAMS
, NULL
, HFILL
}},
94 {&hf_asb_secsrc_nodeid
, {"Security Source", "bpsec.asb.secsrc.nodeid", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
95 {&hf_asb_secsrc_uri
, {"Security Source URI", "bpsec.asb.secsrc.uri", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
96 {&hf_asb_param_list
, {"Security Parameters, Count", "bpsec.asb.param_count", FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
97 {&hf_asb_param_pair
, {"Parameter", "bpsec.asb.param", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
98 {&hf_asb_param_id
, {"Type ID", "bpsec.asb.param.id", FT_INT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
99 {&hf_asb_result_all_list
, {"Security Result Targets, Count", "bpsec.asb.result_count", FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
100 {&hf_asb_result_tgt_ref
, {"Associated Target Block Number", "bpsec.asb.result_tgt_ref", FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
101 {&hf_asb_result_tgt_list
, {"Security Results, Count", "bpsec.asb.result_count", FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
102 {&hf_asb_result_pair
, {"Result", "bpsec.asb.result", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
103 {&hf_asb_result_id
, {"Type ID", "bpsec.asb.result.id", FT_INT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
105 {&hf_defaultsc_shavar
, {"SHA Variant", "bpsec.defaultsc.shavar", FT_UINT64
, BASE_DEC
| BASE_VAL64_STRING
, VALS64(shavar_vals
), 0x0, NULL
, HFILL
}},
106 {&hf_defaultsc_wrapedkey
, {"Wrapped Key", "bpsec.defaultsc.wrappedkey", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
107 {&hf_defaultsc_scope
, {"BIB Scope", "bpsec.defaultsc.scope", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
108 {&hf_defaultsc_scope_pri_block
, {"Primary Block", "bpsec.defaultsc.scope.pri_block", FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), 0x0001, NULL
, HFILL
}},
109 {&hf_defaultsc_scope_tgt_head
, {"Target Header", "bpsec.defaultsc.scope.tgt_head", FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), 0x0002, NULL
, HFILL
}},
110 {&hf_defaultsc_scope_sec_head
, {"Security Header", "bpsec.defaultsc.scope.sec_head", FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), 0x0004, NULL
, HFILL
}},
111 {&hf_defaultsc_hmac
, {"Expected HMAC", "bpsec.defaultsc.hmac", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
112 {&hf_defaultsc_iv
, {"IV", "bpsec.defaultsc.iv", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
113 {&hf_defaultsc_aesvar
, {"AES Variant", "bpsec.defaultsc.aesvar", FT_UINT64
, BASE_DEC
| BASE_VAL64_STRING
, VALS64(aesvar_vals
), 0x0, NULL
, HFILL
}},
114 {&hf_defaultsc_authtag
, {"Authentication Tag", "bpsec.defaultsc.authtag", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
117 static int *const asb_flags
[] = {
118 &hf_asb_flags_has_params
,
122 static int *const defaultsc_scope
[] = {
123 &hf_defaultsc_scope_pri_block
,
124 &hf_defaultsc_scope_tgt_head
,
125 &hf_defaultsc_scope_sec_head
,
130 static int ett_asb_flags
;
131 static int ett_tgt_list
;
132 static int ett_param_list
;
133 static int ett_param_pair
;
134 static int ett_result_all_list
;
135 static int ett_result_tgt_list
;
136 static int ett_result_pair
;
137 static int ett_defaultsc_scope
;
139 static int *ett
[] = {
145 &ett_result_all_list
,
146 &ett_result_tgt_list
,
148 &ett_defaultsc_scope
,
151 static expert_field ei_secsrc_diff
;
152 static expert_field ei_ctxid_zero
;
153 static expert_field ei_ctxid_priv
;
154 static expert_field ei_target_invalid
;
155 static expert_field ei_value_partial_decode
;
156 static ei_register_info expertitems
[] = {
157 {&ei_secsrc_diff
, {"bpsec.secsrc_diff", PI_SECURITY
, PI_CHAT
, "BPSec Security Source different from bundle Source", EXPFILL
}},
158 {&ei_ctxid_zero
, {"bpsec.ctxid_zero", PI_SECURITY
, PI_WARN
, "BPSec Security Context ID zero is reserved", EXPFILL
}},
159 {&ei_ctxid_priv
, {"bpsec.ctxid_priv", PI_SECURITY
, PI_NOTE
, "BPSec Security Context ID from private/experimental block", EXPFILL
}},
160 {&ei_target_invalid
, {"bpsec.target_invalid", PI_PROTOCOL
, PI_WARN
, "Target block number not present", EXPFILL
}},
161 {&ei_value_partial_decode
, {"bpsec.value_partial_decode", PI_UNDECODED
, PI_WARN
, "Value data not fully dissected", EXPFILL
}},
164 bpsec_id_t
* bpsec_id_new(wmem_allocator_t
*alloc
, int64_t context_id
, int64_t type_id
) {
167 obj
= wmem_new(alloc
, bpsec_id_t
);
170 obj
= g_new(bpsec_id_t
, 1);
172 obj
->context_id
= context_id
;
173 obj
->type_id
= type_id
;
177 void bpsec_id_free(wmem_allocator_t
*alloc
, void *ptr
) {
178 //bpsec_id_t *obj = (bpsec_id_t *)ptr;
179 wmem_free(alloc
, ptr
);
182 gboolean
bpsec_id_equal(const void *a
, const void *b
) {
183 const bpsec_id_t
*aobj
= a
;
184 const bpsec_id_t
*bobj
= b
;
187 && (aobj
->context_id
== bobj
->context_id
)
188 && (aobj
->type_id
== bobj
->type_id
)
192 unsigned bpsec_id_hash(const void *key
) {
193 const bpsec_id_t
*obj
= key
;
195 g_int64_hash(&(obj
->context_id
))
196 ^ g_int64_hash(&(obj
->type_id
))
200 /** Dissect an ID-value pair within a context.
203 static int dissect_value(dissector_handle_t dissector
, bpsec_dissector_data_t
*const data
, tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
206 sublen
= call_dissector_with_data(dissector
, tvb
, pinfo
, tree
, data
);
207 if ((sublen
< 0) || ((unsigned)sublen
< tvb_captured_length(tvb
))) {
208 expert_add_info(pinfo
, proto_tree_get_parent(tree
), &ei_value_partial_decode
);
212 sublen
= call_dissector(handle_cbor
, tvb
, pinfo
, tree
);
217 /** Dissector for abstract security block structure.
219 static int dissect_block_asb(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const bp_dissector_data_t
*const data
, int root_hfindex
) {
220 proto_item
*item_asb
= proto_tree_add_item(tree
, root_hfindex
, tvb
, 0, -1, ENC_NA
);
221 proto_tree
*tree_asb
= proto_item_add_subtree(item_asb
, ett_asb
);
224 wmem_array_t
*targets
;
225 targets
= wmem_array_new(pinfo
->pool
, sizeof(uint64_t));
227 wscbor_chunk_t
*chunk_tgt_list
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
228 wscbor_require_array(chunk_tgt_list
);
229 proto_item
*item_tgt_list
= proto_tree_add_cbor_container(tree_asb
, hf_asb_target_list
, pinfo
, tvb
, chunk_tgt_list
);
230 if (!wscbor_skip_if_errors(pinfo
->pool
, tvb
, &offset
, chunk_tgt_list
)) {
231 proto_tree
*tree_tgt_list
= proto_item_add_subtree(item_tgt_list
, ett_tgt_list
);
233 // iterate all targets
234 for (uint64_t param_ix
= 0; param_ix
< chunk_tgt_list
->head_value
; ++param_ix
) {
235 wscbor_chunk_t
*chunk_tgt
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
236 uint64_t *tgt_blknum
= wscbor_require_uint64(pinfo
->pool
, chunk_tgt
);
237 proto_item
*item_tgt
= proto_tree_add_cbor_uint64(tree_tgt_list
, hf_asb_target
, pinfo
, tvb
, chunk_tgt
, tgt_blknum
);
239 wmem_array_append(targets
, tgt_blknum
, 1);
241 wmem_map_t
*map
= NULL
;
242 if (*tgt_blknum
== 0) {
243 map
= (root_hfindex
== hf_bib
)
244 ? data
->bundle
->primary
->sec
.data_i
245 : data
->bundle
->primary
->sec
.data_c
;
248 bp_block_canonical_t
*found
= wmem_map_lookup(data
->bundle
->block_nums
, tgt_blknum
);
250 map
= (root_hfindex
== hf_bib
)
255 expert_add_info(pinfo
, item_tgt
, &ei_target_invalid
);
258 if (map
&& (data
->block
->block_number
)) {
261 data
->block
->block_number
,
268 proto_item_set_len(item_tgt_list
, offset
- chunk_tgt_list
->start
);
271 wscbor_chunk_t
*chunk_ctxid
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
272 int64_t *ctxid
= wscbor_require_int64(pinfo
->pool
, chunk_ctxid
);
273 proto_item
*item_ctxid
= proto_tree_add_cbor_int64(tree_asb
, hf_asb_ctxid
, pinfo
, tvb
, chunk_ctxid
, ctxid
);
274 if (ctxid
&& item_ctxid
) {
276 expert_add_info(pinfo
, item_ctxid
, &ei_ctxid_zero
);
278 else if (*ctxid
< 0) {
279 expert_add_info(pinfo
, item_ctxid
, &ei_ctxid_priv
);
282 // apply label if registered
283 dissector_handle_t ctx_dis
= dissector_get_custom_table_handle(secctx_dissectors
, ctxid
);
284 const char *dis_name
= dissector_handle_get_description(ctx_dis
);
286 const header_field_info
*hfinfo
= PITEM_HFINFO(item_ctxid
);
287 proto_item_set_text(item_ctxid
, "%s: %s (%" PRId64
")", hfinfo
? hfinfo
->name
: NULL
, dis_name
, *ctxid
);
291 wscbor_chunk_t
*chunk_flags
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
292 uint64_t *flags
= wscbor_require_uint64(pinfo
->pool
, chunk_flags
);
293 proto_tree_add_cbor_bitmask(tree_asb
, hf_asb_flags
, ett_asb_flags
, asb_flags
, pinfo
, tvb
, chunk_flags
, flags
);
296 bp_eid_t
*secsrc
= bp_eid_new(pinfo
->pool
);
297 proto_item
*item_secsrc
= proto_tree_add_cbor_eid(tree_asb
, hf_asb_secsrc_nodeid
, hf_asb_secsrc_uri
, pinfo
, tvb
, &offset
, secsrc
);
298 if (!bp_eid_equal(data
->bundle
->primary
->src_nodeid
, secsrc
)) {
299 expert_add_info(pinfo
, item_secsrc
, &ei_secsrc_diff
);
303 if (flags
&& (*flags
& BPSEC_ASB_HAS_PARAMS
)) {
304 wscbor_chunk_t
*chunk_param_list
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
305 wscbor_require_array(chunk_param_list
);
306 proto_item
*item_param_list
= proto_tree_add_cbor_container(tree_asb
, hf_asb_param_list
, pinfo
, tvb
, chunk_param_list
);
307 if (!wscbor_skip_if_errors(pinfo
->pool
, tvb
, &offset
, chunk_param_list
)) {
308 proto_tree
*tree_param_list
= proto_item_add_subtree(item_param_list
, ett_param_list
);
310 // iterate all parameters
311 for (uint64_t param_ix
= 0; param_ix
< chunk_param_list
->head_value
; ++param_ix
) {
312 wscbor_chunk_t
*chunk_param_pair
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
313 wscbor_require_array_size(chunk_param_pair
, 2, 2);
314 proto_item
*item_param_pair
= proto_tree_add_cbor_container(tree_param_list
, hf_asb_param_pair
, pinfo
, tvb
, chunk_param_pair
);
315 if (!wscbor_skip_if_errors(pinfo
->pool
, tvb
, &offset
, chunk_param_pair
)) {
316 proto_tree
*tree_param_pair
= proto_item_add_subtree(item_param_pair
, ett_param_pair
);
318 wscbor_chunk_t
*chunk_paramid
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
319 int64_t *paramid
= wscbor_require_int64(pinfo
->pool
, chunk_paramid
);
320 proto_tree_add_cbor_int64(tree_param_pair
, hf_asb_param_id
, pinfo
, tvb
, chunk_paramid
, paramid
);
322 const int offset_value
= offset
;
323 if (!wscbor_skip_next_item(pinfo
->pool
, tvb
, &offset
)) {
326 tvbuff_t
*tvb_value
= tvb_new_subset_length(tvb
, offset_value
, offset
- offset_value
);
328 bpsec_dissector_data_t bpsec_data
= { .bp
= data
};
329 dissector_handle_t value_dissect
= NULL
;
330 if (ctxid
&& paramid
) {
331 bpsec_data
.id
.context_id
= *ctxid
;
332 bpsec_data
.id
.type_id
= *paramid
;
333 value_dissect
= dissector_get_custom_table_handle(param_dissectors
, &(bpsec_data
.id
));
335 const char *dis_name
= dissector_handle_get_description(value_dissect
);
337 proto_item_append_text(item_param_pair
, ": %s (%" PRId64
")", dis_name
, *paramid
);
339 dissect_value(value_dissect
, &bpsec_data
, tvb_value
, pinfo
, tree_param_pair
);
341 proto_item_set_len(item_param_pair
, offset
- chunk_param_pair
->start
);
345 proto_item_set_len(item_param_list
, offset
- chunk_param_list
->start
);
349 // array sizes should agree
350 const unsigned tgt_size
= wmem_array_get_count(targets
);
352 wscbor_chunk_t
*chunk_result_all_list
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
353 wscbor_require_array_size(chunk_result_all_list
, tgt_size
, tgt_size
);
354 proto_item
*item_result_all_list
= proto_tree_add_cbor_container(tree_asb
, hf_asb_result_all_list
, pinfo
, tvb
, chunk_result_all_list
);
355 if (!wscbor_skip_if_errors(pinfo
->pool
, tvb
, &offset
, chunk_result_all_list
)) {
356 proto_tree
*tree_result_all_list
= proto_item_add_subtree(item_result_all_list
, ett_result_all_list
);
358 // iterate each target's results
359 for (unsigned tgt_ix
= 0; tgt_ix
< tgt_size
; ++tgt_ix
) {
360 wscbor_chunk_t
*chunk_result_tgt_list
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
361 wscbor_require_array(chunk_result_tgt_list
);
362 proto_item
*item_result_tgt_list
= proto_tree_add_cbor_container(tree_result_all_list
, hf_asb_result_tgt_list
, pinfo
, tvb
, chunk_result_tgt_list
);
363 if (!wscbor_skip_if_errors(pinfo
->pool
, tvb
, &offset
, chunk_result_tgt_list
)) {
364 proto_tree
*tree_result_tgt_list
= proto_item_add_subtree(item_result_tgt_list
, ett_result_tgt_list
);
366 // Hint at the associated target number
367 if (tgt_ix
< tgt_size
) {
368 const uint64_t *tgt_blknum
= wmem_array_index(targets
, tgt_ix
);
369 proto_item
*item_tgt_blknum
= proto_tree_add_uint64(tree_result_tgt_list
, hf_asb_result_tgt_ref
, tvb
, 0, 0, *tgt_blknum
);
370 proto_item_set_generated(item_tgt_blknum
);
373 // iterate all results for this target
374 for (uint64_t result_ix
= 0; result_ix
< chunk_result_tgt_list
->head_value
; ++result_ix
) {
375 wscbor_chunk_t
*chunk_result_pair
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
376 wscbor_require_array_size(chunk_result_pair
, 2, 2);
377 proto_item
*item_result_pair
= proto_tree_add_cbor_container(tree_result_tgt_list
, hf_asb_result_pair
, pinfo
, tvb
, chunk_result_pair
);
378 if (!wscbor_skip_if_errors(pinfo
->pool
, tvb
, &offset
, chunk_result_pair
)) {
379 proto_tree
*tree_result_pair
= proto_item_add_subtree(item_result_pair
, ett_result_pair
);
381 wscbor_chunk_t
*chunk_resultid
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
382 int64_t *resultid
= wscbor_require_int64(pinfo
->pool
, chunk_resultid
);
383 proto_tree_add_cbor_int64(tree_result_pair
, hf_asb_result_id
, pinfo
, tvb
, chunk_resultid
, resultid
);
385 const int offset_value
= offset
;
386 if (!wscbor_skip_next_item(pinfo
->pool
, tvb
, &offset
)) {
389 tvbuff_t
*tvb_value
= tvb_new_subset_length(tvb
, offset_value
, offset
- offset_value
);
391 bpsec_dissector_data_t bpsec_data
= { .bp
= data
};
392 dissector_handle_t value_dissect
= NULL
;
393 if (ctxid
&& resultid
) {
394 bpsec_data
.id
.context_id
= *ctxid
;
395 bpsec_data
.id
.type_id
= *resultid
;
396 value_dissect
= dissector_get_custom_table_handle(result_dissectors
, &(bpsec_data
.id
));
398 const char *dis_name
= dissector_handle_get_description(value_dissect
);
400 proto_item_append_text(item_result_pair
, ": %s (%" PRId64
")", dis_name
, *resultid
);
402 dissect_value(value_dissect
, &bpsec_data
, tvb_value
, pinfo
, tree_result_pair
);
404 proto_item_set_len(item_result_pair
, offset
- chunk_result_pair
->start
);
408 proto_item_set_len(item_result_tgt_list
, offset
- chunk_result_tgt_list
->start
);
412 proto_item_set_len(item_result_all_list
, offset
- chunk_result_all_list
->start
);
415 proto_item_set_len(item_asb
, offset
);
419 /** Dissector for Bundle Integrity block.
421 static int dissect_block_bib(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
422 return dissect_block_asb(tvb
, pinfo
, tree
, (bp_dissector_data_t
*)data
, hf_bib
);
425 /** Dissector for Bundle Confidentiality block.
427 static int dissect_block_bcb(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
428 return dissect_block_asb(tvb
, pinfo
, tree
, (bp_dissector_data_t
*)data
, hf_bcb
);
431 static int dissect_defaultsc_param_shavar(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
433 wscbor_chunk_t
*chunk
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
434 uint64_t *val
= wscbor_require_uint64(pinfo
->pool
, chunk
);
435 proto_tree_add_cbor_uint64(tree
, hf_defaultsc_shavar
, pinfo
, tvb
, chunk
, val
);
439 static int dissect_defaultsc_param_wrappedkey(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
441 wscbor_chunk_t
*chunk
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
442 wscbor_require_bstr(pinfo
->pool
, chunk
);
443 proto_tree_add_cbor_bstr(tree
, hf_defaultsc_wrapedkey
, pinfo
, tvb
, chunk
);
447 static int dissect_defaultsc_param_scope(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
449 wscbor_chunk_t
*chunk
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
450 uint64_t *flags
= wscbor_require_uint64(pinfo
->pool
, chunk
);
451 proto_tree_add_cbor_bitmask(tree
, hf_defaultsc_scope
, ett_defaultsc_scope
, defaultsc_scope
, pinfo
, tvb
, chunk
, flags
);
455 static int dissect_defaultsc_result_hmac(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
457 wscbor_chunk_t
*chunk
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
458 wscbor_require_bstr(pinfo
->pool
, chunk
);
459 proto_tree_add_cbor_bstr(tree
, hf_defaultsc_hmac
, pinfo
, tvb
, chunk
);
463 static int dissect_defaultsc_param_iv(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
465 wscbor_chunk_t
*chunk
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
466 wscbor_require_bstr(pinfo
->pool
, chunk
);
467 proto_tree_add_cbor_bstr(tree
, hf_defaultsc_iv
, pinfo
, tvb
, chunk
);
471 static int dissect_defaultsc_param_aesvar(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
473 wscbor_chunk_t
*chunk
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
474 uint64_t *val
= wscbor_require_uint64(pinfo
->pool
, chunk
);
475 proto_tree_add_cbor_uint64(tree
, hf_defaultsc_aesvar
, pinfo
, tvb
, chunk
, val
);
479 static int dissect_defaultsc_result_authtag(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
481 wscbor_chunk_t
*chunk
= wscbor_chunk_read(pinfo
->pool
, tvb
, &offset
);
482 wscbor_require_bstr(pinfo
->pool
, chunk
);
483 proto_tree_add_cbor_bstr(tree
, hf_defaultsc_authtag
, pinfo
, tvb
, chunk
);
487 /// Re-initialize after a configuration change
488 static void reinit_bpsec(void) {
491 /// Overall registration of the protocol
492 void proto_register_bpsec(void) {
493 proto_bpsec
= proto_register_protocol("DTN Bundle Protocol Security", "BPSec", "bpsec");
495 proto_register_field_array(proto_bpsec
, fields
, array_length(fields
));
496 proto_register_subtree_array(ett
, array_length(ett
));
497 expert_module_t
*expert
= expert_register_protocol(proto_bpsec
);
498 expert_register_field_array(expert
, expertitems
, array_length(expertitems
));
500 secctx_dissectors
= register_custom_dissector_table("bpsec.ctx", "BPSec Context", proto_bpsec
, g_int64_hash
, g_int64_equal
, g_free
);
501 param_dissectors
= register_custom_dissector_table("bpsec.param", "BPSec Parameter", proto_bpsec
, bpsec_id_hash
, bpsec_id_equal
, g_free
);
502 result_dissectors
= register_custom_dissector_table("bpsec.result", "BPSec Result", proto_bpsec
, bpsec_id_hash
, bpsec_id_equal
, g_free
);
504 prefs_register_protocol(proto_bpsec
, reinit_bpsec
);
507 void proto_reg_handoff_bpsec(void) {
508 handle_cbor
= find_dissector("cbor");
510 /* Packaged extensions */
512 uint64_t *key
= g_new(uint64_t, 1);
513 *key
= BP_BLOCKTYPE_BIB
;
514 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_block_bib
, proto_bpsec
, NULL
, "Block Integrity Block");
515 dissector_add_custom_table_handle("bpv7.block_type", key
, hdl
);
518 uint64_t *key
= g_new(uint64_t, 1);
519 *key
= BP_BLOCKTYPE_BCB
;
520 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_block_bcb
, proto_bpsec
, NULL
, "Block Confidentiality Block");
521 dissector_add_custom_table_handle("bpv7.block_type", key
, hdl
);
524 // Context 1: BIB-HMAC-SHA2
526 int64_t *key
= g_new0(int64_t, 1);
528 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(NULL
, proto_bpsec
, NULL
, "BIB-HMAC-SHA2");
529 dissector_add_custom_table_handle("bpsec.ctx", key
, hdl
);
532 bpsec_id_t
*key
= g_new(bpsec_id_t
, 1);
535 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_defaultsc_param_shavar
, proto_bpsec
, NULL
, "BIB-HMAC-SHA2 SHA Variant");
536 dissector_add_custom_table_handle("bpsec.param", key
, hdl
);
539 bpsec_id_t
*key
= g_new(bpsec_id_t
, 1);
542 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_defaultsc_param_wrappedkey
, proto_bpsec
, NULL
, "BIB-HMAC-SHA2 Wrapped Key");
543 dissector_add_custom_table_handle("bpsec.param", key
, hdl
);
546 bpsec_id_t
*key
= g_new(bpsec_id_t
, 1);
549 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_defaultsc_param_scope
, proto_bpsec
, NULL
, "BIB-HMAC-SHA2 AAD Scope");
550 dissector_add_custom_table_handle("bpsec.param", key
, hdl
);
553 bpsec_id_t
*key
= g_new(bpsec_id_t
, 1);
556 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_defaultsc_result_hmac
, proto_bpsec
, NULL
, "BIB-HMAC-SHA2 Tag");
557 dissector_add_custom_table_handle("bpsec.result", key
, hdl
);
559 // Context 2: BCB-AES-GCM
561 int64_t *key
= g_new0(int64_t, 1);
563 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(NULL
, proto_bpsec
, NULL
, "BCB-AES-GCM");
564 dissector_add_custom_table_handle("bpsec.ctx", key
, hdl
);
567 bpsec_id_t
*key
= g_new(bpsec_id_t
, 1);
570 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_defaultsc_param_iv
, proto_bpsec
, NULL
, "BCB-AES-GCM IV");
571 dissector_add_custom_table_handle("bpsec.param", key
, hdl
);
574 bpsec_id_t
*key
= g_new(bpsec_id_t
, 1);
577 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_defaultsc_param_aesvar
, proto_bpsec
, NULL
, "BCB-AES-GCM AES Variant");
578 dissector_add_custom_table_handle("bpsec.param", key
, hdl
);
581 bpsec_id_t
*key
= g_new(bpsec_id_t
, 1);
584 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_defaultsc_param_wrappedkey
, proto_bpsec
, NULL
, "BCB-AES-GCM Wrapped Key");
585 dissector_add_custom_table_handle("bpsec.param", key
, hdl
);
588 bpsec_id_t
*key
= g_new(bpsec_id_t
, 1);
591 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_defaultsc_param_scope
, proto_bpsec
, NULL
, "BCB-AES-GCM AAD Scope");
592 dissector_add_custom_table_handle("bpsec.param", key
, hdl
);
595 bpsec_id_t
*key
= g_new(bpsec_id_t
, 1);
598 dissector_handle_t hdl
= create_dissector_handle_with_name_and_description(dissect_defaultsc_result_authtag
, proto_bpsec
, NULL
, "BCB-AES-GCM Tag");
599 dissector_add_custom_table_handle("bpsec.result", key
, hdl
);