Use MAC address documentation range in filter examples
[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 <epan/packet.h>
41 #include <epan/prefs.h>
42 #include <epan/asn1.h>
43 #include "packet-x509af.h"
44
45 void proto_register_mikey(void);
46 void proto_reg_handoff_mikey(void);
47
48 #define PORT_MIKEY 2269
49 static guint global_mikey_tcp_port = PORT_MIKEY;
50
51 static guint global_mikey_udp_port = PORT_MIKEY;
52
53 static const value_string on_off_vals[] = {
54         { 0, "Off" },
55         { 1, "On" },
56         { 0, NULL }
57 };
58
59 enum data_type_t {
60         MIKEY_TYPE_PSK_INIT = 0,
61         MIKEY_TYPE_PSK_RESP,
62         MIKEY_TYPE_PK_INIT,
63         MIKEY_TYPE_PK_RESP,
64         MIKEY_TYPE_DH_INIT,
65         MIKEY_TYPE_DH_RESP,
66         MIKEY_TYPE_ERROR,
67         MIKEY_TYPE_DHHMAC_INIT,
68         MIKEY_TYPE_DHHMAC_RESP,
69         MIKEY_TYPE_RSA_R_INIT,
70         MIKEY_TYPE_RSA_R_RESP,
71         MIKEY_TYPE_SAKKE_INIT = 26,
72         MIKEY_TYPE_SAKKE_RESP
73 };
74
75 static const value_string data_type_vals[] = {
76         { MIKEY_TYPE_PSK_INIT,    "Pre-shared" },
77         { MIKEY_TYPE_PSK_RESP,    "PSK ver msg" },
78         { MIKEY_TYPE_PK_INIT,     "Public key" },
79         { MIKEY_TYPE_PK_RESP,     "PK ver msg" },
80         { MIKEY_TYPE_DH_INIT,     "D-H init" },
81         { MIKEY_TYPE_DH_RESP,     "D-H resp" },
82         { MIKEY_TYPE_ERROR,       "Error" },
83         { MIKEY_TYPE_DHHMAC_INIT, "DHHMAC init" },
84         { MIKEY_TYPE_DHHMAC_RESP, "DHHMAC resp" },
85         { MIKEY_TYPE_RSA_R_INIT,  "RSA-R I_MSG" },
86         { MIKEY_TYPE_RSA_R_RESP,  "RSA-R R_MSG" },
87         { MIKEY_TYPE_SAKKE_INIT,  "SAKKE" },
88         { MIKEY_TYPE_SAKKE_RESP,  "CS Id map Update" },
89         { 0, NULL }
90 };
91 static value_string_ext data_type_vals_ext = VALUE_STRING_EXT_INIT(data_type_vals);
92
93 enum cs_id_map_t {
94         CS_ID_SRTP = 0
95 };
96
97 static const value_string cs_id_map_vals[] = {
98         { CS_ID_SRTP, "SRTP-ID" },
99         { 0, NULL }
100 };
101
102 enum payload_t {
103         PL_HDR      = -1,
104         PL_LAST,
105         PL_KEMAC,
106         PL_PKE,
107         PL_DH,
108         PL_SIGN,
109         PL_T,
110         PL_ID,
111         PL_CERT,
112         PL_CHASH,
113         PL_V,
114         PL_SP,
115         PL_RAND,
116         PL_ERR,
117         PL_TR       = 13, /* MIKEY-TICKET (6043) */
118         PL_IDR,
119         PL_RANDR,
120         PL_TP,
121         PL_TICKET,
122         PL_KEY_DATA = 20,
123         PL_GENERAL_EXT,
124         PL_SAKKE    = 26,
125         PL_MAX
126 };
127
128 #define PL_HDR_TEXT         "Common Header (HDR)"
129 #define PL_LAST_TEXT        "Last payload"
130 #define PL_KEMAC_TEXT       "Key Data Transport (KEMAC)"
131 #define PL_PKE_TEXT         "Envelope Data (PKE)"
132 #define PL_DH_TEXT          "DH Data (DH)"
133 #define PL_SIGN_TEXT        "Signature (SIGN)"
134 #define PL_T_TEXT           "Timestamp (T)"
135 #define PL_ID_TEXT          "ID"
136 #define PL_CERT_TEXT        "Certificate (CERT)"
137 #define PL_CHASH_TEXT       "CHASH"
138 #define PL_V_TEXT           "Ver msg (V)"
139 #define PL_SP_TEXT          "Security Policy (SP)"
140 #define PL_RAND_TEXT        "RAND"
141 #define PL_ERR_TEXT         "Error (ERR)"
142 #define PL_KEY_DATA_TEXT    "Key data (KEY)"
143 #define PL_IDR_TEXT         "IDR"
144 #define PL_GENERAL_EXT_TEXT "General Extension (EXT)"
145 #define PL_SAKKE_TEXT       "SAKKE Encapsulated Data (SAKKE)"
146
147 static const value_string payload_vals[] = {
148         { PL_HDR,         PL_HDR_TEXT },
149         { PL_LAST,        PL_LAST_TEXT },
150         { PL_KEMAC,       PL_KEMAC_TEXT },
151         { PL_PKE,         PL_PKE_TEXT },
152         { PL_DH,          PL_DH_TEXT },
153         { PL_SIGN,        PL_SIGN_TEXT },
154         { PL_T,           PL_T_TEXT },
155         { PL_ID,          PL_ID_TEXT },
156         { PL_CERT,        PL_CERT_TEXT },
157         { PL_CHASH,       PL_CHASH_TEXT },
158         { PL_V,           PL_V_TEXT },
159         { PL_SP,          PL_SP_TEXT },
160         { PL_RAND,        PL_RAND_TEXT },
161         { PL_ERR,         PL_ERR_TEXT },
162         { PL_IDR,         PL_IDR_TEXT },
163         { PL_KEY_DATA,    PL_KEY_DATA_TEXT },
164         { PL_GENERAL_EXT, PL_GENERAL_EXT_TEXT },
165         { PL_SAKKE,       PL_SAKKE_TEXT },
166         { 0, NULL }
167 };
168 #if 0 /* First entry (PL_HDR) is -1 and there are gaps so this doesn't work */
169 static value_string_ext payload_vals_ext = VALUE_STRING_EXT_INIT(payload_vals);
170 #endif
171
172 enum ts_type_t {
173         T_NTP_UTC = 0,
174         T_NTP,
175         T_COUNTER
176 };
177
178 static const value_string ts_type_vals[] = {
179         { T_NTP_UTC, "NTP-UTC" },
180         { T_NTP,     "NTP" },
181         { T_COUNTER, "COUNTER" },
182         { 0, NULL }
183 };
184
185 enum encr_alg_t {
186         ENCR_NULL = 0,
187         ENCR_AES_CM_128,
188         ENCR_AES_KW_128
189 };
190
191 static const value_string encr_alg_vals[] = {
192         { ENCR_NULL,       "NULL" },
193         { ENCR_AES_CM_128, "AES-CM-128" },
194         { ENCR_AES_KW_128, "AES-KW-128" },
195         { 0, NULL }
196 };
197
198 enum oakley_t {
199         DH_OAKLEY_5 = 0,
200         DH_OAKLEY_1,
201         DH_OAKLEY_2
202 };
203
204 static const value_string oakley_vals[] = {
205         { DH_OAKLEY_5, "OAKLEY 5" },
206         { DH_OAKLEY_1, "OAKLEY 1" },
207         { DH_OAKLEY_2, "OAKLEY 2" },
208         { 0, NULL }
209 };
210
211 enum mac_alg_t {
212         MAC_NULL = 0,
213         MAC_HMAC_SHA_1_160
214 };
215
216 static const value_string mac_alg_vals[] = {
217         { MAC_NULL,           "NULL" },
218         { MAC_HMAC_SHA_1_160, "HMAC-SHA-1-160" },
219         { 0, NULL }
220 };
221
222 enum pke_c_t {
223         PKE_C_NO_CACHE = 0,
224         PKE_C_CACHE,
225         PKE_C_CACHE_CSB
226 };
227
228 static const value_string pke_c_vals[] = {
229         { PKE_C_NO_CACHE,  "No cache" },
230         { PKE_C_CACHE,     "Cache" },
231         { PKE_C_CACHE_CSB, "Cache for CSB" },
232         { 0, NULL }
233 };
234
235 enum sign_s_t {
236         SIGN_S_PKCS1 = 0,
237         SIGN_S_PSS,
238         SIGN_S_ECCSI
239 };
240
241 static const value_string sign_s_vals[] = {
242         { SIGN_S_PKCS1, "RSA/PKCS#1/1.5" },
243         { SIGN_S_PSS,   "RSA/PSS" },
244         { SIGN_S_ECCSI, "ECCSI" },
245         { 0, NULL }
246 };
247
248 enum id_type_t {
249         ID_TYPE_NAI = 0,
250         ID_TYPE_URI,
251         ID_TYPE_BYTE_STRING
252 };
253
254 static const value_string id_type_vals[] = {
255         { ID_TYPE_NAI,         "NAI" },
256         { ID_TYPE_URI,         "URI" },
257         { ID_TYPE_BYTE_STRING, "Byte string" },
258         { 0, NULL }
259 };
260
261 enum id_role_t {
262         ID_ROLE_RESERVED = 0,
263         ID_ROLE_INIT,
264         ID_ROLE_RESP,
265         ID_ROLE_KMS,
266         ID_ROLE_PSK,
267         ID_ROLE_APP,
268         ID_ROLE_INIT_KMS,
269         ID_ROLE_RESP_KMS
270 };
271
272 static const value_string id_role_vals[] = {
273         { ID_ROLE_RESERVED, "Reserved" },
274         { ID_ROLE_INIT,     "Initiator (IDRi)" },
275         { ID_ROLE_RESP,     "Responder (IDRr)" },
276         { ID_ROLE_KMS,      "KMS (IDRkms)" },
277         { ID_ROLE_PSK,      "Pre-Shared Key (IDRpsk)" },
278         { ID_ROLE_APP,      "Application (IDRapp)" },
279         { ID_ROLE_INIT_KMS, "Initiator's KMS (IDRkmsi)" },
280         { ID_ROLE_RESP_KMS, "Responder's KMS (IDRkmsr)" },
281         { 0, NULL }
282 };
283
284 enum cert_type_t {
285         CERT_TYPE_X509V3 = 0,
286         CERT_TYPE_X509V3_URL,
287         CERT_TYPE_X509V3_SIGN,
288         CERT_TYPE_X509V3_ENCR
289 };
290
291 static const value_string cert_type_vals[] = {
292         { CERT_TYPE_X509V3,      "X.509v3" },
293         { CERT_TYPE_X509V3_URL,  "X.509v3 URL" },
294         { CERT_TYPE_X509V3_SIGN, "X.509v3 Sign" },
295         { CERT_TYPE_X509V3_ENCR, "X.509v3 Encr" },
296         { 0, NULL }
297 };
298
299 enum srtp_policy_type_t {
300         SP_ENCR_ALG,
301         SP_ENCR_LEN,
302         SP_AUTH_ALG,
303         SP_AUTH_KEY_LEN,
304         SP_SALT_LEN,
305         SP_PRF,
306         SP_KD_RATE,
307         SP_SRTP_ENCR,
308         SP_SRTCP_ENCR,
309         SP_FEC,
310         SP_SRTP_AUTH,
311         SP_AUTH_TAG_LEN,
312         SP_SRTP_PREFIX,
313         SP_MAX
314 };
315
316 #define SP_TEXT_ENCR_ALG     "Encryption algorithm"
317 #define SP_TEXT_ENCR_LEN     "Session Encr. key length"
318 #define SP_TEXT_AUTH_ALG     "Authentication algorithm"
319 #define SP_TEXT_AUTH_KEY_LEN "Session Auth. key length"
320 #define SP_TEXT_SALT_LEN     "Session Salt key length"
321 #define SP_TEXT_PRF          "SRTP Pseudo Random Function"
322 #define SP_TEXT_KD_RATE      "Key derivation rate"
323 #define SP_TEXT_SRTP_ENCR    "SRTP encryption"
324 #define SP_TEXT_SRTCP_ENCR   "SRTCP encryption"
325 #define SP_TEXT_FEC          "Sender's FEC order"
326 #define SP_TEXT_SRTP_AUTH    "SRTP authentication"
327 #define SP_TEXT_AUTH_TAG_LEN "Authentication tag length"
328 #define SP_TEXT_SRTP_PREFIX  "SRTP prefix length"
329
330 #if 0
331 static const value_string srtp_policy_type_vals[] = {
332         { SP_ENCR_ALG,     SP_TEXT_ENCR_ALG },
333         { SP_ENCR_LEN,     SP_TEXT_ENCR_LEN },
334         { SP_AUTH_ALG,     SP_TEXT_AUTH_ALG },
335         { SP_AUTH_KEY_LEN, SP_TEXT_AUTH_KEY_LEN },
336         { SP_SALT_LEN,     SP_TEXT_SALT_LEN },
337         { SP_PRF,          SP_TEXT_PRF },
338         { SP_KD_RATE,      SP_TEXT_KD_RATE },
339         { SP_SRTP_ENCR,    SP_TEXT_SRTP_ENCR },
340         { SP_SRTCP_ENCR,   SP_TEXT_SRTCP_ENCR },
341         { SP_FEC,          SP_TEXT_FEC },
342         { SP_SRTP_AUTH,    SP_TEXT_SRTP_AUTH },
343         { SP_AUTH_TAG_LEN, SP_TEXT_AUTH_TAG_LEN },
344         { SP_SRTP_PREFIX,  SP_TEXT_SRTP_PREFIX },
345         { 0, NULL }
346 };
347 #endif
348
349 enum sp_encr_alg_t {
350         SP_ENCR_NULL = 0,
351         SP_ENCR_AES_CM,
352         SP_ENCR_AES_F8
353 };
354
355 static const value_string sp_encr_alg_vals[] = {
356         { SP_ENCR_NULL,   "NULL" },
357         { SP_ENCR_AES_CM, "AES-CM" },
358         { SP_ENCR_AES_F8, "AES-F8" },
359         { 0, NULL }
360 };
361
362 enum sp_auth_alg_t {
363         SP_AUTH_NULL = 0,
364         SP_AUTH_HMAC_SHA_1
365 };
366
367 static const value_string sp_auth_alg_vals[] = {
368         { SP_AUTH_NULL,       "NULL" },
369         { SP_AUTH_HMAC_SHA_1, "HMAC-SHA-1" },
370         { 0, NULL }
371 };
372
373 enum sp_prf_t {
374         SP_PRF_AES_CM = 0
375 };
376
377 static const value_string sp_prf_vals[] = {
378         { SP_PRF_AES_CM, "AES-CM" },
379         { 0, NULL }
380 };
381
382 enum sp_fec_t {
383         SP_FEC_SRTP = 0
384 };
385
386 static const value_string sp_fec_vals[] = {
387         { SP_FEC_SRTP, "FEC-SRTP" },
388         { 0, NULL }
389 };
390
391 enum sp_prot_t {
392         SP_PROT_TYPE_SRTP = 0
393 };
394
395 static const value_string sp_prot_type_vals[] = {
396         { SP_PROT_TYPE_SRTP, "SRTP" },
397         { 0, NULL }
398 };
399
400 enum prf_func_t {
401         PRF_FUNC_MIKEY_1 = 0
402 };
403
404 static const value_string prf_func_vals[] = {
405         { PRF_FUNC_MIKEY_1, "MIKEY-1" },
406         { 0, NULL }
407 };
408
409 enum kv_t {
410         KV_NULL = 0,
411         KV_SPI,
412         KV_INTERVAL
413 };
414
415 static const value_string kv_vals[] = {
416         { KV_NULL,     "Null" },
417         { KV_SPI,      "SPI/MKI" },
418         { KV_INTERVAL, "Interval" },
419         { 0, NULL }
420 };
421
422 enum kd_t {
423         KD_TGK = 0,
424         KD_TGK_SALT,
425         KD_TEK,
426         KD_TEK_SALT
427 };
428
429 static const value_string kd_vals[] = {
430         { KD_TGK,      "TGK" },
431         { KD_TGK_SALT, "TGK+SALT" },
432         { KD_TEK,      "TEK" },
433         { KD_TEK_SALT, "TEK+SALT" },
434         { 0, NULL }
435 };
436
437 enum err_t {
438         ERR_AUTH_FAILURE = 0,
439         ERR_INVALID_TS,
440         ERR_INVALID_PRF,
441         ERR_INVALID_MAC,
442         ERR_INVALID_EA,
443         ERR_INVALID_HA,
444         ERR_INVALID_DH,
445         ERR_INVALID_ID,
446         ERR_INVALID_CERT,
447         ERR_INVALID_SP,
448         ERR_INVALID_SPPAR,
449         ERR_INVALID_DT,
450         ERR_UNKNOWN
451 };
452
453 static const value_string err_vals[] = {
454         { ERR_AUTH_FAILURE,  "Authentication failure" },
455         { ERR_INVALID_TS,    "Invalid timestamp" },
456         { ERR_INVALID_PRF,   "PRF function not supported" },
457         { ERR_INVALID_MAC,   "MAC algorithm not supported" },
458         { ERR_INVALID_EA,    "Encryption algorithm not supported" },
459         { ERR_INVALID_HA,    "Hash function not supported" },
460         { ERR_INVALID_DH,    "DH group not supported" },
461         { ERR_INVALID_ID,    "ID not supported" },
462         { ERR_INVALID_CERT,  "Certificate not supported" },
463         { ERR_INVALID_SP,    "SP type not supported" },
464         { ERR_INVALID_SPPAR, "SP parameters not supported" },
465         { ERR_INVALID_DT,    "Data type not supported" },
466         { ERR_UNKNOWN,       "Unspecified error" },
467         { 0, NULL }
468 };
469 static value_string_ext err_vals_ext = VALUE_STRING_EXT_INIT(err_vals);
470
471 enum genext_t {
472         GEN_EXT_VENDOR_ID = 0,
473         GEN_EXT_SDP_ID
474 };
475
476 static const value_string genext_type_vals[] = {
477         { GEN_EXT_VENDOR_ID, "Vendor-ID" },
478         { GEN_EXT_SDP_ID,    "SDP-IDs" },
479         { 0, NULL }
480 };
481
482 enum {
483         /* HDR */
484         POS_HDR_VERSION=0,
485         POS_HDR_DATA_TYPE,
486         POS_HDR_V,
487         POS_HDR_PRF_FUNC,
488         POS_HDR_CSB_ID,
489         POS_HDR_CS_COUNT,
490         POS_HDR_CS_ID_MAP_TYPE,
491         POS_ID_SRTP,
492         POS_ID_SRTP_NO,
493         POS_ID_SRTP_SSRC,
494         POS_ID_SRTP_ROC,
495
496         /* KEMAC */
497         POS_KEMAC_ENCR_ALG,
498         POS_KEMAC_ENCR_DATA_LEN,
499         POS_KEMAC_ENCR_DATA,
500         POS_KEMAC_MAC_ALG,
501         POS_KEMAC_MAC,
502
503         /* PKE */
504         POS_PKE_C,
505         POS_PKE_DATA_LEN,
506         POS_PKE_DATA,
507
508         /* DH */
509         POS_DH_GROUP,
510         POS_DH_VALUE,
511         POS_DH_RESERV,
512         POS_DH_KV,
513
514         /* SIGN */
515         POS_SIGNATURE_LEN,
516         POS_SIGNATURE,
517         POS_SIGN_S_TYPE,
518
519         /* T */
520         POS_TS_TYPE,
521         POS_TS_NTP,
522
523         /* ID/IDR */
524         POS_ID_ROLE,
525         POS_ID_TYPE,
526         POS_ID_LEN,
527         POS_ID,
528
529         /* CERT */
530         POS_CERT_TYPE,
531         POS_CERT_LEN,
532         POS_CERTIFICATE,
533
534         /* V */
535         POS_V_AUTH_ALG,
536         POS_V_DATA,
537
538         /* SP */
539         POS_SP_NO,
540         POS_SP_TYPE,
541         POS_SP_PARAM_LEN,
542 /*      POS_SP_PARAM, */
543
544         /* SP param */
545         POS_SP_PARAM_F,
546         POS_SP_PARAM_F_TYPE,
547         POS_SP_PARAM_F_LEN,
548         POS_SP_PARAM_F_VALUE,
549
550         /* RAND */
551         POS_RAND_LEN,
552         POS_RAND,
553
554         /* Error */
555         POS_ERR_NO,
556         POS_ERR_RESERVED,
557
558         /* Key data */
559         POS_KEY_DATA_TYPE,
560         POS_KEY_DATA_KV,
561         POS_KEY_DATA_LEN,
562         POS_KEY_DATA,
563         POS_KEY_SALT_LEN,
564         POS_KEY_SALT,
565         POS_KEY_KV_FROM_LEN,
566         POS_KEY_KV_FROM,
567         POS_KEY_KV_TO_LEN,
568         POS_KEY_KV_TO,
569         POS_KEY_KV_SPI_LEN,
570         POS_KEY_KV_SPI,
571
572         /* General Ext. */
573         POS_GENERAL_EXT_TYPE,
574         POS_GENERAL_EXT_LEN,
575         POS_GENERAL_EXT_DATA,
576         POS_GENERAL_EXT_VALUE,
577
578         /* SAKKE */
579         POS_SAKKE_PARAMS,
580         POS_SAKKE_ID_SCHEME,
581         POS_SAKKE_LEN,
582         POS_SAKKE_DATA,
583
584         /* MIKEY */
585         POS_PAYLOAD_STR,
586         POS_NEXT_PAYLOAD,
587
588         /* Unused */
589 /*      POS_PAYLOAD, */
590
591         MAX_POS
592 };
593
594 typedef struct tag_mikey_t {
595         guint8 type;
596 } mikey_t;
597
598 typedef int (*mikey_dissector_t)(mikey_t *, tvbuff_t *, packet_info *, proto_tree *);
599 struct mikey_dissector_entry {
600         int type;
601         mikey_dissector_t dissector;
602 };
603
604 /* Forward declaration we need below */
605 static int dissect_payload(int payload, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
606
607
608 /* Initialize the protocol and registered fields */
609 static int proto_mikey = -1;
610 static int hf_mikey[MAX_POS+1];
611 static int hf_mikey_sp_param[SP_MAX+1];
612 static int hf_mikey_pl[PL_MAX];
613
614 /* Initialize the subtree pointers */
615 static gint ett_mikey = -1;
616 static gint ett_mikey_payload = -1;
617 static gint ett_mikey_sp_param = -1;
618 static gint ett_mikey_hdr_id = -1;
619 static gint ett_mikey_enc_data = -1;
620
621 static dissector_handle_t mikey_handle;
622
623 static const struct mikey_dissector_entry *
624 mikey_dissector_lookup(const struct mikey_dissector_entry *map, int type)
625 {
626         unsigned int i;
627         for (i = 0; map[i].dissector != NULL; i++) {
628                 if (map[i].type == type) {
629                         return &map[i];
630                 }
631         }
632
633         return NULL;
634 }
635
636 static void
637 add_next_payload(tvbuff_t *tvb, proto_tree *tree, int offset)
638 {
639         proto_tree_add_item(tree, hf_mikey[POS_NEXT_PAYLOAD], tvb, offset, 1, ENC_BIG_ENDIAN);
640 }
641
642
643 static int
644 dissect_payload_cs_id_srtp(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_,  proto_tree *tree)
645 {
646         if (tree) {
647                 proto_item *id_ti;
648                 proto_tree *id_tree;
649                 guint8      no;
650                 guint32     ssrc;
651                 guint32     roc;
652
653                 no   = tvb_get_guint8(tvb, 0);
654                 ssrc = tvb_get_ntohl(tvb, 1);
655                 roc  = tvb_get_ntohl(tvb, 5);
656
657                 id_ti = proto_tree_add_none_format(tree, hf_mikey[POS_ID_SRTP], tvb, 0, 9,
658                                                    "SRTP ID: Policy: %d, SSRC: 0x%x, ROC: 0x%x", no, ssrc, roc);
659                 id_tree = proto_item_add_subtree(id_ti, ett_mikey_hdr_id);
660
661                 proto_tree_add_item(id_tree, hf_mikey[POS_ID_SRTP_NO],   tvb, 0, 1, ENC_BIG_ENDIAN);
662                 proto_tree_add_item(id_tree, hf_mikey[POS_ID_SRTP_SSRC], tvb, 1, 4, ENC_BIG_ENDIAN);
663                 proto_tree_add_item(id_tree, hf_mikey[POS_ID_SRTP_ROC],  tvb, 5, 4, ENC_BIG_ENDIAN);
664         }
665         return 9;
666 }
667
668 static const struct mikey_dissector_entry cs_id_map[] = {
669         { CS_ID_SRTP, dissect_payload_cs_id_srtp },
670         { 0, NULL }
671 };
672
673 static int
674 dissect_payload_cs_id(int type, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
675 {
676         const struct mikey_dissector_entry *entry;
677
678         entry = mikey_dissector_lookup(cs_id_map, type);
679
680         if (!entry || !entry->dissector) {
681                 return 0;
682         }
683
684         return entry->dissector(mikey, tvb, pinfo, tree);
685
686 }
687
688 static int
689 dissect_payload_hdr(mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
690 {
691         int    offset = 0;
692         guint8 cs_id_map_type;
693         guint8 ncs;
694         int    i;
695
696         tvb_ensure_bytes_exist(tvb, offset, 10);
697         mikey->type = tvb_get_guint8(tvb, offset+1);
698         ncs = tvb_get_guint8(tvb, offset+8);
699         cs_id_map_type = tvb_get_guint8(tvb, offset+9);
700
701         if (tree) {
702                 proto_item* parent;
703                 proto_tree_add_item(tree, hf_mikey[POS_HDR_VERSION],
704                                         tvb, offset+0, 1, ENC_BIG_ENDIAN);
705
706                 proto_tree_add_item(tree, hf_mikey[POS_HDR_DATA_TYPE], tvb, offset+1, 1, ENC_BIG_ENDIAN);
707                 parent = proto_tree_get_parent(tree);
708                 proto_item_append_text(parent, " Type: %s",
709                                        val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
710
711                 add_next_payload(tvb, tree, offset+2);
712
713                 proto_tree_add_item(tree, hf_mikey[POS_HDR_V], tvb, offset+3, 1, ENC_BIG_ENDIAN);
714                 proto_tree_add_item(tree, hf_mikey[POS_HDR_PRF_FUNC], tvb, offset+3, 1, ENC_BIG_ENDIAN);
715
716                 proto_tree_add_item(tree, hf_mikey[POS_HDR_CSB_ID], tvb, offset+4, 4, ENC_BIG_ENDIAN);
717
718                 proto_tree_add_item(tree, hf_mikey[POS_HDR_CS_COUNT], tvb, offset+8, 1, ENC_BIG_ENDIAN);
719                 proto_tree_add_item(tree, hf_mikey[POS_HDR_CS_ID_MAP_TYPE], tvb, offset+9, 1, ENC_BIG_ENDIAN);
720         }
721
722         offset += 10;
723         for (i=0; i < ncs; i++) {
724                 tvbuff_t *sub_tvb;
725                 int       len;
726
727                 sub_tvb = tvb_new_subset_remaining(tvb, offset);
728                 len = dissect_payload_cs_id(cs_id_map_type, mikey, sub_tvb, pinfo, tree);
729
730                 if (len < 0)
731                         return 0;
732
733                 offset += len;
734         }
735
736         return offset;
737 }
738
739 static int
740 dissect_payload_kemac(mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
741 {
742         int     offset = 0;
743         guint8  encr_alg;
744         guint16 encr_length;
745         guint16 mac_length;
746         guint8  mac_alg;
747
748         encr_alg    = tvb_get_guint8(tvb, offset+1);
749         encr_length = tvb_get_ntohs(tvb, offset+2);
750         tvb_ensure_bytes_exist(tvb, offset+4, encr_length+1);
751         mac_alg     = tvb_get_guint8(tvb, offset+4+encr_length);
752
753         if (tree) {
754                 tvbuff_t *sub_tvb;
755                 proto_tree_add_item(tree, hf_mikey[POS_KEMAC_ENCR_ALG],      tvb, 1, 1, ENC_BIG_ENDIAN);
756                 proto_tree_add_item(tree, hf_mikey[POS_KEMAC_ENCR_DATA_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
757                 /* TODO: Add key decode for MIKEY_TYPE_PK_INIT and MIKEY_TYPE_RSA_R_RESP with NULL encryption */
758                 if ((encr_alg == ENCR_NULL) && (mikey->type == MIKEY_TYPE_PSK_INIT) && (encr_length > 0)) {
759                         proto_item *key_data_item;
760                         proto_tree *key_data_tree;
761                         /* We can decode easily the Key Data if NULL encryption is used */
762                         key_data_item = proto_tree_add_item(tree, hf_mikey_pl[PL_KEY_DATA], tvb, 4, encr_length, ENC_NA);
763                         key_data_tree = proto_item_add_subtree(key_data_item, ett_mikey_enc_data);
764
765                         sub_tvb = tvb_new_subset_length(tvb, offset+4, encr_length);
766                         dissect_payload(PL_KEY_DATA, mikey, sub_tvb, pinfo, key_data_tree);
767                 } else {
768                         /* If Key Data is encrypted, show only the encr_data */
769                         proto_tree_add_item(tree, hf_mikey[POS_KEMAC_ENCR_DATA], tvb, 4, encr_length, ENC_NA);
770                 }
771                 proto_tree_add_item(tree, hf_mikey[POS_KEMAC_MAC_ALG], tvb, 4+encr_length, 1, ENC_BIG_ENDIAN);
772         }
773
774         switch (mac_alg) {
775         case MAC_NULL:
776                 mac_length = 0;
777                 break;
778         case MAC_HMAC_SHA_1_160:
779                 mac_length = 160/8;
780                 break;
781         default:
782                 return 0;
783         }
784
785         proto_tree_add_item(tree, hf_mikey[POS_KEMAC_MAC], tvb, 4+encr_length+1, mac_length, ENC_NA);
786
787         return 4+encr_length+1+mac_length;
788 }
789
790 static int
791 dissect_payload_pke(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
792 {
793         int     offset = 0;
794         guint16 length;
795
796         length = tvb_get_ntohs(tvb, offset+1) &0x3ff;
797
798         if (tree) {
799                 proto_tree_add_item(tree, hf_mikey[POS_PKE_C], tvb, 1, 2, ENC_BIG_ENDIAN);
800
801                 proto_tree_add_item(tree, hf_mikey[POS_PKE_DATA_LEN], tvb, 1, 2, ENC_BIG_ENDIAN);
802         }
803
804         proto_tree_add_item(tree, hf_mikey[POS_PKE_DATA], tvb, 3, length, ENC_NA);
805         return 3 + length;
806 }
807
808 static int
809 dissect_payload_dh(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
810 {
811         int    offset = 0;
812         guint8 dh_group;
813         int    dh_length;
814         guint8 kv;
815
816         dh_group = tvb_get_guint8(tvb, offset+1);
817
818         switch (dh_group) {
819         case DH_OAKLEY_5:
820                 dh_length = 1536/8;
821                 break;
822         case DH_OAKLEY_1:
823                 dh_length = 768/8;
824                 break;
825         case DH_OAKLEY_2:
826                 dh_length = 1024/8;
827                 break;
828         default:
829                 return 0;
830         }
831
832         kv = tvb_get_guint8(tvb, offset+2+dh_length) & 0x0f;
833
834         if (tree) {
835                 proto_tree_add_item(tree, hf_mikey[POS_DH_GROUP], tvb, 1, 1, ENC_BIG_ENDIAN);
836                 proto_tree_add_item(tree, hf_mikey[POS_DH_VALUE], tvb, 2, dh_length, ENC_NA);
837                 proto_tree_add_item(tree, hf_mikey[POS_DH_RESERV], tvb, 2+dh_length, 1, ENC_BIG_ENDIAN);
838                 proto_tree_add_item(tree, hf_mikey[POS_DH_KV], tvb, 2+dh_length, 1, ENC_BIG_ENDIAN);
839         }
840
841         if (kv != 0) {
842                 return 0;
843         }
844
845         return 2 + dh_length + 1;
846 }
847
848 static int
849 dissect_payload_sign(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
850 {
851         int     offset = 0;
852         guint16 length;
853
854         length = ((tvb_get_guint8(tvb, offset+0) & 0x0f) << 8) + tvb_get_guint8(tvb, offset+1);
855
856         if (tree) {
857                 proto_tree_add_item(tree, hf_mikey[POS_SIGN_S_TYPE], tvb, 0, 2, ENC_BIG_ENDIAN);
858                 proto_tree_add_uint(tree, hf_mikey[POS_SIGNATURE_LEN], tvb, 0, 2, length);
859         }
860
861         proto_tree_add_item(tree, hf_mikey[POS_SIGNATURE], tvb, 2, length, ENC_NA);
862         return 2 + length;
863 }
864
865 static int
866 dissect_payload_t(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
867 {
868         guint8 ts_type;
869         int    offset = 0;
870         int    len    = 0;
871
872         ts_type = tvb_get_guint8(tvb, offset+1);
873
874         if (tree) {
875                 proto_tree *parent;
876                 parent = proto_tree_get_parent(tree);
877                 proto_item_append_text(parent, " Type: %s", val_to_str_const(ts_type, ts_type_vals, "Unknown"));
878                 proto_tree_add_item(tree, hf_mikey[POS_TS_TYPE], tvb, offset+1, 1, ENC_BIG_ENDIAN);
879         }
880
881         switch (ts_type) {
882         case T_NTP:
883         case T_NTP_UTC:
884                 proto_tree_add_item(tree, hf_mikey[POS_TS_NTP], tvb, offset+2, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN);
885                 len = 10;
886                 break;
887         case T_COUNTER:
888                 len = 6;
889                 break;
890         default:
891                 len = 0;
892                 break;
893         }
894
895         return len;
896 }
897
898 static int
899 dissect_payload_id(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
900 {
901         int     offset = 0;
902         guint8  type;
903         guint16 length;
904
905         type   = tvb_get_guint8(tvb, offset+1);
906         length = tvb_get_ntohs(tvb,  offset+2);
907         if (tree) {
908                 proto_tree_add_item(tree, hf_mikey[POS_ID_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
909                 proto_tree_add_item(tree, hf_mikey[POS_ID_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
910         }
911
912         if (tree) {
913                 proto_item* parent;
914                 proto_tree_add_item(tree, hf_mikey[POS_ID], tvb, 4, length, ENC_ASCII|ENC_NA);
915
916                 parent = proto_tree_get_parent(tree);
917                 proto_item_append_text(parent, " %s: %s",
918                                        val_to_str_const(type, id_type_vals, "Unknown"),
919                                        tvb_get_string_enc(wmem_packet_scope(), tvb, 4, length, ENC_ASCII));
920         }
921
922         return 4 + length;
923 }
924
925 static int
926 dissect_payload_idr(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
927 {
928         int     offset = 0;
929         guint8  type;
930         guint16 length;
931
932         type = tvb_get_guint8(tvb, offset+2);
933         length = tvb_get_ntohs(tvb, offset+3);
934         if (tree) {
935                 proto_tree_add_item(tree, hf_mikey[POS_ID_ROLE], tvb, 1, 1, ENC_BIG_ENDIAN);
936                 proto_tree_add_item(tree, hf_mikey[POS_ID_TYPE], tvb, 2, 1, ENC_BIG_ENDIAN);
937                 proto_tree_add_item(tree, hf_mikey[POS_ID_LEN],  tvb, 3, 2, ENC_BIG_ENDIAN);
938         }
939
940         if (tree) {
941                 proto_item *parent;
942                 proto_tree_add_item(tree, hf_mikey[POS_ID], tvb, 5, length, ENC_ASCII|ENC_NA);
943
944                 parent = proto_tree_get_parent(tree);
945                 proto_item_append_text(parent, " %s: %s",
946                                        val_to_str_const(type, id_type_vals, "Unknown"),
947                                        tvb_get_string_enc(wmem_packet_scope(), tvb, 5, length, ENC_ASCII));
948         }
949
950         return 5 + length;
951 }
952
953 static int
954 dissect_payload_cert(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
955 {
956         int          offset = 0;
957         guint8       type;
958         guint16      length;
959         tvbuff_t    *subtvb;
960         asn1_ctx_t   asn1_ctx;
961
962         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
963
964         type   = tvb_get_guint8(tvb, offset+1);
965         length = tvb_get_ntohs(tvb, offset+2);
966
967         tvb_ensure_bytes_exist(tvb, offset+4, length);
968
969         if (tree) {
970                 proto_item *parent;
971                 parent = proto_tree_get_parent(tree);
972                 proto_tree_add_item(tree, hf_mikey[POS_CERT_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
973                 proto_tree_add_item(tree, hf_mikey[POS_CERT_LEN], tvb, 1, 2, ENC_BIG_ENDIAN);
974
975                 proto_item_append_text(parent, " Type: %s", val_to_str_const(type, cert_type_vals, "Unknown"));
976         }
977
978         subtvb = tvb_new_subset_length(tvb, offset+4, length);
979         dissect_x509af_Certificate(FALSE, subtvb, 0, &asn1_ctx, tree, hf_mikey[POS_CERTIFICATE]);
980
981         return 4 + length;
982 }
983
984 static int
985 dissect_payload_v(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
986 {
987         int     offset = 0;
988         guint16 length;
989         guint8  alg;
990
991         alg = tvb_get_guint8(tvb, offset+1);
992
993         proto_tree_add_item(tree, hf_mikey[POS_V_AUTH_ALG], tvb, 1, 1, ENC_BIG_ENDIAN);
994
995         switch (alg) {
996         case MAC_NULL:
997                 length = 0;
998                 break;
999         case MAC_HMAC_SHA_1_160:
1000                 length = 160/8;
1001                 break;
1002         default:
1003                 return 0;
1004         }
1005
1006         proto_tree_add_item(tree, hf_mikey[POS_V_DATA], tvb, 2, length, ENC_NA);
1007
1008         return 2 + length;
1009 }
1010
1011 static int
1012 dissect_payload_sp_param(enum sp_prot_t proto, tvbuff_t *tvb, proto_tree *tree)
1013 {
1014         int    offset = 0;
1015         guint8 type;
1016         guint8 length;
1017         int    hfindex;
1018
1019         type = tvb_get_guint8(tvb, offset+0);
1020         length = tvb_get_guint8(tvb, offset+1);
1021
1022         /* Default */
1023         hfindex = hf_mikey[POS_SP_PARAM_F];
1024
1025         switch(proto) {
1026         case SP_PROT_TYPE_SRTP:
1027                 if (type < array_length(hf_mikey_sp_param))
1028                         hfindex = hf_mikey_sp_param[type];
1029                 break;
1030         }
1031
1032         if (tree) {
1033                 proto_item *param_ti;
1034                 proto_tree *param_tree;
1035                 /*
1036                  * All the parameters in question are either FT_BYTES,
1037                  * in which case the byte order is inapplicable, or
1038                  * FT_UINT8, in which case it could be given as
1039                  * FT_BIG_ENDIAN as per bigger FT_UINT values, but
1040                  * ENC_NA also works, as there's only one byte.
1041                  */
1042                 param_ti = proto_tree_add_item(tree, hfindex, tvb, 2, length, ENC_NA);
1043                 param_tree = proto_item_add_subtree(param_ti, ett_mikey_sp_param);
1044
1045                 proto_tree_add_item(param_tree, hf_mikey[POS_SP_PARAM_F_TYPE], tvb, 0, 1, ENC_BIG_ENDIAN);
1046                 proto_tree_add_item(param_tree, hf_mikey[POS_SP_PARAM_F_LEN], tvb, 1, 1, ENC_BIG_ENDIAN);
1047                 proto_tree_add_item(param_tree, hf_mikey[POS_SP_PARAM_F_VALUE], tvb, 2, length, ENC_NA);
1048         }
1049
1050         return 2+length;
1051 }
1052
1053 static int
1054 dissect_payload_sp(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1055 {
1056         int            offset = 0;
1057         guint16        length;
1058         int            sub_pos;
1059         guint8         no;
1060         enum sp_prot_t type;
1061
1062         length = tvb_get_ntohs(tvb, offset+3);
1063         no     = tvb_get_guint8(tvb, offset+1);
1064         type   = (enum sp_prot_t)tvb_get_guint8(tvb, offset+2);
1065
1066         if (tree) {
1067                 proto_item *parent;
1068                 parent = proto_tree_get_parent(tree);
1069                 proto_tree_add_item(tree, hf_mikey[POS_SP_NO],        tvb, 1, 1, ENC_BIG_ENDIAN);
1070                 proto_tree_add_item(tree, hf_mikey[POS_SP_TYPE],      tvb, 2, 1, ENC_BIG_ENDIAN);
1071                 proto_tree_add_item(tree, hf_mikey[POS_SP_PARAM_LEN], tvb, 3, 2, ENC_BIG_ENDIAN);
1072
1073                 proto_item_append_text(parent, " No: %d, Type: %s", no,
1074                                        val_to_str_const(type, sp_prot_type_vals, "Unknown"));
1075         }
1076
1077         tvb_ensure_bytes_exist(tvb, offset+5, length);
1078 /*      proto_tree_add_item(tree, hf_mikey[POS_SP_PARAM], tvb, 5, length, ENC_NA); */
1079
1080         offset += 5;
1081         sub_pos = 0;
1082
1083         while (sub_pos < length) {
1084                 int       param_len;
1085                 tvbuff_t *subtvb;
1086
1087                 subtvb = tvb_new_subset_length(tvb, offset+sub_pos, length-sub_pos);
1088                 param_len = dissect_payload_sp_param(type, subtvb, tree);
1089
1090                 if (param_len < 0)
1091                         return 0;
1092
1093                 sub_pos += param_len;
1094         }
1095
1096         return 5 + length;
1097 }
1098
1099 static int
1100 dissect_payload_rand(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1101 {
1102         int     offset = 0;
1103         guint16 length;
1104
1105         length = tvb_get_guint8(tvb, offset+1);
1106
1107         proto_tree_add_item(tree, hf_mikey[POS_RAND_LEN], tvb, 1, 1, ENC_BIG_ENDIAN);
1108         proto_tree_add_item(tree, hf_mikey[POS_RAND], tvb, 2, length, ENC_NA);
1109
1110         return 2 + length;
1111 }
1112
1113 static int
1114 dissect_payload_err(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1115 {
1116         if (tree) {
1117                 proto_item *parent;
1118                 guint8 err_no;
1119                 err_no = tvb_get_guint8(tvb, 1);
1120                 proto_tree_add_item(tree, hf_mikey[POS_ERR_NO], tvb, 1, 1, ENC_BIG_ENDIAN);
1121                 proto_tree_add_item(tree, hf_mikey[POS_ERR_RESERVED], tvb, 2, 2, ENC_NA);
1122                 parent = proto_tree_get_parent(tree);
1123                 proto_item_append_text(parent, ": %s", val_to_str_ext_const(err_no, &err_vals_ext, "Unknown"));
1124         }
1125
1126         return 4;
1127 }
1128
1129 static int
1130 dissect_payload_keydata(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1131 {
1132         guint16 offset;
1133         guint16 data_len;
1134         guint8  key_type;
1135         guint8  kv_type;
1136
1137         offset = 0;
1138         key_type = tvb_get_guint8(tvb, 1) >> 4;
1139         kv_type  = tvb_get_guint8(tvb, 1) & 0x0f;
1140         data_len = tvb_get_ntohs(tvb, 2);
1141
1142         offset += 4;
1143
1144         if (tree) {
1145                 proto_item *parent;
1146                 proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA_TYPE], tvb, 1, 1,        ENC_BIG_ENDIAN);
1147                 proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA_KV],   tvb, 1, 1,        ENC_BIG_ENDIAN);
1148                 proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA_LEN],  tvb, 2, 2,        ENC_BIG_ENDIAN);
1149                 proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA],      tvb, 4, data_len, ENC_NA);
1150
1151                 parent = proto_tree_get_parent(tree);
1152                 proto_item_append_text(parent, " Type: %s", val_to_str_const(key_type, kd_vals, "Unknown"));
1153         }
1154
1155         offset += data_len;
1156
1157         /* Dissect SALT key */
1158         if ((key_type == KD_TGK_SALT) || (key_type == KD_TEK_SALT)) {
1159                 guint16 salt_len;
1160                 salt_len = tvb_get_ntohs(tvb, offset);
1161                 if (salt_len > 0) {
1162                         proto_tree_add_item(tree, hf_mikey[POS_KEY_SALT_LEN], tvb, offset, 2, ENC_BIG_ENDIAN);
1163                         proto_tree_add_item(tree, hf_mikey[POS_KEY_SALT], tvb, offset+2, salt_len, ENC_NA);
1164                 }
1165                 offset += 2+salt_len;
1166         }
1167
1168         /* Dissect Key Validity */
1169         if (kv_type == KV_INTERVAL) {
1170                 guint16 kv_from_len;
1171                 guint16 kv_to_len;
1172
1173                 kv_from_len = tvb_get_guint8(tvb, offset);
1174                 proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_FROM_LEN], tvb, offset, 1, ENC_BIG_ENDIAN);
1175                 if (kv_from_len > 0) {
1176                         proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_FROM], tvb, offset+1, kv_from_len, ENC_NA);
1177                 }
1178                 offset += 1+kv_from_len;
1179
1180                 kv_to_len = tvb_get_guint8(tvb, offset);
1181                 proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_TO_LEN], tvb, offset, 1, ENC_BIG_ENDIAN);
1182                 if (kv_to_len > 0) {
1183                         proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_TO], tvb, offset+1, kv_to_len, ENC_NA);
1184                 }
1185                 offset += 1+kv_to_len;
1186         } else if (kv_type == KV_SPI) {
1187                 guint16 kv_spi_len;
1188
1189                 kv_spi_len = tvb_get_guint8(tvb, offset);
1190                 proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_SPI_LEN], tvb, offset, 1, ENC_BIG_ENDIAN);
1191                 if (kv_spi_len > 0) {
1192                         proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_SPI], tvb, offset+1, kv_spi_len, ENC_NA);
1193                 }
1194                 offset += 1+kv_spi_len;
1195         }
1196
1197         return offset;
1198 }
1199
1200 static int
1201 dissect_payload_general_ext(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1202 {
1203         int     offset = 0;
1204         guint8  type;
1205         guint16 data_len;
1206
1207         type     = tvb_get_guint8(tvb, offset+1);
1208         data_len = tvb_get_ntohs(tvb, offset+2);
1209
1210         if (tree) {
1211                 proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
1212                 proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
1213         }
1214
1215         if (tree) {
1216                 proto_item *parent;
1217
1218                 parent = proto_tree_get_parent(tree);
1219                 if (type == 1) {
1220                         /* For SDP-IDs, show a string instead of raw bytes */
1221                         proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_VALUE], tvb, 4, data_len, ENC_ASCII|ENC_NA);
1222                 } else {
1223                         proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_DATA], tvb, 4, data_len, ENC_NA);
1224                 }
1225                 proto_item_append_text(parent, " Type: %s", val_to_str_const(type, genext_type_vals, "Unknown"));
1226         }
1227         return 4 + data_len;
1228 }
1229
1230 static int
1231 dissect_payload_sakke(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1232 {
1233         int     offset = 0;
1234         guint16 data_len;
1235
1236         data_len = tvb_get_ntohs(tvb, offset+3);
1237
1238         if (tree) {
1239                 proto_tree_add_item(tree, hf_mikey[POS_SAKKE_PARAMS],    tvb, 1, 1, ENC_BIG_ENDIAN);
1240                 proto_tree_add_item(tree, hf_mikey[POS_SAKKE_ID_SCHEME], tvb, 2, 1, ENC_BIG_ENDIAN);
1241                 proto_tree_add_item(tree, hf_mikey[POS_SAKKE_LEN],       tvb, 3, 2, ENC_BIG_ENDIAN);
1242         }
1243
1244         proto_tree_add_item(tree, hf_mikey[POS_SAKKE_DATA], tvb, 5, data_len, ENC_NA);
1245         return 5 + data_len;
1246 }
1247
1248 static const struct mikey_dissector_entry payload_map[] = {
1249         { PL_HDR,         dissect_payload_hdr },
1250         { PL_KEMAC,       dissect_payload_kemac },
1251         { PL_PKE,         dissect_payload_pke },
1252         { PL_DH,          dissect_payload_dh },
1253         { PL_SIGN,        dissect_payload_sign },
1254         { PL_T,           dissect_payload_t },
1255         { PL_ID,          dissect_payload_id },
1256         { PL_CERT,        dissect_payload_cert },
1257         { PL_V,           dissect_payload_v },
1258         { PL_SP,          dissect_payload_sp },
1259         { PL_RAND,        dissect_payload_rand },
1260         { PL_ERR,         dissect_payload_err },
1261         { PL_IDR,         dissect_payload_idr },
1262         { PL_KEY_DATA,    dissect_payload_keydata },
1263         { PL_GENERAL_EXT, dissect_payload_general_ext },
1264         { PL_SAKKE,       dissect_payload_sakke },
1265         { 0, NULL }
1266 };
1267
1268 static int
1269 dissect_payload(int payload, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1270 {
1271         const struct mikey_dissector_entry *entry;
1272
1273         entry = mikey_dissector_lookup(payload_map, payload);
1274
1275         if (!entry || !entry->dissector) {
1276                 return 0;
1277         }
1278
1279         return entry->dissector(mikey, tvb, pinfo, tree);
1280 }
1281
1282 /* MIKEY dissector */
1283 static int
1284 dissect_mikey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1285 {
1286         proto_item *ti         = NULL;
1287         proto_tree *mikey_tree = NULL;
1288         int         offset     = 0;
1289         int         next_payload_offset;
1290         int         payload;
1291         mikey_t    *mikey;
1292
1293         mikey = (mikey_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mikey, 0);
1294
1295         if (!mikey) {
1296                 mikey = wmem_new0(wmem_file_scope(), mikey_t);
1297                 mikey->type = -1;
1298                 p_add_proto_data(wmem_file_scope(), pinfo, proto_mikey, 0, mikey);
1299         }
1300
1301
1302         tvb_ensure_bytes_exist(tvb, offset, 3);
1303         next_payload_offset = offset + 2;
1304         payload = -1;
1305
1306         if (tree) {
1307                 ti = proto_tree_add_item(tree, proto_mikey, tvb, 0, -1, ENC_NA);
1308                 mikey_tree = proto_item_add_subtree(ti, ett_mikey);
1309         }
1310
1311         while (payload != 0) {
1312                 int         len;
1313                 proto_item *sub_ti             = NULL;
1314                 proto_tree *mikey_payload_tree = NULL;
1315                 int         next_payload;
1316                 tvbuff_t   *subtvb;
1317
1318                 next_payload = tvb_get_guint8(tvb, next_payload_offset);
1319                 subtvb = tvb_new_subset_remaining(tvb, offset);
1320
1321                 if (mikey_tree) {
1322                         int hf = payload;
1323
1324                         if (hf >= PL_MAX)
1325                                 return -1;
1326
1327                         if (hf == -1)
1328                                 hf = 0;
1329
1330                         sub_ti = proto_tree_add_item(mikey_tree, hf_mikey_pl[hf], subtvb, 0, -1, ENC_NA);
1331
1332                         mikey_payload_tree = proto_item_add_subtree(sub_ti, ett_mikey_payload);
1333                         if ((payload != PL_HDR) && (payload != PL_SIGN))
1334                                 add_next_payload(tvb, mikey_payload_tree, next_payload_offset);
1335                 }
1336
1337                 len = dissect_payload(payload, mikey, subtvb, pinfo, mikey_payload_tree);
1338                 if (len <= 0) {
1339                         /* protocol violation or invalid data, stop dissecting
1340                          * but accept the data retrieved so far */
1341                         return tvb_captured_length(tvb);
1342                 }
1343
1344                 if (sub_ti)
1345                         proto_item_set_len(sub_ti, len);
1346
1347                 if (payload == PL_SIGN)
1348                         break;
1349
1350                 payload = next_payload;
1351                 offset += len;
1352                 next_payload_offset = offset;
1353         }
1354
1355         if (ti) {
1356                 proto_item_append_text(ti, ": %s",
1357                                        val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
1358         }
1359
1360         col_append_str(pinfo->cinfo, COL_PROTOCOL, "/MIKEY");
1361
1362         col_append_fstr(pinfo->cinfo, COL_INFO, ", Mikey: %s",
1363                                 val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
1364
1365         /* Return the amount of data this dissector was able to dissect */
1366         return tvb_captured_length(tvb);
1367 }
1368
1369
1370 /* Register the protocol with Wireshark */
1371
1372 void
1373 proto_register_mikey(void)
1374 {
1375
1376         /* Setup list of header fields */
1377         static hf_register_info hf[] = {
1378                 /* Payload types */
1379                 { &hf_mikey_pl[PL_HDR+1],
1380                   { PL_HDR_TEXT, "mikey.hdr",
1381                     FT_NONE, BASE_NONE, NULL, 0x0,
1382                     NULL, HFILL }},
1383                 { &hf_mikey_pl[PL_KEMAC],
1384                   { PL_KEMAC_TEXT, "mikey.kemac",
1385                     FT_NONE, BASE_NONE, NULL, 0x0,
1386                     NULL, HFILL }},
1387                 { &hf_mikey_pl[PL_PKE],
1388                   { PL_PKE_TEXT, "mikey.pke",
1389                     FT_NONE, BASE_NONE, NULL, 0x0,
1390                     NULL, HFILL }},
1391                 { &hf_mikey_pl[PL_DH],
1392                   { PL_DH_TEXT, "mikey.dh",
1393                     FT_NONE, BASE_NONE, NULL, 0x0,
1394                     NULL, HFILL }},
1395                 { &hf_mikey_pl[PL_SIGN],
1396                   { PL_SIGN_TEXT, "mikey.sign",
1397                     FT_NONE, BASE_NONE, NULL, 0x0,
1398                     NULL, HFILL }},
1399                 { &hf_mikey_pl[PL_T],
1400                   { PL_T_TEXT, "mikey.t",
1401                     FT_NONE, BASE_NONE, NULL, 0x0,
1402                     NULL, HFILL }},
1403                 { &hf_mikey_pl[PL_ID],
1404                   { PL_ID_TEXT, "mikey.id",
1405                     FT_NONE, BASE_NONE, NULL, 0x0,
1406                     NULL, HFILL }},
1407                 { &hf_mikey_pl[PL_CERT],
1408                   { PL_CERT_TEXT, "mikey.cert",
1409                     FT_NONE, BASE_NONE, NULL, 0x0,
1410                     NULL, HFILL }},
1411                 { &hf_mikey_pl[PL_CHASH],
1412                   { PL_CHASH_TEXT, "mikey.chash",
1413                     FT_NONE, BASE_NONE, NULL, 0x0,
1414                     NULL, HFILL }},
1415                 { &hf_mikey_pl[PL_V],
1416                   { PL_V_TEXT, "mikey.v",
1417                     FT_NONE, BASE_NONE, NULL, 0x0,
1418                     NULL, HFILL }},
1419                 { &hf_mikey_pl[PL_SP],
1420                   { PL_SP_TEXT, "mikey.sp",
1421                     FT_NONE, BASE_NONE, NULL, 0x0,
1422                     NULL, HFILL }},
1423                 { &hf_mikey_pl[PL_RAND],
1424                   { PL_RAND_TEXT, "mikey.rand",
1425                     FT_NONE, BASE_NONE, NULL, 0x0,
1426                     NULL, HFILL }},
1427                 { &hf_mikey_pl[PL_ERR],
1428                   { PL_ERR_TEXT, "mikey.err",
1429                     FT_NONE, BASE_NONE, NULL, 0x0,
1430                     NULL, HFILL }},
1431                 { &hf_mikey_pl[PL_IDR],
1432                   { PL_IDR_TEXT, "mikey.idr",
1433                     FT_NONE, BASE_NONE, NULL, 0x0,
1434                     NULL, HFILL }},
1435                 { &hf_mikey_pl[PL_KEY_DATA],
1436                   { PL_KEY_DATA_TEXT, "mikey.key",
1437                     FT_NONE, BASE_NONE, NULL, 0x0,
1438                     NULL, HFILL }},
1439                 { &hf_mikey_pl[PL_GENERAL_EXT],
1440                   { PL_GENERAL_EXT_TEXT, "mikey.ext",
1441                     FT_NONE, BASE_NONE, NULL, 0x0,
1442                     NULL, HFILL }},
1443                 { &hf_mikey_pl[PL_SAKKE],
1444                   { PL_SAKKE_TEXT, "mikey.sakke",
1445                     FT_NONE, BASE_NONE, NULL, 0x0,
1446                     NULL, HFILL }},
1447
1448                 /* Common Header payload (HDR) */
1449                 { &hf_mikey[POS_HDR_VERSION],
1450                   { "Version", "mikey.version",
1451                     FT_UINT8, BASE_DEC, NULL, 0x0,
1452                     NULL, HFILL }},
1453                 { &hf_mikey[POS_HDR_DATA_TYPE],
1454                   { "Data Type", "mikey.type",
1455                     FT_UINT8, BASE_DEC|BASE_EXT_STRING, &data_type_vals_ext, 0x0,
1456                     NULL, HFILL }},
1457                 { &hf_mikey[POS_NEXT_PAYLOAD],
1458                   { "Next Payload", "mikey.next_payload",
1459                     FT_UINT8, BASE_DEC, VALS(payload_vals), 0x0,
1460                     NULL, HFILL }},
1461                 { &hf_mikey[POS_HDR_V],
1462                   { "V", "mikey.v",
1463                     FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80,
1464                     NULL, HFILL }},
1465                 { &hf_mikey[POS_HDR_PRF_FUNC],
1466                   { "PRF func", "mikey.prf_func",
1467                     FT_UINT8, BASE_DEC, VALS(prf_func_vals), 0x7f,
1468                     NULL, HFILL }},
1469                 { &hf_mikey[POS_HDR_CSB_ID],
1470                   { "CSB ID", "mikey.csb_id",
1471                     FT_UINT32, BASE_HEX, NULL, 0x0,
1472                     NULL, HFILL }},
1473                 { &hf_mikey[POS_HDR_CS_COUNT],
1474                   { "#CS", "mikey.cs_count",
1475                     FT_UINT8, BASE_DEC, NULL, 0x0,
1476                     NULL, HFILL }},
1477                 { &hf_mikey[POS_HDR_CS_ID_MAP_TYPE],
1478                   { "CS ID map type", "mikey.cs_id_map_type",
1479                     FT_UINT8, BASE_DEC, VALS(cs_id_map_vals), 0x0,
1480                     NULL, HFILL }},
1481
1482                 /* SRTP ID */
1483                 { &hf_mikey[POS_ID_SRTP],
1484                   { "SRTP ID", "mikey.srtp_id",
1485                     FT_NONE, BASE_NONE, NULL, 0x0,
1486                     NULL, HFILL }},
1487                 { &hf_mikey[POS_ID_SRTP_NO],
1488                   { "Policy No", "mikey.srtp_id.policy_no",
1489                     FT_UINT8, BASE_DEC, NULL, 0x0,
1490                     NULL, HFILL }},
1491                 { &hf_mikey[POS_ID_SRTP_SSRC],
1492                   { "SSRC", "mikey.srtp_id.ssrc",
1493                     FT_UINT32, BASE_HEX, NULL, 0x0,
1494                     NULL, HFILL }},
1495                 { &hf_mikey[POS_ID_SRTP_ROC],
1496                   { "ROC", "mikey.srtp_id.roc",
1497                     FT_UINT32, BASE_HEX, NULL, 0x0,
1498                     NULL, HFILL }},
1499
1500                 /* Key Data Transport payload (KEMAC) */
1501                 { &hf_mikey[POS_KEMAC_ENCR_ALG],
1502                   { "Encr alg", "mikey.kemac.encr_alg",
1503                     FT_UINT8, BASE_DEC, VALS(encr_alg_vals), 0x0,
1504                     NULL, HFILL }},
1505                 { &hf_mikey[POS_KEMAC_ENCR_DATA_LEN],
1506                   { "Key data len", "mikey.kemac.key_data_len",
1507                     FT_UINT16, BASE_DEC, NULL, 0x0,
1508                     NULL, HFILL }},
1509                 { &hf_mikey[POS_KEMAC_ENCR_DATA],
1510                   { "Key data", "mikey.kemac.key_data",
1511                     FT_BYTES, BASE_NONE, NULL, 0x0,
1512                     NULL, HFILL }},
1513                 { &hf_mikey[POS_KEMAC_MAC_ALG],
1514                   { "Mac alg", "mikey.kemac.mac_alg",
1515                     FT_UINT8, BASE_DEC, VALS(mac_alg_vals), 0x0,
1516                     NULL, HFILL }},
1517                 { &hf_mikey[POS_KEMAC_MAC],
1518                   { "MAC", "mikey.kemac.mac",
1519                     FT_BYTES, BASE_NONE, NULL, 0x0,
1520                     NULL, HFILL }},
1521
1522                 /* Envelope Data payload (PKE) */
1523                 { &hf_mikey[POS_PKE_C],
1524                   { "C", "mikey.pke.c",
1525                     FT_UINT16, BASE_DEC, VALS(pke_c_vals), 0xc000,
1526                     NULL, HFILL }},
1527                 { &hf_mikey[POS_PKE_DATA_LEN],
1528                   { "Data len", "mikey.pke.len",
1529                     FT_UINT16, BASE_DEC, NULL, 0x3fff,
1530                     NULL, HFILL }},
1531                 { &hf_mikey[POS_PKE_DATA],
1532                   { "Data", "mikey.pke.data",
1533                     FT_BYTES, BASE_NONE, NULL, 0x0,
1534                     NULL, HFILL }},
1535
1536                 /* DH data payload (DH) */
1537                 { &hf_mikey[POS_DH_GROUP],
1538                   { "DH-Group", "mikey.dh.group",
1539                     FT_UINT8, BASE_DEC, VALS(oakley_vals), 0x0,
1540                     NULL, HFILL }},
1541                 { &hf_mikey[POS_DH_VALUE],
1542                   { "DH-Value", "mikey.dh.value",
1543                     FT_BYTES, BASE_NONE, NULL, 0x0,
1544                     NULL, HFILL }},
1545                 { &hf_mikey[POS_DH_RESERV],
1546                   { "Reserv", "mikey.dh.reserv",
1547                     FT_UINT8, BASE_HEX, NULL, 0xf0,
1548                     NULL, HFILL }},
1549                 { &hf_mikey[POS_DH_KV],
1550                   { "KV", "mikey.dh.kv",
1551                     FT_UINT8, BASE_DEC, VALS(kv_vals), 0x0f,
1552                     NULL, HFILL }},
1553
1554                 /* Signature payload (SIGN) */
1555                 { &hf_mikey[POS_SIGN_S_TYPE],
1556                   { "Signature type", "mikey.sign.type",
1557                     FT_UINT16, BASE_DEC, VALS(sign_s_vals), 0xf000,
1558                     NULL, HFILL }},
1559                 { &hf_mikey[POS_SIGNATURE_LEN],
1560                   { "Signature len", "mikey.sign.len",
1561                     FT_UINT16, BASE_DEC, NULL, 0x0fff,
1562                     NULL, HFILL }},
1563                 { &hf_mikey[POS_SIGNATURE],
1564                   { "Signature", "mikey.sign.data",
1565                     FT_BYTES, BASE_NONE, NULL, 0x0,
1566                     NULL, HFILL }},
1567
1568                 /* Timestamp payload (T) */
1569                 { &hf_mikey[POS_TS_TYPE],
1570                   { "TS type", "mikey.t.ts_type",
1571                     FT_UINT8, BASE_DEC, VALS(ts_type_vals), 0x0,
1572                     NULL, HFILL }},
1573                 { &hf_mikey[POS_TS_NTP],
1574                   { "NTP timestamp", "mikey.t.ntp",
1575                     FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
1576                     NULL, HFILL }},
1577
1578                 { &hf_mikey[POS_PAYLOAD_STR],
1579                   { "Payload", "mikey.payload",
1580                     FT_STRING, BASE_NONE, NULL, 0x0,
1581                     NULL, HFILL }},
1582
1583                 /* ID payload (ID) */
1584                 { &hf_mikey[POS_ID_TYPE],
1585                   { "ID type", "mikey.id.type",
1586                     FT_UINT8, BASE_DEC, VALS(id_type_vals), 0x0,
1587                     NULL, HFILL }},
1588                 { &hf_mikey[POS_ID_LEN],
1589                   { "ID len", "mikey.id.len",
1590                     FT_UINT16, BASE_DEC, NULL, 0x0,
1591                     NULL, HFILL }},
1592                 { &hf_mikey[POS_ID],
1593                   { "ID", "mikey.id.data",
1594                     FT_STRING, BASE_NONE, NULL, 0x0,
1595                     NULL, HFILL }},
1596
1597                 /* Certificate payload (CERT) */
1598                 { &hf_mikey[POS_CERT_LEN],
1599                   { "Certificate len", "mikey.cert.len",
1600                     FT_UINT16, BASE_DEC, NULL, 0x0,
1601                     NULL, HFILL }},
1602                 { &hf_mikey[POS_CERT_TYPE],
1603                   { "Certificate type", "mikey.cert.type",
1604                     FT_UINT8, BASE_DEC, VALS(cert_type_vals), 0x0,
1605                     NULL, HFILL }},
1606                 { &hf_mikey[POS_CERTIFICATE],
1607                   { "Certificate", "mikey.cert.data",
1608                     FT_BYTES, BASE_NONE, NULL, 0x0,
1609                     NULL, HFILL }},
1610
1611                 /* Ver msg payload (V) */
1612                 { &hf_mikey[POS_V_AUTH_ALG],
1613                   { "Auth alg", "mikey.v.auth_alg",
1614                     FT_UINT8, BASE_DEC, VALS(mac_alg_vals), 0x0,
1615                     NULL, HFILL }},
1616                 { &hf_mikey[POS_V_DATA],
1617                   { "Ver data", "mikey.v.ver_data",
1618                     FT_BYTES, BASE_NONE, NULL, 0x0,
1619                     NULL, HFILL }},
1620
1621                 /* Security Policy payload (SP) */
1622                 { &hf_mikey[POS_SP_NO],
1623                   { "Policy No", "mikey.sp.no",
1624                     FT_UINT8, BASE_DEC, NULL, 0x0,
1625                     NULL, HFILL }},
1626                 { &hf_mikey[POS_SP_TYPE],
1627                   { "Protocol type", "mikey.sp.proto_type",
1628                     FT_UINT8, BASE_DEC, VALS(sp_prot_type_vals), 0x0,
1629                     NULL, HFILL }},
1630                 { &hf_mikey[POS_SP_PARAM_LEN],
1631                   { "Policy param length", "mikey.sp.param_len",
1632                     FT_UINT16, BASE_DEC, NULL, 0x0,
1633                     NULL, HFILL }},
1634
1635                 /* Security Policy param */
1636                 { &hf_mikey[POS_SP_PARAM_F],
1637                   { "Policy param", "mikey.sp.param",
1638                     FT_BYTES, BASE_NONE, NULL, 0x0,
1639                     NULL, HFILL }},
1640                 { &hf_mikey[POS_SP_PARAM_F_TYPE],
1641                   { "Type", "mikey.sp.param.type",
1642                     FT_UINT8, BASE_DEC, NULL, 0x0,
1643                     NULL, HFILL }},
1644                 { &hf_mikey[POS_SP_PARAM_F_LEN],
1645                   { "Length", "mikey.sp.param.len",
1646                     FT_UINT8, BASE_DEC, NULL, 0x0,
1647                     NULL, HFILL }},
1648                 { &hf_mikey[POS_SP_PARAM_F_VALUE],
1649                   { "Value", "mikey.sp.patam.value",
1650                     FT_BYTES, BASE_NONE, NULL, 0x0,
1651                     NULL, HFILL }},
1652
1653                 /* SRTP policy param */
1654                 { &hf_mikey_sp_param[SP_ENCR_ALG],
1655                   { SP_TEXT_ENCR_ALG, "mikey.sp.encr_alg",
1656                     FT_UINT8, BASE_DEC, VALS(sp_encr_alg_vals), 0x0,
1657                     NULL, HFILL }},
1658                 { &hf_mikey_sp_param[SP_ENCR_LEN],
1659                   { SP_TEXT_ENCR_LEN, "mikey.sp.encr_len",
1660                     FT_UINT8, BASE_DEC, NULL, 0x0,
1661                     NULL, HFILL }},
1662                 { &hf_mikey_sp_param[SP_AUTH_ALG],
1663                   { SP_TEXT_AUTH_ALG, "mikey.sp.auth_alg",
1664                     FT_UINT8, BASE_DEC, VALS(sp_auth_alg_vals), 0x0,
1665                     NULL, HFILL }},
1666                 { &hf_mikey_sp_param[SP_AUTH_KEY_LEN],
1667                   { SP_TEXT_AUTH_KEY_LEN, "mikey.sp.auth_key_len",
1668                     FT_UINT8, BASE_DEC, NULL, 0x0,
1669                     NULL, HFILL }},
1670                 { &hf_mikey_sp_param[SP_SALT_LEN],
1671                   { SP_TEXT_SALT_LEN, "mikey.sp.salt_len",
1672                     FT_UINT8, BASE_DEC, NULL, 0x0,
1673                     NULL, HFILL }},
1674                 { &hf_mikey_sp_param[SP_PRF],
1675                   { SP_TEXT_PRF, "mikey.sp.prf",
1676                     FT_UINT8, BASE_DEC, VALS(sp_prf_vals), 0x0,
1677                     NULL, HFILL }},
1678                 { &hf_mikey_sp_param[SP_KD_RATE],
1679                   { SP_TEXT_KD_RATE, "mikey.sp.kd_rate",
1680                     FT_UINT8, BASE_DEC, NULL, 0x0,
1681                     NULL, HFILL }},
1682                 { &hf_mikey_sp_param[SP_SRTP_ENCR],
1683                   { SP_TEXT_SRTP_ENCR, "mikey.sp.srtp_encr",
1684                     FT_UINT8, BASE_DEC, VALS(on_off_vals), 0x0,
1685                     NULL, HFILL }},
1686                 { &hf_mikey_sp_param[SP_SRTCP_ENCR],
1687                   { SP_TEXT_SRTCP_ENCR, "mikey.sp.srtcp_encr",
1688                     FT_UINT8, BASE_DEC, VALS(on_off_vals), 0x0,
1689                     NULL, HFILL }},
1690                 { &hf_mikey_sp_param[SP_FEC],
1691                   { SP_TEXT_FEC, "mikey.sp.fec",
1692                     FT_UINT8, BASE_DEC, VALS(sp_fec_vals), 0x0,
1693                     NULL, HFILL }},
1694                 { &hf_mikey_sp_param[SP_SRTP_AUTH],
1695                   { SP_TEXT_SRTP_AUTH, "mikey.sp.srtp_auth",
1696                     FT_UINT8, BASE_DEC, VALS(on_off_vals), 0x0,
1697                     NULL, HFILL }},
1698                 { &hf_mikey_sp_param[SP_AUTH_TAG_LEN],
1699                   { SP_TEXT_AUTH_TAG_LEN, "mikey.sp.auth_tag_len",
1700                     FT_UINT8, BASE_DEC, NULL, 0x0,
1701                     NULL, HFILL }},
1702                 { &hf_mikey_sp_param[SP_SRTP_PREFIX],
1703                   { SP_TEXT_SRTP_PREFIX, "mikey.sp.srtp_prefix",
1704                     FT_UINT8, BASE_DEC, NULL, 0x0,
1705                     NULL, HFILL }},
1706
1707                 /* RAND payload (RAND) */
1708                 { &hf_mikey[POS_RAND_LEN],
1709                   { "RAND len", "mikey.rand.len",
1710                     FT_UINT8, BASE_DEC, NULL, 0x0,
1711                     NULL, HFILL }},
1712                 { &hf_mikey[POS_RAND],
1713                   { "RAND", "mikey.rand.data",
1714                     FT_BYTES, BASE_NONE, NULL, 0x0,
1715                     NULL, HFILL }},
1716
1717                 /* Error payload (ERR) */
1718                 { &hf_mikey[POS_ERR_NO],
1719                   { "Error no.", "mikey.err.no",
1720                     FT_UINT8, BASE_DEC|BASE_EXT_STRING, &err_vals_ext, 0x0,
1721                     NULL, HFILL }},
1722                 { &hf_mikey[POS_ERR_RESERVED],
1723                   { "Reserved", "mikey.err.reserved",
1724                     FT_BYTES, BASE_NONE, NULL, 0x0,
1725                     NULL, HFILL }},
1726
1727                 /* IDR */
1728                 { &hf_mikey[POS_ID_ROLE],
1729                   { "ID role", "mikey.id.role",
1730                     FT_UINT8, BASE_DEC, VALS(id_role_vals), 0x0,
1731                     NULL, HFILL }},
1732
1733                 /* Key data sub-payload */
1734                 { &hf_mikey[POS_KEY_DATA_TYPE],
1735                   { "Type", "mikey.key.type",
1736                     FT_UINT8, BASE_DEC, VALS(kd_vals), 0xf0,
1737                     NULL, HFILL }},
1738                 { &hf_mikey[POS_KEY_DATA_KV],
1739                   { "KV", "mikey.key.kv",
1740                     FT_UINT8, BASE_DEC, VALS(kv_vals), 0x0f,
1741                     NULL, HFILL }},
1742                 { &hf_mikey[POS_KEY_DATA_LEN],
1743                   { "Key len", "mikey.key.data.len",
1744                     FT_UINT16, BASE_DEC, NULL, 0x0,
1745                     NULL, HFILL }},
1746                 { &hf_mikey[POS_KEY_DATA],
1747                   { "Key", "mikey.key.data",
1748                     FT_BYTES, BASE_NONE, NULL, 0x0,
1749                     NULL, HFILL }},
1750                 { &hf_mikey[POS_KEY_SALT_LEN],
1751                   { "Salt key len", "mikey.key.salt.len",
1752                     FT_UINT16, BASE_DEC, NULL, 0x0,
1753                     NULL, HFILL }},
1754                 { &hf_mikey[POS_KEY_SALT],
1755                   { "Salt key", "mikey.key.salt",
1756                     FT_BYTES, BASE_NONE, NULL, 0x0,
1757                     NULL, HFILL }},
1758                 { &hf_mikey[POS_KEY_KV_FROM_LEN],
1759                   { "Valid from len", "mikey.key.kv.from.len",
1760                     FT_UINT8, BASE_DEC, NULL, 0x0,
1761                     NULL, HFILL }},
1762                 { &hf_mikey[POS_KEY_KV_FROM],
1763                   { "Valid from", "mikey.key.kv.from",
1764                     FT_BYTES, BASE_NONE, NULL, 0x0,
1765                     NULL, HFILL }},
1766                 { &hf_mikey[POS_KEY_KV_TO_LEN],
1767                   { "Valid to len", "mikey.key.kv.to.len",
1768                     FT_UINT8, BASE_DEC, NULL, 0x0,
1769                     NULL, HFILL }},
1770                 { &hf_mikey[POS_KEY_KV_TO],
1771                   { "Valid to", "mikey.key.kv.to",
1772                     FT_BYTES, BASE_NONE, NULL, 0x0,
1773                     NULL, HFILL }},
1774                 { &hf_mikey[POS_KEY_KV_SPI_LEN],
1775                   { "Valid SPI len", "mikey.key.kv.spi.len",
1776                     FT_UINT8, BASE_DEC, NULL, 0x0,
1777                     NULL, HFILL }},
1778                 { &hf_mikey[POS_KEY_KV_SPI],
1779                   { "Valid SPI", "mikey.key.kv.spi",
1780                     FT_BYTES, BASE_NONE, NULL, 0x0,
1781                     NULL, HFILL }},
1782
1783                 /* General Extension payload (GENERAL_EXT) */
1784                 { &hf_mikey[POS_GENERAL_EXT_TYPE],
1785                   { "Extension type", "mikey.ext.type",
1786                     FT_UINT8, BASE_DEC, VALS(genext_type_vals), 0x0,
1787                     NULL, HFILL }},
1788                 { &hf_mikey[POS_GENERAL_EXT_LEN],
1789                   { "Length", "mikey.ext.len",
1790                     FT_UINT16, BASE_DEC, NULL, 0x0,
1791                     NULL, HFILL }},
1792                 { &hf_mikey[POS_GENERAL_EXT_DATA],
1793                   { "Data", "mikey.ext.data",
1794                     FT_BYTES, BASE_NONE, NULL, 0x0,
1795                     NULL, HFILL }},
1796                 { &hf_mikey[POS_GENERAL_EXT_VALUE],
1797                   { "Value", "mikey.ext.value",
1798                     FT_STRING, BASE_NONE, NULL, 0x0,
1799                     NULL, HFILL }},
1800
1801                 /* SAKKE */
1802                 { &hf_mikey[POS_SAKKE_PARAMS],
1803                   { "SAKKE params", "mikey.sakke.params",
1804                     FT_UINT8, BASE_DEC, NULL, 0x0,
1805                     NULL, HFILL }},
1806                 { &hf_mikey[POS_SAKKE_ID_SCHEME],
1807                   { "ID scheme", "mikey.sakke.idscheme",
1808                     FT_UINT8, BASE_DEC, NULL, 0x0,
1809                     NULL, HFILL }},
1810                 { &hf_mikey[POS_SAKKE_LEN],
1811                   { "SAKKE data length", "mikey.sakke.len",
1812                     FT_UINT16, BASE_DEC, NULL, 0x0,
1813                     NULL, HFILL }},
1814                 { &hf_mikey[POS_SAKKE_DATA],
1815                   { "SAKKE data", "mikey.sakke.data",
1816                     FT_BYTES, BASE_NONE, NULL, 0x0,
1817                     NULL, HFILL }},
1818
1819 /*
1820                 { &hf_mikey[POS_SP_PARAM],
1821                   { "Policy param", "mikey.policy_param",
1822                     FT_BYTES, BASE_NONE, NULL, 0x0,
1823                     NULL, HFILL }},
1824
1825                 { &hf_mikey[POS_PAYLOAD],
1826                   { "Payload", "mikey.payload",
1827                     FT_BYTES, BASE_HEX, NULL, 0x0,
1828                     NULL, HFILL }},
1829 */
1830         };
1831
1832         /* Setup protocol subtree array */
1833         static gint *ett[] = {
1834                 &ett_mikey,
1835                 &ett_mikey_payload,
1836                 &ett_mikey_sp_param,
1837                 &ett_mikey_hdr_id,
1838                 &ett_mikey_enc_data
1839         };
1840
1841         module_t *mikey_module;
1842
1843         /* Register the protocol name and description */
1844         proto_mikey = proto_register_protocol("Multimedia Internet KEYing",
1845                 "MIKEY", "mikey");
1846
1847         mikey_handle = new_register_dissector("mikey", dissect_mikey, proto_mikey);
1848
1849         /* Required function calls to register the header fields and subtrees used */
1850         proto_register_field_array(proto_mikey, hf, array_length(hf));
1851         proto_register_subtree_array(ett, array_length(ett));
1852
1853         /* Register our configuration options */
1854         mikey_module = prefs_register_protocol(proto_mikey, proto_reg_handoff_mikey);
1855
1856         prefs_register_uint_preference(mikey_module, "udp.port", "MIKEY UDP Port",
1857                 "Set the port for MIKEY messages (if other than the default of 2269)",
1858                 10, &global_mikey_udp_port);
1859
1860         prefs_register_uint_preference(mikey_module, "tcp.port", "MIKEY TCP Port",
1861                 "Set the port for MIKEY messages (if other than the default of 2269)",
1862                 10, &global_mikey_tcp_port);
1863
1864 }
1865
1866
1867 void
1868 proto_reg_handoff_mikey(void)
1869 {
1870         static guint              mikey_tcp_port;
1871         static guint              mikey_udp_port;
1872         static gboolean inited = FALSE;
1873
1874         if (!inited) {
1875                 dissector_add_string("key_mgmt", "mikey", mikey_handle);
1876                 inited = TRUE;
1877         } else {
1878                 dissector_delete_uint("udp.port", mikey_udp_port, mikey_handle);
1879                 dissector_delete_uint("tcp.port", mikey_tcp_port, mikey_handle);
1880         }
1881
1882         dissector_add_uint("udp.port", global_mikey_udp_port, mikey_handle);
1883         dissector_add_uint("tcp.port", global_mikey_tcp_port, mikey_handle);
1884
1885         mikey_udp_port = global_mikey_udp_port;
1886         mikey_tcp_port = global_mikey_tcp_port;
1887 }
1888 /*
1889  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1890  *
1891  * Local variables:
1892  * c-basic-offset: 8
1893  * tab-width: 8
1894  * indent-tabs-mode: t
1895  * End:
1896  *
1897  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1898  * :indentSize=8:tabSize=8:noTabs=false:
1899  */