Revert "Fixup: tvb_* -> tvb_captured"
[metze/wireshark/wip.git] / epan / dissectors / packet-mikey.c
1 /* packet-mikey.c
2  * Routines for Multimedia Internet KEYing dissection
3  * Copyright 2007, Mikael Magnusson <mikma@users.sourceforge.net>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23  *
24  * Ref:
25  * http://tools.ietf.org/html/rfc3830  MIKEY
26  * http://tools.ietf.org/html/rfc6043  MIKEY-TICKET (ID role required for SAKKE)
27  * http://tools.ietf.org/html/rfc6509  MIKEY-SAKKE
28  */
29
30 /*
31  * TODO
32  * tvbuff offset in 32-bit variable.
33  * Support CHASH
34  * Decode Mikey-PK and Mikey-RSA-R with NULL encryption
35  */
36
37
38 #include "config.h"
39
40 #include <glib.h>
41
42 #include <epan/packet.h>
43 #include <epan/wmem/wmem.h>
44 #include <epan/prefs.h>
45 #include <epan/asn1.h>
46 #include <epan/dissectors/packet-x509af.h>
47
48 void proto_register_mikey(void);
49 void proto_reg_handoff_mikey(void);
50
51 #define PORT_MIKEY 2269
52 static guint global_mikey_tcp_port = PORT_MIKEY;
53
54 static guint global_mikey_udp_port = PORT_MIKEY;
55
56 static const value_string on_off_vals[] = {
57         { 0, "Off" },
58         { 1, "On" },
59         { 0, NULL }
60 };
61
62 enum data_type_t {
63         MIKEY_TYPE_PSK_INIT = 0,
64         MIKEY_TYPE_PSK_RESP,
65         MIKEY_TYPE_PK_INIT,
66         MIKEY_TYPE_PK_RESP,
67         MIKEY_TYPE_DH_INIT,
68         MIKEY_TYPE_DH_RESP,
69         MIKEY_TYPE_ERROR,
70         MIKEY_TYPE_DHHMAC_INIT,
71         MIKEY_TYPE_DHHMAC_RESP,
72         MIKEY_TYPE_RSA_R_INIT,
73         MIKEY_TYPE_RSA_R_RESP,
74         MIKEY_TYPE_SAKKE_INIT = 26,
75         MIKEY_TYPE_SAKKE_RESP
76 };
77
78 static const value_string data_type_vals[] = {
79         { MIKEY_TYPE_PSK_INIT,    "Pre-shared" },
80         { MIKEY_TYPE_PSK_RESP,    "PSK ver msg" },
81         { MIKEY_TYPE_PK_INIT,     "Public key" },
82         { MIKEY_TYPE_PK_RESP,     "PK ver msg" },
83         { MIKEY_TYPE_DH_INIT,     "D-H init" },
84         { MIKEY_TYPE_DH_RESP,     "D-H resp" },
85         { MIKEY_TYPE_ERROR,       "Error" },
86         { MIKEY_TYPE_DHHMAC_INIT, "DHHMAC init" },
87         { MIKEY_TYPE_DHHMAC_RESP, "DHHMAC resp" },
88         { MIKEY_TYPE_RSA_R_INIT,  "RSA-R I_MSG" },
89         { MIKEY_TYPE_RSA_R_RESP,  "RSA-R R_MSG" },
90         { MIKEY_TYPE_SAKKE_INIT,  "SAKKE" },
91         { MIKEY_TYPE_SAKKE_RESP,  "CS Id map Update" },
92         { 0, NULL }
93 };
94 static value_string_ext data_type_vals_ext = VALUE_STRING_EXT_INIT(data_type_vals);
95
96 enum cs_id_map_t {
97         CS_ID_SRTP = 0
98 };
99
100 static const value_string cs_id_map_vals[] = {
101         { CS_ID_SRTP, "SRTP-ID" },
102         { 0, NULL }
103 };
104
105 enum payload_t {
106         PL_HDR      = -1,
107         PL_LAST,
108         PL_KEMAC,
109         PL_PKE,
110         PL_DH,
111         PL_SIGN,
112         PL_T,
113         PL_ID,
114         PL_CERT,
115         PL_CHASH,
116         PL_V,
117         PL_SP,
118         PL_RAND,
119         PL_ERR,
120         PL_TR       = 13, /* MIKEY-TICKET (6043) */
121         PL_IDR,
122         PL_RANDR,
123         PL_TP,
124         PL_TICKET,
125         PL_KEY_DATA = 20,
126         PL_GENERAL_EXT,
127         PL_SAKKE    = 26,
128         PL_MAX
129 };
130
131 #define PL_HDR_TEXT         "Common Header (HDR)"
132 #define PL_LAST_TEXT        "Last payload"
133 #define PL_KEMAC_TEXT       "Key Data Transport (KEMAC)"
134 #define PL_PKE_TEXT         "Envelope Data (PKE)"
135 #define PL_DH_TEXT          "DH Data (DH)"
136 #define PL_SIGN_TEXT        "Signature (SIGN)"
137 #define PL_T_TEXT           "Timestamp (T)"
138 #define PL_ID_TEXT          "ID"
139 #define PL_CERT_TEXT        "Certificate (CERT)"
140 #define PL_CHASH_TEXT       "CHASH"
141 #define PL_V_TEXT           "Ver msg (V)"
142 #define PL_SP_TEXT          "Security Policy (SP)"
143 #define PL_RAND_TEXT        "RAND"
144 #define PL_ERR_TEXT         "Error (ERR)"
145 #define PL_KEY_DATA_TEXT    "Key data (KEY)"
146 #define PL_IDR_TEXT         "IDR"
147 #define PL_GENERAL_EXT_TEXT "General Extension (EXT)"
148 #define PL_SAKKE_TEXT       "SAKKE Encapsulated Data (SAKKE)"
149
150 static const value_string payload_vals[] = {
151         { PL_HDR,         PL_HDR_TEXT },
152         { PL_LAST,        PL_LAST_TEXT },
153         { PL_KEMAC,       PL_KEMAC_TEXT },
154         { PL_PKE,         PL_PKE_TEXT },
155         { PL_DH,          PL_DH_TEXT },
156         { PL_SIGN,        PL_SIGN_TEXT },
157         { PL_T,           PL_T_TEXT },
158         { PL_ID,          PL_ID_TEXT },
159         { PL_CERT,        PL_CERT_TEXT },
160         { PL_CHASH,       PL_CHASH_TEXT },
161         { PL_V,           PL_V_TEXT },
162         { PL_SP,          PL_SP_TEXT },
163         { PL_RAND,        PL_RAND_TEXT },
164         { PL_ERR,         PL_ERR_TEXT },
165         { PL_IDR,         PL_IDR_TEXT },
166         { PL_KEY_DATA,    PL_KEY_DATA_TEXT },
167         { PL_GENERAL_EXT, PL_GENERAL_EXT_TEXT },
168         { PL_SAKKE,       PL_SAKKE_TEXT },
169         { 0, NULL }
170 };
171 #if 0 /* First entry (PL_HDR) is -1 and there are gaps so this doesn't work */
172 static value_string_ext payload_vals_ext = VALUE_STRING_EXT_INIT(payload_vals);
173 #endif
174
175 enum ts_type_t {
176         T_NTP_UTC = 0,
177         T_NTP,
178         T_COUNTER
179 };
180
181 static const value_string ts_type_vals[] = {
182         { T_NTP_UTC, "NTP-UTC" },
183         { T_NTP,     "NTP" },
184         { T_COUNTER, "COUNTER" },
185         { 0, NULL }
186 };
187
188 enum encr_alg_t {
189         ENCR_NULL = 0,
190         ENCR_AES_CM_128,
191         ENCR_AES_KW_128
192 };
193
194 static const value_string encr_alg_vals[] = {
195         { ENCR_NULL,       "NULL" },
196         { ENCR_AES_CM_128, "AES-CM-128" },
197         { ENCR_AES_KW_128, "AES-KW-128" },
198         { 0, NULL }
199 };
200
201 enum oakley_t {
202         DH_OAKLEY_5 = 0,
203         DH_OAKLEY_1,
204         DH_OAKLEY_2
205 };
206
207 static const value_string oakley_vals[] = {
208         { DH_OAKLEY_5, "OAKLEY 5" },
209         { DH_OAKLEY_1, "OAKLEY 1" },
210         { DH_OAKLEY_2, "OAKLEY 2" },
211         { 0, NULL }
212 };
213
214 enum mac_alg_t {
215         MAC_NULL = 0,
216         MAC_HMAC_SHA_1_160
217 };
218
219 static const value_string mac_alg_vals[] = {
220         { MAC_NULL,           "NULL" },
221         { MAC_HMAC_SHA_1_160, "HMAC-SHA-1-160" },
222         { 0, NULL }
223 };
224
225 enum pke_c_t {
226         PKE_C_NO_CACHE = 0,
227         PKE_C_CACHE,
228         PKE_C_CACHE_CSB
229 };
230
231 static const value_string pke_c_vals[] = {
232         { PKE_C_NO_CACHE,  "No cache" },
233         { PKE_C_CACHE,     "Cache" },
234         { PKE_C_CACHE_CSB, "Cache for CSB" },
235         { 0, NULL }
236 };
237
238 enum sign_s_t {
239         SIGN_S_PKCS1 = 0,
240         SIGN_S_PSS,
241         SIGN_S_ECCSI
242 };
243
244 static const value_string sign_s_vals[] = {
245         { SIGN_S_PKCS1, "RSA/PKCS#1/1.5" },
246         { SIGN_S_PSS,   "RSA/PSS" },
247         { SIGN_S_ECCSI, "ECCSI" },
248         { 0, NULL }
249 };
250
251 enum id_type_t {
252         ID_TYPE_NAI = 0,
253         ID_TYPE_URI,
254         ID_TYPE_BYTE_STRING
255 };
256
257 static const value_string id_type_vals[] = {
258         { ID_TYPE_NAI,         "NAI" },
259         { ID_TYPE_URI,         "URI" },
260         { ID_TYPE_BYTE_STRING, "Byte string" },
261         { 0, NULL }
262 };
263
264 enum id_role_t {
265         ID_ROLE_RESERVED = 0,
266         ID_ROLE_INIT,
267         ID_ROLE_RESP,
268         ID_ROLE_KMS,
269         ID_ROLE_PSK,
270         ID_ROLE_APP,
271         ID_ROLE_INIT_KMS,
272         ID_ROLE_RESP_KMS
273 };
274
275 static const value_string id_role_vals[] = {
276         { ID_ROLE_RESERVED, "Reserved" },
277         { ID_ROLE_INIT,     "Initiator (IDRi)" },
278         { ID_ROLE_RESP,     "Responder (IDRr)" },
279         { ID_ROLE_KMS,      "KMS (IDRkms)" },
280         { ID_ROLE_PSK,      "Pre-Shared Key (IDRpsk)" },
281         { ID_ROLE_APP,      "Application (IDRapp)" },
282         { ID_ROLE_INIT_KMS, "Initiator's KMS (IDRkmsi)" },
283         { ID_ROLE_RESP_KMS, "Responder's KMS (IDRkmsr)" },
284         { 0, NULL }
285 };
286
287 enum cert_type_t {
288         CERT_TYPE_X509V3 = 0,
289         CERT_TYPE_X509V3_URL,
290         CERT_TYPE_X509V3_SIGN,
291         CERT_TYPE_X509V3_ENCR
292 };
293
294 static const value_string cert_type_vals[] = {
295         { CERT_TYPE_X509V3,      "X.509v3" },
296         { CERT_TYPE_X509V3_URL,  "X.509v3 URL" },
297         { CERT_TYPE_X509V3_SIGN, "X.509v3 Sign" },
298         { CERT_TYPE_X509V3_ENCR, "X.509v3 Encr" },
299         { 0, NULL }
300 };
301
302 enum srtp_policy_type_t {
303         SP_ENCR_ALG,
304         SP_ENCR_LEN,
305         SP_AUTH_ALG,
306         SP_AUTH_KEY_LEN,
307         SP_SALT_LEN,
308         SP_PRF,
309         SP_KD_RATE,
310         SP_SRTP_ENCR,
311         SP_SRTCP_ENCR,
312         SP_FEC,
313         SP_SRTP_AUTH,
314         SP_AUTH_TAG_LEN,
315         SP_SRTP_PREFIX,
316         SP_MAX
317 };
318
319 #define SP_TEXT_ENCR_ALG     "Encryption algorithm"
320 #define SP_TEXT_ENCR_LEN     "Session Encr. key length"
321 #define SP_TEXT_AUTH_ALG     "Authentication algorithm"
322 #define SP_TEXT_AUTH_KEY_LEN "Session Auth. key length"
323 #define SP_TEXT_SALT_LEN     "Session Salt key length"
324 #define SP_TEXT_PRF          "SRTP Pseudo Random Function"
325 #define SP_TEXT_KD_RATE      "Key derivation rate"
326 #define SP_TEXT_SRTP_ENCR    "SRTP encryption"
327 #define SP_TEXT_SRTCP_ENCR   "SRTCP encryption"
328 #define SP_TEXT_FEC          "Sender's FEC order"
329 #define SP_TEXT_SRTP_AUTH    "SRTP authentication"
330 #define SP_TEXT_AUTH_TAG_LEN "Authentication tag length"
331 #define SP_TEXT_SRTP_PREFIX  "SRTP prefix length"
332
333 #if 0
334 static const value_string srtp_policy_type_vals[] = {
335         { SP_ENCR_ALG,     SP_TEXT_ENCR_ALG },
336         { SP_ENCR_LEN,     SP_TEXT_ENCR_LEN },
337         { SP_AUTH_ALG,     SP_TEXT_AUTH_ALG },
338         { SP_AUTH_KEY_LEN, SP_TEXT_AUTH_KEY_LEN },
339         { SP_SALT_LEN,     SP_TEXT_SALT_LEN },
340         { SP_PRF,          SP_TEXT_PRF },
341         { SP_KD_RATE,      SP_TEXT_KD_RATE },
342         { SP_SRTP_ENCR,    SP_TEXT_SRTP_ENCR },
343         { SP_SRTCP_ENCR,   SP_TEXT_SRTCP_ENCR },
344         { SP_FEC,          SP_TEXT_FEC },
345         { SP_SRTP_AUTH,    SP_TEXT_SRTP_AUTH },
346         { SP_AUTH_TAG_LEN, SP_TEXT_AUTH_TAG_LEN },
347         { SP_SRTP_PREFIX,  SP_TEXT_SRTP_PREFIX },
348         { 0, NULL }
349 };
350 #endif
351
352 enum sp_encr_alg_t {
353         SP_ENCR_NULL = 0,
354         SP_ENCR_AES_CM,
355         SP_ENCR_AES_F8
356 };
357
358 static const value_string sp_encr_alg_vals[] = {
359         { SP_ENCR_NULL,   "NULL" },
360         { SP_ENCR_AES_CM, "AES-CM" },
361         { SP_ENCR_AES_F8, "AES-F8" },
362         { 0, NULL }
363 };
364
365 enum sp_auth_alg_t {
366         SP_AUTH_NULL = 0,
367         SP_AUTH_HMAC_SHA_1
368 };
369
370 static const value_string sp_auth_alg_vals[] = {
371         { SP_AUTH_NULL,       "NULL" },
372         { SP_AUTH_HMAC_SHA_1, "HMAC-SHA-1" },
373         { 0, NULL }
374 };
375
376 enum sp_prf_t {
377         SP_PRF_AES_CM = 0
378 };
379
380 static const value_string sp_prf_vals[] = {
381         { SP_PRF_AES_CM, "AES-CM" },
382         { 0, NULL }
383 };
384
385 enum sp_fec_t {
386         SP_FEC_SRTP = 0
387 };
388
389 static const value_string sp_fec_vals[] = {
390         { SP_FEC_SRTP, "FEC-SRTP" },
391         { 0, NULL }
392 };
393
394 enum sp_prot_t {
395         SP_PROT_TYPE_SRTP = 0
396 };
397
398 static const value_string sp_prot_type_vals[] = {
399         { SP_PROT_TYPE_SRTP, "SRTP" },
400         { 0, NULL }
401 };
402
403 enum prf_func_t {
404         PRF_FUNC_MIKEY_1 = 0
405 };
406
407 static const value_string prf_func_vals[] = {
408         { PRF_FUNC_MIKEY_1, "MIKEY-1" },
409         { 0, NULL }
410 };
411
412 enum kv_t {
413         KV_NULL = 0,
414         KV_SPI,
415         KV_INTERVAL
416 };
417
418 static const value_string kv_vals[] = {
419         { KV_NULL,     "Null" },
420         { KV_SPI,      "SPI/MKI" },
421         { KV_INTERVAL, "Interval" },
422         { 0, NULL }
423 };
424
425 enum kd_t {
426         KD_TGK = 0,
427         KD_TGK_SALT,
428         KD_TEK,
429         KD_TEK_SALT
430 };
431
432 static const value_string kd_vals[] = {
433         { KD_TGK,      "TGK" },
434         { KD_TGK_SALT, "TGK+SALT" },
435         { KD_TEK,      "TEK" },
436         { KD_TEK_SALT, "TEK+SALT" },
437         { 0, NULL }
438 };
439
440 enum err_t {
441         ERR_AUTH_FAILURE = 0,
442         ERR_INVALID_TS,
443         ERR_INVALID_PRF,
444         ERR_INVALID_MAC,
445         ERR_INVALID_EA,
446         ERR_INVALID_HA,
447         ERR_INVALID_DH,
448         ERR_INVALID_ID,
449         ERR_INVALID_CERT,
450         ERR_INVALID_SP,
451         ERR_INVALID_SPPAR,
452         ERR_INVALID_DT,
453         ERR_UNKNOWN
454 };
455
456 static const value_string err_vals[] = {
457         { ERR_AUTH_FAILURE,  "Authentication failure" },
458         { ERR_INVALID_TS,    "Invalid timestamp" },
459         { ERR_INVALID_PRF,   "PRF function not supported" },
460         { ERR_INVALID_MAC,   "MAC algorithm not supported" },
461         { ERR_INVALID_EA,    "Encryption algorithm not supported" },
462         { ERR_INVALID_HA,    "Hash function not supported" },
463         { ERR_INVALID_DH,    "DH group not supported" },
464         { ERR_INVALID_ID,    "ID not supported" },
465         { ERR_INVALID_CERT,  "Certificate not supported" },
466         { ERR_INVALID_SP,    "SP type not supported" },
467         { ERR_INVALID_SPPAR, "SP parameters not supported" },
468         { ERR_INVALID_DT,    "Data type not supported" },
469         { ERR_UNKNOWN,       "Unspecified error" },
470         { 0, NULL }
471 };
472 static value_string_ext err_vals_ext = VALUE_STRING_EXT_INIT(err_vals);
473
474 enum genext_t {
475         GEN_EXT_VENDOR_ID = 0,
476         GEN_EXT_SDP_ID
477 };
478
479 static const value_string genext_type_vals[] = {
480         { GEN_EXT_VENDOR_ID, "Vendor-ID" },
481         { GEN_EXT_SDP_ID,    "SDP-IDs" },
482         { 0, NULL }
483 };
484
485 enum {
486         /* HDR */
487         POS_HDR_VERSION=0,
488         POS_HDR_DATA_TYPE,
489         POS_HDR_V,
490         POS_HDR_PRF_FUNC,
491         POS_HDR_CSB_ID,
492         POS_HDR_CS_COUNT,
493         POS_HDR_CS_ID_MAP_TYPE,
494         POS_ID_SRTP,
495         POS_ID_SRTP_NO,
496         POS_ID_SRTP_SSRC,
497         POS_ID_SRTP_ROC,
498
499         /* KEMAC */
500         POS_KEMAC_ENCR_ALG,
501         POS_KEMAC_ENCR_DATA_LEN,
502         POS_KEMAC_ENCR_DATA,
503         POS_KEMAC_MAC_ALG,
504         POS_KEMAC_MAC,
505
506         /* PKE */
507         POS_PKE_C,
508         POS_PKE_DATA_LEN,
509         POS_PKE_DATA,
510
511         /* DH */
512         POS_DH_GROUP,
513         POS_DH_VALUE,
514         POS_DH_RESERV,
515         POS_DH_KV,
516
517         /* SIGN */
518         POS_SIGNATURE_LEN,
519         POS_SIGNATURE,
520         POS_SIGN_S_TYPE,
521
522         /* T */
523         POS_TS_TYPE,
524         POS_TS_NTP,
525
526         /* ID/IDR */
527         POS_ID_ROLE,
528         POS_ID_TYPE,
529         POS_ID_LEN,
530         POS_ID,
531
532         /* CERT */
533         POS_CERT_TYPE,
534         POS_CERT_LEN,
535         POS_CERTIFICATE,
536
537         /* V */
538         POS_V_AUTH_ALG,
539         POS_V_DATA,
540
541         /* SP */
542         POS_SP_NO,
543         POS_SP_TYPE,
544         POS_SP_PARAM_LEN,
545 /*      POS_SP_PARAM, */
546
547         /* SP param */
548         POS_SP_PARAM_F,
549         POS_SP_PARAM_F_TYPE,
550         POS_SP_PARAM_F_LEN,
551         POS_SP_PARAM_F_VALUE,
552
553         /* RAND */
554         POS_RAND_LEN,
555         POS_RAND,
556
557         /* Error */
558         POS_ERR_NO,
559         POS_ERR_RESERVED,
560
561         /* Key data */
562         POS_KEY_DATA_TYPE,
563         POS_KEY_DATA_KV,
564         POS_KEY_DATA_LEN,
565         POS_KEY_DATA,
566         POS_KEY_SALT_LEN,
567         POS_KEY_SALT,
568         POS_KEY_KV_FROM_LEN,
569         POS_KEY_KV_FROM,
570         POS_KEY_KV_TO_LEN,
571         POS_KEY_KV_TO,
572         POS_KEY_KV_SPI_LEN,
573         POS_KEY_KV_SPI,
574
575         /* General Ext. */
576         POS_GENERAL_EXT_TYPE,
577         POS_GENERAL_EXT_LEN,
578         POS_GENERAL_EXT_DATA,
579         POS_GENERAL_EXT_VALUE,
580
581         /* SAKKE */
582         POS_SAKKE_PARAMS,
583         POS_SAKKE_ID_SCHEME,
584         POS_SAKKE_LEN,
585         POS_SAKKE_DATA,
586
587         /* MIKEY */
588         POS_PAYLOAD_STR,
589         POS_NEXT_PAYLOAD,
590
591         /* Unused */
592 /*      POS_PAYLOAD, */
593
594         MAX_POS
595 };
596
597 typedef struct tag_mikey_t {
598         guint8 type;
599 } mikey_t;
600
601 typedef int (*mikey_dissector_t)(mikey_t *, tvbuff_t *, packet_info *, proto_tree *);
602 struct mikey_dissector_entry {
603         int type;
604         mikey_dissector_t dissector;
605 };
606
607 /* Forward declaration we need below */
608 static int dissect_payload(int payload, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
609
610
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];
616
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;
623
624 static dissector_handle_t mikey_handle;
625
626 static const struct mikey_dissector_entry *
627 mikey_dissector_lookup(const struct mikey_dissector_entry *map, int type)
628 {
629         unsigned int i;
630         for (i = 0; map[i].dissector != NULL; i++) {
631                 if (map[i].type == type) {
632                         return &map[i];
633                 }
634         }
635
636         return NULL;
637 }
638
639 static void
640 add_next_payload(tvbuff_t *tvb, proto_tree *tree, int offset)
641 {
642         proto_tree_add_item(tree, hf_mikey[POS_NEXT_PAYLOAD], tvb, offset, 1, ENC_BIG_ENDIAN);
643 }
644
645
646 static int
647 dissect_payload_cs_id_srtp(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_,  proto_tree *tree)
648 {
649         tvb_ensure_bytes_exist(tvb, 0, 9);
650
651         if (tree) {
652                 proto_item *id_ti;
653                 proto_tree *id_tree;
654                 guint8      no;
655                 guint32     ssrc;
656                 guint32     roc;
657
658                 no   = tvb_get_guint8(tvb, 0);
659                 ssrc = tvb_get_ntohl(tvb, 1);
660                 roc  = tvb_get_ntohl(tvb, 5);
661
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);
665
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);
669         }
670         return 9;
671 }
672
673 static const struct mikey_dissector_entry cs_id_map[] = {
674         { CS_ID_SRTP, dissect_payload_cs_id_srtp },
675         { 0, NULL }
676 };
677
678 static int
679 dissect_payload_cs_id(int type, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
680 {
681         const struct mikey_dissector_entry *entry;
682
683         entry = mikey_dissector_lookup(cs_id_map, type);
684
685         if (!entry || !entry->dissector) {
686                 return -1;
687         }
688
689         return entry->dissector(mikey, tvb, pinfo, tree);
690
691 }
692
693 static int
694 dissect_payload_hdr(mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
695 {
696         int    offset = 0;
697         guint8 cs_id_map_type;
698         guint8 ncs;
699         int    i;
700
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);
705
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);
710
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"));
715
716                 add_next_payload(tvb, tree, offset+2);
717
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);
720
721                 proto_tree_add_item(tree, hf_mikey[POS_HDR_CSB_ID], tvb, offset+4, 4, ENC_BIG_ENDIAN);
722
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);
725         }
726
727         offset += 10;
728         for (i=0; i < ncs; i++) {
729                 tvbuff_t *sub_tvb;
730                 int       len;
731
732                 sub_tvb = tvb_new_subset_remaining(tvb, offset);
733                 len = dissect_payload_cs_id(cs_id_map_type, mikey, sub_tvb, pinfo, tree);
734
735                 if (len < 0)
736                         return -1;
737
738                 offset += len;
739         }
740
741         return offset;
742 }
743
744 static int
745 dissect_payload_kemac(mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
746 {
747         int     offset = 0;
748         guint8  encr_alg;
749         guint16 encr_length;
750         guint16 mac_length;
751         guint8  mac_alg;
752
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);
758
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);
770
771                         sub_tvb = tvb_new_subset_length(tvb, offset+4, 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);
776                 }
777                 proto_tree_add_item(tree, hf_mikey[POS_KEMAC_MAC_ALG], tvb, 4+encr_length, 1, ENC_BIG_ENDIAN);
778         }
779
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;
789         }
790
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);
794         }
795
796         return 4+encr_length+1+mac_length;
797 }
798
799 static int
800 dissect_payload_pke(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
801 {
802         int     offset = 0;
803         guint16 length;
804
805         tvb_ensure_bytes_exist(tvb, offset+0, 3);
806         length = tvb_get_ntohs(tvb, offset+1) &0x3ff;
807
808         if (tree) {
809                 proto_tree_add_item(tree, hf_mikey[POS_PKE_C], tvb, 1, 2, ENC_BIG_ENDIAN);
810
811                 proto_tree_add_item(tree, hf_mikey[POS_PKE_DATA_LEN], tvb, 1, 2, ENC_BIG_ENDIAN);
812         }
813
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);
817         }
818         return 3 + length;
819 }
820
821 static int
822 dissect_payload_dh(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
823 {
824         int    offset = 0;
825         guint8 dh_group;
826         int    dh_length;
827         guint8 kv;
828
829         tvb_ensure_bytes_exist(tvb, offset+0, 2);
830         dh_group = tvb_get_guint8(tvb, offset+1);
831
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;
844         }
845
846         tvb_ensure_bytes_exist(tvb, offset+2, dh_length+1);
847         kv = tvb_get_guint8(tvb, offset+2+dh_length) & 0x0f;
848
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);
854         }
855
856         if (kv != 0) {
857                 return -1;
858         }
859
860         return 2 + dh_length + 1;
861 }
862
863 static int
864 dissect_payload_sign(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
865 {
866         int     offset = 0;
867         guint16 length;
868
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);
871
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);
875         }
876
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);
880         }
881         return 2 + length;
882 }
883
884 static int
885 dissect_payload_t(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
886 {
887         guint8 ts_type;
888         int    offset = 0;
889         int    len    = 0;
890
891         tvb_ensure_bytes_exist(tvb, offset+0, 2);
892         ts_type = tvb_get_guint8(tvb, offset+1);
893
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);
899         }
900
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;
913         }
914
915         return len;
916 }
917
918 static int
919 dissect_payload_id(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
920 {
921         int     offset = 0;
922         guint8  type;
923         guint16 length;
924
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);
931         }
932
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);
937
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_enc(wmem_packet_scope(), tvb, 4, length, ENC_ASCII));
942         }
943
944         return 4 + length;
945 }
946
947 static int
948 dissect_payload_idr(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
949 {
950         int     offset = 0;
951         guint8  type;
952         guint16 length;
953
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);
961         }
962
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);
967
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_enc(wmem_packet_scope(), tvb, 5, length, ENC_ASCII));
972         }
973
974         return 5 + length;
975 }
976
977 static int
978 dissect_payload_cert(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
979 {
980         int          offset = 0;
981         guint8       type;
982         guint16      length;
983         tvbuff_t    *subtvb;
984         asn1_ctx_t   asn1_ctx;
985
986         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
987
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);
991
992         tvb_ensure_bytes_exist(tvb, offset+4, length);
993
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);
999
1000                 proto_item_append_text(parent, " Type: %s", val_to_str_const(type, cert_type_vals, "Unknown"));
1001         }
1002
1003         subtvb = tvb_new_subset_length(tvb, offset+4, length);
1004         dissect_x509af_Certificate(FALSE, subtvb, 0, &asn1_ctx, tree, hf_mikey[POS_CERTIFICATE]);
1005
1006         return 4 + length;
1007 }
1008
1009 static int
1010 dissect_payload_v(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1011 {
1012         int     offset = 0;
1013         guint16 length;
1014         guint8  alg;
1015
1016         tvb_ensure_bytes_exist(tvb, offset+0, 2);
1017         alg = tvb_get_guint8(tvb, offset+1);
1018
1019         if (tree) {
1020                 proto_tree_add_item(tree, hf_mikey[POS_V_AUTH_ALG], tvb, 1, 1, ENC_BIG_ENDIAN);
1021         }
1022
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;
1032         }
1033
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);
1037         }
1038
1039         return 2 + length;
1040 }
1041
1042 static int
1043 dissect_payload_sp_param(enum sp_prot_t proto, tvbuff_t *tvb, proto_tree *tree)
1044 {
1045         int    offset = 0;
1046         guint8 type;
1047         guint8 length;
1048         int    hfindex;
1049
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);
1054
1055         /* Default */
1056         hfindex = hf_mikey[POS_SP_PARAM_F];
1057
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;
1063         }
1064
1065         if (tree) {
1066                 proto_item *param_ti;
1067                 proto_tree *param_tree;
1068                 /*
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.
1074                  */
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);
1077
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);
1081         }
1082
1083         return 2+length;
1084 }
1085
1086 static int
1087 dissect_payload_sp(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1088 {
1089         int            offset = 0;
1090         guint16        length;
1091         int            sub_pos;
1092         guint8         no;
1093         enum sp_prot_t type;
1094
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);
1099
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);
1106
1107                 proto_item_append_text(parent, " No: %d, Type: %s", no,
1108                                        val_to_str_const(type, sp_prot_type_vals, "Unknown"));
1109         }
1110
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); */
1113
1114         offset += 5;
1115         sub_pos = 0;
1116
1117         while (sub_pos < length) {
1118                 int       param_len;
1119                 tvbuff_t *subtvb;
1120
1121                 subtvb = tvb_new_subset_length(tvb, offset+sub_pos, length-sub_pos);
1122                 param_len = dissect_payload_sp_param(type, subtvb, tree);
1123
1124                 if (param_len < 0)
1125                         return -1;
1126
1127                 sub_pos += param_len;
1128         }
1129
1130         return 5 + length;
1131 }
1132
1133 static int
1134 dissect_payload_rand(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1135 {
1136         int     offset = 0;
1137         guint16 length;
1138
1139         tvb_ensure_bytes_exist(tvb, offset+0, 2);
1140         length = tvb_get_guint8(tvb, offset+1);
1141
1142         if (tree) {
1143                 proto_tree_add_item(tree, hf_mikey[POS_RAND_LEN], tvb, 1, 1, ENC_BIG_ENDIAN);
1144         }
1145
1146         tvb_ensure_bytes_exist(tvb, offset+2, length);
1147
1148         if (tree) {
1149                 proto_tree_add_item(tree, hf_mikey[POS_RAND], tvb, 2, length, ENC_NA);
1150         }
1151         return 2 + length;
1152 }
1153
1154 static int
1155 dissect_payload_err(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1156 {
1157         tvb_ensure_bytes_exist(tvb, 0, 4);
1158
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"));
1167         }
1168
1169         return 4;
1170 }
1171
1172 static int
1173 dissect_payload_keydata(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1174 {
1175         guint16 offset;
1176         guint16 data_len;
1177         guint8  key_type;
1178         guint8  kv_type;
1179
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);
1185
1186         tvb_ensure_bytes_exist(tvb, 4, data_len);
1187         offset += 4;
1188
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);
1195
1196                 parent = proto_tree_get_parent(tree);
1197                 proto_item_append_text(parent, " Type: %s", val_to_str_const(key_type, kd_vals, "Unknown"));
1198         }
1199
1200         offset += data_len;
1201
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);
1212                         }
1213                 }
1214                 offset += 2+salt_len;
1215         }
1216
1217         /* Dissect Key Validity */
1218         if (kv_type == KV_INTERVAL) {
1219                 guint16 kv_from_len;
1220                 guint16 kv_to_len;
1221
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);
1228                 }
1229                 offset += 1+kv_from_len;
1230
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);
1237                 }
1238                 offset += 1+kv_to_len;
1239         } else if (kv_type == KV_SPI) {
1240                 guint16 kv_spi_len;
1241
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);
1248                 }
1249                 offset += 1+kv_spi_len;
1250         }
1251
1252         return offset;
1253 }
1254
1255 static int
1256 dissect_payload_general_ext(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1257 {
1258         int     offset = 0;
1259         guint8  type;
1260         guint16 data_len;
1261
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);
1265
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);
1269         }
1270
1271         tvb_ensure_bytes_exist(tvb, offset+3, data_len);
1272
1273         if (tree) {
1274                 proto_item *parent;
1275
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);
1282                 }
1283                 proto_item_append_text(parent, " Type: %s", val_to_str_const(type, genext_type_vals, "Unknown"));
1284         }
1285         return 4 + data_len;
1286 }
1287
1288 static int
1289 dissect_payload_sakke(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1290 {
1291         int     offset = 0;
1292         guint16 data_len;
1293
1294         tvb_ensure_bytes_exist(tvb, offset+0, 5);
1295         data_len = tvb_get_ntohs(tvb, offset+3);
1296
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);
1301         }
1302
1303         tvb_ensure_bytes_exist(tvb, offset+5, data_len);
1304
1305         if (tree) {
1306                 proto_tree_add_item(tree, hf_mikey[POS_SAKKE_DATA], tvb, 5, data_len, ENC_NA);
1307         }
1308         return 5 + data_len;
1309 }
1310
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 }
1329 };
1330
1331 static int
1332 dissect_payload(int payload, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1333 {
1334         const struct mikey_dissector_entry *entry;
1335
1336         entry = mikey_dissector_lookup(payload_map, payload);
1337
1338         if (!entry || !entry->dissector) {
1339                 return -1;
1340         }
1341
1342         return entry->dissector(mikey, tvb, pinfo, tree);
1343 }
1344
1345 /* MIKEY dissector */
1346 static int
1347 dissect_mikey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1348 {
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;
1355
1356         mikey = (mikey_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mikey, 0);
1357
1358         if (!mikey) {
1359                 mikey = wmem_new0(wmem_file_scope(), mikey_t);
1360                 mikey->type = -1;
1361                 p_add_proto_data(wmem_file_scope(), pinfo, proto_mikey, 0, mikey);
1362         }
1363
1364
1365         tvb_ensure_bytes_exist(tvb, offset, 3);
1366         next_payload_offset = offset + 2;
1367         payload = -1;
1368
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);
1372         }
1373
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;
1380
1381                 next_payload = tvb_get_guint8(tvb, next_payload_offset);
1382                 subtvb = tvb_new_subset_remaining(tvb, offset);
1383
1384                 if (mikey_tree) {
1385                         int hf = payload;
1386
1387                         if (hf >= PL_MAX)
1388                                 return -1;
1389
1390                         if (hf == -1)
1391                                 hf = 0;
1392
1393                         sub_ti = proto_tree_add_item(mikey_tree, hf_mikey_pl[hf], subtvb, 0, -1, ENC_NA);
1394
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);
1398                 }
1399
1400                 len = dissect_payload(payload, mikey, subtvb, pinfo, mikey_payload_tree);
1401                 if (len < 0) {
1402                         return -1;
1403                 }
1404
1405                 if (sub_ti)
1406                         proto_item_set_len(sub_ti, len);
1407
1408                 if (payload == PL_SIGN)
1409                         break;
1410
1411                 payload = next_payload;
1412                 offset += len;
1413                 next_payload_offset = offset;
1414         }
1415
1416         if (ti) {
1417                 proto_item_append_text(ti, ": %s",
1418                                        val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
1419         }
1420
1421         col_append_str(pinfo->cinfo, COL_PROTOCOL, "/MIKEY");
1422
1423         col_append_fstr(pinfo->cinfo, COL_INFO, ", Mikey: %s",
1424                                 val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
1425
1426         /* Return the amount of data this dissector was able to dissect */
1427         return tvb_length(tvb);
1428 }
1429
1430
1431 /* Register the protocol with Wireshark */
1432
1433 void
1434 proto_register_mikey(void)
1435 {
1436
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 }},
1508
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 }},
1542
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 }},
1560
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 }},
1582
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 }},
1596
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 }},
1614
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 }},
1628
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 }},
1638
1639                 { &hf_mikey[POS_PAYLOAD_STR],
1640                   { "Payload", "mikey.payload",
1641                     FT_STRING, BASE_NONE, NULL, 0x0,
1642                     NULL, HFILL }},
1643
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 }},
1657
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 }},
1671
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 }},
1681
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 }},
1695
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 }},
1713
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 }},
1767
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 }},
1777
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 }},
1787
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 }},
1793
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 }},
1843
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 }},
1861
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 }},
1879
1880 /*
1881                 { &hf_mikey[POS_SP_PARAM],
1882                   { "Policy param", "mikey.policy_param",
1883                     FT_BYTES, BASE_NONE, NULL, 0x0,
1884                     NULL, HFILL }},
1885
1886                 { &hf_mikey[POS_PAYLOAD],
1887                   { "Payload", "mikey.payload",
1888                     FT_BYTES, BASE_HEX, NULL, 0x0,
1889                     NULL, HFILL }},
1890 */
1891         };
1892
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
1900         };
1901
1902         module_t *mikey_module;
1903
1904         /* Register the protocol name and description */
1905         proto_mikey = proto_register_protocol("Multimedia Internet KEYing",
1906                 "MIKEY", "mikey");
1907
1908         mikey_handle = new_register_dissector("mikey", dissect_mikey, proto_mikey);
1909
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));
1913
1914         /* Register our configuration options */
1915         mikey_module = prefs_register_protocol(proto_mikey, proto_reg_handoff_mikey);
1916
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);
1920
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);
1924
1925 }
1926
1927
1928 void
1929 proto_reg_handoff_mikey(void)
1930 {
1931         static guint              mikey_tcp_port;
1932         static guint              mikey_udp_port;
1933         static gboolean inited = FALSE;
1934
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);
1941         }
1942
1943         dissector_add_uint("udp.port", global_mikey_udp_port, mikey_handle);
1944         dissector_add_uint("tcp.port", global_mikey_tcp_port, mikey_handle);
1945
1946         mikey_udp_port = global_mikey_udp_port;
1947         mikey_tcp_port = global_mikey_tcp_port;
1948 }