/src/wireshark/epan/dissectors/packet-cose.c
Line | Count | Source |
1 | | /* packet-cose.c |
2 | | * Routines for CBOR Object Signing and Encryption (COSE) dissection |
3 | | * References: |
4 | | * RFC 8949: https://tools.ietf.org/html/rfc8949 |
5 | | * RFC 9052: https://tools.ietf.org/html/rfc9052 |
6 | | * RFC 9053: https://tools.ietf.org/html/rfc9053 |
7 | | * RFC 9360: https://tools.ietf.org/html/rfc9360 |
8 | | * RFC 9459: https://tools.ietf.org/html/rfc9459 |
9 | | * RFC 9861: https://tools.ietf.org/html/rfc9861 |
10 | | * |
11 | | * Copyright 2019-2021, Brian Sipos <brian.sipos@gmail.com> |
12 | | * |
13 | | * Wireshark - Network traffic analyzer |
14 | | * By Gerald Combs <gerald@wireshark.org> |
15 | | * Copyright 1998 Gerald Combs |
16 | | * |
17 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
18 | | */ |
19 | | |
20 | | #include "config.h" |
21 | | #define WS_LOG_DOMAIN "packet-cose" |
22 | | |
23 | | #include "packet-cose.h" |
24 | | #include "packet-media-type.h" |
25 | | #include <epan/wscbor.h> |
26 | | #include <epan/packet.h> |
27 | | #include <epan/prefs.h> |
28 | | #include <epan/proto.h> |
29 | | #include <epan/media_params.h> |
30 | | #include <epan/expert.h> |
31 | | #include <epan/exceptions.h> |
32 | | #include <wsutil/array.h> |
33 | | #include <gcrypt.h> |
34 | | #include <inttypes.h> |
35 | | |
36 | | void proto_register_cose(void); |
37 | | void proto_reg_handoff_cose(void); |
38 | | |
39 | | /// Protocol column name |
40 | | static const char *const proto_name_cose = "COSE"; |
41 | | |
42 | | /// Protocol preferences and defaults |
43 | | |
44 | | /// Protocol handles |
45 | | static int proto_cose; |
46 | | static int proto_cose_params; |
47 | | |
48 | | /// Dissect opaque CBOR data |
49 | | static dissector_handle_t handle_cbor; |
50 | | /// Dissector handles |
51 | | static dissector_handle_t handle_cose_msg_hdr; |
52 | | static dissector_handle_t handle_cose_msg_tagged; |
53 | | static dissector_handle_t handle_cose_media_type; |
54 | | static dissector_handle_t handle_cose_sign; |
55 | | static dissector_handle_t handle_cose_sign1; |
56 | | static dissector_handle_t handle_cose_encrypt; |
57 | | static dissector_handle_t handle_cose_encrypt0; |
58 | | static dissector_handle_t handle_cose_mac; |
59 | | static dissector_handle_t handle_cose_mac0; |
60 | | static dissector_handle_t handle_cose_key; |
61 | | static dissector_handle_t handle_cose_key_set; |
62 | | |
63 | | /// Dissect opaque data |
64 | | static dissector_table_t table_media; |
65 | | /// Dissect extension items |
66 | | static dissector_table_t table_cose_msg_tag; |
67 | | static dissector_table_t table_cose_media_subtype; |
68 | | static dissector_table_t table_header; |
69 | | static dissector_table_t table_keyparam; |
70 | | |
71 | | static const val64_string alg_vals[] = { |
72 | | {-65535, "RS1"}, |
73 | | {-65534, "A128CTR"}, |
74 | | {-65533, "A192CTR"}, |
75 | | {-65532, "A256CTR"}, |
76 | | {-65531, "A128CBC"}, |
77 | | {-65530, "A192CBC"}, |
78 | | {-65529, "A256CBC"}, |
79 | | {-268, "ESB512"}, |
80 | | {-267, "ESB384"}, |
81 | | {-266, "ESB320"}, |
82 | | {-265, "ESB256"}, |
83 | | {-264, "KT256"}, |
84 | | {-263, "KT128"}, |
85 | | {-260, "WalnutDSA"}, |
86 | | {-259, "RS512"}, |
87 | | {-258, "RS384"}, |
88 | | {-257, "RS256"}, |
89 | | {-53, "Ed448"}, |
90 | | {-52, "ESP512"}, |
91 | | {-51, "ESP384"}, |
92 | | {-50, "ML-DSA-87"}, |
93 | | {-49, "ML-DSA-65"}, |
94 | | {-48, "ML-DSA-44"}, |
95 | | {-47, "ES256K"}, |
96 | | {-46, "HSS-LMS"}, |
97 | | {-45, "SHAKE256"}, |
98 | | {-44, "SHA-512"}, |
99 | | {-43, "SHA-384"}, |
100 | | {-42, "RSAES-OAEP w/ SHA-512"}, |
101 | | {-41, "RSAES-OAEP w/ SHA-256"}, |
102 | | {-40, "RSAES-OAEP w/ SHA-1"}, |
103 | | {-39, "PS512"}, |
104 | | {-38, "PS384"}, |
105 | | {-37, "PS256"}, |
106 | | {-36, "ES512"}, |
107 | | {-35, "ES384"}, |
108 | | {-34, "ECDH-SS + A256KW"}, |
109 | | {-33, "ECDH-SS + A192KW"}, |
110 | | {-32, "ECDH-SS + A128KW"}, |
111 | | {-31, "ECDH-ES + A256KW"}, |
112 | | {-30, "ECDH-ES + A192KW"}, |
113 | | {-29, "ECDH-ES + A128KW"}, |
114 | | {-28, "ECDH-SS + HKDF-512"}, |
115 | | {-27, "ECDH-SS + HKDF-256"}, |
116 | | {-26, "ECDH-ES + HKDF-512"}, |
117 | | {-25, "ECDH-ES + HKDF-256"}, |
118 | | {-19, "Ed25519"}, |
119 | | {-18, "SHAKE128"}, |
120 | | {-17, "SHA-512/256"}, |
121 | | {-16, "SHA-256"}, |
122 | | {-15, "SHA-256/64"}, |
123 | | {-14, "SHA-1"}, |
124 | | {-13, "direct+HKDF-AES-256"}, |
125 | | {-12, "direct+HKDF-AES-128"}, |
126 | | {-11, "direct+HKDF-SHA-512"}, |
127 | | {-10, "direct+HKDF-SHA-256"}, |
128 | | {-9, "ESP256"}, |
129 | | {-8, "EdDSA"}, |
130 | | {-7, "ES256"}, |
131 | | {-6, "direct"}, |
132 | | {-5, "A256KW"}, |
133 | | {-4, "A192KW"}, |
134 | | {-3, "A128KW"}, |
135 | | {0, "Reserved"}, |
136 | | {1, "A128GCM"}, |
137 | | {2, "A192GCM"}, |
138 | | {3, "A256GCM"}, |
139 | | {4, "HMAC 256/64"}, |
140 | | {5, "HMAC 256/256"}, |
141 | | {6, "HMAC 384/384"}, |
142 | | {7, "HMAC 512/512"}, |
143 | | {10, "AES-CCM-16-64-128"}, |
144 | | {11, "AES-CCM-16-64-256"}, |
145 | | {12, "AES-CCM-64-64-128"}, |
146 | | {13, "AES-CCM-64-64-256"}, |
147 | | {14, "AES-MAC 128/64"}, |
148 | | {15, "AES-MAC 256/64"}, |
149 | | {24, "ChaCha20/Poly1305"}, |
150 | | {25, "AES-MAC 128/128"}, |
151 | | {26, "AES-MAC 256/128"}, |
152 | | {30, "AES-CCM-16-128-128"}, |
153 | | {31, "AES-CCM-16-128-256"}, |
154 | | {32, "AES-CCM-64-128-128"}, |
155 | | {33, "AES-CCM-64-128-256"}, |
156 | | {34, "IV-GENERATION"}, |
157 | | {0, NULL}, |
158 | | }; |
159 | | |
160 | | static const val64_string kty_vals[] = { |
161 | | {0, "Reserved"}, |
162 | | {1, "OKP"}, |
163 | | {2, "EC2"}, |
164 | | {3, "RSA"}, |
165 | | {4, "Symmetric"}, |
166 | | {5, "HSS-LMS"}, |
167 | | {6, "WalnutDSA"}, |
168 | | {7, "AKP"}, |
169 | | {0, NULL}, |
170 | | }; |
171 | | |
172 | | static const val64_string keyops_vals[] = { |
173 | | {1, "sign"}, |
174 | | {2, "verify"}, |
175 | | {3, "encrypt"}, |
176 | | {4, "decrypt"}, |
177 | | {5, "key wrap"}, |
178 | | {6, "key unwrap"}, |
179 | | {7, "derive key"}, |
180 | | {8, "derive bits"}, |
181 | | {9, "MAC create"}, |
182 | | {10, "MAC verify"}, |
183 | | {0, NULL}, |
184 | | }; |
185 | | |
186 | | static const val64_string crv_vals[] = { |
187 | | {0, "Reserved"}, |
188 | | {1, "P-256"}, |
189 | | {2, "P-384"}, |
190 | | {3, "P-521"}, |
191 | | {4, "X25519"}, |
192 | | {5, "X448"}, |
193 | | {6, "Ed25519"}, |
194 | | {7, "Ed448"}, |
195 | | {0, NULL}, |
196 | | }; |
197 | | |
198 | | static int hf_msg_tag; |
199 | | static int hf_hdr_prot_bstr; |
200 | | static int hf_hdr_unprot; |
201 | | static int hf_payload_null; |
202 | | static int hf_payload_bstr; |
203 | | static int hf_cose_signature_list; |
204 | | static int hf_cose_signature; |
205 | | static int hf_signature; |
206 | | static int hf_ciphertext_null; |
207 | | static int hf_ciphertext_bstr; |
208 | | static int hf_cose_recipient_list; |
209 | | static int hf_cose_recipient; |
210 | | static int hf_tag; |
211 | | |
212 | | static int hf_hdr_label_int; |
213 | | static int hf_hdr_label_tstr; |
214 | | |
215 | | static int hf_hdr_salt; |
216 | | static int hf_hdr_static_key; |
217 | | static int hf_hdr_ephem_key; |
218 | | static int hf_hdr_alg_int; |
219 | | static int hf_hdr_alg_tstr; |
220 | | static int hf_hdr_crit_list; |
221 | | static int hf_hdr_ctype_uint; |
222 | | static int hf_hdr_ctype_tstr; |
223 | | static int hf_hdr_kid; |
224 | | static int hf_hdr_kid_text; |
225 | | static int hf_hdr_iv; |
226 | | static int hf_hdr_piv; |
227 | | static int hf_hdr_x5bag; |
228 | | static int hf_hdr_x5chain; |
229 | | static int hf_hdr_x5t; |
230 | | static int hf_hdr_x5t_hash; |
231 | | static int hf_hdr_x5u; |
232 | | |
233 | | static int hf_key; |
234 | | |
235 | | static int hf_keyparam_kty_int; |
236 | | static int hf_keyparam_kty_tstr; |
237 | | static int hf_keyparam_keyops_list; |
238 | | static int hf_keyparam_keyops_int; |
239 | | static int hf_keyparam_keyops_tstr; |
240 | | static int hf_keyparam_baseiv; |
241 | | static int hf_keyparam_crv_int; |
242 | | static int hf_keyparam_crv_tstr; |
243 | | static int hf_keyparam_xcoord; |
244 | | static int hf_keyparam_ycoord; |
245 | | static int hf_keyparam_dcoord; |
246 | | static int hf_keyparam_k; |
247 | | static int hf_keyparam_pub; |
248 | | static int hf_keyparam_priv; |
249 | | |
250 | | /// Field definitions |
251 | | static hf_register_info fields[] = { |
252 | | {&hf_msg_tag, {"Message type tag", "cose.msgtag", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
253 | | {&hf_hdr_prot_bstr, {"Protected Headers (bstr)", "cose.msg.prot_bstr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
254 | | {&hf_hdr_unprot, {"Unprotected Headers", "cose.msg.unprot", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
255 | | |
256 | | {&hf_payload_null, {"Payload Detached", "cose.msg.detached_payload", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
257 | | {&hf_payload_bstr, {"Payload", "cose.msg.payload", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
258 | | {&hf_signature, {"Signature", "cose.msg.signature", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
259 | | {&hf_cose_signature_list, {"Signature List, Count", "cose.msg.signature_list", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
260 | | {&hf_cose_signature, {"COSE_Signature", "cose.msg.cose_signature", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
261 | | {&hf_ciphertext_null, {"Ciphertext Detached", "cose.msg.detached_ciphertext", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
262 | | {&hf_ciphertext_bstr, {"Ciphertext", "cose.msg.ciphertext", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
263 | | {&hf_cose_recipient_list, {"Recipient List, Count", "cose.msg.recipient_list", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
264 | | {&hf_cose_recipient, {"COSE_Recipient", "cose.msg.cose_recipient", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
265 | | {&hf_tag, {"Tag", "cose.msg.mac_tag", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
266 | | |
267 | | {&hf_hdr_label_int, {"Label", "cose.header_label.int", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
268 | | {&hf_hdr_label_tstr, {"Label", "cose.header_label.tstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
269 | | |
270 | | {&hf_hdr_salt, {"Salt", "cose.salt", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
271 | | {&hf_hdr_static_key, {"Static Key", "cose.static_key", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
272 | | {&hf_hdr_ephem_key, {"Ephemeral Key", "cose.ephem_key", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
273 | | {&hf_hdr_alg_int, {"Algorithm", "cose.alg.int", FT_INT64, BASE_DEC | BASE_VAL64_STRING, VALS64(alg_vals), 0x0, NULL, HFILL}}, |
274 | | {&hf_hdr_alg_tstr, {"Algorithm", "cose.alg.tstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
275 | | {&hf_hdr_crit_list, {"Critical Headers, Count", "cose.crit", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
276 | | {&hf_hdr_ctype_uint, {"Content-Format", "cose.content-type.uint", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
277 | | {&hf_hdr_ctype_tstr, {"Content-Type", "cose.content-type.tstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
278 | | {&hf_hdr_kid, {"Key identifier", "cose.kid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
279 | | {&hf_hdr_kid_text, {"As Text", "cose.kid.as_text", FT_STRING, BASE_NONE, NULL, 0x0, "The kid byte string interpreted as UTF-8 text", HFILL}}, |
280 | | {&hf_hdr_iv, {"IV", "cose.iv", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
281 | | {&hf_hdr_piv, {"Partial IV", "cose.piv", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
282 | | |
283 | | {&hf_hdr_x5bag, {"X509 Bag (x5bag)", "cose.x5bag", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
284 | | {&hf_hdr_x5chain, {"X509 Chain (x5chain)", "cose.x5chain", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
285 | | {&hf_hdr_x5t, {"X509 Thumbprint (x5t)", "cose.x5t", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
286 | | {&hf_hdr_x5t_hash, {"Hash Value", "cose.x5t.hash", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
287 | | {&hf_hdr_x5u, {"X509 URI (x5u)", "cose.x5u", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
288 | | |
289 | | {&hf_key, {"COSE_Key", "cose.key", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
290 | | |
291 | | {&hf_keyparam_kty_int, {"Key Type", "cose.kty.int", FT_INT64, BASE_DEC | BASE_VAL64_STRING, VALS64(kty_vals), 0x0, NULL, HFILL}}, |
292 | | {&hf_keyparam_kty_tstr, {"Key Type", "cose.kty.tstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
293 | | {&hf_keyparam_keyops_list, {"Key Operations", "cose.keyops", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
294 | | {&hf_keyparam_keyops_int, {"Operation", "cose.keyops.int", FT_INT64, BASE_DEC | BASE_VAL64_STRING, VALS64(keyops_vals), 0x0, NULL, HFILL}}, |
295 | | {&hf_keyparam_keyops_tstr, {"Operation", "cose.keyops.tstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
296 | | {&hf_keyparam_baseiv, {"Base IV", "cose.baseiv", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
297 | | {&hf_keyparam_crv_int, {"Curve Type", "cose.crv.int", FT_INT64, BASE_DEC | BASE_VAL64_STRING, VALS64(crv_vals), 0x0, NULL, HFILL}}, |
298 | | {&hf_keyparam_crv_tstr, {"Curve Type", "cose.crv.tstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
299 | | {&hf_keyparam_xcoord, {"X-coordinate", "cose.key.xcoord", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
300 | | {&hf_keyparam_ycoord, {"Y-coordinate", "cose.key.ycoord", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
301 | | {&hf_keyparam_dcoord, {"Private Key", "cose.key.dcoord", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
302 | | {&hf_keyparam_k, {"Key", "cose.key.k", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
303 | | {&hf_keyparam_pub, {"Public key", "cose.key.pub", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
304 | | {&hf_keyparam_priv, {"Private key", "cose.key.priv", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
305 | | }; |
306 | | |
307 | | static int ett_msg; |
308 | | static int ett_sig_list; |
309 | | static int ett_sig; |
310 | | static int ett_recip_list; |
311 | | static int ett_recip; |
312 | | static int ett_prot_bstr; |
313 | | static int ett_unprot; |
314 | | static int ett_hdr_map; |
315 | | static int ett_hdr_label; |
316 | | static int ett_hdr_kid; |
317 | | static int ett_hdr_static_key; |
318 | | static int ett_hdr_ephem_key; |
319 | | static int ett_hdr_crit_list; |
320 | | static int ett_hdr_x5cert_list; |
321 | | static int ett_hdr_x5t_list; |
322 | | static int ett_key; |
323 | | static int ett_key_set; |
324 | | static int ett_keyops_list; |
325 | | /// Tree structures |
326 | | static int *ett[] = { |
327 | | &ett_msg, |
328 | | &ett_sig_list, |
329 | | &ett_sig, |
330 | | &ett_recip_list, |
331 | | &ett_recip, |
332 | | &ett_prot_bstr, |
333 | | &ett_unprot, |
334 | | &ett_hdr_map, |
335 | | &ett_hdr_label, |
336 | | &ett_hdr_kid, |
337 | | &ett_hdr_static_key, |
338 | | &ett_hdr_ephem_key, |
339 | | &ett_hdr_crit_list, |
340 | | &ett_hdr_x5cert_list, |
341 | | &ett_hdr_x5t_list, |
342 | | &ett_key, |
343 | | &ett_key_set, |
344 | | &ett_keyops_list, |
345 | | }; |
346 | | |
347 | | static expert_field ei_invalid_tag; |
348 | | static expert_field ei_value_partial_decode; |
349 | | static ei_register_info expertitems[] = { |
350 | | {&ei_invalid_tag, { "cose.invalid_tag", PI_UNDECODED, PI_WARN, "COSE dissector did not match any known tag", EXPFILL}}, |
351 | | {&ei_value_partial_decode, { "cose.partial_decode", PI_MALFORMED, PI_WARN, "Value is only partially decoded", EXPFILL}}, |
352 | | }; |
353 | | |
354 | | /* Compatible with GHashFunc signature. */ |
355 | 31.0k | static unsigned cose_param_key_hash(const void *ptr) { |
356 | 31.0k | const cose_param_key_t *obj = (const cose_param_key_t *)ptr; |
357 | 31.0k | unsigned val = 0; |
358 | 31.0k | if (obj->principal) { |
359 | 12.8k | val ^= g_int64_hash(obj->principal); |
360 | 12.8k | } |
361 | 31.0k | if (obj->label) { |
362 | 25.0k | val ^= g_variant_hash(obj->label); |
363 | 25.0k | } |
364 | 31.0k | return val; |
365 | 31.0k | } |
366 | | |
367 | | /* Compatible with GEqualFunc signature. */ |
368 | 26.9k | static gboolean cose_param_key_equal(const void *a, const void *b) { |
369 | 26.9k | const cose_param_key_t *aobj = (const cose_param_key_t *)a; |
370 | 26.9k | const cose_param_key_t *bobj = (const cose_param_key_t *)b; |
371 | | |
372 | 26.9k | if (aobj->principal && bobj->principal) { |
373 | 4.25k | if (!g_variant_equal(aobj->principal, bobj->principal)) { |
374 | 3.10k | return FALSE; |
375 | 3.10k | } |
376 | 4.25k | } |
377 | 22.7k | else if ((aobj->principal == NULL) != (bobj->principal == NULL)) { |
378 | 0 | return FALSE; |
379 | 0 | } |
380 | | |
381 | 23.8k | gboolean match; |
382 | 23.8k | if (aobj->label && bobj->label) { |
383 | 16.2k | match = g_variant_equal(aobj->label, bobj->label); |
384 | 16.2k | } |
385 | 7.60k | else { |
386 | | // don't care |
387 | 7.60k | match = FALSE; |
388 | 7.60k | } |
389 | 23.8k | return match; |
390 | 26.9k | } |
391 | | |
392 | | /* Compatible with GDestroyNotify signature. */ |
393 | 0 | static void cose_param_key_free(void *ptr) { |
394 | 0 | cose_param_key_t *obj = (cose_param_key_t *)ptr; |
395 | 0 | if (obj->principal) { |
396 | 0 | g_variant_unref(obj->principal); |
397 | 0 | } |
398 | 0 | if (obj->label) { |
399 | 0 | g_variant_unref(obj->label); |
400 | 0 | } |
401 | 0 | g_free(obj); |
402 | 0 | } |
403 | | |
404 | | /// Known hash properties |
405 | | static const cose_hash_props_t cose_hash_props_list[] = { |
406 | | {-45, GCRY_MD_SHAKE256, 64}, |
407 | | {-44, GCRY_MD_SHA512, 64}, |
408 | | {-43, GCRY_MD_SHA384, 48}, |
409 | | {-18, GCRY_MD_SHAKE128, 32}, |
410 | | {-17, GCRY_MD_SHA512, 32}, // truncated |
411 | | {-16, GCRY_MD_SHA256, 32}, |
412 | | {-15, GCRY_MD_SHA256, 16}, // truncated |
413 | | {-14, GCRY_MD_SHA1, 20}, |
414 | | }; |
415 | | /// Derived lookup map |
416 | | static GHashTable *cose_hash_props_map = NULL; |
417 | | |
418 | 0 | const cose_hash_props_t * cose_get_hash_props(int64_t alg) { |
419 | 0 | if (cose_hash_props_map) { |
420 | | // fast lookup when available |
421 | 0 | return g_hash_table_lookup(cose_hash_props_map, &alg); |
422 | 0 | } |
423 | 0 | else { |
424 | 0 | return NULL; |
425 | 0 | } |
426 | 0 | } |
427 | | |
428 | | /// Known AEAD properties |
429 | | static const cose_aead_props_t cose_aead_props_list[] = { |
430 | | {1, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_GCM, 16, 12, 16}, |
431 | | {2, GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_GCM, 24, 12, 16}, |
432 | | {3, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, 32, 12, 16}, |
433 | | |
434 | | {10, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CCM, 16, 13, 8}, |
435 | | {11, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CCM, 32, 13, 8}, |
436 | | {12, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CCM, 16, 7, 8}, |
437 | | {13, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CCM, 32, 7, 8}, |
438 | | |
439 | | {24, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_POLY1305, 32, 12, 16}, |
440 | | |
441 | | {30, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CCM, 16, 13, 16}, |
442 | | {31, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CCM, 32, 13, 16}, |
443 | | {32, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CCM, 16, 7, 16}, |
444 | | {33, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CCM, 32, 7, 16}, |
445 | | }; |
446 | | /// Derived lookup map |
447 | | static GHashTable *cose_aead_props_map = NULL; |
448 | | |
449 | 0 | const cose_aead_props_t * cose_get_aead_props(int64_t alg) { |
450 | 0 | if (cose_aead_props_map) { |
451 | | // fast lookup when available |
452 | 0 | return g_hash_table_lookup(cose_aead_props_map, &alg); |
453 | 0 | } |
454 | 0 | else { |
455 | 0 | return NULL; |
456 | 0 | } |
457 | 0 | } |
458 | | |
459 | | /// Known curve properties |
460 | | static const cose_ecc_props_t cose_ecc_props_list[] = { |
461 | | {1, 32}, // P-256 |
462 | | {2, 48}, // P-384 |
463 | | {3, 66}, // P-521 |
464 | | {4, 32}, // X25519 |
465 | | {5, 57}, // X448 |
466 | | {6, 32}, // Ed25519 |
467 | | {7, 57}, // Ed448 |
468 | | {8, 32}, // secp256k1 |
469 | | }; |
470 | | /// Derived lookup map |
471 | | static GHashTable *cose_ecc_props_map = NULL; |
472 | | |
473 | 0 | const cose_ecc_props_t * cose_get_ecc_props(int64_t crv) { |
474 | 0 | if (cose_ecc_props_map) { |
475 | | // fast lookup when available |
476 | 0 | return g_hash_table_lookup(cose_ecc_props_map, &crv); |
477 | 0 | } |
478 | 0 | else { |
479 | 0 | return NULL; |
480 | 0 | } |
481 | 0 | } |
482 | | |
483 | | /** Get a specific item value (map key or value) from a header map. |
484 | | * @param alloc The allocator for temporary data. |
485 | | * @param tvb The buffer to read from. |
486 | | * @param[in,out] offset The starting offset to read and advance. |
487 | | * @return A pointer to the simple value or NULL. |
488 | | */ |
489 | 24.5k | static GVariant * get_header_value(wmem_allocator_t *alloc, tvbuff_t *tvb, int *offset) { |
490 | 24.5k | GVariant *result = NULL; |
491 | | |
492 | 24.5k | wscbor_chunk_t *chunk = wscbor_chunk_read(alloc, tvb, offset); |
493 | 24.5k | switch (chunk->type_major) { |
494 | 11.3k | case CBOR_TYPE_UINT: |
495 | 15.1k | case CBOR_TYPE_NEGINT: { |
496 | 15.1k | int64_t *label = wscbor_require_int64(alloc, chunk); |
497 | 15.1k | if (label) { |
498 | 15.1k | result = g_variant_new_int64(*label); |
499 | 15.1k | } |
500 | 15.1k | break; |
501 | 11.3k | } |
502 | 1.94k | case CBOR_TYPE_STRING: { |
503 | 1.94k | const char *label = wscbor_require_tstr(alloc, chunk); |
504 | 1.94k | if (label) { |
505 | 1.92k | result = g_variant_new_string(label); |
506 | 1.92k | } |
507 | 1.94k | break; |
508 | 11.3k | } |
509 | 7.34k | default: |
510 | 7.34k | break; |
511 | 24.5k | } |
512 | 24.4k | wscbor_chunk_free(chunk); |
513 | 24.4k | return result; |
514 | 24.5k | } |
515 | | |
516 | | /** Dissect an ID-value pair within a context. |
517 | | * |
518 | | * @param dis_table The cose_param_key_t dissector table. |
519 | | * @param[in,out] ctx The context from other pairs. |
520 | | * @return True if the pair was dissected (even as opaque CBOR data). |
521 | | */ |
522 | 16.0k | static bool dissect_header_pair(dissector_table_t dis_table, cose_header_context_t *ctx, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
523 | 16.0k | wscbor_chunk_t *chunk_label = wscbor_chunk_read(pinfo->pool, tvb, offset); |
524 | | |
525 | 16.0k | proto_item *item_label = NULL; |
526 | 16.0k | proto_tree *volatile tree_label = NULL; |
527 | 16.0k | tvbuff_t *volatile tvb_value = NULL; |
528 | | |
529 | 16.0k | cose_param_key_t key = { 0 }; |
530 | | |
531 | 16.0k | const char *label_str = NULL; |
532 | 16.0k | switch (chunk_label->type_major) { |
533 | 8.84k | case CBOR_TYPE_UINT: |
534 | 11.9k | case CBOR_TYPE_NEGINT: { |
535 | 11.9k | int64_t *label = wscbor_require_int64(pinfo->pool, chunk_label); |
536 | 11.9k | item_label = proto_tree_add_cbor_int64(tree, hf_hdr_label_int, pinfo, tvb, chunk_label, label); |
537 | 11.9k | if (label) { |
538 | 11.9k | key.label = ctx->label = |
539 | 11.9k | g_variant_new_int64(*label); |
540 | 11.9k | label_str = wmem_strdup_printf(pinfo->pool, "%" PRId64, *label); |
541 | 11.9k | } |
542 | 11.9k | break; |
543 | 8.84k | } |
544 | 1.10k | case CBOR_TYPE_STRING: { |
545 | 1.10k | const char *label = wscbor_require_tstr(pinfo->pool, chunk_label); |
546 | 1.10k | item_label = proto_tree_add_cbor_tstr(tree, hf_hdr_label_tstr, pinfo, tvb, chunk_label); |
547 | 1.10k | if (label) { |
548 | 1.08k | key.label = ctx->label = |
549 | 1.08k | g_variant_new_string(label); |
550 | 1.08k | label_str = label; |
551 | 1.08k | } |
552 | 1.10k | break; |
553 | 8.84k | } |
554 | 3.01k | default: |
555 | 3.01k | break; |
556 | 16.0k | } |
557 | | |
558 | | // First attempt with context then without |
559 | 16.0k | key.principal = ctx->principal; |
560 | 16.0k | dissector_handle_t dissector = dissector_get_custom_table_handle(dis_table, &key); |
561 | 16.0k | if (!dissector) { |
562 | 14.5k | key.principal = NULL; |
563 | 14.5k | dissector = dissector_get_custom_table_handle(dis_table, &key); |
564 | 14.5k | } |
565 | 16.0k | const char *dis_name = dissector_handle_get_description(dissector); |
566 | 16.0k | if (item_label && dis_name) { |
567 | 4.00k | proto_item_set_text(item_label, "%s: %s (%s)", |
568 | 4.00k | PITEM_HFINFO(item_label)->name, dis_name, label_str); |
569 | 4.00k | } |
570 | | |
571 | 16.0k | tree_label = proto_item_add_subtree(item_label, ett_hdr_label); |
572 | | |
573 | | // Peek into the value as tvb |
574 | 16.0k | const int offset_value = *offset; |
575 | 16.0k | if (!wscbor_skip_next_item(pinfo->pool, tvb, offset)) { |
576 | 815 | return false; |
577 | 815 | } |
578 | 15.2k | tvb_value = tvb_new_subset_length(tvb, offset_value, *offset - offset_value); |
579 | | |
580 | 15.2k | int sublen = 0; |
581 | 15.2k | if (dissector) { |
582 | 3.91k | sublen = call_dissector_only(dissector, tvb_value, pinfo, tree_label, ctx); |
583 | 3.91k | if ((sublen < 0) || |
584 | 3.91k | ((sublen > 0) && ((unsigned)sublen < tvb_reported_length(tvb_value)))) { |
585 | 83 | expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_value_partial_decode); |
586 | 83 | } |
587 | 3.91k | } |
588 | 15.2k | if (ctx->label) { |
589 | 12.5k | g_variant_unref(ctx->label); |
590 | 12.5k | ctx->label = NULL; |
591 | 12.5k | } |
592 | 15.2k | if (sublen == 0) { |
593 | 11.2k | TRY { |
594 | 11.2k | call_dissector(handle_cbor, tvb_value, pinfo, tree_label); |
595 | 11.2k | } |
596 | 11.2k | CATCH_ALL {} |
597 | 11.2k | ENDTRY; |
598 | 11.2k | } |
599 | 15.2k | return true; |
600 | 16.0k | } |
601 | | |
602 | | static void |
603 | 1.49k | cose_header_context_cleanup(void *user_data) { |
604 | 1.49k | cose_header_context_t *ctx = (cose_header_context_t *)user_data; |
605 | | |
606 | 1.49k | if (ctx->principal) { |
607 | 567 | g_variant_unref(ctx->principal); |
608 | 567 | } |
609 | 1.49k | if (ctx->label) { |
610 | 417 | g_variant_unref(ctx->label); |
611 | 417 | ctx->label = NULL; |
612 | 417 | } |
613 | 1.49k | } |
614 | | |
615 | | static void |
616 | 22.3k | g_variant_cleanup(void *user_data) { |
617 | 22.3k | GVariant *var = (GVariant *)user_data; |
618 | 22.3k | g_variant_unref(var); |
619 | 22.3k | } |
620 | | |
621 | | /** Dissect an entire header map, either for messages, recipients, or keys. |
622 | | * |
623 | | * @param dis_table The cose_param_key_t dissector table. |
624 | | * @param tvb The source data. |
625 | | * @param tree The parent of the header map. |
626 | | * @param[in,out] offset The data offset. |
627 | | * @param principal_key The map key associated with a principal value to read first. |
628 | | */ |
629 | 22.3k | static void dissect_header_map(dissector_table_t dis_table, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, GVariant *principal_key) { |
630 | 22.3k | wscbor_chunk_t *chunk_hdr_map = wscbor_chunk_read(pinfo->pool, tvb, offset); |
631 | 22.3k | wscbor_require_map(chunk_hdr_map); |
632 | 22.3k | proto_item *item_hdr_map = proto_tree_get_parent(tree); |
633 | 22.3k | wscbor_chunk_mark_errors(pinfo, item_hdr_map, chunk_hdr_map); |
634 | 22.3k | if (!wscbor_skip_if_errors(pinfo->pool, tvb, offset, chunk_hdr_map)) { |
635 | 1.49k | proto_tree *tree_hdr_map = proto_item_add_subtree(item_hdr_map, ett_hdr_map); |
636 | | |
637 | 1.49k | cose_header_context_t *ctx = wmem_new0(pinfo->pool, cose_header_context_t); |
638 | 1.49k | CLEANUP_PUSH(cose_header_context_cleanup, ctx); |
639 | | |
640 | | // Peek ahead to principal key (and value) first |
641 | 1.49k | if (principal_key) { |
642 | 1.49k | int peek_offset = *offset; |
643 | 24.6k | for (uint64_t ix = 0; ix < chunk_hdr_map->head_value; ++ix) { |
644 | 23.6k | GVariant *key = get_header_value(pinfo->pool, tvb, &peek_offset); |
645 | 23.6k | if (key) { |
646 | 16.5k | if (g_variant_equal(key, principal_key)) { |
647 | 839 | ctx->principal = get_header_value(pinfo->pool, tvb, &peek_offset); |
648 | 839 | } |
649 | 16.5k | g_variant_unref(key); |
650 | 16.5k | if (ctx->principal) { |
651 | 567 | break; |
652 | 567 | } |
653 | 16.5k | } |
654 | | // ignore non-principal value entirely |
655 | 23.1k | wscbor_skip_next_item(pinfo->pool, tvb, &peek_offset); |
656 | 23.1k | } |
657 | 1.49k | } |
658 | | |
659 | 16.7k | for (uint64_t ix = 0; ix < chunk_hdr_map->head_value; ++ix) { |
660 | 16.0k | if (!dissect_header_pair(dis_table, ctx, tvb, pinfo, tree_hdr_map, offset)) { |
661 | 815 | break; |
662 | 815 | } |
663 | 16.0k | } |
664 | | |
665 | 1.49k | CLEANUP_CALL_AND_POP; |
666 | 1.49k | wmem_free(pinfo->pool, ctx); |
667 | 1.49k | } |
668 | | |
669 | 22.3k | proto_item_set_len(item_hdr_map, *offset - chunk_hdr_map->start); |
670 | 22.3k | } |
671 | | |
672 | 0 | static int dissect_cose_msg_header_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
673 | 0 | int offset = 0; |
674 | 0 | GVariant *alg_key = g_variant_new_int64(1); |
675 | 0 | CLEANUP_PUSH(g_variant_cleanup, alg_key); |
676 | |
|
677 | 0 | dissect_header_map(table_header, tvb, pinfo, tree, &offset, alg_key); |
678 | |
|
679 | 0 | CLEANUP_CALL_AND_POP; |
680 | 0 | return offset; |
681 | 0 | } |
682 | | |
683 | | /** Indicate the tag which informed the message type. |
684 | | */ |
685 | 0 | static void dissect_msg_tag(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree_msg, const wscbor_chunk_t *chunk_msg _U_, const void *data) { |
686 | 0 | if (!data) { |
687 | 0 | return; |
688 | 0 | } |
689 | 0 | const wscbor_tag_t *tag = (const wscbor_tag_t *)data; |
690 | |
|
691 | 0 | proto_tree_add_uint64(tree_msg, hf_msg_tag, tvb, tag->start, tag->length, tag->value); |
692 | 0 | } |
693 | | |
694 | | /** Common behavior for pair of header maps. |
695 | | */ |
696 | 0 | static void dissect_headers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
697 | | // Protected in bstr |
698 | 0 | wscbor_chunk_t *chunk_prot_bstr = wscbor_chunk_read(pinfo->pool, tvb, offset); |
699 | 0 | tvbuff_t *tvb_prot = wscbor_require_bstr(pinfo->pool, chunk_prot_bstr); |
700 | 0 | proto_item *item_prot_bstr = proto_tree_add_cbor_bstr(tree, hf_hdr_prot_bstr, pinfo, tvb, chunk_prot_bstr); |
701 | 0 | if (tvb_prot) { |
702 | 0 | proto_tree *tree_prot = proto_item_add_subtree(item_prot_bstr, ett_prot_bstr); |
703 | |
|
704 | 0 | if (tvb_reported_length(tvb_prot) > 0) { |
705 | 0 | dissect_cose_msg_header_map(tvb_prot, pinfo, tree_prot, NULL); |
706 | 0 | } |
707 | 0 | } |
708 | | |
709 | | // Unprotected |
710 | 0 | tvbuff_t *tvb_unprot = tvb_new_subset_remaining(tvb, *offset); |
711 | 0 | proto_item *item_unprot = proto_tree_add_item(tree, hf_hdr_unprot, tvb_unprot, 0, -1, ENC_NA); |
712 | 0 | proto_tree *tree_unprot = proto_item_add_subtree(item_unprot, ett_unprot); |
713 | 0 | const int sublen = dissect_cose_msg_header_map(tvb_unprot, pinfo, tree_unprot, NULL); |
714 | 0 | *offset += sublen; |
715 | 0 | proto_item_set_len(item_unprot, sublen); |
716 | 0 | } |
717 | | |
718 | | /** Common behavior for payload. |
719 | | */ |
720 | 0 | static void dissect_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
721 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, offset); |
722 | 0 | if (chunk->type_major == CBOR_TYPE_FLOAT_CTRL) { |
723 | 0 | proto_tree_add_cbor_ctrl(tree, hf_payload_null, pinfo, tvb, chunk); |
724 | 0 | } |
725 | 0 | else { |
726 | 0 | wscbor_require_bstr(pinfo->pool, chunk); |
727 | 0 | proto_tree_add_cbor_bstr(tree, hf_payload_bstr, pinfo, tvb, chunk); |
728 | 0 | } |
729 | 0 | } |
730 | 0 | static void dissect_signature(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
731 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, offset); |
732 | 0 | wscbor_require_bstr(pinfo->pool, chunk); |
733 | 0 | proto_tree_add_cbor_bstr(tree, hf_signature, pinfo, tvb, chunk); |
734 | 0 | } |
735 | 0 | static void dissect_cose_signature(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
736 | 0 | wscbor_chunk_t *chunk_sig = wscbor_chunk_read(pinfo->pool, tvb, offset); |
737 | 0 | wscbor_require_array_size(chunk_sig, 3, 3); |
738 | 0 | proto_item *item_sig = proto_tree_add_cbor_container(tree, hf_cose_signature, pinfo, tvb, chunk_sig); |
739 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, offset, chunk_sig)) { |
740 | 0 | proto_tree *tree_sig = proto_item_add_subtree(item_sig, ett_sig); |
741 | |
|
742 | 0 | dissect_headers(tvb, pinfo, tree_sig, offset); |
743 | 0 | dissect_signature(tvb, pinfo, tree_sig, offset); |
744 | 0 | } |
745 | 0 | proto_item_set_len(item_sig, *offset - chunk_sig->start); |
746 | 0 | } |
747 | 0 | static void dissect_ciphertext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
748 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, offset); |
749 | 0 | if (chunk->type_major == CBOR_TYPE_FLOAT_CTRL) { |
750 | 0 | proto_tree_add_cbor_ctrl(tree, hf_ciphertext_null, pinfo, tvb, chunk); |
751 | 0 | } |
752 | 0 | else { |
753 | 0 | wscbor_require_bstr(pinfo->pool, chunk); |
754 | 0 | proto_tree_add_cbor_bstr(tree, hf_ciphertext_bstr, pinfo, tvb, chunk); |
755 | 0 | } |
756 | 0 | } |
757 | | static void dissect_cose_recipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset); |
758 | | |
759 | | // NOLINTNEXTLINE(misc-no-recursion) |
760 | 0 | static void dissect_cose_recipient_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
761 | 0 | wscbor_chunk_t *chunk_list = wscbor_chunk_read(pinfo->pool, tvb, offset); |
762 | 0 | wscbor_require_array(chunk_list); |
763 | 0 | proto_item *item_list = proto_tree_add_cbor_container(tree, hf_cose_recipient_list, pinfo, tvb, chunk_list); |
764 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, offset, chunk_list)) { |
765 | 0 | proto_tree *tree_recip_list = proto_item_add_subtree(item_list, ett_recip_list); |
766 | |
|
767 | 0 | for (uint64_t ix = 0; ix < chunk_list->head_value; ++ix) { |
768 | 0 | dissect_cose_recipient(tvb, pinfo, tree_recip_list, offset); |
769 | 0 | } |
770 | 0 | } |
771 | 0 | proto_item_set_len(item_list, *offset - chunk_list->start); |
772 | 0 | } |
773 | | |
774 | | // NOLINTNEXTLINE(misc-no-recursion) |
775 | 0 | static void dissect_cose_recipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
776 | 0 | wscbor_chunk_t *chunk_recip = wscbor_chunk_read(pinfo->pool, tvb, offset); |
777 | 0 | wscbor_require_array_size(chunk_recip, 3, 4); |
778 | 0 | proto_item *item_recip = proto_tree_add_cbor_container(tree, hf_cose_recipient, pinfo, tvb, chunk_recip); |
779 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, offset, chunk_recip)) { |
780 | 0 | proto_tree *tree_recip = proto_item_add_subtree(item_recip, ett_recip); |
781 | |
|
782 | 0 | dissect_headers(tvb, pinfo, tree_recip, offset); |
783 | 0 | dissect_ciphertext(tvb, pinfo, tree_recip, offset); |
784 | 0 | if (chunk_recip->head_value > 3) { |
785 | 0 | increment_dissection_depth(pinfo); |
786 | 0 | dissect_cose_recipient_list(tvb, pinfo, tree_recip, offset); |
787 | 0 | decrement_dissection_depth(pinfo); |
788 | 0 | } |
789 | 0 | } |
790 | 0 | proto_item_set_len(item_recip, *offset - chunk_recip->start); |
791 | |
|
792 | 0 | } |
793 | 0 | static void dissect_tag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
794 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, offset); |
795 | 0 | wscbor_require_bstr(pinfo->pool, chunk); |
796 | 0 | proto_tree_add_cbor_bstr(tree, hf_tag, pinfo, tvb, chunk); |
797 | 0 | } |
798 | | |
799 | | // Top-level protocol dissectors |
800 | 0 | static int dissect_cose_sign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
801 | 0 | int offset = 0; |
802 | |
|
803 | 0 | wscbor_chunk_t *chunk_msg = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
804 | 0 | wscbor_require_array_size(chunk_msg, 4, 4); |
805 | 0 | proto_item *item_msg = proto_tree_add_cbor_container(tree, proto_cose, pinfo, tvb, chunk_msg); |
806 | 0 | proto_item_append_text(item_msg, ": COSE_Sign"); |
807 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_msg)) { |
808 | 0 | proto_tree *tree_msg = proto_item_add_subtree(item_msg, ett_msg); |
809 | 0 | dissect_msg_tag(tvb, pinfo, tree_msg, chunk_msg, data); |
810 | |
|
811 | 0 | dissect_headers(tvb, pinfo, tree_msg, &offset); |
812 | 0 | dissect_payload(tvb, pinfo, tree_msg, &offset); |
813 | |
|
814 | 0 | wscbor_chunk_t *chunk_sig_list = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
815 | 0 | wscbor_require_array(chunk_sig_list); |
816 | 0 | proto_item *item_sig_list = proto_tree_add_cbor_container(tree_msg, hf_cose_signature_list, pinfo, tvb, chunk_sig_list); |
817 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_sig_list)) { |
818 | 0 | proto_tree *tree_sig_list = proto_item_add_subtree(item_sig_list, ett_sig_list); |
819 | |
|
820 | 0 | for (uint64_t ix = 0; ix < chunk_sig_list->head_value; ++ix) { |
821 | 0 | dissect_cose_signature(tvb, pinfo, tree_sig_list, &offset); |
822 | 0 | } |
823 | 0 | } |
824 | 0 | proto_item_set_len(item_sig_list, offset - chunk_sig_list->start); |
825 | 0 | } |
826 | |
|
827 | 0 | return offset; |
828 | 0 | } |
829 | | |
830 | 0 | static int dissect_cose_sign1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
831 | 0 | int offset = 0; |
832 | |
|
833 | 0 | wscbor_chunk_t *chunk_msg = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
834 | 0 | wscbor_require_array_size(chunk_msg, 4, 4); |
835 | 0 | proto_item *item_msg = proto_tree_add_cbor_container(tree, proto_cose, pinfo, tvb, chunk_msg); |
836 | 0 | proto_item_append_text(item_msg, ": COSE_Sign1"); |
837 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_msg)) { |
838 | 0 | proto_tree *tree_msg = proto_item_add_subtree(item_msg, ett_msg); |
839 | 0 | dissect_msg_tag(tvb, pinfo, tree_msg, chunk_msg, data); |
840 | |
|
841 | 0 | dissect_headers(tvb, pinfo, tree_msg, &offset); |
842 | 0 | dissect_payload(tvb, pinfo, tree_msg, &offset); |
843 | 0 | dissect_signature(tvb, pinfo, tree_msg, &offset); |
844 | 0 | } |
845 | |
|
846 | 0 | return offset; |
847 | 0 | } |
848 | | |
849 | 0 | static int dissect_cose_encrypt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
850 | 0 | int offset = 0; |
851 | |
|
852 | 0 | wscbor_chunk_t *chunk_msg = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
853 | 0 | wscbor_require_array_size(chunk_msg, 4, 4); |
854 | 0 | proto_item *item_msg = proto_tree_add_cbor_container(tree, proto_cose, pinfo, tvb, chunk_msg); |
855 | 0 | proto_item_append_text(item_msg, ": COSE_Encrypt"); |
856 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_msg)) { |
857 | 0 | proto_tree *tree_msg = proto_item_add_subtree(item_msg, ett_msg); |
858 | 0 | dissect_msg_tag(tvb, pinfo, tree_msg, chunk_msg, data); |
859 | |
|
860 | 0 | dissect_headers(tvb, pinfo, tree_msg, &offset); |
861 | 0 | dissect_ciphertext(tvb, pinfo, tree_msg, &offset); |
862 | 0 | dissect_cose_recipient_list(tvb, pinfo, tree_msg, &offset); |
863 | 0 | } |
864 | |
|
865 | 0 | return offset; |
866 | 0 | } |
867 | | |
868 | 0 | static int dissect_cose_encrypt0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
869 | 0 | int offset = 0; |
870 | |
|
871 | 0 | wscbor_chunk_t *chunk_msg = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
872 | 0 | wscbor_require_array_size(chunk_msg, 3, 3); |
873 | 0 | proto_item *item_msg = proto_tree_add_cbor_container(tree, proto_cose, pinfo, tvb, chunk_msg); |
874 | 0 | proto_item_append_text(item_msg, ": COSE_Encrypt0"); |
875 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_msg)) { |
876 | 0 | proto_tree *tree_msg = proto_item_add_subtree(item_msg, ett_msg); |
877 | 0 | dissect_msg_tag(tvb, pinfo, tree_msg, chunk_msg, data); |
878 | |
|
879 | 0 | dissect_headers(tvb, pinfo, tree_msg, &offset); |
880 | 0 | dissect_ciphertext(tvb, pinfo, tree_msg, &offset); |
881 | 0 | } |
882 | |
|
883 | 0 | return offset; |
884 | 0 | } |
885 | | |
886 | 0 | static int dissect_cose_mac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
887 | 0 | int offset = 0; |
888 | |
|
889 | 0 | wscbor_chunk_t *chunk_msg = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
890 | 0 | wscbor_require_array_size(chunk_msg, 5, 5); |
891 | 0 | proto_item *item_msg = proto_tree_add_cbor_container(tree, proto_cose, pinfo, tvb, chunk_msg); |
892 | 0 | proto_item_append_text(item_msg, ": COSE_Mac"); |
893 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_msg)) { |
894 | 0 | proto_tree *tree_msg = proto_item_add_subtree(item_msg, ett_msg); |
895 | 0 | dissect_msg_tag(tvb, pinfo, tree_msg, chunk_msg, data); |
896 | |
|
897 | 0 | dissect_headers(tvb, pinfo, tree_msg, &offset); |
898 | 0 | dissect_payload(tvb, pinfo, tree_msg, &offset); |
899 | 0 | dissect_tag(tvb, pinfo, tree_msg, &offset); |
900 | 0 | dissect_cose_recipient_list(tvb, pinfo, tree_msg, &offset); |
901 | 0 | } |
902 | |
|
903 | 0 | return offset; |
904 | 0 | } |
905 | | |
906 | 0 | static int dissect_cose_mac0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
907 | 0 | int offset = 0; |
908 | |
|
909 | 0 | wscbor_chunk_t *chunk_msg = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
910 | 0 | wscbor_require_array_size(chunk_msg, 4, 4); |
911 | 0 | proto_item *item_msg = proto_tree_add_cbor_container(tree, proto_cose, pinfo, tvb, chunk_msg); |
912 | 0 | proto_item_append_text(item_msg, ": COSE_Mac0"); |
913 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_msg)) { |
914 | 0 | proto_tree *tree_msg = proto_item_add_subtree(item_msg, ett_msg); |
915 | 0 | dissect_msg_tag(tvb, pinfo, tree_msg, chunk_msg, data); |
916 | |
|
917 | 0 | dissect_headers(tvb, pinfo, tree_msg, &offset); |
918 | 0 | dissect_payload(tvb, pinfo, tree_msg, &offset); |
919 | 0 | dissect_tag(tvb, pinfo, tree_msg, &offset); |
920 | 0 | } |
921 | |
|
922 | 0 | return offset; |
923 | 0 | } |
924 | | |
925 | | /** Dissect a tagged COSE message. |
926 | | */ |
927 | 0 | static int dissect_cose_msg_tagged(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
928 | 0 | int offset = 0; |
929 | | |
930 | | // All messages have the same base structure, attempt all tags present |
931 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
932 | 0 | for (wmem_list_frame_t *it = wmem_list_head(chunk->tags); it; |
933 | 0 | it = wmem_list_frame_next(it)) { |
934 | 0 | wscbor_tag_t *tag = (wscbor_tag_t *) wmem_list_frame_data(it); |
935 | | // first usable tag wins |
936 | 0 | dissector_handle_t dissector = dissector_get_custom_table_handle(table_cose_msg_tag, &(tag->value)); |
937 | 0 | if (!dissector) { |
938 | 0 | continue; |
939 | 0 | } |
940 | 0 | int sublen = call_dissector_only(dissector, tvb, pinfo, tree, tag); |
941 | 0 | if (sublen > 0) { |
942 | 0 | return sublen; |
943 | 0 | } |
944 | 0 | } |
945 | | |
946 | 0 | proto_item *item_msg = proto_tree_add_item(tree, proto_cose, tvb, 0, -1, ENC_NA); |
947 | 0 | expert_add_info(pinfo, item_msg, &ei_invalid_tag); |
948 | 0 | return -1; |
949 | 0 | } |
950 | | |
951 | | /** Dissect the application/cose media type with optional parameters. |
952 | | */ |
953 | 0 | static int dissect_cose_media_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
954 | 0 | const media_content_info_t *content_info = (media_content_info_t *)data; |
955 | |
|
956 | 0 | const char *subtype = NULL; |
957 | 0 | if (content_info->media_str) { |
958 | 0 | subtype = ws_find_media_type_parameter(pinfo->pool, content_info->media_str, "cose-type"); |
959 | 0 | } |
960 | |
|
961 | 0 | dissector_handle_t dissector; |
962 | 0 | if (subtype) { |
963 | 0 | dissector = dissector_get_string_handle(table_cose_media_subtype, subtype); |
964 | 0 | } |
965 | 0 | else { |
966 | | // no media type parameter, require tagged message |
967 | 0 | dissector = handle_cose_msg_tagged; |
968 | 0 | } |
969 | |
|
970 | 0 | int sublen = call_dissector_only(dissector, tvb, pinfo, tree, NULL); |
971 | 0 | if (sublen > 0) { |
972 | 0 | return sublen; |
973 | 0 | } |
974 | | |
975 | 0 | proto_item *item_msg = proto_tree_add_item(tree, proto_cose, tvb, 0, -1, ENC_NA); |
976 | 0 | expert_add_info(pinfo, item_msg, &ei_invalid_tag); |
977 | 0 | return -1; |
978 | 0 | } |
979 | | |
980 | 318 | static void dissect_value_alg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
981 | 318 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, offset); |
982 | 318 | switch (chunk->type_major) { |
983 | 245 | case CBOR_TYPE_UINT: |
984 | 272 | case CBOR_TYPE_NEGINT: { |
985 | 272 | int64_t *val = wscbor_require_int64(pinfo->pool, chunk); |
986 | 272 | proto_tree_add_cbor_int64(tree, hf_hdr_alg_int, pinfo, tvb, chunk, val); |
987 | 272 | break; |
988 | 245 | } |
989 | 6 | case CBOR_TYPE_STRING: { |
990 | 6 | proto_tree_add_cbor_tstr(tree, hf_hdr_alg_tstr, pinfo, tvb, chunk); |
991 | 6 | break; |
992 | 245 | } |
993 | 40 | default: |
994 | 40 | break; |
995 | 318 | } |
996 | 318 | } |
997 | | |
998 | 0 | static int dissect_header_salt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
999 | 0 | int offset = 0; |
1000 | |
|
1001 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1002 | 0 | wscbor_require_bstr(pinfo->pool, chunk); |
1003 | 0 | proto_tree_add_cbor_bstr(tree, hf_hdr_salt, pinfo, tvb, chunk); |
1004 | |
|
1005 | 0 | return offset; |
1006 | 0 | } |
1007 | | |
1008 | 22.3k | static void dissect_value_cose_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
1009 | 22.3k | GVariant *kty_key = g_variant_new_int64(1); |
1010 | 22.3k | CLEANUP_PUSH(g_variant_cleanup, kty_key); |
1011 | | |
1012 | 22.3k | dissect_header_map(table_keyparam, tvb, pinfo, tree, offset, kty_key); |
1013 | | |
1014 | 22.3k | CLEANUP_CALL_AND_POP; |
1015 | 22.3k | } |
1016 | | |
1017 | 0 | static int dissect_header_static_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1018 | 0 | int offset = 0; |
1019 | 0 | proto_item *item_ctr = proto_tree_add_item(tree, hf_hdr_static_key, tvb, 0, -1, ENC_NA); |
1020 | 0 | proto_tree *tree_ctr = proto_item_add_subtree(item_ctr, ett_hdr_static_key); |
1021 | 0 | dissect_value_cose_key(tvb, pinfo, tree_ctr, &offset); |
1022 | 0 | return offset; |
1023 | 0 | } |
1024 | | |
1025 | 0 | static int dissect_header_ephem_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1026 | 0 | int offset = 0; |
1027 | 0 | proto_item *item_ctr = proto_tree_add_item(tree, hf_hdr_ephem_key, tvb, 0, -1, ENC_NA); |
1028 | 0 | proto_tree *tree_ctr = proto_item_add_subtree(item_ctr, ett_hdr_ephem_key); |
1029 | 0 | dissect_value_cose_key(tvb, pinfo, tree_ctr, &offset); |
1030 | 0 | return offset; |
1031 | 0 | } |
1032 | | |
1033 | 318 | static int dissect_header_alg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1034 | 318 | int offset = 0; |
1035 | 318 | dissect_value_alg(tvb, pinfo, tree, &offset); |
1036 | 318 | return offset; |
1037 | 318 | } |
1038 | | |
1039 | 0 | static int dissect_header_crit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1040 | 0 | int offset = 0; |
1041 | |
|
1042 | 0 | wscbor_chunk_t *chunk_list = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1043 | 0 | wscbor_require_array(chunk_list); |
1044 | 0 | proto_item *item_list = proto_tree_add_cbor_container(tree, hf_hdr_crit_list, pinfo, tvb, chunk_list); |
1045 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_list)) { |
1046 | 0 | proto_tree *tree_list = proto_item_add_subtree(item_list, ett_hdr_crit_list); |
1047 | |
|
1048 | 0 | for (uint64_t ix = 0; ix < chunk_list->head_value; ++ix) { |
1049 | 0 | wscbor_chunk_t *chunk_label = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1050 | 0 | switch (chunk_label->type_major) { |
1051 | 0 | case CBOR_TYPE_UINT: |
1052 | 0 | case CBOR_TYPE_NEGINT: { |
1053 | 0 | int64_t *label = wscbor_require_int64(pinfo->pool, chunk_label); |
1054 | 0 | proto_tree_add_cbor_int64(tree_list, hf_hdr_label_int, pinfo, tvb, chunk_label, label); |
1055 | 0 | break; |
1056 | 0 | } |
1057 | 0 | case CBOR_TYPE_STRING: { |
1058 | 0 | proto_tree_add_cbor_tstr(tree_list, hf_hdr_label_tstr, pinfo, tvb, chunk_label); |
1059 | 0 | break; |
1060 | 0 | } |
1061 | 0 | default: |
1062 | 0 | break; |
1063 | 0 | } |
1064 | 0 | } |
1065 | 0 | } |
1066 | | |
1067 | 0 | proto_item_set_len(item_list, offset); |
1068 | 0 | return offset; |
1069 | 0 | } |
1070 | | |
1071 | 0 | static int dissect_header_ctype(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1072 | 0 | int offset = 0; |
1073 | |
|
1074 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1075 | 0 | switch (chunk->type_major) { |
1076 | 0 | case CBOR_TYPE_UINT: { |
1077 | 0 | uint64_t *val = wscbor_require_uint64(pinfo->pool, chunk); |
1078 | 0 | proto_tree_add_cbor_uint64(tree, hf_hdr_ctype_uint, pinfo, tvb, chunk, val); |
1079 | 0 | break; |
1080 | 0 | } |
1081 | 0 | case CBOR_TYPE_STRING: { |
1082 | 0 | proto_tree_add_cbor_tstr(tree, hf_hdr_ctype_tstr, pinfo, tvb, chunk); |
1083 | 0 | break; |
1084 | 0 | } |
1085 | 0 | default: |
1086 | 0 | break; |
1087 | 0 | } |
1088 | | |
1089 | 0 | return offset; |
1090 | 0 | } |
1091 | | |
1092 | 845 | static int dissect_header_kid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1093 | 845 | int offset = 0; |
1094 | | |
1095 | 845 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1096 | 845 | tvbuff_t *val = wscbor_require_bstr(pinfo->pool, chunk); |
1097 | 845 | proto_item *item_kid = proto_tree_add_cbor_bstr(tree, hf_hdr_kid, pinfo, tvb, chunk); |
1098 | | |
1099 | 845 | if (val && tvb_utf_8_isprint_remaining(val, 0)) { |
1100 | 22 | proto_tree *tree_kid = proto_item_add_subtree(item_kid, ett_hdr_kid); |
1101 | 22 | proto_item *kid_text = proto_tree_add_item(tree_kid, hf_hdr_kid_text, val, 0, tvb_reported_length(val), ENC_UTF_8); |
1102 | 22 | proto_item_set_generated(kid_text); |
1103 | 22 | } |
1104 | | |
1105 | 845 | return offset; |
1106 | 845 | } |
1107 | | |
1108 | 0 | static int dissect_header_iv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1109 | 0 | int offset = 0; |
1110 | |
|
1111 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1112 | 0 | wscbor_require_bstr(pinfo->pool, chunk); |
1113 | 0 | proto_tree_add_cbor_bstr(tree, hf_hdr_iv, pinfo, tvb, chunk); |
1114 | |
|
1115 | 0 | return offset; |
1116 | 0 | } |
1117 | | |
1118 | 0 | static int dissect_header_piv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1119 | 0 | int offset = 0; |
1120 | |
|
1121 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1122 | 0 | wscbor_require_bstr(pinfo->pool, chunk); |
1123 | 0 | proto_tree_add_cbor_bstr(tree, hf_hdr_piv, pinfo, tvb, chunk); |
1124 | |
|
1125 | 0 | return offset; |
1126 | 0 | } |
1127 | | |
1128 | 0 | static void dissect_value_x5cert(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset) { |
1129 | 0 | wscbor_chunk_t *chunk_item = wscbor_chunk_read(pinfo->pool, tvb, offset); |
1130 | 0 | tvbuff_t *tvb_item = wscbor_require_bstr(pinfo->pool, chunk_item); |
1131 | |
|
1132 | 0 | if (tvb_item) { |
1133 | | // disallow column text rewrite |
1134 | 0 | char *info_text = wmem_strdup(pinfo->pool, col_get_text(pinfo->cinfo, COL_INFO)); |
1135 | |
|
1136 | 0 | TRY { |
1137 | 0 | dissector_try_string_with_data( |
1138 | 0 | table_media, |
1139 | 0 | "application/pkix-cert", |
1140 | 0 | tvb_item, |
1141 | 0 | pinfo, |
1142 | 0 | tree, |
1143 | 0 | true, |
1144 | 0 | NULL |
1145 | 0 | ); |
1146 | 0 | } |
1147 | 0 | CATCH_ALL {} |
1148 | 0 | ENDTRY; |
1149 | |
|
1150 | 0 | col_add_str(pinfo->cinfo, COL_INFO, info_text); |
1151 | 0 | } |
1152 | |
|
1153 | 0 | } |
1154 | 0 | static void dissect_value_cosex509(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int hfindex, int *offset) { |
1155 | 0 | proto_item *item_ctr = proto_tree_add_item(tree, hfindex, tvb, 0, -1, ENC_NA); |
1156 | 0 | proto_tree *tree_ctr = proto_item_add_subtree(item_ctr, ett_hdr_x5cert_list); |
1157 | |
|
1158 | 0 | wscbor_chunk_t *chunk_ctr = wscbor_chunk_read(pinfo->pool, tvb, offset); |
1159 | 0 | switch (chunk_ctr->type_major) { |
1160 | 0 | case CBOR_TYPE_ARRAY: { |
1161 | 0 | wscbor_require_array(chunk_ctr); |
1162 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, offset, chunk_ctr)) { |
1163 | 0 | for (uint64_t ix = 0; ix < chunk_ctr->head_value; ++ix) { |
1164 | 0 | dissect_value_x5cert(tvb, pinfo, tree_ctr, offset); |
1165 | 0 | } |
1166 | 0 | } |
1167 | 0 | break; |
1168 | 0 | } |
1169 | 0 | case CBOR_TYPE_BYTESTRING: { |
1170 | | // re-read this chunk as cert |
1171 | 0 | *offset = chunk_ctr->start; |
1172 | 0 | dissect_value_x5cert(tvb, pinfo, tree_ctr, offset); |
1173 | 0 | break; |
1174 | 0 | } |
1175 | 0 | default: |
1176 | 0 | break; |
1177 | 0 | } |
1178 | |
|
1179 | 0 | } |
1180 | 0 | static int dissect_header_x5bag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1181 | 0 | int offset = 0; |
1182 | 0 | dissect_value_cosex509(tvb, pinfo, tree, hf_hdr_x5bag, &offset); |
1183 | 0 | return offset; |
1184 | 0 | } |
1185 | 0 | static int dissect_header_x5chain(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1186 | 0 | int offset = 0; |
1187 | 0 | dissect_value_cosex509(tvb, pinfo, tree, hf_hdr_x5chain, &offset); |
1188 | 0 | return offset; |
1189 | 0 | } |
1190 | | |
1191 | 0 | static int dissect_header_x5t(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1192 | 0 | int offset = 0; |
1193 | |
|
1194 | 0 | wscbor_chunk_t *chunk_list = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1195 | 0 | wscbor_require_array_size(chunk_list, 2, 2); |
1196 | 0 | proto_item *item_list = proto_tree_add_cbor_container(tree, hf_hdr_x5t, pinfo, tvb, chunk_list); |
1197 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_list)) { |
1198 | 0 | proto_tree *tree_list = proto_item_add_subtree(item_list, ett_hdr_x5t_list); |
1199 | |
|
1200 | 0 | dissect_value_alg(tvb, pinfo, tree_list, &offset); |
1201 | |
|
1202 | 0 | wscbor_chunk_t *chunk_hash = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1203 | 0 | wscbor_require_bstr(pinfo->pool, chunk_hash); |
1204 | 0 | proto_tree_add_cbor_bstr(tree_list, hf_hdr_x5t_hash, pinfo, tvb, chunk_hash); |
1205 | |
|
1206 | 0 | } |
1207 | |
|
1208 | 0 | return offset; |
1209 | 0 | } |
1210 | | |
1211 | 0 | static int dissect_header_x5u(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1212 | 0 | int offset = 0; |
1213 | |
|
1214 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1215 | 0 | wscbor_require_major_type(chunk, CBOR_TYPE_STRING); |
1216 | 0 | proto_tree_add_cbor_tstr(tree, hf_hdr_x5u, pinfo, tvb, chunk); |
1217 | |
|
1218 | 0 | return offset; |
1219 | 0 | } |
1220 | | |
1221 | 274 | static int dissect_cose_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1222 | 274 | int offset = 0; |
1223 | | |
1224 | 274 | proto_item *item_key = proto_tree_add_item(tree, proto_cose, tvb, 0, -1, ENC_NA); |
1225 | 274 | proto_item_append_text(item_key, ": COSE_Key"); |
1226 | 274 | proto_tree *tree_key = proto_item_add_subtree(item_key, ett_key); |
1227 | | |
1228 | 274 | dissect_value_cose_key(tvb, pinfo, tree_key, &offset); |
1229 | | |
1230 | 274 | return offset; |
1231 | 274 | } |
1232 | | |
1233 | 296 | static int dissect_cose_key_set(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1234 | 296 | int offset = 0; |
1235 | | |
1236 | 296 | wscbor_chunk_t *chunk_set = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1237 | 296 | wscbor_require_array(chunk_set); |
1238 | 296 | proto_item *item_set = proto_tree_add_cbor_container(tree, proto_cose, pinfo, tvb, chunk_set); |
1239 | 296 | proto_item_append_text(item_set, ": COSE_KeySet"); |
1240 | 296 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_set)) { |
1241 | 294 | proto_tree *tree_set = proto_item_add_subtree(item_set, ett_key_set); |
1242 | | |
1243 | 22.4k | for (uint64_t ix = 0; ix < chunk_set->head_value; ++ix) { |
1244 | 22.1k | proto_item *item_key = proto_tree_add_item(tree_set, hf_key, tvb, offset, -1, ENC_NA); |
1245 | 22.1k | proto_tree *tree_key = proto_item_add_subtree(item_key, ett_key); |
1246 | | |
1247 | 22.1k | const int offset_key = offset; |
1248 | 22.1k | dissect_value_cose_key(tvb, pinfo, tree_key, &offset); |
1249 | 22.1k | proto_item_set_len(item_key, offset - offset_key); |
1250 | 22.1k | } |
1251 | 294 | } |
1252 | | |
1253 | 296 | proto_item_set_len(item_set, offset); |
1254 | 296 | return offset; |
1255 | 296 | } |
1256 | | |
1257 | 892 | static int dissect_keyparam_kty(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1258 | 892 | int offset = 0; |
1259 | | |
1260 | 892 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1261 | 892 | switch (chunk->type_major) { |
1262 | 599 | case CBOR_TYPE_UINT: |
1263 | 711 | case CBOR_TYPE_NEGINT: { |
1264 | 711 | int64_t *val = wscbor_require_int64(pinfo->pool, chunk); |
1265 | 711 | proto_tree_add_cbor_int64(tree, hf_keyparam_kty_int, pinfo, tvb, chunk, val); |
1266 | 711 | break; |
1267 | 599 | } |
1268 | 46 | case CBOR_TYPE_STRING: { |
1269 | 46 | proto_tree_add_cbor_tstr(tree, hf_keyparam_kty_tstr, pinfo, tvb, chunk); |
1270 | 46 | break; |
1271 | 599 | } |
1272 | 135 | default: |
1273 | 135 | break; |
1274 | 892 | } |
1275 | | |
1276 | 892 | return offset; |
1277 | 892 | } |
1278 | | |
1279 | 294 | static int dissect_keyparam_keyops(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1280 | 294 | int offset = 0; |
1281 | | |
1282 | 294 | wscbor_chunk_t *chunk_list = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1283 | 294 | wscbor_require_array(chunk_list); |
1284 | 294 | proto_item *item_list = proto_tree_add_cbor_container(tree, hf_keyparam_keyops_list, pinfo, tvb, chunk_list); |
1285 | 294 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_list)) { |
1286 | 12 | proto_tree *tree_list = proto_item_add_subtree(item_list, ett_keyops_list); |
1287 | | |
1288 | 132 | for (uint64_t ix = 0; ix < chunk_list->head_value; ++ix) { |
1289 | 120 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1290 | 120 | switch (chunk->type_major) { |
1291 | 66 | case CBOR_TYPE_UINT: |
1292 | 94 | case CBOR_TYPE_NEGINT: { |
1293 | 94 | int64_t *val = wscbor_require_int64(pinfo->pool, chunk); |
1294 | 94 | proto_tree_add_cbor_int64(tree_list, hf_keyparam_keyops_int, pinfo, tvb, chunk, val); |
1295 | 94 | break; |
1296 | 66 | } |
1297 | 8 | case CBOR_TYPE_STRING: { |
1298 | 8 | proto_tree_add_cbor_tstr(tree_list, hf_keyparam_keyops_tstr, pinfo, tvb, chunk); |
1299 | 8 | break; |
1300 | 66 | } |
1301 | 18 | default: |
1302 | 18 | break; |
1303 | 120 | } |
1304 | 120 | } |
1305 | 12 | } |
1306 | 294 | proto_item_set_len(item_list, offset - chunk_list->start); |
1307 | | |
1308 | 294 | return offset; |
1309 | 294 | } |
1310 | | |
1311 | 422 | static int dissect_keyparam_baseiv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1312 | 422 | int offset = 0; |
1313 | | |
1314 | 422 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1315 | 422 | wscbor_require_bstr(pinfo->pool, chunk); |
1316 | 422 | proto_tree_add_cbor_bstr(tree, hf_keyparam_baseiv, pinfo, tvb, chunk); |
1317 | | |
1318 | 422 | return offset; |
1319 | 422 | } |
1320 | | |
1321 | 411 | static int dissect_keyparam_crv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1322 | 411 | int offset = 0; |
1323 | | |
1324 | 411 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1325 | 411 | switch (chunk->type_major) { |
1326 | 78 | case CBOR_TYPE_UINT: |
1327 | 340 | case CBOR_TYPE_NEGINT: { |
1328 | 340 | int64_t *val = wscbor_require_int64(pinfo->pool, chunk); |
1329 | 340 | proto_tree_add_cbor_int64(tree, hf_keyparam_crv_int, pinfo, tvb, chunk, val); |
1330 | 340 | break; |
1331 | 78 | } |
1332 | 24 | case CBOR_TYPE_STRING: { |
1333 | 24 | proto_tree_add_cbor_tstr(tree, hf_keyparam_crv_tstr, pinfo, tvb, chunk); |
1334 | 24 | break; |
1335 | 78 | } |
1336 | 47 | default: |
1337 | 47 | break; |
1338 | 411 | } |
1339 | | |
1340 | 411 | return offset; |
1341 | 411 | } |
1342 | | |
1343 | 75 | static int dissect_keyparam_xcoord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1344 | 75 | int offset = 0; |
1345 | | |
1346 | 75 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1347 | 75 | wscbor_require_bstr(pinfo->pool, chunk); |
1348 | 75 | proto_tree_add_cbor_bstr(tree, hf_keyparam_xcoord, pinfo, tvb, chunk); |
1349 | | |
1350 | 75 | return offset; |
1351 | 75 | } |
1352 | | |
1353 | 326 | static int dissect_keyparam_ycoord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1354 | 326 | int offset = 0; |
1355 | | |
1356 | 326 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1357 | 326 | switch (chunk->type_major) { |
1358 | 7 | case CBOR_TYPE_FLOAT_CTRL: { |
1359 | 7 | proto_tree_add_item(tree, hf_keyparam_ycoord, tvb, 0, 0, ENC_NA); |
1360 | 7 | break; |
1361 | 0 | } |
1362 | 1 | case CBOR_TYPE_BYTESTRING: { |
1363 | 1 | proto_tree_add_cbor_bstr(tree, hf_keyparam_ycoord, pinfo, tvb, chunk); |
1364 | 1 | break; |
1365 | 0 | } |
1366 | 318 | default: |
1367 | 318 | break; |
1368 | 326 | } |
1369 | | |
1370 | 326 | return offset; |
1371 | 326 | } |
1372 | | |
1373 | 265 | static int dissect_keyparam_dcoord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1374 | 265 | int offset = 0; |
1375 | | |
1376 | 265 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1377 | 265 | wscbor_require_bstr(pinfo->pool, chunk); |
1378 | 265 | proto_tree_add_cbor_bstr(tree, hf_keyparam_dcoord, pinfo, tvb, chunk); |
1379 | | |
1380 | 265 | return offset; |
1381 | 265 | } |
1382 | | |
1383 | 49 | static int dissect_keyparam_k(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1384 | 49 | int offset = 0; |
1385 | | |
1386 | 49 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1387 | 49 | wscbor_require_bstr(pinfo->pool, chunk); |
1388 | 49 | proto_tree_add_cbor_bstr(tree, hf_keyparam_k, pinfo, tvb, chunk); |
1389 | | |
1390 | 49 | return offset; |
1391 | 49 | } |
1392 | | |
1393 | 16 | static int dissect_keyparam_pub(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1394 | 16 | int offset = 0; |
1395 | | |
1396 | 16 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1397 | 16 | wscbor_require_bstr(pinfo->pool, chunk); |
1398 | 16 | proto_tree_add_cbor_bstr(tree, hf_keyparam_pub, pinfo, tvb, chunk); |
1399 | | |
1400 | 16 | return offset; |
1401 | 16 | } |
1402 | | |
1403 | 0 | static int dissect_keyparam_priv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1404 | 0 | int offset = 0; |
1405 | |
|
1406 | 0 | wscbor_chunk_t *chunk = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
1407 | 0 | wscbor_require_bstr(pinfo->pool, chunk); |
1408 | 0 | proto_tree_add_cbor_bstr(tree, hf_keyparam_priv, pinfo, tvb, chunk); |
1409 | |
|
1410 | 0 | return offset; |
1411 | 0 | } |
1412 | | |
1413 | | /** Register a message dissector. |
1414 | | */ |
1415 | 90 | static void register_msg_dissector(dissector_handle_t dis_h, uint64_t tag_int, const char *media_subtype) { |
1416 | 90 | uint64_t *key_int = g_new(uint64_t, 1); |
1417 | 90 | *key_int = tag_int; |
1418 | 90 | dissector_add_custom_table_handle("cose.msgtag", key_int, dis_h); |
1419 | | |
1420 | 90 | dissector_add_string("cose.mediasub", media_subtype, dis_h); |
1421 | 90 | } |
1422 | | |
1423 | | /** Register a header dissector. |
1424 | | * @param dissector The dissector function. |
1425 | | * @param label The associated map label. |
1426 | | * @param name The header name. |
1427 | | */ |
1428 | 255 | static void register_header_dissector(dissector_t dissector, GVariant *label, const char *name) { |
1429 | 255 | dissector_handle_t dis_h = create_dissector_handle_with_name_and_description(dissector, proto_cose_params, NULL, name); |
1430 | | |
1431 | 255 | cose_param_key_t *key = g_new0(cose_param_key_t, 1); |
1432 | 255 | key->label = label; |
1433 | | |
1434 | 255 | dissector_add_custom_table_handle("cose.header", key, dis_h); |
1435 | 255 | } |
1436 | | |
1437 | | /** Register a key parameter dissector. |
1438 | | * @param dissector The dissector function. |
1439 | | * @param kty The associated key type "kty" or NULL. |
1440 | | * @param label The associated map label. |
1441 | | * @param name The header name. |
1442 | | */ |
1443 | 240 | static void register_keyparam_dissector(dissector_t dissector, GVariant *kty, GVariant *label, const char *name) { |
1444 | 240 | dissector_handle_t dis_h = create_dissector_handle_with_name_and_description(dissector, proto_cose_params, NULL, name); |
1445 | | |
1446 | 240 | cose_param_key_t *key = g_new0(cose_param_key_t, 1); |
1447 | 240 | if (kty) { |
1448 | 165 | g_variant_ref(kty); |
1449 | 165 | key->principal = kty; |
1450 | 165 | } |
1451 | 240 | key->label = label; |
1452 | | |
1453 | 240 | dissector_add_custom_table_handle("cose.keyparam", key, dis_h); |
1454 | 240 | } |
1455 | | |
1456 | | /// Shutdown global stores |
1457 | 0 | static void cose_shutdown(void) { |
1458 | 0 | g_hash_table_unref(cose_hash_props_map); |
1459 | 0 | cose_hash_props_map = NULL; |
1460 | 0 | g_hash_table_unref(cose_aead_props_map); |
1461 | 0 | cose_aead_props_map = NULL; |
1462 | 0 | g_hash_table_unref(cose_ecc_props_map); |
1463 | 0 | cose_ecc_props_map = NULL; |
1464 | 0 | } |
1465 | | |
1466 | | /// Re-initialize after a configuration change |
1467 | 15 | static void cose_reinit(void) { |
1468 | 15 | } |
1469 | | |
1470 | | /// Overall registration of the protocol |
1471 | 15 | void proto_register_cose(void) { |
1472 | | // Global scope data |
1473 | 15 | register_shutdown_routine(&cose_shutdown); |
1474 | 15 | cose_hash_props_map = g_hash_table_new(g_int64_hash, g_int64_equal); |
1475 | 15 | for (const cose_hash_props_t *item = cose_hash_props_list; |
1476 | 135 | item < cose_hash_props_list + array_length(cose_hash_props_list); ++item) { |
1477 | 120 | g_hash_table_insert(cose_hash_props_map, (void *)&(item->value), (void *)item); |
1478 | 120 | } |
1479 | 15 | cose_aead_props_map = g_hash_table_new(g_int64_hash, g_int64_equal); |
1480 | 15 | for (const cose_aead_props_t *item = cose_aead_props_list; |
1481 | 195 | item < cose_aead_props_list + array_length(cose_aead_props_list); ++item) { |
1482 | 180 | g_hash_table_insert(cose_aead_props_map, (void *)&(item->value), (void *)item); |
1483 | 180 | } |
1484 | 15 | cose_ecc_props_map = g_hash_table_new(g_int64_hash, g_int64_equal); |
1485 | 15 | for (const cose_ecc_props_t *item = cose_ecc_props_list; |
1486 | 135 | item < cose_ecc_props_list + array_length(cose_ecc_props_list); ++item) { |
1487 | 120 | g_hash_table_insert(cose_ecc_props_map, (void *)&(item->value), (void *)item); |
1488 | 120 | } |
1489 | | |
1490 | 15 | proto_cose = proto_register_protocol("CBOR Object Signing and Encryption", proto_name_cose, "cose"); |
1491 | 15 | proto_cose_params = proto_register_protocol_in_name_only( |
1492 | 15 | "COSE Parameter Subdissectors", |
1493 | 15 | "COSE Parameter Subdissectors", |
1494 | 15 | "cose_params", |
1495 | 15 | proto_cose, |
1496 | 15 | FT_PROTOCOL |
1497 | 15 | ); |
1498 | | |
1499 | 15 | proto_register_field_array(proto_cose, fields, array_length(fields)); |
1500 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
1501 | 15 | expert_module_t *expert = expert_register_protocol(proto_cose); |
1502 | 15 | expert_register_field_array(expert, expertitems, array_length(expertitems)); |
1503 | | |
1504 | 15 | handle_cose_msg_hdr = register_dissector("cose.msg.headers", dissect_cose_msg_header_map, proto_cose); |
1505 | | |
1506 | 15 | table_cose_msg_tag = register_custom_dissector_table("cose.msgtag", "COSE Message Tag", proto_cose, g_int64_hash, g_int64_equal, g_free); |
1507 | 15 | table_cose_media_subtype = register_dissector_table("cose.mediasub", "COSE Media Subtype", proto_cose, FT_STRINGZ, STRING_CASE_INSENSITIVE); |
1508 | | |
1509 | 15 | handle_cose_msg_tagged = register_dissector("cose", dissect_cose_msg_tagged, proto_cose_params); |
1510 | 15 | handle_cose_media_type = create_dissector_handle_with_name(dissect_cose_media_type, proto_cose, "cose"); |
1511 | | |
1512 | | // RFC 9052 data item names (Table 1) |
1513 | 15 | handle_cose_sign = register_dissector_with_description("cose_sign", "COSE_Sign", dissect_cose_sign, proto_cose); |
1514 | 15 | handle_cose_sign1 = register_dissector_with_description("cose_sign1", "COSE_Sign1", dissect_cose_sign1, proto_cose); |
1515 | 15 | handle_cose_encrypt = register_dissector_with_description("cose_encrypt", "COSE_Encrypt", dissect_cose_encrypt, proto_cose); |
1516 | 15 | handle_cose_encrypt0 = register_dissector_with_description("cose_encrypt0", "COSE_Encrypt0", dissect_cose_encrypt0, proto_cose); |
1517 | 15 | handle_cose_mac = register_dissector_with_description("cose_mac", "COSE_Mac", dissect_cose_mac, proto_cose); |
1518 | 15 | handle_cose_mac0 = register_dissector_with_description("cose_mac0", "COSE_Mac0", dissect_cose_mac0, proto_cose); |
1519 | | |
1520 | 15 | table_header = register_custom_dissector_table("cose.header", "COSE Header Parameter", proto_cose, cose_param_key_hash, cose_param_key_equal, cose_param_key_free); |
1521 | | |
1522 | | // RFC 9052 data item names (Section 11.3.2) |
1523 | 15 | handle_cose_key = register_dissector_with_description("cose_key", "COSE_Key", dissect_cose_key, proto_cose); |
1524 | 15 | handle_cose_key_set = register_dissector_with_description("cose_key_set", "COSE_KeySet", dissect_cose_key_set, proto_cose); |
1525 | | |
1526 | 15 | table_keyparam = register_custom_dissector_table("cose.keyparam", "COSE Key Parameter", proto_cose, cose_param_key_hash, cose_param_key_equal, cose_param_key_free); |
1527 | | |
1528 | 15 | module_t *module_cose = prefs_register_protocol(proto_cose, cose_reinit); |
1529 | 15 | (void)module_cose; |
1530 | 15 | } |
1531 | | |
1532 | 15 | void proto_reg_handoff_cose(void) { |
1533 | 15 | table_media = find_dissector_table("media_type"); |
1534 | 15 | handle_cbor = find_dissector("cbor"); |
1535 | | |
1536 | 15 | dissector_add_string("media_type", "application/cose", handle_cose_media_type); |
1537 | 15 | dissector_add_string("media_type.suffix", "cose", handle_cose_media_type); |
1538 | | |
1539 | | // RFC 9052 tags and media type "cose-type" names (Table 1) |
1540 | 15 | register_msg_dissector(handle_cose_sign, 98, "cose-sign"); |
1541 | 15 | register_msg_dissector(handle_cose_sign1, 18, "cose-sign1"); |
1542 | 15 | register_msg_dissector(handle_cose_encrypt, 96, "cose-encrypt"); |
1543 | 15 | register_msg_dissector(handle_cose_encrypt0, 16, "cose-encrypt0"); |
1544 | 15 | register_msg_dissector(handle_cose_mac, 97, "cose-mac"); |
1545 | 15 | register_msg_dissector(handle_cose_mac0, 17, "cose-mac0"); |
1546 | | |
1547 | | // RFC 9053 header labels |
1548 | 15 | register_header_dissector(dissect_header_salt, g_variant_new_int64(-20), "salt"); |
1549 | 15 | register_header_dissector(dissect_header_kid, g_variant_new_int64(-3), "static kid"); |
1550 | 15 | register_header_dissector(dissect_header_static_key, g_variant_new_int64(-2), "static key"); |
1551 | 15 | register_header_dissector(dissect_header_ephem_key, g_variant_new_int64(-1), "ephemeral key"); |
1552 | 15 | register_header_dissector(dissect_header_alg, g_variant_new_int64(1), "alg"); |
1553 | 15 | register_header_dissector(dissect_header_crit, g_variant_new_int64(2), "crit"); |
1554 | 15 | register_header_dissector(dissect_header_ctype, g_variant_new_int64(3), "content type"); |
1555 | 15 | register_header_dissector(dissect_header_kid, g_variant_new_int64(4), "kid"); |
1556 | 15 | register_header_dissector(dissect_header_iv, g_variant_new_int64(5), "IV"); |
1557 | 15 | register_header_dissector(dissect_header_piv, g_variant_new_int64(6), "Partial IV"); |
1558 | | // RFC 9360 header labels |
1559 | 15 | register_header_dissector(dissect_header_x5chain, g_variant_new_int64(-29), "x5chain-sender"); |
1560 | 15 | register_header_dissector(dissect_header_x5u, g_variant_new_int64(-28), "x5u-sender"); |
1561 | 15 | register_header_dissector(dissect_header_x5t, g_variant_new_int64(-27), "x5t-sender"); |
1562 | 15 | register_header_dissector(dissect_header_x5bag, g_variant_new_int64(32), "x5bag"); |
1563 | 15 | register_header_dissector(dissect_header_x5chain, g_variant_new_int64(33), "x5chain"); |
1564 | 15 | register_header_dissector(dissect_header_x5t, g_variant_new_int64(34), "x5t"); |
1565 | 15 | register_header_dissector(dissect_header_x5u, g_variant_new_int64(35), "x5u"); |
1566 | | |
1567 | 15 | dissector_add_string("media_type", "application/cose-key", handle_cose_key); |
1568 | 15 | dissector_add_string("media_type", "application/cose-key-set", handle_cose_key_set); |
1569 | | // RFC 9052 key parameter labels |
1570 | 15 | register_keyparam_dissector(dissect_keyparam_kty, NULL, g_variant_new_int64(1), "kty"); |
1571 | 15 | register_keyparam_dissector(dissect_header_kid, NULL, g_variant_new_int64(2), "kid"); |
1572 | 15 | register_keyparam_dissector(dissect_header_alg, NULL, g_variant_new_int64(3), "alg"); |
1573 | 15 | register_keyparam_dissector(dissect_keyparam_keyops, NULL, g_variant_new_int64(4), "key_ops"); |
1574 | 15 | register_keyparam_dissector(dissect_keyparam_baseiv, NULL, g_variant_new_int64(5), "Base IV"); |
1575 | | // kty-specific parameters |
1576 | 15 | { |
1577 | 15 | GVariant *kty = g_variant_new_int64(1); |
1578 | 15 | register_keyparam_dissector(dissect_keyparam_crv, kty, g_variant_new_int64(-1), "crv"); |
1579 | 15 | register_keyparam_dissector(dissect_keyparam_xcoord, kty, g_variant_new_int64(-2), "x"); |
1580 | 15 | register_keyparam_dissector(dissect_keyparam_dcoord, kty, g_variant_new_int64(-3), "d"); |
1581 | 15 | g_variant_unref(kty); |
1582 | 15 | } |
1583 | 15 | { |
1584 | 15 | GVariant *kty = g_variant_new_int64(2); |
1585 | 15 | register_keyparam_dissector(dissect_keyparam_crv, kty, g_variant_new_int64(-1), "crv"); |
1586 | 15 | register_keyparam_dissector(dissect_keyparam_xcoord, kty, g_variant_new_int64(-2), "x"); |
1587 | 15 | register_keyparam_dissector(dissect_keyparam_ycoord, kty, g_variant_new_int64(-3), "y"); |
1588 | 15 | register_keyparam_dissector(dissect_keyparam_dcoord, kty, g_variant_new_int64(-4), "d"); |
1589 | 15 | g_variant_unref(kty); |
1590 | 15 | } |
1591 | 15 | { |
1592 | 15 | GVariant *kty = g_variant_new_int64(4); |
1593 | 15 | register_keyparam_dissector(dissect_keyparam_k, kty, g_variant_new_int64(-1), "k"); |
1594 | 15 | g_variant_unref(kty); |
1595 | 15 | } |
1596 | 15 | { |
1597 | 15 | GVariant *kty = g_variant_new_int64(5); |
1598 | 15 | register_keyparam_dissector(dissect_keyparam_pub, kty, g_variant_new_int64(-1), "pub"); |
1599 | 15 | g_variant_unref(kty); |
1600 | 15 | } |
1601 | 15 | { |
1602 | 15 | GVariant *kty = g_variant_new_int64(7); |
1603 | 15 | register_keyparam_dissector(dissect_keyparam_pub, kty, g_variant_new_int64(-1), "pub"); |
1604 | 15 | register_keyparam_dissector(dissect_keyparam_priv, kty, g_variant_new_int64(-2), "priv"); |
1605 | 15 | g_variant_unref(kty); |
1606 | 15 | } |
1607 | | |
1608 | 15 | cose_reinit(); |
1609 | 15 | } |