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