HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-mikey.c
blobc671a48d738ad2e7d7c7a584c45ac652e15dda6e
1 /* packet-mikey.c
2 * Routines for Multimedia Internet KEYing dissection
3 * Copyright 2007, Mikael Magnusson <mikma@users.sourceforge.net>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 * Ref:
27 * http://tools.ietf.org/html/rfc3830 MIKEY
28 * http://tools.ietf.org/html/rfc6043 MIKEY-TICKET (ID role required for SAKKE)
29 * http://tools.ietf.org/html/rfc6509 MIKEY-SAKKE
33 * TODO
34 * tvbuff offset in 32-bit variable.
35 * Support CHASH
36 * Decode Mikey-PK and Mikey-RSA-R with NULL encryption
40 #include "config.h"
42 #include <glib.h>
44 #include <epan/packet.h>
45 #include <epan/wmem/wmem.h>
46 #include <epan/prefs.h>
47 #include <epan/asn1.h>
48 #include <epan/dissectors/packet-x509af.h>
50 #define PORT_MIKEY 2269
51 static guint global_mikey_tcp_port = PORT_MIKEY;
53 static guint global_mikey_udp_port = PORT_MIKEY;
55 static const value_string on_off_vals[] = {
56 { 0, "Off" },
57 { 1, "On" },
58 { 0, NULL }
61 enum data_type_t {
62 MIKEY_TYPE_PSK_INIT = 0,
63 MIKEY_TYPE_PSK_RESP,
64 MIKEY_TYPE_PK_INIT,
65 MIKEY_TYPE_PK_RESP,
66 MIKEY_TYPE_DH_INIT,
67 MIKEY_TYPE_DH_RESP,
68 MIKEY_TYPE_ERROR,
69 MIKEY_TYPE_DHHMAC_INIT,
70 MIKEY_TYPE_DHHMAC_RESP,
71 MIKEY_TYPE_RSA_R_INIT,
72 MIKEY_TYPE_RSA_R_RESP,
73 MIKEY_TYPE_SAKKE_INIT = 26,
74 MIKEY_TYPE_SAKKE_RESP
77 static const value_string data_type_vals[] = {
78 { MIKEY_TYPE_PSK_INIT, "Pre-shared" },
79 { MIKEY_TYPE_PSK_RESP, "PSK ver msg" },
80 { MIKEY_TYPE_PK_INIT, "Public key" },
81 { MIKEY_TYPE_PK_RESP, "PK ver msg" },
82 { MIKEY_TYPE_DH_INIT, "D-H init" },
83 { MIKEY_TYPE_DH_RESP, "D-H resp" },
84 { MIKEY_TYPE_ERROR, "Error" },
85 { MIKEY_TYPE_DHHMAC_INIT, "DHHMAC init" },
86 { MIKEY_TYPE_DHHMAC_RESP, "DHHMAC resp" },
87 { MIKEY_TYPE_RSA_R_INIT, "RSA-R I_MSG" },
88 { MIKEY_TYPE_RSA_R_RESP, "RSA-R R_MSG" },
89 { MIKEY_TYPE_SAKKE_INIT, "SAKKE" },
90 { MIKEY_TYPE_SAKKE_RESP, "CS Id map Update" },
91 { 0, NULL }
93 static value_string_ext data_type_vals_ext = VALUE_STRING_EXT_INIT(data_type_vals);
95 enum cs_id_map_t {
96 CS_ID_SRTP = 0
99 static const value_string cs_id_map_vals[] = {
100 { CS_ID_SRTP, "SRTP-ID" },
101 { 0, NULL }
104 enum payload_t {
105 PL_HDR = -1,
106 PL_LAST,
107 PL_KEMAC,
108 PL_PKE,
109 PL_DH,
110 PL_SIGN,
111 PL_T,
112 PL_ID,
113 PL_CERT,
114 PL_CHASH,
115 PL_V,
116 PL_SP,
117 PL_RAND,
118 PL_ERR,
119 PL_TR = 13, /* MIKEY-TICKET (6043) */
120 PL_IDR,
121 PL_RANDR,
122 PL_TP,
123 PL_TICKET,
124 PL_KEY_DATA = 20,
125 PL_GENERAL_EXT,
126 PL_SAKKE = 26,
127 PL_MAX
130 #define PL_HDR_TEXT "Common Header (HDR)"
131 #define PL_LAST_TEXT "Last payload"
132 #define PL_KEMAC_TEXT "Key Data Transport (KEMAC)"
133 #define PL_PKE_TEXT "Envelope Data (PKE)"
134 #define PL_DH_TEXT "DH Data (DH)"
135 #define PL_SIGN_TEXT "Signature (SIGN)"
136 #define PL_T_TEXT "Timestamp (T)"
137 #define PL_ID_TEXT "ID"
138 #define PL_CERT_TEXT "Certificate (CERT)"
139 #define PL_CHASH_TEXT "CHASH"
140 #define PL_V_TEXT "Ver msg (V)"
141 #define PL_SP_TEXT "Security Policy (SP)"
142 #define PL_RAND_TEXT "RAND"
143 #define PL_ERR_TEXT "Error (ERR)"
144 #define PL_KEY_DATA_TEXT "Key data (KEY)"
145 #define PL_IDR_TEXT "IDR"
146 #define PL_GENERAL_EXT_TEXT "General Extension (EXT)"
147 #define PL_SAKKE_TEXT "SAKKE Encapsulated Data (SAKKE)"
149 static const value_string payload_vals[] = {
150 { PL_HDR, PL_HDR_TEXT },
151 { PL_LAST, PL_LAST_TEXT },
152 { PL_KEMAC, PL_KEMAC_TEXT },
153 { PL_PKE, PL_PKE_TEXT },
154 { PL_DH, PL_DH_TEXT },
155 { PL_SIGN, PL_SIGN_TEXT },
156 { PL_T, PL_T_TEXT },
157 { PL_ID, PL_ID_TEXT },
158 { PL_CERT, PL_CERT_TEXT },
159 { PL_CHASH, PL_CHASH_TEXT },
160 { PL_V, PL_V_TEXT },
161 { PL_SP, PL_SP_TEXT },
162 { PL_RAND, PL_RAND_TEXT },
163 { PL_ERR, PL_ERR_TEXT },
164 { PL_IDR, PL_IDR_TEXT },
165 { PL_KEY_DATA, PL_KEY_DATA_TEXT },
166 { PL_GENERAL_EXT, PL_GENERAL_EXT_TEXT },
167 { PL_SAKKE, PL_SAKKE_TEXT },
168 { 0, NULL }
170 #if 0 /* First entry (PL_HDR) is -1 and there are gaps so this doesn't work */
171 static value_string_ext payload_vals_ext = VALUE_STRING_EXT_INIT(payload_vals);
172 #endif
174 enum ts_type_t {
175 T_NTP_UTC = 0,
176 T_NTP,
177 T_COUNTER
180 static const value_string ts_type_vals[] = {
181 { T_NTP_UTC, "NTP-UTC" },
182 { T_NTP, "NTP" },
183 { T_COUNTER, "COUNTER" },
184 { 0, NULL }
187 enum encr_alg_t {
188 ENCR_NULL = 0,
189 ENCR_AES_CM_128,
190 ENCR_AES_KW_128
193 static const value_string encr_alg_vals[] = {
194 { ENCR_NULL, "NULL" },
195 { ENCR_AES_CM_128, "AES-CM-128" },
196 { ENCR_AES_KW_128, "AES-KW-128" },
197 { 0, NULL }
200 enum oakley_t {
201 DH_OAKLEY_5 = 0,
202 DH_OAKLEY_1,
203 DH_OAKLEY_2
206 static const value_string oakley_vals[] = {
207 { DH_OAKLEY_5, "OAKLEY 5" },
208 { DH_OAKLEY_1, "OAKLEY 1" },
209 { DH_OAKLEY_2, "OAKLEY 2" },
210 { 0, NULL }
213 enum mac_alg_t {
214 MAC_NULL = 0,
215 MAC_HMAC_SHA_1_160
218 static const value_string mac_alg_vals[] = {
219 { MAC_NULL, "NULL" },
220 { MAC_HMAC_SHA_1_160, "HMAC-SHA-1-160" },
221 { 0, NULL }
224 enum pke_c_t {
225 PKE_C_NO_CACHE = 0,
226 PKE_C_CACHE,
227 PKE_C_CACHE_CSB
230 static const value_string pke_c_vals[] = {
231 { PKE_C_NO_CACHE, "No cache" },
232 { PKE_C_CACHE, "Cache" },
233 { PKE_C_CACHE_CSB, "Cache for CSB" },
234 { 0, NULL }
237 enum sign_s_t {
238 SIGN_S_PKCS1 = 0,
239 SIGN_S_PSS,
240 SIGN_S_ECCSI
243 static const value_string sign_s_vals[] = {
244 { SIGN_S_PKCS1, "RSA/PKCS#1/1.5" },
245 { SIGN_S_PSS, "RSA/PSS" },
246 { SIGN_S_ECCSI, "ECCSI" },
247 { 0, NULL }
250 enum id_type_t {
251 ID_TYPE_NAI = 0,
252 ID_TYPE_URI,
253 ID_TYPE_BYTE_STRING
256 static const value_string id_type_vals[] = {
257 { ID_TYPE_NAI, "NAI" },
258 { ID_TYPE_URI, "URI" },
259 { ID_TYPE_BYTE_STRING, "Byte string" },
260 { 0, NULL }
263 enum id_role_t {
264 ID_ROLE_RESERVED = 0,
265 ID_ROLE_INIT,
266 ID_ROLE_RESP,
267 ID_ROLE_KMS,
268 ID_ROLE_PSK,
269 ID_ROLE_APP,
270 ID_ROLE_INIT_KMS,
271 ID_ROLE_RESP_KMS
274 static const value_string id_role_vals[] = {
275 { ID_ROLE_RESERVED, "Reserved" },
276 { ID_ROLE_INIT, "Initiator (IDRi)" },
277 { ID_ROLE_RESP, "Responder (IDRr)" },
278 { ID_ROLE_KMS, "KMS (IDRkms)" },
279 { ID_ROLE_PSK, "Pre-Shared Key (IDRpsk)" },
280 { ID_ROLE_APP, "Application (IDRapp)" },
281 { ID_ROLE_INIT_KMS, "Initiator's KMS (IDRkmsi)" },
282 { ID_ROLE_RESP_KMS, "Responder's KMS (IDRkmsr)" },
283 { 0, NULL }
286 enum cert_type_t {
287 CERT_TYPE_X509V3 = 0,
288 CERT_TYPE_X509V3_URL,
289 CERT_TYPE_X509V3_SIGN,
290 CERT_TYPE_X509V3_ENCR
293 static const value_string cert_type_vals[] = {
294 { CERT_TYPE_X509V3, "X.509v3" },
295 { CERT_TYPE_X509V3_URL, "X.509v3 URL" },
296 { CERT_TYPE_X509V3_SIGN, "X.509v3 Sign" },
297 { CERT_TYPE_X509V3_ENCR, "X.509v3 Encr" },
298 { 0, NULL }
301 enum srtp_policy_type_t {
302 SP_ENCR_ALG,
303 SP_ENCR_LEN,
304 SP_AUTH_ALG,
305 SP_AUTH_KEY_LEN,
306 SP_SALT_LEN,
307 SP_PRF,
308 SP_KD_RATE,
309 SP_SRTP_ENCR,
310 SP_SRTCP_ENCR,
311 SP_FEC,
312 SP_SRTP_AUTH,
313 SP_AUTH_TAG_LEN,
314 SP_SRTP_PREFIX,
315 SP_MAX
318 #define SP_TEXT_ENCR_ALG "Encryption algorithm"
319 #define SP_TEXT_ENCR_LEN "Session Encr. key length"
320 #define SP_TEXT_AUTH_ALG "Authentication algorithm"
321 #define SP_TEXT_AUTH_KEY_LEN "Session Auth. key length"
322 #define SP_TEXT_SALT_LEN "Session Salt key length"
323 #define SP_TEXT_PRF "SRTP Pseudo Random Function"
324 #define SP_TEXT_KD_RATE "Key derivation rate"
325 #define SP_TEXT_SRTP_ENCR "SRTP encryption"
326 #define SP_TEXT_SRTCP_ENCR "SRTCP encryption"
327 #define SP_TEXT_FEC "Sender's FEC order"
328 #define SP_TEXT_SRTP_AUTH "SRTP authentication"
329 #define SP_TEXT_AUTH_TAG_LEN "Authentication tag length"
330 #define SP_TEXT_SRTP_PREFIX "SRTP prefix length"
332 #if 0
333 static const value_string srtp_policy_type_vals[] = {
334 { SP_ENCR_ALG, SP_TEXT_ENCR_ALG },
335 { SP_ENCR_LEN, SP_TEXT_ENCR_LEN },
336 { SP_AUTH_ALG, SP_TEXT_AUTH_ALG },
337 { SP_AUTH_KEY_LEN, SP_TEXT_AUTH_KEY_LEN },
338 { SP_SALT_LEN, SP_TEXT_SALT_LEN },
339 { SP_PRF, SP_TEXT_PRF },
340 { SP_KD_RATE, SP_TEXT_KD_RATE },
341 { SP_SRTP_ENCR, SP_TEXT_SRTP_ENCR },
342 { SP_SRTCP_ENCR, SP_TEXT_SRTCP_ENCR },
343 { SP_FEC, SP_TEXT_FEC },
344 { SP_SRTP_AUTH, SP_TEXT_SRTP_AUTH },
345 { SP_AUTH_TAG_LEN, SP_TEXT_AUTH_TAG_LEN },
346 { SP_SRTP_PREFIX, SP_TEXT_SRTP_PREFIX },
347 { 0, NULL }
349 #endif
351 enum sp_encr_alg_t {
352 SP_ENCR_NULL = 0,
353 SP_ENCR_AES_CM,
354 SP_ENCR_AES_F8
357 static const value_string sp_encr_alg_vals[] = {
358 { SP_ENCR_NULL, "NULL" },
359 { SP_ENCR_AES_CM, "AES-CM" },
360 { SP_ENCR_AES_F8, "AES-F8" },
361 { 0, NULL }
364 enum sp_auth_alg_t {
365 SP_AUTH_NULL = 0,
366 SP_AUTH_HMAC_SHA_1
369 static const value_string sp_auth_alg_vals[] = {
370 { SP_AUTH_NULL, "NULL" },
371 { SP_AUTH_HMAC_SHA_1, "HMAC-SHA-1" },
372 { 0, NULL }
375 enum sp_prf_t {
376 SP_PRF_AES_CM = 0
379 static const value_string sp_prf_vals[] = {
380 { SP_PRF_AES_CM, "AES-CM" },
381 { 0, NULL }
384 enum sp_fec_t {
385 SP_FEC_SRTP = 0
388 static const value_string sp_fec_vals[] = {
389 { SP_FEC_SRTP, "FEC-SRTP" },
390 { 0, NULL }
393 enum sp_prot_t {
394 SP_PROT_TYPE_SRTP = 0
397 static const value_string sp_prot_type_vals[] = {
398 { SP_PROT_TYPE_SRTP, "SRTP" },
399 { 0, NULL }
402 enum prf_func_t {
403 PRF_FUNC_MIKEY_1 = 0
406 static const value_string prf_func_vals[] = {
407 { PRF_FUNC_MIKEY_1, "MIKEY-1" },
408 { 0, NULL }
411 enum kv_t {
412 KV_NULL = 0,
413 KV_SPI,
414 KV_INTERVAL
417 static const value_string kv_vals[] = {
418 { KV_NULL, "Null" },
419 { KV_SPI, "SPI/MKI" },
420 { KV_INTERVAL, "Interval" },
421 { 0, NULL }
424 enum kd_t {
425 KD_TGK = 0,
426 KD_TGK_SALT,
427 KD_TEK,
428 KD_TEK_SALT
431 static const value_string kd_vals[] = {
432 { KD_TGK, "TGK" },
433 { KD_TGK_SALT, "TGK+SALT" },
434 { KD_TEK, "TEK" },
435 { KD_TEK_SALT, "TEK+SALT" },
436 { 0, NULL }
439 enum err_t {
440 ERR_AUTH_FAILURE = 0,
441 ERR_INVALID_TS,
442 ERR_INVALID_PRF,
443 ERR_INVALID_MAC,
444 ERR_INVALID_EA,
445 ERR_INVALID_HA,
446 ERR_INVALID_DH,
447 ERR_INVALID_ID,
448 ERR_INVALID_CERT,
449 ERR_INVALID_SP,
450 ERR_INVALID_SPPAR,
451 ERR_INVALID_DT,
452 ERR_UNKNOWN
455 static const value_string err_vals[] = {
456 { ERR_AUTH_FAILURE, "Authentication failure" },
457 { ERR_INVALID_TS, "Invalid timestamp" },
458 { ERR_INVALID_PRF, "PRF function not supported" },
459 { ERR_INVALID_MAC, "MAC algorithm not supported" },
460 { ERR_INVALID_EA, "Encryption algorithm not supported" },
461 { ERR_INVALID_HA, "Hash function not supported" },
462 { ERR_INVALID_DH, "DH group not supported" },
463 { ERR_INVALID_ID, "ID not supported" },
464 { ERR_INVALID_CERT, "Certificate not supported" },
465 { ERR_INVALID_SP, "SP type not supported" },
466 { ERR_INVALID_SPPAR, "SP parameters not supported" },
467 { ERR_INVALID_DT, "Data type not supported" },
468 { ERR_UNKNOWN, "Unspecified error" },
469 { 0, NULL }
471 static value_string_ext err_vals_ext = VALUE_STRING_EXT_INIT(err_vals);
473 enum genext_t {
474 GEN_EXT_VENDOR_ID = 0,
475 GEN_EXT_SDP_ID
478 static const value_string genext_type_vals[] = {
479 { GEN_EXT_VENDOR_ID, "Vendor-ID" },
480 { GEN_EXT_SDP_ID, "SDP-IDs" },
481 { 0, NULL }
484 enum {
485 /* HDR */
486 POS_HDR_VERSION=0,
487 POS_HDR_DATA_TYPE,
488 POS_HDR_V,
489 POS_HDR_PRF_FUNC,
490 POS_HDR_CSB_ID,
491 POS_HDR_CS_COUNT,
492 POS_HDR_CS_ID_MAP_TYPE,
493 POS_ID_SRTP,
494 POS_ID_SRTP_NO,
495 POS_ID_SRTP_SSRC,
496 POS_ID_SRTP_ROC,
498 /* KEMAC */
499 POS_KEMAC_ENCR_ALG,
500 POS_KEMAC_ENCR_DATA_LEN,
501 POS_KEMAC_ENCR_DATA,
502 POS_KEMAC_MAC_ALG,
503 POS_KEMAC_MAC,
505 /* PKE */
506 POS_PKE_C,
507 POS_PKE_DATA_LEN,
508 POS_PKE_DATA,
510 /* DH */
511 POS_DH_GROUP,
512 POS_DH_VALUE,
513 POS_DH_RESERV,
514 POS_DH_KV,
516 /* SIGN */
517 POS_SIGNATURE_LEN,
518 POS_SIGNATURE,
519 POS_SIGN_S_TYPE,
521 /* T */
522 POS_TS_TYPE,
523 POS_TS_NTP,
525 /* ID/IDR */
526 POS_ID_ROLE,
527 POS_ID_TYPE,
528 POS_ID_LEN,
529 POS_ID,
531 /* CERT */
532 POS_CERT_TYPE,
533 POS_CERT_LEN,
534 POS_CERTIFICATE,
536 /* V */
537 POS_V_AUTH_ALG,
538 POS_V_DATA,
540 /* SP */
541 POS_SP_NO,
542 POS_SP_TYPE,
543 POS_SP_PARAM_LEN,
544 /* POS_SP_PARAM, */
546 /* SP param */
547 POS_SP_PARAM_F,
548 POS_SP_PARAM_F_TYPE,
549 POS_SP_PARAM_F_LEN,
550 POS_SP_PARAM_F_VALUE,
552 /* RAND */
553 POS_RAND_LEN,
554 POS_RAND,
556 /* Error */
557 POS_ERR_NO,
558 POS_ERR_RESERVED,
560 /* Key data */
561 POS_KEY_DATA_TYPE,
562 POS_KEY_DATA_KV,
563 POS_KEY_DATA_LEN,
564 POS_KEY_DATA,
565 POS_KEY_SALT_LEN,
566 POS_KEY_SALT,
567 POS_KEY_KV_FROM_LEN,
568 POS_KEY_KV_FROM,
569 POS_KEY_KV_TO_LEN,
570 POS_KEY_KV_TO,
571 POS_KEY_KV_SPI_LEN,
572 POS_KEY_KV_SPI,
574 /* General Ext. */
575 POS_GENERAL_EXT_TYPE,
576 POS_GENERAL_EXT_LEN,
577 POS_GENERAL_EXT_DATA,
578 POS_GENERAL_EXT_VALUE,
580 /* SAKKE */
581 POS_SAKKE_PARAMS,
582 POS_SAKKE_ID_SCHEME,
583 POS_SAKKE_LEN,
584 POS_SAKKE_DATA,
586 /* MIKEY */
587 POS_PAYLOAD_STR,
588 POS_NEXT_PAYLOAD,
590 /* Unused */
591 /* POS_PAYLOAD, */
593 MAX_POS
596 typedef struct tag_mikey_t {
597 guint8 type;
598 } mikey_t;
600 typedef int (*mikey_dissector_t)(mikey_t *, tvbuff_t *, packet_info *, proto_tree *);
601 struct mikey_dissector_entry {
602 int type;
603 mikey_dissector_t dissector;
606 /* Forward declaration we need below */
607 void proto_reg_handoff_mikey(void);
608 static int dissect_payload(int payload, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
611 /* Initialize the protocol and registered fields */
612 static int proto_mikey = -1;
613 static int hf_mikey[MAX_POS+1];
614 static int hf_mikey_sp_param[SP_MAX+1];
615 static int hf_mikey_pl[PL_MAX];
617 /* Initialize the subtree pointers */
618 static gint ett_mikey = -1;
619 static gint ett_mikey_payload = -1;
620 static gint ett_mikey_sp_param = -1;
621 static gint ett_mikey_hdr_id = -1;
622 static gint ett_mikey_enc_data = -1;
624 static dissector_handle_t mikey_handle;
626 static const struct mikey_dissector_entry *
627 mikey_dissector_lookup(const struct mikey_dissector_entry *map, int type)
629 unsigned int i;
630 for (i = 0; map[i].dissector != NULL; i++) {
631 if (map[i].type == type) {
632 return &map[i];
636 return NULL;
639 static void
640 add_next_payload(tvbuff_t *tvb, proto_tree *tree, int offset)
642 proto_tree_add_item(tree, hf_mikey[POS_NEXT_PAYLOAD], tvb, offset, 1, ENC_BIG_ENDIAN);
646 static int
647 dissect_payload_cs_id_srtp(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
649 tvb_ensure_bytes_exist(tvb, 0, 9);
651 if (tree) {
652 proto_item *id_ti;
653 proto_tree *id_tree;
654 guint8 no;
655 guint32 ssrc;
656 guint32 roc;
658 no = tvb_get_guint8(tvb, 0);
659 ssrc = tvb_get_ntohl(tvb, 1);
660 roc = tvb_get_ntohl(tvb, 5);
662 id_ti = proto_tree_add_none_format(tree, hf_mikey[POS_ID_SRTP], tvb, 0, 9,
663 "SRTP ID: Policy: %d, SSRC: 0x%x, ROC: 0x%x", no, ssrc, roc);
664 id_tree = proto_item_add_subtree(id_ti, ett_mikey_hdr_id);
666 proto_tree_add_item(id_tree, hf_mikey[POS_ID_SRTP_NO], tvb, 0, 1, ENC_BIG_ENDIAN);
667 proto_tree_add_item(id_tree, hf_mikey[POS_ID_SRTP_SSRC], tvb, 1, 4, ENC_BIG_ENDIAN);
668 proto_tree_add_item(id_tree, hf_mikey[POS_ID_SRTP_ROC], tvb, 5, 4, ENC_BIG_ENDIAN);
670 return 9;
673 static const struct mikey_dissector_entry cs_id_map[] = {
674 { CS_ID_SRTP, dissect_payload_cs_id_srtp },
675 { 0, NULL }
678 static int
679 dissect_payload_cs_id(int type, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
681 const struct mikey_dissector_entry *entry;
683 entry = mikey_dissector_lookup(cs_id_map, type);
685 if (!entry || !entry->dissector) {
686 return -1;
689 return entry->dissector(mikey, tvb, pinfo, tree);
693 static int
694 dissect_payload_hdr(mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
696 int offset = 0;
697 guint8 cs_id_map_type;
698 guint8 ncs;
699 int i;
701 tvb_ensure_bytes_exist(tvb, offset, 10);
702 mikey->type = tvb_get_guint8(tvb, offset+1);
703 ncs = tvb_get_guint8(tvb, offset+8);
704 cs_id_map_type = tvb_get_guint8(tvb, offset+9);
706 if (tree) {
707 proto_item* parent;
708 proto_tree_add_item(tree, hf_mikey[POS_HDR_VERSION],
709 tvb, offset+0, 1, ENC_BIG_ENDIAN);
711 proto_tree_add_item(tree, hf_mikey[POS_HDR_DATA_TYPE], tvb, offset+1, 1, ENC_BIG_ENDIAN);
712 parent = proto_tree_get_parent(tree);
713 proto_item_append_text(parent, " Type: %s",
714 val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
716 add_next_payload(tvb, tree, offset+2);
718 proto_tree_add_item(tree, hf_mikey[POS_HDR_V], tvb, offset+3, 1, ENC_BIG_ENDIAN);
719 proto_tree_add_item(tree, hf_mikey[POS_HDR_PRF_FUNC], tvb, offset+3, 1, ENC_BIG_ENDIAN);
721 proto_tree_add_item(tree, hf_mikey[POS_HDR_CSB_ID], tvb, offset+4, 4, ENC_BIG_ENDIAN);
723 proto_tree_add_item(tree, hf_mikey[POS_HDR_CS_COUNT], tvb, offset+8, 1, ENC_BIG_ENDIAN);
724 proto_tree_add_item(tree, hf_mikey[POS_HDR_CS_ID_MAP_TYPE], tvb, offset+9, 1, ENC_BIG_ENDIAN);
727 offset += 10;
728 for (i=0; i < ncs; i++) {
729 tvbuff_t *sub_tvb;
730 int len;
732 sub_tvb = tvb_new_subset_remaining(tvb, offset);
733 len = dissect_payload_cs_id(cs_id_map_type, mikey, sub_tvb, pinfo, tree);
735 if (len < 0)
736 return -1;
738 offset += len;
741 return offset;
744 static int
745 dissect_payload_kemac(mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
747 int offset = 0;
748 guint8 encr_alg;
749 guint16 encr_length;
750 guint16 mac_length;
751 guint8 mac_alg;
753 tvb_ensure_bytes_exist(tvb, offset+0, 4);
754 encr_alg = tvb_get_guint8(tvb, offset+1);
755 encr_length = tvb_get_ntohs(tvb, offset+2);
756 tvb_ensure_bytes_exist(tvb, offset+4, encr_length+1);
757 mac_alg = tvb_get_guint8(tvb, offset+4+encr_length);
759 if (tree) {
760 tvbuff_t *sub_tvb;
761 proto_tree_add_item(tree, hf_mikey[POS_KEMAC_ENCR_ALG], tvb, 1, 1, ENC_BIG_ENDIAN);
762 proto_tree_add_item(tree, hf_mikey[POS_KEMAC_ENCR_DATA_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
763 /* TODO: Add key decode for MIKEY_TYPE_PK_INIT and MIKEY_TYPE_RSA_R_RESP with NULL encryption */
764 if ((encr_alg == ENCR_NULL) && (mikey->type == MIKEY_TYPE_PSK_INIT) && (encr_length > 0)) {
765 proto_item *key_data_item;
766 proto_tree *key_data_tree;
767 /* We can decode easily the Key Data if NULL encryption is used */
768 key_data_item = proto_tree_add_item(tree, hf_mikey_pl[PL_KEY_DATA], tvb, 4, encr_length, ENC_NA);
769 key_data_tree = proto_item_add_subtree(key_data_item, ett_mikey_enc_data);
771 sub_tvb = tvb_new_subset(tvb, offset+4, encr_length, encr_length);
772 dissect_payload(PL_KEY_DATA, mikey, sub_tvb, pinfo, key_data_tree);
773 } else {
774 /* If Key Data is encrypted, show only the encr_data */
775 proto_tree_add_item(tree, hf_mikey[POS_KEMAC_ENCR_DATA], tvb, 4, encr_length, ENC_NA);
777 proto_tree_add_item(tree, hf_mikey[POS_KEMAC_MAC_ALG], tvb, 4+encr_length, 1, ENC_BIG_ENDIAN);
780 switch (mac_alg) {
781 case MAC_NULL:
782 mac_length = 0;
783 break;
784 case MAC_HMAC_SHA_1_160:
785 mac_length = 160/8;
786 break;
787 default:
788 return -1;
791 tvb_ensure_bytes_exist(tvb, offset+4+encr_length+1, mac_length);
792 if (tree) {
793 proto_tree_add_item(tree, hf_mikey[POS_KEMAC_MAC], tvb, 4+encr_length+1, mac_length, ENC_NA);
796 return 4+encr_length+1+mac_length;
799 static int
800 dissect_payload_pke(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
802 int offset = 0;
803 guint16 length;
805 tvb_ensure_bytes_exist(tvb, offset+0, 3);
806 length = tvb_get_ntohs(tvb, offset+1) &0x3ff;
808 if (tree) {
809 proto_tree_add_item(tree, hf_mikey[POS_PKE_C], tvb, 1, 2, ENC_BIG_ENDIAN);
811 proto_tree_add_item(tree, hf_mikey[POS_PKE_DATA_LEN], tvb, 1, 2, ENC_BIG_ENDIAN);
814 tvb_ensure_bytes_exist(tvb, offset+3, length);
815 if (tree) {
816 proto_tree_add_item(tree, hf_mikey[POS_PKE_DATA], tvb, 3, length, ENC_NA);
818 return 3 + length;
821 static int
822 dissect_payload_dh(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
824 int offset = 0;
825 guint8 dh_group;
826 int dh_length;
827 guint8 kv;
829 tvb_ensure_bytes_exist(tvb, offset+0, 2);
830 dh_group = tvb_get_guint8(tvb, offset+1);
832 switch (dh_group) {
833 case DH_OAKLEY_5:
834 dh_length = 1536/8;
835 break;
836 case DH_OAKLEY_1:
837 dh_length = 768/8;
838 break;
839 case DH_OAKLEY_2:
840 dh_length = 1024/8;
841 break;
842 default:
843 return -1;
846 tvb_ensure_bytes_exist(tvb, offset+2, dh_length+1);
847 kv = tvb_get_guint8(tvb, offset+2+dh_length) & 0x0f;
849 if (tree) {
850 proto_tree_add_item(tree, hf_mikey[POS_DH_GROUP], tvb, 1, 1, ENC_BIG_ENDIAN);
851 proto_tree_add_item(tree, hf_mikey[POS_DH_VALUE], tvb, 2, dh_length, ENC_NA);
852 proto_tree_add_item(tree, hf_mikey[POS_DH_RESERV], tvb, 2+dh_length, 1, ENC_BIG_ENDIAN);
853 proto_tree_add_item(tree, hf_mikey[POS_DH_KV], tvb, 2+dh_length, 1, ENC_BIG_ENDIAN);
856 if (kv != 0) {
857 return -1;
860 return 2 + dh_length + 1;
863 static int
864 dissect_payload_sign(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
866 int offset = 0;
867 guint16 length;
869 tvb_ensure_bytes_exist(tvb, offset+0, 2);
870 length = ((tvb_get_guint8(tvb, offset+0) & 0x0f) << 8) + tvb_get_guint8(tvb, offset+1);
872 if (tree) {
873 proto_tree_add_item(tree, hf_mikey[POS_SIGN_S_TYPE], tvb, 0, 2, ENC_BIG_ENDIAN);
874 proto_tree_add_uint(tree, hf_mikey[POS_SIGNATURE_LEN], tvb, 0, 2, length);
877 tvb_ensure_bytes_exist(tvb, offset+2, length);
878 if (tree) {
879 proto_tree_add_item(tree, hf_mikey[POS_SIGNATURE], tvb, 2, length, ENC_NA);
881 return 2 + length;
884 static int
885 dissect_payload_t(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
887 guint8 ts_type;
888 int offset = 0;
889 int len = 0;
891 tvb_ensure_bytes_exist(tvb, offset+0, 2);
892 ts_type = tvb_get_guint8(tvb, offset+1);
894 if (tree) {
895 proto_tree *parent;
896 parent = proto_tree_get_parent(tree);
897 proto_item_append_text(parent, " Type: %s", val_to_str_const(ts_type, ts_type_vals, "Unknown"));
898 proto_tree_add_item(tree, hf_mikey[POS_TS_TYPE], tvb, offset+1, 1, ENC_BIG_ENDIAN);
901 switch (ts_type) {
902 case T_NTP:
903 case T_NTP_UTC:
904 proto_tree_add_item(tree, hf_mikey[POS_TS_NTP], tvb, offset+2, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN);
905 len = 10;
906 break;
907 case T_COUNTER:
908 len = 6;
909 break;
910 default:
911 len = -1;
912 break;
915 return len;
918 static int
919 dissect_payload_id(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
921 int offset = 0;
922 guint8 type;
923 guint16 length;
925 tvb_ensure_bytes_exist(tvb, offset+0, 4);
926 type = tvb_get_guint8(tvb, offset+1);
927 length = tvb_get_ntohs(tvb, offset+2);
928 if (tree) {
929 proto_tree_add_item(tree, hf_mikey[POS_ID_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
930 proto_tree_add_item(tree, hf_mikey[POS_ID_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
933 tvb_ensure_bytes_exist(tvb, offset+4, length);
934 if (tree) {
935 proto_item* parent;
936 proto_tree_add_item(tree, hf_mikey[POS_ID], tvb, 4, length, ENC_ASCII|ENC_NA);
938 parent = proto_tree_get_parent(tree);
939 proto_item_append_text(parent, " %s: %s",
940 val_to_str_const(type, id_type_vals, "Unknown"),
941 tvb_get_string(wmem_packet_scope(), tvb, 4, length));
944 return 4 + length;
947 static int
948 dissect_payload_idr(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
950 int offset = 0;
951 guint8 type;
952 guint16 length;
954 tvb_ensure_bytes_exist(tvb, offset+0, 5);
955 type = tvb_get_guint8(tvb, offset+2);
956 length = tvb_get_ntohs(tvb, offset+3);
957 if (tree) {
958 proto_tree_add_item(tree, hf_mikey[POS_ID_ROLE], tvb, 1, 1, ENC_NA);
959 proto_tree_add_item(tree, hf_mikey[POS_ID_TYPE], tvb, 2, 1, ENC_NA);
960 proto_tree_add_item(tree, hf_mikey[POS_ID_LEN], tvb, 3, 2, ENC_NA);
963 tvb_ensure_bytes_exist(tvb, offset+5, length);
964 if (tree) {
965 proto_item *parent;
966 proto_tree_add_item(tree, hf_mikey[POS_ID], tvb, 5, length, ENC_ASCII|ENC_NA);
968 parent = proto_tree_get_parent(tree);
969 proto_item_append_text(parent, " %s: %s",
970 val_to_str_const(type, id_type_vals, "Unknown"),
971 tvb_get_string(wmem_packet_scope(), tvb, 5, length));
974 return 5 + length;
977 static int
978 dissect_payload_cert(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
980 int offset = 0;
981 guint8 type;
982 guint16 length;
983 tvbuff_t *subtvb;
984 asn1_ctx_t asn1_ctx;
986 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
988 tvb_ensure_bytes_exist(tvb, offset+0, 4);
989 type = tvb_get_guint8(tvb, offset+1);
990 length = tvb_get_ntohs(tvb, offset+2);
992 tvb_ensure_bytes_exist(tvb, offset+4, length);
994 if (tree) {
995 proto_item *parent;
996 parent = proto_tree_get_parent(tree);
997 proto_tree_add_item(tree, hf_mikey[POS_CERT_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
998 proto_tree_add_item(tree, hf_mikey[POS_CERT_LEN], tvb, 1, 2, ENC_BIG_ENDIAN);
1000 proto_item_append_text(parent, " Type: %s", val_to_str_const(type, cert_type_vals, "Unknown"));
1003 subtvb = tvb_new_subset(tvb, offset+4, length, length);
1004 dissect_x509af_Certificate(FALSE, subtvb, 0, &asn1_ctx, tree, hf_mikey[POS_CERTIFICATE]);
1006 return 4 + length;
1009 static int
1010 dissect_payload_v(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1012 int offset = 0;
1013 guint16 length;
1014 guint8 alg;
1016 tvb_ensure_bytes_exist(tvb, offset+0, 2);
1017 alg = tvb_get_guint8(tvb, offset+1);
1019 if (tree) {
1020 proto_tree_add_item(tree, hf_mikey[POS_V_AUTH_ALG], tvb, 1, 1, ENC_BIG_ENDIAN);
1023 switch (alg) {
1024 case MAC_NULL:
1025 length = 0;
1026 break;
1027 case MAC_HMAC_SHA_1_160:
1028 length = 160/8;
1029 break;
1030 default:
1031 return -1;
1034 tvb_ensure_bytes_exist(tvb, offset+2, length);
1035 if (tree) {
1036 proto_tree_add_item(tree, hf_mikey[POS_V_DATA], tvb, 2, length, ENC_NA);
1039 return 2 + length;
1042 static int
1043 dissect_payload_sp_param(enum sp_prot_t proto, tvbuff_t *tvb, proto_tree *tree)
1045 int offset = 0;
1046 guint8 type;
1047 guint8 length;
1048 int hfindex;
1050 tvb_ensure_bytes_exist(tvb, offset+0, 2);
1051 type = tvb_get_guint8(tvb, offset+0);
1052 length = tvb_get_guint8(tvb, offset+1);
1053 tvb_ensure_bytes_exist(tvb, offset+2, length);
1055 /* Default */
1056 hfindex = hf_mikey[POS_SP_PARAM_F];
1058 switch(proto) {
1059 case SP_PROT_TYPE_SRTP:
1060 if (type < array_length(hf_mikey_sp_param))
1061 hfindex = hf_mikey_sp_param[type];
1062 break;
1065 if (tree) {
1066 proto_item *param_ti;
1067 proto_tree *param_tree;
1069 * All the parameters in question are either FT_BYTES,
1070 * in which case the byte order is inapplicable, or
1071 * FT_UINT8, in which case it could be given as
1072 * FT_BIG_ENDIAN as per bigger FT_UINT values, but
1073 * ENC_NA also works, as there's only one byte.
1075 param_ti = proto_tree_add_item(tree, hfindex, tvb, 2, length, ENC_NA);
1076 param_tree = proto_item_add_subtree(param_ti, ett_mikey_sp_param);
1078 proto_tree_add_item(param_tree, hf_mikey[POS_SP_PARAM_F_TYPE], tvb, 0, 1, ENC_BIG_ENDIAN);
1079 proto_tree_add_item(param_tree, hf_mikey[POS_SP_PARAM_F_LEN], tvb, 1, 1, ENC_BIG_ENDIAN);
1080 proto_tree_add_item(param_tree, hf_mikey[POS_SP_PARAM_F_VALUE], tvb, 2, length, ENC_NA);
1083 return 2+length;
1086 static int
1087 dissect_payload_sp(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1089 int offset = 0;
1090 guint16 length;
1091 int sub_pos;
1092 guint8 no;
1093 enum sp_prot_t type;
1095 tvb_ensure_bytes_exist(tvb, offset+0, 5);
1096 length = tvb_get_ntohs(tvb, offset+3);
1097 no = tvb_get_guint8(tvb, offset+1);
1098 type = (enum sp_prot_t)tvb_get_guint8(tvb, offset+2);
1100 if (tree) {
1101 proto_item *parent;
1102 parent = proto_tree_get_parent(tree);
1103 proto_tree_add_item(tree, hf_mikey[POS_SP_NO], tvb, 1, 1, ENC_BIG_ENDIAN);
1104 proto_tree_add_item(tree, hf_mikey[POS_SP_TYPE], tvb, 2, 1, ENC_BIG_ENDIAN);
1105 proto_tree_add_item(tree, hf_mikey[POS_SP_PARAM_LEN], tvb, 3, 2, ENC_BIG_ENDIAN);
1107 proto_item_append_text(parent, " No: %d, Type: %s", no,
1108 val_to_str_const(type, sp_prot_type_vals, "Unknown"));
1111 tvb_ensure_bytes_exist(tvb, offset+5, length);
1112 /* proto_tree_add_item(tree, hf_mikey[POS_SP_PARAM], tvb, 5, length, ENC_NA); */
1114 offset += 5;
1115 sub_pos = 0;
1117 while (sub_pos < length) {
1118 int param_len;
1119 tvbuff_t *subtvb;
1121 subtvb = tvb_new_subset(tvb, offset+sub_pos, length-sub_pos, length-sub_pos);
1122 param_len = dissect_payload_sp_param(type, subtvb, tree);
1124 if (param_len < 0)
1125 return -1;
1127 sub_pos += param_len;
1130 return 5 + length;
1133 static int
1134 dissect_payload_rand(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1136 int offset = 0;
1137 guint16 length;
1139 tvb_ensure_bytes_exist(tvb, offset+0, 2);
1140 length = tvb_get_guint8(tvb, offset+1);
1142 if (tree) {
1143 proto_tree_add_item(tree, hf_mikey[POS_RAND_LEN], tvb, 1, 1, ENC_BIG_ENDIAN);
1146 tvb_ensure_bytes_exist(tvb, offset+2, length);
1148 if (tree) {
1149 proto_tree_add_item(tree, hf_mikey[POS_RAND], tvb, 2, length, ENC_NA);
1151 return 2 + length;
1154 static int
1155 dissect_payload_err(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1157 tvb_ensure_bytes_exist(tvb, 0, 4);
1159 if (tree) {
1160 proto_item *parent;
1161 guint8 err_no;
1162 err_no = tvb_get_guint8(tvb, 1);
1163 proto_tree_add_item(tree, hf_mikey[POS_ERR_NO], tvb, 1, 1, ENC_BIG_ENDIAN);
1164 proto_tree_add_item(tree, hf_mikey[POS_ERR_RESERVED], tvb, 2, 2, ENC_NA);
1165 parent = proto_tree_get_parent(tree);
1166 proto_item_append_text(parent, ": %s", val_to_str_ext_const(err_no, &err_vals_ext, "Unknown"));
1169 return 4;
1172 static int
1173 dissect_payload_keydata(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1175 guint16 offset;
1176 guint16 data_len;
1177 guint8 key_type;
1178 guint8 kv_type;
1180 offset = 0;
1181 tvb_ensure_bytes_exist(tvb, 0, 4);
1182 key_type = tvb_get_guint8(tvb, 1) >> 4;
1183 kv_type = tvb_get_guint8(tvb, 1) & 0x0f;
1184 data_len = tvb_get_ntohs(tvb, 2);
1186 tvb_ensure_bytes_exist(tvb, 4, data_len);
1187 offset += 4;
1189 if (tree) {
1190 proto_item *parent;
1191 proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
1192 proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA_KV], tvb, 1, 1, ENC_BIG_ENDIAN);
1193 proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
1194 proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA], tvb, 4, data_len, ENC_NA);
1196 parent = proto_tree_get_parent(tree);
1197 proto_item_append_text(parent, " Type: %s", val_to_str_const(key_type, kd_vals, "Unknown"));
1200 offset += data_len;
1202 /* Dissect SALT key */
1203 if ((key_type == KD_TGK_SALT) || (key_type == KD_TEK_SALT)) {
1204 guint16 salt_len;
1205 tvb_ensure_bytes_exist(tvb, offset, 2);
1206 salt_len = tvb_get_ntohs(tvb, offset);
1207 if (salt_len > 0) {
1208 tvb_ensure_bytes_exist(tvb, offset+2, salt_len);
1209 if (tree) {
1210 proto_tree_add_item(tree, hf_mikey[POS_KEY_SALT_LEN], tvb, offset, 2, ENC_BIG_ENDIAN);
1211 proto_tree_add_item(tree, hf_mikey[POS_KEY_SALT], tvb, offset+2, salt_len, ENC_NA);
1214 offset += 2+salt_len;
1217 /* Dissect Key Validity */
1218 if (kv_type == KV_INTERVAL) {
1219 guint16 kv_from_len;
1220 guint16 kv_to_len;
1222 tvb_ensure_bytes_exist(tvb, offset, 1);
1223 kv_from_len = tvb_get_guint8(tvb, offset);
1224 proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_FROM_LEN], tvb, offset, 1, ENC_BIG_ENDIAN);
1225 if (kv_from_len > 0) {
1226 tvb_ensure_bytes_exist(tvb, offset+1, kv_from_len);
1227 proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_FROM], tvb, offset+1, kv_from_len, ENC_NA);
1229 offset += 1+kv_from_len;
1231 tvb_ensure_bytes_exist(tvb, offset, 1);
1232 kv_to_len = tvb_get_guint8(tvb, offset);
1233 proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_TO_LEN], tvb, offset, 1, ENC_BIG_ENDIAN);
1234 if (kv_to_len > 0) {
1235 tvb_ensure_bytes_exist(tvb, offset+1, kv_to_len);
1236 proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_TO], tvb, offset+1, kv_to_len, ENC_NA);
1238 offset += 1+kv_to_len;
1239 } else if (kv_type == KV_SPI) {
1240 guint16 kv_spi_len;
1242 tvb_ensure_bytes_exist(tvb, offset, 1);
1243 kv_spi_len = tvb_get_guint8(tvb, offset);
1244 proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_SPI_LEN], tvb, offset, 1, ENC_BIG_ENDIAN);
1245 if (kv_spi_len > 0) {
1246 tvb_ensure_bytes_exist(tvb, offset+1, kv_spi_len);
1247 proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_SPI], tvb, offset+1, kv_spi_len, ENC_NA);
1249 offset += 1+kv_spi_len;
1252 return offset;
1255 static int
1256 dissect_payload_general_ext(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1258 int offset = 0;
1259 guint8 type;
1260 guint16 data_len;
1262 tvb_ensure_bytes_exist(tvb, offset+0, 4);
1263 type = tvb_get_guint8(tvb, offset+1);
1264 data_len = tvb_get_ntohs(tvb, offset+2);
1266 if (tree) {
1267 proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
1268 proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
1271 tvb_ensure_bytes_exist(tvb, offset+3, data_len);
1273 if (tree) {
1274 proto_item *parent;
1276 parent = proto_tree_get_parent(tree);
1277 if (type == 1) {
1278 /* For SDP-IDs, show a string instead of raw bytes */
1279 proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_VALUE], tvb, 4, data_len, ENC_ASCII|ENC_NA);
1280 } else {
1281 proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_DATA], tvb, 4, data_len, ENC_NA);
1283 proto_item_append_text(parent, " Type: %s", val_to_str_const(type, genext_type_vals, "Unknown"));
1285 return 4 + data_len;
1288 static int
1289 dissect_payload_sakke(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1291 int offset = 0;
1292 guint16 data_len;
1294 tvb_ensure_bytes_exist(tvb, offset+0, 5);
1295 data_len = tvb_get_ntohs(tvb, offset+3);
1297 if (tree) {
1298 proto_tree_add_item(tree, hf_mikey[POS_SAKKE_PARAMS], tvb, 1, 1, ENC_BIG_ENDIAN);
1299 proto_tree_add_item(tree, hf_mikey[POS_SAKKE_ID_SCHEME], tvb, 2, 1, ENC_BIG_ENDIAN);
1300 proto_tree_add_item(tree, hf_mikey[POS_SAKKE_LEN], tvb, 3, 2, ENC_BIG_ENDIAN);
1303 tvb_ensure_bytes_exist(tvb, offset+5, data_len);
1305 if (tree) {
1306 proto_tree_add_item(tree, hf_mikey[POS_SAKKE_DATA], tvb, 5, data_len, ENC_NA);
1308 return 5 + data_len;
1311 static const struct mikey_dissector_entry payload_map[] = {
1312 { PL_HDR, dissect_payload_hdr },
1313 { PL_KEMAC, dissect_payload_kemac },
1314 { PL_PKE, dissect_payload_pke },
1315 { PL_DH, dissect_payload_dh },
1316 { PL_SIGN, dissect_payload_sign },
1317 { PL_T, dissect_payload_t },
1318 { PL_ID, dissect_payload_id },
1319 { PL_CERT, dissect_payload_cert },
1320 { PL_V, dissect_payload_v },
1321 { PL_SP, dissect_payload_sp },
1322 { PL_RAND, dissect_payload_rand },
1323 { PL_ERR, dissect_payload_err },
1324 { PL_IDR, dissect_payload_idr },
1325 { PL_KEY_DATA, dissect_payload_keydata },
1326 { PL_GENERAL_EXT, dissect_payload_general_ext },
1327 { PL_SAKKE, dissect_payload_sakke },
1328 { 0, NULL }
1331 static int
1332 dissect_payload(int payload, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1334 const struct mikey_dissector_entry *entry;
1336 entry = mikey_dissector_lookup(payload_map, payload);
1338 if (!entry || !entry->dissector) {
1339 return -1;
1342 return entry->dissector(mikey, tvb, pinfo, tree);
1345 /* MIKEY dissector */
1346 static int
1347 dissect_mikey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1349 proto_item *ti = NULL;
1350 proto_tree *mikey_tree = NULL;
1351 int offset = 0;
1352 int next_payload_offset;
1353 int payload;
1354 mikey_t *mikey;
1356 mikey = (mikey_t *)p_get_proto_data(pinfo->fd, proto_mikey, 0);
1358 if (!mikey) {
1359 mikey = wmem_new0(wmem_file_scope(), mikey_t);
1360 mikey->type = -1;
1361 p_add_proto_data(pinfo->fd, proto_mikey, 0, mikey);
1365 tvb_ensure_bytes_exist(tvb, offset, 3);
1366 next_payload_offset = offset + 2;
1367 payload = -1;
1369 if (tree) {
1370 ti = proto_tree_add_item(tree, proto_mikey, tvb, 0, -1, ENC_NA);
1371 mikey_tree = proto_item_add_subtree(ti, ett_mikey);
1374 while (payload != 0) {
1375 int len;
1376 proto_item *sub_ti = NULL;
1377 proto_tree *mikey_payload_tree = NULL;
1378 int next_payload;
1379 tvbuff_t *subtvb;
1381 next_payload = tvb_get_guint8(tvb, next_payload_offset);
1382 subtvb = tvb_new_subset_remaining(tvb, offset);
1384 if (mikey_tree) {
1385 int hf = payload;
1387 if (hf >= PL_MAX)
1388 return -1;
1390 if (hf == -1)
1391 hf = 0;
1393 sub_ti = proto_tree_add_item(mikey_tree, hf_mikey_pl[hf], subtvb, 0, -1, ENC_NA);
1395 mikey_payload_tree = proto_item_add_subtree(sub_ti, ett_mikey_payload);
1396 if ((payload != PL_HDR) && (payload != PL_SIGN))
1397 add_next_payload(tvb, mikey_payload_tree, next_payload_offset);
1400 len = dissect_payload(payload, mikey, subtvb, pinfo, mikey_payload_tree);
1401 if (len < 0) {
1402 return -1;
1405 if (sub_ti)
1406 proto_item_set_len(sub_ti, len);
1408 if (payload == PL_SIGN)
1409 break;
1411 payload = next_payload;
1412 offset += len;
1413 next_payload_offset = offset;
1416 if (ti) {
1417 proto_item_append_text(ti, ": %s",
1418 val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
1421 col_append_str(pinfo->cinfo, COL_PROTOCOL, "/MIKEY");
1423 col_append_fstr(pinfo->cinfo, COL_INFO, ", Mikey: %s",
1424 val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
1426 /* Return the amount of data this dissector was able to dissect */
1427 return tvb_length(tvb);
1431 /* Register the protocol with Wireshark */
1433 void
1434 proto_register_mikey(void)
1437 /* Setup list of header fields */
1438 static hf_register_info hf[] = {
1439 /* Payload types */
1440 { &hf_mikey_pl[PL_HDR+1],
1441 { PL_HDR_TEXT, "mikey.hdr",
1442 FT_NONE, BASE_NONE, NULL, 0x0,
1443 NULL, HFILL }},
1444 { &hf_mikey_pl[PL_KEMAC],
1445 { PL_KEMAC_TEXT, "mikey.kemac",
1446 FT_NONE, BASE_NONE, NULL, 0x0,
1447 NULL, HFILL }},
1448 { &hf_mikey_pl[PL_PKE],
1449 { PL_PKE_TEXT, "mikey.",
1450 FT_NONE, BASE_NONE, NULL, 0x0,
1451 NULL, HFILL }},
1452 { &hf_mikey_pl[PL_DH],
1453 { PL_DH_TEXT, "mikey.dh",
1454 FT_NONE, BASE_NONE, NULL, 0x0,
1455 NULL, HFILL }},
1456 { &hf_mikey_pl[PL_SIGN],
1457 { PL_SIGN_TEXT, "mikey.sign",
1458 FT_NONE, BASE_NONE, NULL, 0x0,
1459 NULL, HFILL }},
1460 { &hf_mikey_pl[PL_T],
1461 { PL_T_TEXT, "mikey.t",
1462 FT_NONE, BASE_NONE, NULL, 0x0,
1463 NULL, HFILL }},
1464 { &hf_mikey_pl[PL_ID],
1465 { PL_ID_TEXT, "mikey.id",
1466 FT_NONE, BASE_NONE, NULL, 0x0,
1467 NULL, HFILL }},
1468 { &hf_mikey_pl[PL_CERT],
1469 { PL_CERT_TEXT, "mikey.cert",
1470 FT_NONE, BASE_NONE, NULL, 0x0,
1471 NULL, HFILL }},
1472 { &hf_mikey_pl[PL_CHASH],
1473 { PL_CHASH_TEXT, "mikey.chash",
1474 FT_NONE, BASE_NONE, NULL, 0x0,
1475 NULL, HFILL }},
1476 { &hf_mikey_pl[PL_V],
1477 { PL_V_TEXT, "mikey.v",
1478 FT_NONE, BASE_NONE, NULL, 0x0,
1479 NULL, HFILL }},
1480 { &hf_mikey_pl[PL_SP],
1481 { PL_SP_TEXT, "mikey.sp",
1482 FT_NONE, BASE_NONE, NULL, 0x0,
1483 NULL, HFILL }},
1484 { &hf_mikey_pl[PL_RAND],
1485 { PL_RAND_TEXT, "mikey.rand",
1486 FT_NONE, BASE_NONE, NULL, 0x0,
1487 NULL, HFILL }},
1488 { &hf_mikey_pl[PL_ERR],
1489 { PL_ERR_TEXT, "mikey.err",
1490 FT_NONE, BASE_NONE, NULL, 0x0,
1491 NULL, HFILL }},
1492 { &hf_mikey_pl[PL_IDR],
1493 { PL_IDR_TEXT, "mikey.idr",
1494 FT_NONE, BASE_NONE, NULL, 0x0,
1495 NULL, HFILL }},
1496 { &hf_mikey_pl[PL_KEY_DATA],
1497 { PL_KEY_DATA_TEXT, "mikey.key",
1498 FT_NONE, BASE_NONE, NULL, 0x0,
1499 NULL, HFILL }},
1500 { &hf_mikey_pl[PL_GENERAL_EXT],
1501 { PL_GENERAL_EXT_TEXT, "mikey.ext",
1502 FT_NONE, BASE_NONE, NULL, 0x0,
1503 NULL, HFILL }},
1504 { &hf_mikey_pl[PL_SAKKE],
1505 { PL_SAKKE_TEXT, "mikey.sakke",
1506 FT_NONE, BASE_NONE, NULL, 0x0,
1507 NULL, HFILL }},
1509 /* Common Header payload (HDR) */
1510 { &hf_mikey[POS_HDR_VERSION],
1511 { "Version", "mikey.version",
1512 FT_UINT8, BASE_DEC, NULL, 0x0,
1513 NULL, HFILL }},
1514 { &hf_mikey[POS_HDR_DATA_TYPE],
1515 { "Data Type", "mikey.type",
1516 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &data_type_vals_ext, 0x0,
1517 NULL, HFILL }},
1518 { &hf_mikey[POS_NEXT_PAYLOAD],
1519 { "Next Payload", "mikey.next_payload",
1520 FT_UINT8, BASE_DEC, VALS(payload_vals), 0x0,
1521 NULL, HFILL }},
1522 { &hf_mikey[POS_HDR_V],
1523 { "V", "mikey.v",
1524 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80,
1525 NULL, HFILL }},
1526 { &hf_mikey[POS_HDR_PRF_FUNC],
1527 { "PRF func", "mikey.prf_func",
1528 FT_UINT8, BASE_DEC, VALS(prf_func_vals), 0x7f,
1529 NULL, HFILL }},
1530 { &hf_mikey[POS_HDR_CSB_ID],
1531 { "CSB ID", "mikey.csb_id",
1532 FT_UINT32, BASE_HEX, NULL, 0x0,
1533 NULL, HFILL }},
1534 { &hf_mikey[POS_HDR_CS_COUNT],
1535 { "#CS", "mikey.cs_count",
1536 FT_UINT8, BASE_DEC, NULL, 0x0,
1537 NULL, HFILL }},
1538 { &hf_mikey[POS_HDR_CS_ID_MAP_TYPE],
1539 { "CS ID map type", "mikey.cs_id_map_type",
1540 FT_UINT8, BASE_DEC, VALS(cs_id_map_vals), 0x0,
1541 NULL, HFILL }},
1543 /* SRTP ID */
1544 { &hf_mikey[POS_ID_SRTP],
1545 { "SRTP ID", "mikey.srtp_id",
1546 FT_NONE, BASE_NONE, NULL, 0x0,
1547 NULL, HFILL }},
1548 { &hf_mikey[POS_ID_SRTP_NO],
1549 { "Policy No", "mikey.srtp_id.policy_no",
1550 FT_UINT8, BASE_DEC, NULL, 0x0,
1551 NULL, HFILL }},
1552 { &hf_mikey[POS_ID_SRTP_SSRC],
1553 { "SSRC", "mikey.srtp_id.ssrc",
1554 FT_UINT32, BASE_HEX, NULL, 0x0,
1555 NULL, HFILL }},
1556 { &hf_mikey[POS_ID_SRTP_ROC],
1557 { "ROC", "mikey.srtp_id.roc",
1558 FT_UINT32, BASE_HEX, NULL, 0x0,
1559 NULL, HFILL }},
1561 /* Key Data Transport payload (KEMAC) */
1562 { &hf_mikey[POS_KEMAC_ENCR_ALG],
1563 { "Encr alg", "mikey.kemac.encr_alg",
1564 FT_UINT8, BASE_DEC, VALS(encr_alg_vals), 0x0,
1565 NULL, HFILL }},
1566 { &hf_mikey[POS_KEMAC_ENCR_DATA_LEN],
1567 { "Key data len", "mikey.kemac.key_data_len",
1568 FT_UINT16, BASE_DEC, NULL, 0x0,
1569 NULL, HFILL }},
1570 { &hf_mikey[POS_KEMAC_ENCR_DATA],
1571 { "Key data", "mikey.kemac.key_data",
1572 FT_BYTES, BASE_NONE, NULL, 0x0,
1573 NULL, HFILL }},
1574 { &hf_mikey[POS_KEMAC_MAC_ALG],
1575 { "Mac alg", "mikey.kemac.mac_alg",
1576 FT_UINT8, BASE_DEC, VALS(mac_alg_vals), 0x0,
1577 NULL, HFILL }},
1578 { &hf_mikey[POS_KEMAC_MAC],
1579 { "MAC", "mikey.kemac.mac",
1580 FT_BYTES, BASE_NONE, NULL, 0x0,
1581 NULL, HFILL }},
1583 /* Envelope Data payload (PKE) */
1584 { &hf_mikey[POS_PKE_C],
1585 { "C", "mikey.pke.c",
1586 FT_UINT16, BASE_DEC, VALS(pke_c_vals), 0xc000,
1587 NULL, HFILL }},
1588 { &hf_mikey[POS_PKE_DATA_LEN],
1589 { "Data len", "mikey.pke.len",
1590 FT_UINT16, BASE_DEC, NULL, 0x3fff,
1591 NULL, HFILL }},
1592 { &hf_mikey[POS_PKE_DATA],
1593 { "Data", "mikey.pke.data",
1594 FT_BYTES, BASE_NONE, NULL, 0x0,
1595 NULL, HFILL }},
1597 /* DH data payload (DH) */
1598 { &hf_mikey[POS_DH_GROUP],
1599 { "DH-Group", "mikey.dh.group",
1600 FT_UINT8, BASE_DEC, VALS(oakley_vals), 0x0,
1601 NULL, HFILL }},
1602 { &hf_mikey[POS_DH_VALUE],
1603 { "DH-Value", "mikey.dh.value",
1604 FT_BYTES, BASE_NONE, NULL, 0x0,
1605 NULL, HFILL }},
1606 { &hf_mikey[POS_DH_RESERV],
1607 { "Reserv", "mikey.dh.reserv",
1608 FT_UINT8, BASE_HEX, NULL, 0xf0,
1609 NULL, HFILL }},
1610 { &hf_mikey[POS_DH_KV],
1611 { "KV", "mikey.dh.kv",
1612 FT_UINT8, BASE_DEC, VALS(kv_vals), 0x0f,
1613 NULL, HFILL }},
1615 /* Signature payload (SIGN) */
1616 { &hf_mikey[POS_SIGN_S_TYPE],
1617 { "Signature type", "mikey.sign.type",
1618 FT_UINT16, BASE_DEC, VALS(sign_s_vals), 0xf000,
1619 NULL, HFILL }},
1620 { &hf_mikey[POS_SIGNATURE_LEN],
1621 { "Signature len", "mikey.sign.len",
1622 FT_UINT16, BASE_DEC, NULL, 0x0fff,
1623 NULL, HFILL }},
1624 { &hf_mikey[POS_SIGNATURE],
1625 { "Signature", "mikey.sign.data",
1626 FT_BYTES, BASE_NONE, NULL, 0x0,
1627 NULL, HFILL }},
1629 /* Timestamp payload (T) */
1630 { &hf_mikey[POS_TS_TYPE],
1631 { "TS type", "mikey.t.ts_type",
1632 FT_UINT8, BASE_DEC, VALS(ts_type_vals), 0x0,
1633 NULL, HFILL }},
1634 { &hf_mikey[POS_TS_NTP],
1635 { "NTP timestamp", "mikey.t.ntp",
1636 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
1637 NULL, HFILL }},
1639 { &hf_mikey[POS_PAYLOAD_STR],
1640 { "Payload", "mikey.payload",
1641 FT_STRING, BASE_NONE, NULL, 0x0,
1642 NULL, HFILL }},
1644 /* ID payload (ID) */
1645 { &hf_mikey[POS_ID_TYPE],
1646 { "ID type", "mikey.id.type",
1647 FT_UINT8, BASE_DEC, VALS(id_type_vals), 0x0,
1648 NULL, HFILL }},
1649 { &hf_mikey[POS_ID_LEN],
1650 { "ID len", "mikey.id.len",
1651 FT_UINT16, BASE_DEC, NULL, 0x0,
1652 NULL, HFILL }},
1653 { &hf_mikey[POS_ID],
1654 { "ID", "mikey.id.data",
1655 FT_STRING, BASE_NONE, NULL, 0x0,
1656 NULL, HFILL }},
1658 /* Certificate payload (CERT) */
1659 { &hf_mikey[POS_CERT_LEN],
1660 { "Certificate len", "mikey.cert.len",
1661 FT_UINT16, BASE_DEC, NULL, 0x0,
1662 NULL, HFILL }},
1663 { &hf_mikey[POS_CERT_TYPE],
1664 { "Certificate type", "mikey.cert.type",
1665 FT_UINT8, BASE_DEC, VALS(cert_type_vals), 0x0,
1666 NULL, HFILL }},
1667 { &hf_mikey[POS_CERTIFICATE],
1668 { "Certificate", "mikey.cert.data",
1669 FT_BYTES, BASE_NONE, NULL, 0x0,
1670 NULL, HFILL }},
1672 /* Ver msg payload (V) */
1673 { &hf_mikey[POS_V_AUTH_ALG],
1674 { "Auth alg", "mikey.v.auth_alg",
1675 FT_UINT8, BASE_DEC, VALS(mac_alg_vals), 0x0,
1676 NULL, HFILL }},
1677 { &hf_mikey[POS_V_DATA],
1678 { "Ver data", "mikey.v.ver_data",
1679 FT_BYTES, BASE_NONE, NULL, 0x0,
1680 NULL, HFILL }},
1682 /* Security Policy payload (SP) */
1683 { &hf_mikey[POS_SP_NO],
1684 { "Policy No", "mikey.sp.no",
1685 FT_UINT8, BASE_DEC, NULL, 0x0,
1686 NULL, HFILL }},
1687 { &hf_mikey[POS_SP_TYPE],
1688 { "Protocol type", "mikey.sp.proto_type",
1689 FT_UINT8, BASE_DEC, VALS(sp_prot_type_vals), 0x0,
1690 NULL, HFILL }},
1691 { &hf_mikey[POS_SP_PARAM_LEN],
1692 { "Policy param length", "mikey.sp.param_len",
1693 FT_UINT16, BASE_DEC, NULL, 0x0,
1694 NULL, HFILL }},
1696 /* Security Policy param */
1697 { &hf_mikey[POS_SP_PARAM_F],
1698 { "Policy param", "mikey.sp.param",
1699 FT_BYTES, BASE_NONE, NULL, 0x0,
1700 NULL, HFILL }},
1701 { &hf_mikey[POS_SP_PARAM_F_TYPE],
1702 { "Type", "mikey.sp.param.type",
1703 FT_UINT8, BASE_DEC, NULL, 0x0,
1704 NULL, HFILL }},
1705 { &hf_mikey[POS_SP_PARAM_F_LEN],
1706 { "Length", "mikey.sp.param.len",
1707 FT_UINT8, BASE_DEC, NULL, 0x0,
1708 NULL, HFILL }},
1709 { &hf_mikey[POS_SP_PARAM_F_VALUE],
1710 { "Value", "mikey.sp.patam.value",
1711 FT_BYTES, BASE_NONE, NULL, 0x0,
1712 NULL, HFILL }},
1714 /* SRTP policy param */
1715 { &hf_mikey_sp_param[SP_ENCR_ALG],
1716 { SP_TEXT_ENCR_ALG, "mikey.sp.encr_alg",
1717 FT_UINT8, BASE_DEC, VALS(sp_encr_alg_vals), 0x0,
1718 NULL, HFILL }},
1719 { &hf_mikey_sp_param[SP_ENCR_LEN],
1720 { SP_TEXT_ENCR_LEN, "mikey.sp.encr_len",
1721 FT_UINT8, BASE_DEC, NULL, 0x0,
1722 NULL, HFILL }},
1723 { &hf_mikey_sp_param[SP_AUTH_ALG],
1724 { SP_TEXT_AUTH_ALG, "mikey.sp.auth_alg",
1725 FT_UINT8, BASE_DEC, VALS(sp_auth_alg_vals), 0x0,
1726 NULL, HFILL }},
1727 { &hf_mikey_sp_param[SP_AUTH_KEY_LEN],
1728 { SP_TEXT_AUTH_KEY_LEN, "mikey.sp.auth_key_len",
1729 FT_UINT8, BASE_DEC, NULL, 0x0,
1730 NULL, HFILL }},
1731 { &hf_mikey_sp_param[SP_SALT_LEN],
1732 { SP_TEXT_SALT_LEN, "mikey.sp.salt_len",
1733 FT_UINT8, BASE_DEC, NULL, 0x0,
1734 NULL, HFILL }},
1735 { &hf_mikey_sp_param[SP_PRF],
1736 { SP_TEXT_PRF, "mikey.sp.prf",
1737 FT_UINT8, BASE_DEC, VALS(sp_prf_vals), 0x0,
1738 NULL, HFILL }},
1739 { &hf_mikey_sp_param[SP_KD_RATE],
1740 { SP_TEXT_KD_RATE, "mikey.sp.kd_rate",
1741 FT_UINT8, BASE_DEC, NULL, 0x0,
1742 NULL, HFILL }},
1743 { &hf_mikey_sp_param[SP_SRTP_ENCR],
1744 { SP_TEXT_SRTP_ENCR, "mikey.sp.srtp_encr",
1745 FT_UINT8, BASE_DEC, VALS(on_off_vals), 0x0,
1746 NULL, HFILL }},
1747 { &hf_mikey_sp_param[SP_SRTCP_ENCR],
1748 { SP_TEXT_SRTCP_ENCR, "mikey.sp.srtcp_encr",
1749 FT_UINT8, BASE_DEC, VALS(on_off_vals), 0x0,
1750 NULL, HFILL }},
1751 { &hf_mikey_sp_param[SP_FEC],
1752 { SP_TEXT_FEC, "mikey.sp.fec",
1753 FT_UINT8, BASE_DEC, VALS(sp_fec_vals), 0x0,
1754 NULL, HFILL }},
1755 { &hf_mikey_sp_param[SP_SRTP_AUTH],
1756 { SP_TEXT_SRTP_AUTH, "mikey.sp.srtp_auth",
1757 FT_UINT8, BASE_DEC, VALS(on_off_vals), 0x0,
1758 NULL, HFILL }},
1759 { &hf_mikey_sp_param[SP_AUTH_TAG_LEN],
1760 { SP_TEXT_AUTH_TAG_LEN, "mikey.sp.auth_tag_len",
1761 FT_UINT8, BASE_DEC, NULL, 0x0,
1762 NULL, HFILL }},
1763 { &hf_mikey_sp_param[SP_SRTP_PREFIX],
1764 { SP_TEXT_SRTP_PREFIX, "mikey.sp.srtp_prefix",
1765 FT_UINT8, BASE_DEC, NULL, 0x0,
1766 NULL, HFILL }},
1768 /* RAND payload (RAND) */
1769 { &hf_mikey[POS_RAND_LEN],
1770 { "RAND len", "mikey.rand.len",
1771 FT_UINT8, BASE_DEC, NULL, 0x0,
1772 NULL, HFILL }},
1773 { &hf_mikey[POS_RAND],
1774 { "RAND", "mikey.rand.data",
1775 FT_BYTES, BASE_NONE, NULL, 0x0,
1776 NULL, HFILL }},
1778 /* Error payload (ERR) */
1779 { &hf_mikey[POS_ERR_NO],
1780 { "Error no.", "mikey.err.no",
1781 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &err_vals_ext, 0x0,
1782 NULL, HFILL }},
1783 { &hf_mikey[POS_ERR_RESERVED],
1784 { "Reserved", "mikey.err.reserved",
1785 FT_BYTES, BASE_NONE, NULL, 0x0,
1786 NULL, HFILL }},
1788 /* IDR */
1789 { &hf_mikey[POS_ID_ROLE],
1790 { "ID role", "mikey.id.role",
1791 FT_UINT8, BASE_DEC, VALS(id_role_vals), 0x0,
1792 NULL, HFILL }},
1794 /* Key data sub-payload */
1795 { &hf_mikey[POS_KEY_DATA_TYPE],
1796 { "Type", "mikey.key.type",
1797 FT_UINT8, BASE_DEC, VALS(kd_vals), 0xf0,
1798 NULL, HFILL }},
1799 { &hf_mikey[POS_KEY_DATA_KV],
1800 { "KV", "mikey.key.kv",
1801 FT_UINT8, BASE_DEC, VALS(kv_vals), 0x0f,
1802 NULL, HFILL }},
1803 { &hf_mikey[POS_KEY_DATA_LEN],
1804 { "Key len", "mikey.key.data.len",
1805 FT_UINT16, BASE_DEC, NULL, 0x0,
1806 NULL, HFILL }},
1807 { &hf_mikey[POS_KEY_DATA],
1808 { "Key", "mikey.key.data",
1809 FT_BYTES, BASE_NONE, NULL, 0x0,
1810 NULL, HFILL }},
1811 { &hf_mikey[POS_KEY_SALT_LEN],
1812 { "Salt key len", "mikey.key.salt.len",
1813 FT_UINT16, BASE_DEC, NULL, 0x0,
1814 NULL, HFILL }},
1815 { &hf_mikey[POS_KEY_SALT],
1816 { "Salt key", "mikey.key.salt",
1817 FT_BYTES, BASE_NONE, NULL, 0x0,
1818 NULL, HFILL }},
1819 { &hf_mikey[POS_KEY_KV_FROM_LEN],
1820 { "Valid from len", "mikey.key.kv.from.len",
1821 FT_UINT8, BASE_DEC, NULL, 0x0,
1822 NULL, HFILL }},
1823 { &hf_mikey[POS_KEY_KV_FROM],
1824 { "Valid from", "mikey.key.kv.from",
1825 FT_BYTES, BASE_NONE, NULL, 0x0,
1826 NULL, HFILL }},
1827 { &hf_mikey[POS_KEY_KV_TO_LEN],
1828 { "Valid to len", "mikey.key.kv.to.len",
1829 FT_UINT8, BASE_DEC, NULL, 0x0,
1830 NULL, HFILL }},
1831 { &hf_mikey[POS_KEY_KV_TO],
1832 { "Valid to", "mikey.key.kv.to",
1833 FT_BYTES, BASE_NONE, NULL, 0x0,
1834 NULL, HFILL }},
1835 { &hf_mikey[POS_KEY_KV_SPI_LEN],
1836 { "Valid SPI len", "mikey.key.kv.spi.len",
1837 FT_UINT8, BASE_DEC, NULL, 0x0,
1838 NULL, HFILL }},
1839 { &hf_mikey[POS_KEY_KV_SPI],
1840 { "Valid SPI", "mikey.key.kv.spi",
1841 FT_BYTES, BASE_NONE, NULL, 0x0,
1842 NULL, HFILL }},
1844 /* General Extension payload (GENERAL_EXT) */
1845 { &hf_mikey[POS_GENERAL_EXT_TYPE],
1846 { "Extension type", "mikey.ext.type",
1847 FT_UINT8, BASE_DEC, VALS(genext_type_vals), 0x0,
1848 NULL, HFILL }},
1849 { &hf_mikey[POS_GENERAL_EXT_LEN],
1850 { "Length", "mikey.ext.len",
1851 FT_UINT16, BASE_DEC, NULL, 0x0,
1852 NULL, HFILL }},
1853 { &hf_mikey[POS_GENERAL_EXT_DATA],
1854 { "Data", "mikey.ext.data",
1855 FT_BYTES, BASE_NONE, NULL, 0x0,
1856 NULL, HFILL }},
1857 { &hf_mikey[POS_GENERAL_EXT_VALUE],
1858 { "Value", "mikey.ext.value",
1859 FT_STRING, BASE_NONE, NULL, 0x0,
1860 NULL, HFILL }},
1862 /* SAKKE */
1863 { &hf_mikey[POS_SAKKE_PARAMS],
1864 { "SAKKE params", "mikey.sakke.params",
1865 FT_UINT8, BASE_DEC, NULL, 0x0,
1866 NULL, HFILL }},
1867 { &hf_mikey[POS_SAKKE_ID_SCHEME],
1868 { "ID scheme", "mikey.sakke.idscheme",
1869 FT_UINT8, BASE_DEC, NULL, 0x0,
1870 NULL, HFILL }},
1871 { &hf_mikey[POS_SAKKE_LEN],
1872 { "SAKKE data length", "mikey.sakke.len",
1873 FT_UINT16, BASE_DEC, NULL, 0x0,
1874 NULL, HFILL }},
1875 { &hf_mikey[POS_SAKKE_DATA],
1876 { "SAKKE data", "mikey.sakke.data",
1877 FT_BYTES, BASE_NONE, NULL, 0x0,
1878 NULL, HFILL }},
1881 { &hf_mikey[POS_SP_PARAM],
1882 { "Policy param", "mikey.policy_param",
1883 FT_BYTES, BASE_NONE, NULL, 0x0,
1884 NULL, HFILL }},
1886 { &hf_mikey[POS_PAYLOAD],
1887 { "Payload", "mikey.payload",
1888 FT_BYTES, BASE_HEX, NULL, 0x0,
1889 NULL, HFILL }},
1893 /* Setup protocol subtree array */
1894 static gint *ett[] = {
1895 &ett_mikey,
1896 &ett_mikey_payload,
1897 &ett_mikey_sp_param,
1898 &ett_mikey_hdr_id,
1899 &ett_mikey_enc_data
1902 module_t *mikey_module;
1904 /* Register the protocol name and description */
1905 proto_mikey = proto_register_protocol("Multimedia Internet KEYing",
1906 "MIKEY", "mikey");
1908 mikey_handle = new_register_dissector("mikey", dissect_mikey, proto_mikey);
1910 /* Required function calls to register the header fields and subtrees used */
1911 proto_register_field_array(proto_mikey, hf, array_length(hf));
1912 proto_register_subtree_array(ett, array_length(ett));
1914 /* Register our configuration options */
1915 mikey_module = prefs_register_protocol(proto_mikey, proto_reg_handoff_mikey);
1917 prefs_register_uint_preference(mikey_module, "udp.port", "MIKEY UDP Port",
1918 "Set the port for MIKEY messages (if other than the default of 2269)",
1919 10, &global_mikey_udp_port);
1921 prefs_register_uint_preference(mikey_module, "tcp.port", "MIKEY TCP Port",
1922 "Set the port for MIKEY messages (if other than the default of 2269)",
1923 10, &global_mikey_tcp_port);
1928 void
1929 proto_reg_handoff_mikey(void)
1931 static guint mikey_tcp_port;
1932 static guint mikey_udp_port;
1933 static gboolean inited = FALSE;
1935 if (!inited) {
1936 dissector_add_string("key_mgmt", "mikey", mikey_handle);
1937 inited = TRUE;
1938 } else {
1939 dissector_delete_uint("udp.port", mikey_udp_port, mikey_handle);
1940 dissector_delete_uint("tcp.port", mikey_tcp_port, mikey_handle);
1943 dissector_add_uint("udp.port", global_mikey_udp_port, mikey_handle);
1944 dissector_add_uint("tcp.port", global_mikey_tcp_port, mikey_handle);
1946 mikey_udp_port = global_mikey_udp_port;
1947 mikey_tcp_port = global_mikey_tcp_port;