epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-bpsec.c
blob8b6136449cda2e42d880e0a473541e9234911648
1 /* packet-sec.c
2 * Routines for Bundle Protocol Version 7 Security (BPSec) dissection
3 * References:
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
15 #include "config.h"
16 #include <stdint.h>
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>
24 #include <epan/tfs.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";
33 /// Protocol handles
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[] = {
44 {5, "HMAC 256/256"},
45 {6, "HMAC 384/384"},
46 {7, "HMAC 512/512"},
47 {0, NULL},
50 static const val64_string aesvar_vals[] = {
51 {1, "A128GCM"},
52 {3, "A256GCM"},
53 {0, NULL},
56 static int hf_bib;
57 static int hf_bcb;
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;
85 /// Field definitions
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,
119 NULL
122 static int *const defaultsc_scope[] = {
123 &hf_defaultsc_scope_pri_block,
124 &hf_defaultsc_scope_tgt_head,
125 &hf_defaultsc_scope_sec_head,
126 NULL
129 static int ett_asb;
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;
138 /// Tree structures
139 static int *ett[] = {
140 &ett_asb,
141 &ett_asb_flags,
142 &ett_tgt_list,
143 &ett_param_list,
144 &ett_param_pair,
145 &ett_result_all_list,
146 &ett_result_tgt_list,
147 &ett_result_pair,
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) {
165 bpsec_id_t *obj;
166 if (alloc) {
167 obj = wmem_new(alloc, bpsec_id_t);
169 else {
170 obj = g_new(bpsec_id_t, 1);
172 obj->context_id = context_id;
173 obj->type_id = type_id;
174 return obj;
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;
185 return (
186 aobj && bobj
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;
194 return (
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) {
204 int sublen = 0;
205 if (dissector) {
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);
211 if (sublen == 0) {
212 sublen = call_dissector(handle_cbor, tvb, pinfo, tree);
214 return sublen;
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);
222 int offset = 0;
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);
238 if (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;
247 else {
248 bp_block_canonical_t *found = wmem_map_lookup(data->bundle->block_nums, tgt_blknum);
249 if (found) {
250 map = (root_hfindex == hf_bib)
251 ? found->sec.data_i
252 : found->sec.data_c;
254 else {
255 expert_add_info(pinfo, item_tgt, &ei_target_invalid);
258 if (map && (data->block->block_number)) {
259 wmem_map_insert(
260 map,
261 data->block->block_number,
262 NULL
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) {
275 if (*ctxid == 0) {
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);
285 if (dis_name) {
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)) {
324 return 0;
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);
336 if (paramid) {
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)) {
387 return 0;
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);
399 if (resultid) {
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);
416 return 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_) {
432 int offset = 0;
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);
436 return offset;
439 static int dissect_defaultsc_param_wrappedkey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
440 int offset = 0;
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);
444 return offset;
447 static int dissect_defaultsc_param_scope(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
448 int offset = 0;
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);
452 return offset;
455 static int dissect_defaultsc_result_hmac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
456 int offset = 0;
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);
460 return offset;
463 static int dissect_defaultsc_param_iv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
464 int offset = 0;
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);
468 return offset;
471 static int dissect_defaultsc_param_aesvar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
472 int offset = 0;
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);
476 return offset;
479 static int dissect_defaultsc_result_authtag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
480 int offset = 0;
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);
484 return offset;
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);
527 *key = 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);
533 key->context_id = 1;
534 key->type_id = 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);
540 key->context_id = 1;
541 key->type_id = 2;
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);
547 key->context_id = 1;
548 key->type_id = 3;
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);
554 key->context_id = 1;
555 key->type_id = 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);
562 *key = 2;
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);
568 key->context_id = 2;
569 key->type_id = 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);
575 key->context_id = 2;
576 key->type_id = 2;
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);
582 key->context_id = 2;
583 key->type_id = 3;
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);
589 key->context_id = 2;
590 key->type_id = 4;
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);
596 key->context_id = 2;
597 key->type_id = 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);
602 reinit_bpsec();