1 /* packet-ismacryp.c
2  * ISMACryp 1.1 & 2.0 protocol as defined in ISMA Encryption and Authentication see http://www.isma.tv
3  *
4  * David Castleford, Orange Labs / France Telecom R&D
5  * March 2009
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
13 
14 /* 	TODO: get ISMACryp parameters automatically from SDP info,
15  *             if present (typically sent via SAP/SDP),
16  *             rather than having manual insertion via preferences
17  *	TODO: perhaps better check coherence of certain information?
18 */
19 #include "config.h"
20 
21 #include <epan/packet.h>
22 #include <epan/prefs.h>
23 
24 void proto_register_ismacryp(void);
25 void proto_reg_handoff_ismacryp(void);
26 
27 /* keeps track of current position in buffer in terms of bit and byte offset */
28 typedef struct Toffset_struct
29 {
30 	gint offset_bytes;
31 	guint8 offset_bits;
32 
33 } offset_struct;
34 
35 static void dissect_ismacryp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint ismacryp_version);
36 static offset_struct* dissect_auheader( tvbuff_t *tvb, offset_struct *poffset, packet_info *pinfo, proto_tree *tree, guint set_version );
37 static void add_bits(offset_struct* poffset, gint len_bits);
38 
39 #define PROTO_TAG_ISMACRYP	"ISMACRYP"
40 #define PROTO_TAG_ISMACRYP_11	"ISMACryp_11"
41 #define PROTO_TAG_ISMACRYP_20	"ISMACryp_20"
42 #define V11					11
43 #define V20					20
44 #define AAC_HBR_MODE				0
45 #define MPEG4_VIDEO_MODE			1
46 #define AVC_VIDEO_MODE				2
47 /* #define USERMODE				3 */
48 #define DEFAULT_SELECTIVE_ENCRYPTION		TRUE
49 #define DEFAULT_SLICE_INDICATION		FALSE
50 #define DEFAULT_PADDING_INDICATION		FALSE
51 #define DEFAULT_IV_LENGTH			4
52 #define DEFAULT_DELTA_IV_LENGTH			0
53 #define DEFAULT_KEY_INDICATOR_LENGTH		0
54 #define DEFAULT_KEY_INDICATOR_PER_AU		FALSE
55 #define AU_HEADERS_LENGTH_SIZE			2 /* size in bytes */
56 #define DEFAULT_AU_SIZE_LENGTH			0
57 #define DEFAULT_AU_INDEX_LENGTH			0
58 #define DEFAULT_AU_INDEX_DELTA_LENGTH		0
59 #define DEFAULT_CTS_DELTA_LENGTH		0
60 #define DEFAULT_DTS_DELTA_LENGTH		0
61 #define DEFAULT_RANDOM_ACCESS_INDICATION	FALSE
62 #define DEFAULT_STREAM_STATE_INDICATION		0
63 
64 /* Wireshark ID of the ISMACRYP protocol */
65 static int proto_ismacryp = -1;
66 static int proto_ismacryp_v11 = -1;
67 static int proto_ismacryp_v20 = -1;
68 
69 /* parameters set in preferences */
70 static range_t *pref_dynamic_payload_type_range = NULL; /* RTP dynamic payload types */
71 static guint    pref_au_size_length           = DEFAULT_AU_SIZE_LENGTH;            /* default Au size length */
72 static guint    pref_au_index_length          = DEFAULT_AU_INDEX_LENGTH;           /* default Au index length */
73 static guint    pref_au_index_delta_length    = DEFAULT_AU_INDEX_DELTA_LENGTH;     /* default Au index delta length */
74 static guint    pref_cts_delta_length         = DEFAULT_CTS_DELTA_LENGTH;          /* default CTS delta  length */
75 static guint    pref_dts_delta_length         = DEFAULT_DTS_DELTA_LENGTH;          /* default DTS delta  length */
76 static gboolean pref_random_access_indication = DEFAULT_RANDOM_ACCESS_INDICATION;  /* default random access indication */
77 static guint    pref_stream_state_indication  = DEFAULT_STREAM_STATE_INDICATION;   /* default stream state indication */
78 static guint    version_type                  = V11;                               /* default to ISMACryp 1.1 */
79 static guint    mode                          = AVC_VIDEO_MODE;                    /* default codec mode */
80 static gboolean selective_encryption          = DEFAULT_SELECTIVE_ENCRYPTION;      /* default selective encryption flag */
81 static gboolean slice_indication              = DEFAULT_SLICE_INDICATION;          /* default slice indication */
82 static gboolean padding_indication            = DEFAULT_PADDING_INDICATION;        /* default padding indication */
83 static guint    key_indicator_length          = DEFAULT_KEY_INDICATOR_LENGTH;      /* default key indicator length */
84 static gboolean key_indicator_per_au_flag     = DEFAULT_KEY_INDICATOR_PER_AU;      /* default key indicator per au */
85 static guint    iv_length                     = DEFAULT_IV_LENGTH;                 /* default IV length */
86 static guint    delta_iv_length               = DEFAULT_DELTA_IV_LENGTH;           /* default delta IV length */
87 static gboolean pref_user_mode                = FALSE; /* preference user mode instead of RFC3640 mode? */
88 static gboolean override_flag                 = FALSE; /* override use of RTP payload type to deduce ISMACryp version */
89 
90 /* */
91 
92 static guint    au_size_length                = DEFAULT_AU_SIZE_LENGTH;            /* default Au size length */
93 static guint    au_index_length               = DEFAULT_AU_INDEX_LENGTH;           /* default Au index length */
94 static guint    au_index_delta_length         = DEFAULT_AU_INDEX_DELTA_LENGTH;     /* default Au index delta length */
95 static guint    cts_delta_length              = DEFAULT_CTS_DELTA_LENGTH;          /* default CTS delta  length */
96 static guint    dts_delta_length              = DEFAULT_DTS_DELTA_LENGTH;          /* default DTS delta  length */
97 static gboolean random_access_indication      = DEFAULT_RANDOM_ACCESS_INDICATION;  /* default random access indication */
98 static guint    stream_state_indication       = DEFAULT_STREAM_STATE_INDICATION;   /* default stream state indication */
99 static gboolean user_mode                     = FALSE; /* selected user mode instead of RFC3640 mode? */
100 
101 /*static const value_string messagetypenames[] = {};	*/
102 
103 /* ismacryp Parameter Types */
104 /*static const value_string parametertypenames[] = {}; */
105 static const value_string modetypenames[] = {
106 	{ AAC_HBR_MODE,     "aac-hbr" },
107 	{ MPEG4_VIDEO_MODE, "mpeg4-video" },
108 	{ AVC_VIDEO_MODE,   "avc-video" },
109 	{ 0, NULL}
110 };
111 /* The following hf_* variables are used to hold the Wireshark IDs of
112 * our header fields; they are filled out when we call
113 * proto_register_field_array() in proto_register_ismacryp()
114 */
115 /** Kts attempt at defining the protocol */
116 /* static gint hf_ismacryp = -1; */
117 static gint hf_ismacryp_header = -1;
118 static gint hf_ismacryp_au_headers_length = -1;
119 /* static gint hf_ismacryp_header_length = -1; */
120 static gint hf_ismacryp_header_byte = -1;
121 /* static gint hf_ismacryp_version = -1; */
122 /* static gint hf_ismacryp_length = -1; */
123 /* static gint hf_ismacryp_message_type = -1; */
124 /* static gint hf_ismacryp_message_length = -1; */
125 static gint hf_ismacryp_message = -1;
126 /* static gint hf_ismacryp_parameter = -1; */
127 /* static gint hf_ismacryp_parameter_type = -1; */
128 /* static gint hf_ismacryp_parameter_length = -1; */
129 /* static gint hf_ismacryp_parameter_value = -1; */
130 static gint hf_ismacryp_iv = -1;
131 static gint hf_ismacryp_delta_iv = -1;
132 static gint hf_ismacryp_key_indicator = -1;
133 /* static gint hf_ismacryp_delta_iv_length = -1; */
134 static gint hf_ismacryp_au_size = -1;
135 static gint hf_ismacryp_au_index = -1;
136 static gint hf_ismacryp_au_index_delta = -1;
137 static gint hf_ismacryp_cts_delta = -1;
138 static gint hf_ismacryp_cts_flag = -1;
139 static gint hf_ismacryp_dts_flag = -1;
140 static gint hf_ismacryp_dts_delta = -1;
141 static gint hf_ismacryp_rap_flag = -1;
142 static gint hf_ismacryp_au_is_encrypted = -1;
143 static gint hf_ismacryp_slice_start = -1;
144 static gint hf_ismacryp_slice_end = -1;
145 static gint hf_ismacryp_padding_bitcount = -1;
146 static gint hf_ismacryp_padding = -1;
147 static gint hf_ismacryp_reserved_bits = -1;
148 static gint hf_ismacryp_unused_bits = -1;
149 static gint hf_ismacryp_stream_state = -1;
150 
151 /* These are the ids of the subtrees that we may be creating */
152 static gint ett_ismacryp = -1;
153 static gint ett_ismacryp_header = -1;
154 static gint ett_ismacryp_header_byte = -1;
155 static gint ett_ismacryp_message = -1;
156 
157 /* Informative tree structure is shown here:
158 * TREE 	-
159 *	AU Headers Length (2 bytes) - total length of AU header(s)
160 *	- HEADER1
161 *		HEADER BYTE (if present - 1 byte)
162 *			-AU_is_encrypted (1 bit)
163 *			-Slice_start (1 bit)
164 *			-Slice_end (1 bit)
165 *			-Padding_bitcount (3 bits)
166 *			-Reserved (2 bits)
167 *		IV (variable length)
168 *		Key Indicator (variable length)
169 *		AU size (if present - variable length)
170 *		AU index (if present - variable length)
171 *		CTS delta (if present - variable length)
172 *		DTS delta (if present - variable length)
173 *		RAP flag (if present - 1 bit)
174 *		Stream State Indication (if present - variable length)
175 *	- HEADER2 if 2nd header present (depends on AU headers length)
176 *		Header Byte (if present - 1 byte)
177 *			-AU_is_encrypted (1 bit)
178 *			-Slice_start (1 bit)
179 *			-Slice_end (1 bit)
180 *			-Padding_bitcount (3 bits)
181 *			-Reserved (2 bits)
182 *		IV (variable length)
183 *		Key Indicator (variable length)
184 *		AU size (if present - variable length)
185 *		AU index delta(if present - variable length)
186 *		CTS delta (if present - variable length)
187 *		DTS delta (if present - variable length)
188 *		RAP flag (if present - 1 bit)
189 *		Stream State Indication (if present - variable length)
190 *	- more HEADERS if present
191 *	- MESSAGE
192 *		encrypted AU
193 * End informative tree structure
194 */
195 
196 /* Note that check coherence of total AU headers length and that calculated from size of parameters defined by default or preferences.
197 * These are found in SDP and vary e.g. between audio and video and depend on ISMACryp encoding parameters
198 * hence if these values are incorrect displayed values will be strange and can see errors
199 * this could be improved of course
200 */
201 
202 /* dissect_ismacryp_v11 gets called if rtp_dyn_payload_type = "enc-mpeg4-generic" i.e. is set via SDP */
dissect_ismacryp_v11(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)203 static int dissect_ismacryp_v11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
204 {
205 	/* display ISMACryp version */
206 	col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_11);
207 
208 	/* display RTP payload type */
209 	col_set_str(pinfo->cinfo, COL_INFO, "(PT=enc-mpeg4-generic)");
210 
211 	dissect_ismacryp_common( tvb, pinfo, tree, V11);
212 	return tvb_captured_length(tvb);
213 }
214 
215 /* dissect_ismacryp_v20 gets called if rtp_dyn_payload_type = "enc-isoff-generic" i.e. is set via SDP */
dissect_ismacryp_v20(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)216 static int dissect_ismacryp_v20(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
217 {
218 	/* display ISMACryp version */
219 	col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_20);
220 
221 	/* display RTP payload type */
222 	col_set_str(pinfo->cinfo, COL_INFO, "(PT=enc-isoff-generic)");
223 
224 	dissect_ismacryp_common( tvb, pinfo, tree, V20);
225 	return tvb_captured_length(tvb);
226 }
227 
dissect_ismacryp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)228 static int dissect_ismacryp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
229 {
230 	col_set_str(pinfo->cinfo, COL_INFO, "Manual version");
231 	dissect_ismacryp_common( tvb, pinfo, tree, version_type);   /* Unknown version type: Use preference */
232 	return tvb_captured_length(tvb);
233 }
234 
dissect_ismacryp_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint ismacryp_version)235 static void dissect_ismacryp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint ismacryp_version)
236 {
237 	guint set_version;           /* ISMACryp version used during dissection */
238 	proto_item *ismacryp_item;
239 	proto_tree *ismacryp_tree;
240 	proto_tree *ismacryp_message_tree;
241 
242 	/* select and display ISMACryp version */
243 	if ((ismacryp_version != version_type) && override_flag) {
244 		/* override -> use manual preference setting */
245 		col_append_str(pinfo->cinfo, COL_INFO, " Manual version");
246 		set_version = version_type; /* set to preference value */
247 	}
248 	else {
249 		set_version = ismacryp_version;
250 	}
251 
252 	if (set_version == V11) {
253 		col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_11);
254 		/* display mode */
255 		if (pref_user_mode == FALSE) {
256 			col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(mode, modetypenames, "user mode"));
257 		} else {
258 			col_append_str(pinfo->cinfo, COL_INFO, ", user mode");
259 		}
260 		user_mode = pref_user_mode;
261 	}
262 	if (set_version == V20) {
263 		col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_20);
264 		user_mode = TRUE;
265 		/* display mode */
266 		col_append_str(pinfo->cinfo, COL_INFO, ", user mode");
267 	}
268 	/* select correct AU values depending on version & selected mode in preferences menu if not in user_mode */
269 	if (user_mode == TRUE) { /* use values set in preference menu */
270 		au_size_length = pref_au_size_length;
271 		au_index_length = pref_au_index_length;
272 		au_index_delta_length = pref_au_index_delta_length;
273 		cts_delta_length = pref_cts_delta_length;
274 		dts_delta_length = pref_dts_delta_length;
275 		random_access_indication = pref_random_access_indication;
276 		stream_state_indication = pref_stream_state_indication;
277 	} /* end if user_mode == TRUE */
278 	if (user_mode == FALSE) {
279 		switch (mode) {
280 			case AAC_HBR_MODE:
281 				au_size_length = 13;
282 				au_index_length = 3;
283 				au_index_delta_length = 3;
284 				cts_delta_length = 0;
285 				dts_delta_length = 0;
286 				random_access_indication = FALSE;
287 				stream_state_indication = 0;
288 				break;
289 			case MPEG4_VIDEO_MODE:
290 				au_size_length = 0;
291 				au_index_length = 0;
292 				au_index_delta_length = 0;
293 				cts_delta_length = 0;
294 				dts_delta_length = 22;
295 				random_access_indication = TRUE;
296 				stream_state_indication = 0;
297 				break;
298 			case AVC_VIDEO_MODE:
299 				au_size_length = 0;
300 				au_index_length = 0;
301 				au_index_delta_length = 0;
302 				cts_delta_length = 0;
303 				dts_delta_length = 22;
304 				random_access_indication = TRUE;
305 				stream_state_indication = 0;
306 				break;
307 			default:
308 				DISSECTOR_ASSERT_NOT_REACHED();
309 				break;
310 		} /* end switch */
311 	} /* end if user_mode == FALSE */
312 
313 	/* navigate through buffer */
314 	{
315 		guint16 au_headers_length;     /* total length of AU headers */
316 		guint16 totalbits;             /* keeps track of total number of AU header bits treated (used to determine end of AU headers) */
317 		int deltabits;                 /* keeps track of extra bits per AU header treated (used to determine end of AU headers ) */
318 		offset_struct s_offset;
319 		offset_struct* poffset;
320 		guint16 nbmessage_bytes;       /*nb of message data bytes */
321 		s_offset.offset_bytes = 0;     /* initialise byte offset */
322 		s_offset.offset_bits  = 0;     /* initialise bit offset */
323 		poffset = &s_offset;
324 
325 		ismacryp_item = proto_tree_add_item(tree, proto_ismacryp, tvb, 0, -1, ENC_NA);
326 		ismacryp_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp);
327 		proto_item_append_text(tree, ", %s", "ismacryp packet"); /* add text to tree */
328 
329 		/* ismacryp_tree analysis */
330 		/* get total length of AU headers (first 2 bytes) */
331 		proto_tree_add_item(ismacryp_tree, hf_ismacryp_au_headers_length,
332 						    tvb, poffset->offset_bytes, AU_HEADERS_LENGTH_SIZE, ENC_BIG_ENDIAN );
333 		au_headers_length = tvb_get_ntohs(tvb, poffset->offset_bytes); /* 2 byte au headers length */
334 		poffset->offset_bytes += AU_HEADERS_LENGTH_SIZE;
335 		/* ADD HEADER(S) BRANCH  */
336 
337 		/* AU Header loop */
338 		totalbits = (poffset->offset_bytes*8) + poffset->offset_bits;
339 		deltabits = 1;
340 		while( ((totalbits - 8*AU_HEADERS_LENGTH_SIZE)<au_headers_length) && deltabits != 0 ) /* subtract AU headers length bits*/
341 		{
342 			poffset = dissect_auheader( tvb, poffset, pinfo, ismacryp_tree, set_version);
343 			deltabits = (poffset->offset_bytes*8) + poffset->offset_bits - totalbits; /* if zero this means no actual AU header so exit while loop */
344 			totalbits += deltabits;
345 		}
346 		/* reached end of AU Header(s) */
347 		/* sanity check if actual total AU headers length in bits i.e. totalbits is */
348 		/*  the same as expected AU headers length from 2 bytes at start of buffer */
349 		if ( (totalbits - 8*AU_HEADERS_LENGTH_SIZE) != au_headers_length) /* something wrong */
350 		{
351 			proto_item_append_text(ismacryp_item,
352 					       " Error - expected total AU headers size (%d bits) "
353 					       "does not match calculated size (%d bits) - check parameters!",
354 					       au_headers_length, (totalbits - 8*AU_HEADERS_LENGTH_SIZE));
355 		}
356 		/* add padding if need to byte align */
357 		if (poffset->offset_bits != 0)
358 		{
359 			guint16 totalbit_offset;   /* total offset in bits*/
360 			int nbpadding_bits;        /* number of padding bits*/
361 			totalbit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
362 			nbpadding_bits = (8 - poffset->offset_bits); /* number of padding bits for byte alignment */
363 			ismacryp_item = proto_tree_add_bits_item(ismacryp_tree, hf_ismacryp_padding,
364 								 tvb, totalbit_offset, nbpadding_bits , ENC_BIG_ENDIAN); /* padding bits */
365 			proto_item_append_text(ismacryp_item, ": Length=%d bits", nbpadding_bits); /* add padding info */
366 			add_bits(poffset, nbpadding_bits);
367 		}
368 		/* ADD MESSAGE BRANCH  */
369 		ismacryp_item = proto_tree_add_item( ismacryp_tree, hf_ismacryp_message,
370 						     tvb, poffset->offset_bytes, -1, ENC_NA );
371 		ismacryp_message_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_message);
372 		proto_item_append_text(ismacryp_item, ", %s", "Encrypted data"); /* add text to Message tree */
373 		nbmessage_bytes = tvb_reported_length_remaining(tvb, poffset->offset_bytes);
374 		proto_item_append_text(ismacryp_item, ", Length= %d bytes", nbmessage_bytes ); /* add length of message */
375 
376 		/* ismacryp message tree analysis (encrypted AUs) */
377 		if (ismacryp_message_tree)
378 		{
379 			poffset->offset_bytes +=  nbmessage_bytes;	/* */
380 		}
381 	}
382 }
383 /* AU Header dissection */
dissect_auheader(tvbuff_t * tvb,offset_struct * poffset,packet_info * pinfo,proto_tree * ismacryp_tree,guint set_version)384 static offset_struct* dissect_auheader( tvbuff_t *tvb, offset_struct *poffset, packet_info *pinfo, proto_tree *ismacryp_tree, guint set_version )
385 {
386 	proto_item *ismacryp_item;
387 	proto_tree *ismacryp_header_tree;
388 	proto_tree *ismacryp_header_byte_tree;
389 
390 	guint16 header_len_bytes = 0; /* total length of non-first AU header in bytes (rounded up) */
391 	gint header_len = 0; /* length of AU headers in bits */
392 	gint cts_flag =0;
393 	gint dts_flag =0;
394 	gboolean first_au_flag = FALSE;
395 	gint bit_offset = 0;
396 
397 	/*first determine total AU header length */
398 	/* calculate each AU header length in bits first */
399 	switch (set_version) {
400 		case V11:
401 			if (selective_encryption)
402 				header_len += 8; /* add one byte to header length */
403 			break;
404 		case V20:
405 			if (selective_encryption || slice_indication || padding_indication)
406 				header_len += 8; /* add one byte to header length */
407 			break;
408 		default:
409 			DISSECTOR_ASSERT_NOT_REACHED();
410 			break;
411 	}	/* end switch */
412 	header_len += au_size_length; /* add au size length */
413 
414 	if (poffset->offset_bytes == AU_HEADERS_LENGTH_SIZE) {	/*first AU */
415 		header_len += 8*(iv_length);                      /* add IV length */
416 		header_len += 8*key_indicator_length;             /* add key indicator length */
417 		header_len += au_index_length;                    /* add AU index length */
418 		first_au_flag = TRUE;
419 	}
420 	else { /* not the first AU */
421 		if (key_indicator_per_au_flag == TRUE)
422 			header_len += 8*key_indicator_length; /* add key indicator length */
423 		header_len += 8*(delta_iv_length);                /* add delta IV length */
424 		header_len += au_index_delta_length;              /* add AU delta index length */
425 	}
426 	/* CTS flag is present? */
427 	if (cts_delta_length != 0) {    /* need to test whether cts_delta_flag is TRUE or FALSE */
428 		cts_flag = tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8 + header_len, 1); /*fetch 1 bit CTS flag  */
429 		header_len += 1;         /* add CTS flag bit */
430 		if (cts_flag == 1)
431 			header_len += cts_delta_length; /* add CTS delta length bits if CTS flag SET */
432 	}
433 	/* DTS flag is present? */
434 	if (dts_delta_length != 0) { /* need to test whether dts_delta_flag is TRUE or FALSE */
435 		dts_flag = tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8 + header_len, 1); /*fetch 1 bit DTS flag */
436 		header_len += 1;      /* add DTS flag bit */
437 		if (dts_flag == 1)
438 			header_len += dts_delta_length; /* add DTS delta length bits if DTS flag SET */
439 	}
440 	/* RAP flag present? */
441 	if (random_access_indication != FALSE)
442 		header_len += 1;      /* add 1 bit RAP flag */
443 
444 	/* stream state indication present */
445 	if (stream_state_indication !=0)
446 		header_len += stream_state_indication; /* add stream state indication bits */
447 
448 	/* convert header_len to bytes (rounded up) */
449 	if (header_len% 8 != 0)
450 	{
451 		header_len_bytes = ((header_len)/8) + 1; /*add 1 */
452 	}
453 	else
454 		header_len_bytes = ((header_len)/8);
455 
456 	/* add AU header tree  */
457 	ismacryp_item = proto_tree_add_item(ismacryp_tree, hf_ismacryp_header, tvb, poffset->offset_bytes, header_len_bytes, ENC_NA );
458 	proto_item_append_text(ismacryp_item, ": Length=%d bits", header_len); /* add text to Header tree indicating length */
459 	/* sanity check if actual AU header length is zero bits, which indicates an error */
460 	if ( header_len == 0) /* something wrong */
461 	{
462 		proto_item_append_text(ismacryp_item, " Error - zero bit AU header size - check parameters!");
463 	}
464 	ismacryp_header_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header);
465 
466 	/* ismacryp header analysis */
467 
468 	/* Extra 1 Byte Header? */
469 
470 	if ((set_version == V20 && (selective_encryption || slice_indication || padding_indication))
471 		|| (set_version == V11 && selective_encryption)) {
472 
473 		/* add  header byte tree	*/
474 		ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_header_byte,
475 						    tvb, poffset->offset_bytes, 1, ENC_NA );
476 		proto_item_append_text(ismacryp_item, ": Length=8 bits"); /* add text to Header byte tree indicating length */
477 		ismacryp_header_byte_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header_byte);
478 
479 		/*ismacryp_header_byte_tree */
480 		/* tvb is network order, so get MSB bits first, so shift 8 bits and work "backwards" */
481 		add_bits(poffset, 7);   /*shift 7 bits to get correct bit */
482 		/* AU_is_encrypted bit */
483 		bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
484 		if (selective_encryption) { /* bit used */
485 			proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_au_is_encrypted,
486 						 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit AU_is_encrypted */
487 		}
488 		else { /* bit unused */
489 			proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
490 						 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit unused */
491 		}
492 		switch (set_version) { /* ISMACryp version? */
493 			case V11:
494 				/* Reserved bits */
495 				add_bits(poffset, -7); /* move back 7 bits for reserved bits */
496 				bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
497 				proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits,
498 							 tvb, bit_offset, 7, ENC_BIG_ENDIAN); /*fetch 7 bits reserved */
499 				add_bits(poffset, 8);   /* offset to next byte */
500 				break;
501 			case V20:
502 				/* Slice_start bit */
503 				add_bits(poffset, -1); /* move back 1 bit for slice_start */
504 				bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
505 				if (slice_indication) {
506 					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_start,
507 								 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit slice_start */
508 				}
509 				else { /* bit unused */
510 					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
511 								 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit unused */
512 				}
513 				add_bits(poffset, -1); /* move back 1 bit for slice_end */
514 
515 				/* Slice_end bit */
516 				bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
517 				if (slice_indication) {
518 					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_end,
519 								 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit Slice_end */
520 				}
521 				else { /* bit unused */
522 					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
523 								 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /*fetch 1 bit unused */
524 				}
525 				add_bits(poffset, -3); /* move back 3 bits for padding_bitcount */
526 
527 				/* Padding_bitcount bits */
528 				bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
529 				if (padding_indication) {
530 					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_padding_bitcount,
531 								 tvb, bit_offset, 3, ENC_BIG_ENDIAN); /*fetch 3 bits padding_bitcount */
532 				}
533 				else { /* bits unused */
534 					proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
535 								 tvb, bit_offset, 3, ENC_BIG_ENDIAN); /*fetch 3 bits unused */
536 				}
537 				add_bits(poffset, -2); /* move back 2 bits for reserved bits */
538 
539 				/* Reserved bits */
540 				bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
541 				proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits,
542 							 tvb, bit_offset, 2, ENC_BIG_ENDIAN); /*fetch 2 bits reserved */
543 				add_bits(poffset, 8); /* offset to next byte */
544 				break;
545 			default:
546 				DISSECTOR_ASSERT_NOT_REACHED();
547 				break;
548 		} /* end switch set_version */
549 	} /* end selective encryption */
550 	/* IV */
551 	if (first_au_flag == TRUE && iv_length != 0)
552 	{
553 		ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_iv, tvb, poffset->offset_bytes, iv_length, ENC_NA);
554 		proto_item_append_text(ismacryp_item, ": Length=%d bytes", iv_length); /* add IV info */
555 		col_append_fstr( pinfo->cinfo, COL_INFO,
556 			", IV=0x%s", tvb_bytes_to_str_punct(pinfo->pool, tvb, poffset->offset_bytes, iv_length, ' '));
557 
558 		poffset->offset_bytes += iv_length; /* add IV length to offset_bytes */
559 	}
560 	/*Delta  IV */
561 	if (first_au_flag == FALSE && delta_iv_length != 0)
562 	{
563 		ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_delta_iv,
564 						    tvb, poffset->offset_bytes, delta_iv_length, ENC_NA);
565 		proto_item_append_text(ismacryp_item, ": Length=%d bytes", delta_iv_length); /* add delta IV info */
566 		col_append_fstr( pinfo->cinfo, COL_INFO,
567 			", Delta IV=0x%s", tvb_bytes_to_str_punct(pinfo->pool, tvb, poffset->offset_bytes, delta_iv_length, ' '));
568 		poffset->offset_bytes += delta_iv_length; /* add IV length to offset_bytes */
569 	}
570 	/* Key Indicator */
571 	if ( key_indicator_length != 0 && ( first_au_flag == TRUE || key_indicator_per_au_flag == TRUE) )
572 	{
573 		/* (first AU or KI for each AU) and non-zero KeyIndicator size */
574 		ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_key_indicator,
575 						    tvb, poffset->offset_bytes, key_indicator_length, ENC_NA);
576 		proto_item_append_text(ismacryp_item, ": Length=%d bytes", key_indicator_length); /* add KI info */
577 		col_append_fstr( pinfo->cinfo, COL_INFO,
578 					 ", KI=0x%s", tvb_bytes_to_str_punct(pinfo->pool, tvb, poffset->offset_bytes, key_indicator_length, ' '));
579 		poffset->offset_bytes += key_indicator_length; /* add KI length to offset_bytes */
580 	}
581 	/* AU size */
582 	if (au_size_length != 0) /* in bits */
583 	{
584 		bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
585 		ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_au_size,
586 							 tvb, bit_offset, au_size_length, ENC_BIG_ENDIAN);
587 		proto_item_append_text(ismacryp_item, " bytes: Length=%d bits", au_size_length); /* add AU size info */
588 		/*bit_offset += au_size_length;*/
589 		add_bits(poffset, au_size_length);
590 	}
591 	/* AU Index */
592 	if (first_au_flag == TRUE && au_index_length != 0) /* first AU and non-zero AU size */
593 	{
594 		bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
595 		ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_au_index,
596 							 tvb, bit_offset, au_index_length, ENC_BIG_ENDIAN);
597 		proto_item_append_text(ismacryp_item, " bits: Length=%d bits", au_index_length); /* add AU index info */
598 		/*bit_offset += au_index_length;*/
599 		add_bits(poffset, au_index_length);
600 	}
601 	/* AU index delta */
602 	if (first_au_flag == FALSE && au_index_delta_length != 0) /* not first AU and non-zero AU delta size */
603 	{
604 		bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
605 		ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_au_index_delta,
606 							 tvb, bit_offset, au_index_delta_length, ENC_BIG_ENDIAN);
607 		proto_item_append_text(ismacryp_item, ": Length=%d bits", au_index_delta_length); /* add AU index info */
608 		/*bit_offset += au_index_delta_length;*/
609 		add_bits(poffset, au_index_delta_length);
610 	}
611 	/* CTS delta value */
612 	if (cts_delta_length != 0)
613 	{
614 		bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
615 		proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_flag,
616 					 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /* read CTS flag */
617 		add_bits(poffset, 1);
618 		if (cts_flag == 1)
619 		{
620 			/* now fetch CTS delta value (remember offset 1 bit due to CTS flag) */
621 			bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
622 			ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_delta,
623 								 tvb, bit_offset, cts_delta_length, ENC_BIG_ENDIAN); /* read CTS delta value */
624 			proto_item_append_text(ismacryp_item, ": Length=%d bits", cts_delta_length); /* add CTS delta info */
625 			add_bits(poffset, cts_delta_length);
626 		}
627 	}
628 	/* DTS delta value */
629 	if (dts_delta_length != 0)
630 	{
631 		bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
632 		proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_flag,
633 					 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /* read DTS flag */
634 		add_bits(poffset, 1);
635 
636 		/* now fetch DTS delta value (remember offset x bits due to DTS flag) */
637 		if (dts_flag ==1)
638 		{
639 			bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
640 			ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_delta,
641 								 tvb, bit_offset, dts_delta_length, ENC_BIG_ENDIAN); /* read DTS delta value */
642 			proto_item_append_text(ismacryp_item, ": Length=%d bits", dts_delta_length); /* add DTS delta info */
643 			add_bits(poffset, dts_delta_length);
644 		}
645 	}
646 	/* RAP */
647 	if (random_access_indication != FALSE)
648 	{
649 		bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
650 		proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_rap_flag,
651 					 tvb, bit_offset, 1, ENC_BIG_ENDIAN); /* read RAP flag */
652 		add_bits(poffset, 1);
653 	}
654 	/*STREAM STATE */
655 	if (stream_state_indication != 0)
656 	{
657 		bit_offset = (poffset->offset_bytes)*8 + poffset->offset_bits; /* offset in bits */
658 		proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_stream_state,
659 					 tvb, bit_offset, stream_state_indication, ENC_BIG_ENDIAN); /* read stream state */
660 		add_bits(poffset, stream_state_indication);
661 	}
662 return poffset;
663 }
664 
665 /* add len_bits to offset bits and  bytes, handling bits overflow */
add_bits(offset_struct * poffset,gint len_bits)666 static void add_bits(offset_struct* poffset, gint len_bits)
667 {
668 	gint nbbitstotal;
669 	nbbitstotal = poffset->offset_bytes*8 + (poffset->offset_bits) + len_bits; /* total offset in bits */
670 	/* now calculate bytes and bit offsets */
671 	poffset->offset_bytes = (nbbitstotal / 8); /* add integer no. of bytes */
672 	poffset->offset_bits  = (nbbitstotal % 8); /* add remaining bits */
673 }
674 
proto_register_ismacryp(void)675 void proto_register_ismacryp (void)
676 {
677 	/* A header field is something you can search/filter on.
678 	*
679 	* We create a structure to register our fields. It consists of an
680 	* array of hf_register_info structures, each of which are of the format
681 	* {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
682 	*/
683 	static hf_register_info hf[] = {
684 #if 0
685 		{ &hf_ismacryp,
686 		  { "Data", "ismacryp.data", FT_NONE, BASE_NONE, NULL, 0x0,
687 		    NULL, HFILL }},
688 #endif
689 
690 #if 0
691 		{ &hf_ismacryp_length,
692 		  { "Total Length", "ismacryp.len", FT_UINT16, BASE_DEC, NULL, 0x0,	/* length 2 bytes, print as decimal value */
693 		    NULL, HFILL }},
694 #endif
695 
696 		{ &hf_ismacryp_header,
697 		  { "AU Header", "ismacryp.header", FT_NONE, BASE_NONE, NULL, 0x0,
698 		    NULL, HFILL }},
699 
700 #if 0
701 		{ &hf_ismacryp_header_length,
702 		  { "Header Length", "ismacryp.header.length", FT_UINT16, BASE_DEC, NULL, 0x0,
703 		    NULL, HFILL }},
704 #endif
705 
706 		{ &hf_ismacryp_au_headers_length,
707 		  { "AU Headers Length", "ismacryp.au_headers.length", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_bit_bits, 0x0,
708 		    NULL, HFILL }},
709 
710 		{ &hf_ismacryp_header_byte,
711 		  { "Header Byte", "ismacryp.header.byte", FT_NONE, BASE_NONE, NULL, 0x0, /* 1 byte */
712 		    NULL, HFILL }},
713 
714 #if 0
715 		{ &hf_ismacryp_version,
716 		  { "Version", "ismacryp.version", FT_UINT8, BASE_HEX, NULL, 0x0, 	/* version 1 byte */
717 		    NULL, HFILL }},
718 #endif
719 
720 		{ &hf_ismacryp_message,
721 		  { "Message", "ismacryp.message", FT_NONE, BASE_NONE, NULL, 0x0,
722 		    NULL, HFILL }},
723 
724 #if 0
725 		{ &hf_ismacryp_message_length,
726 		  { "Message Length", "ismacryp.message.len", FT_UINT16, BASE_DEC, NULL, 0x0,	/* length 2 bytes, print as decimal value */
727 		    NULL, HFILL }},
728 #endif
729 
730 #if 0
731 		{ &hf_ismacryp_parameter,
732 		  { "Parameter", "ismacryp.parameter", FT_NONE, BASE_NONE, NULL, 0x0,
733 		    NULL, HFILL }},
734 #endif
735 
736 #if 0
737 		{ &hf_ismacryp_parameter_length,
738 		  { "Parameter Length", "ismacryp.parameter.len", FT_UINT16, BASE_DEC, NULL, 0x0, /* length 2 bytes, print as decimal value */
739 		    NULL, HFILL }},
740 #endif
741 
742 		{ &hf_ismacryp_iv,
743 		  { "IV", "ismacryp.iv", FT_BYTES, BASE_NONE, NULL, 0x0, /* variable length */
744 		    NULL, HFILL }},
745 
746 		{ &hf_ismacryp_delta_iv,
747 		  { "Delta IV", "ismacryp.delta_iv", FT_BYTES, BASE_NONE, NULL, 0x0, /* variable length */
748 		    NULL, HFILL }},
749 
750 		{ &hf_ismacryp_key_indicator,
751 		  { "Key Indicator", "ismacryp.key_indicator", FT_BYTES, BASE_NONE, NULL, 0x0, /* variable length */
752 		    NULL, HFILL }},
753 
754 #if 0
755 		{ &hf_ismacryp_parameter_value,
756 		  { "Parameter Value", "ismacryp.parameter.value", FT_NONE, BASE_NONE, NULL, 0x0,
757 		    NULL, HFILL }},
758 #endif
759 
760 		{ &hf_ismacryp_au_size,
761 		  { "AU size", "ismacryp.au.size", FT_UINT64, BASE_DEC, NULL, 0x0,
762 		    NULL, HFILL }},
763 
764 		{ &hf_ismacryp_au_index,
765 		  { "AU index", "ismacryp.au.index", FT_UINT64, BASE_DEC, NULL, 0x0,
766 		    NULL, HFILL }},
767 
768 		{ &hf_ismacryp_au_index_delta,
769 		  { "AU index delta", "ismacryp.au.index_delta", FT_UINT64, BASE_DEC, NULL, 0x0,
770 		    NULL, HFILL }},
771 
772 		{ &hf_ismacryp_cts_delta,
773 		  { "CTS delta", "ismacryp.cts_delta", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
774 		    NULL, HFILL }},
775 
776 		{ &hf_ismacryp_cts_flag,
777 		  { "CTS flag", "ismacryp.cts_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
778 		    NULL, HFILL }},
779 
780 		{ &hf_ismacryp_dts_delta,
781 		  { "DTS delta", "ismacryp.dts_delta", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
782 		    NULL, HFILL }},
783 
784 		{ &hf_ismacryp_dts_flag,
785 		  { "DTS flag", "ismacryp.dts_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
786 		    NULL, HFILL }},
787 
788 		{ &hf_ismacryp_rap_flag,
789 		  { "RAP flag", "ismacryp.rap_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
790 		    NULL, HFILL }},
791 
792 		{ &hf_ismacryp_stream_state,
793 		  { "Stream state", "ismacryp.stream_state", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
794 		    NULL, HFILL }},
795 
796 		{ &hf_ismacryp_au_is_encrypted,
797 		  { "AU_is_encrypted flag", "ismacryp.au_is_encrypted", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
798 		    NULL, HFILL }},
799 
800 		{ &hf_ismacryp_slice_start,
801 		  { "Slice_start flag", "ismacryp.slice_start", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
802 		    NULL, HFILL }},
803 
804 		{ &hf_ismacryp_slice_end,
805 		  { "Slice_end flag", "ismacryp.slice_end", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
806 		    NULL, HFILL }},
807 
808 		{ &hf_ismacryp_padding_bitcount,
809 		  { "Padding_bitcount bits", "ismacryp.padding_bitcount", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
810 		    NULL, HFILL }},
811 
812 		{ &hf_ismacryp_padding,
813 		  { "Padding bits", "ismacryp.padding", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
814 		    NULL, HFILL }},
815 
816 		{ &hf_ismacryp_reserved_bits,
817 		  { "Reserved bits", "ismacryp.reserved", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
818 		    NULL, HFILL }},
819 
820 		{ &hf_ismacryp_unused_bits,
821 		  { "Unused bits", "ismacryp.unused", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
822 		    NULL, HFILL }}
823 	};
824 
825 	static gint *ett[] =
826 	{
827 		&ett_ismacryp,
828 		&ett_ismacryp_header,
829 		&ett_ismacryp_header_byte,
830 		&ett_ismacryp_message
831 	};
832 
833 	static const enum_val_t version_types[] = {
834 		{PROTO_TAG_ISMACRYP_11, "ISMACryp v1.1", V11},
835 		{PROTO_TAG_ISMACRYP_20, "ISMACryp v2.0", V20},
836 		{NULL, NULL, -1}
837 	};
838 
839 	static const enum_val_t mode_types[] = {
840 		{"aac-hbr", "aac-hbr", AAC_HBR_MODE},
841 		{"mpeg4-video", "mpeg4-video", MPEG4_VIDEO_MODE},
842 		{"avc-video", "avc-video", AVC_VIDEO_MODE},
843 		{NULL, NULL, -1}
844 	};
845 
846 	module_t *ismacryp_module;
847 
848 	proto_ismacryp = proto_register_protocol ("ISMACryp Protocol", "ISMACRYP", "ismacryp");
849 	proto_ismacryp_v11 = proto_register_protocol_in_name_only ("ISMACryp Protocol v1.1",
850 			"ISMACRYP 1.1", "ismacryp_v11", proto_ismacryp, FT_PROTOCOL);
851 	proto_ismacryp_v20 = proto_register_protocol_in_name_only ("ISMACryp Protocol v2.0",
852 			"ISMACRYP 2.0", "ismacryp_v20", proto_ismacryp, FT_PROTOCOL);
853 	proto_register_field_array (proto_ismacryp, hf, array_length (hf));
854 	proto_register_subtree_array (ett, array_length (ett));
855 
856 	/* Register our configuration options for ismacryp */
857 	/* this registers our preferences, function proto_reg_handoff_ismacryp is called when preferences are applied */
858 	ismacryp_module = prefs_register_protocol(proto_ismacryp, proto_reg_handoff_ismacryp);
859 
860 	prefs_register_range_preference(ismacryp_module, "dynamic.payload.type",
861 				   "ISMACryp dynamic payload types",
862 				   "Dynamic payload types which will be interpreted as ISMACryp"
863 				   "; values must be in the range 1 - 127",
864 				   &pref_dynamic_payload_type_range, 127);
865 
866 	prefs_register_enum_preference(ismacryp_module, "version",
867 					       "ISMACryp version",
868 					       "ISMACryp version",
869 					       &version_type, version_types, TRUE);
870 
871 	prefs_register_static_text_preference(ismacryp_module, "text_override",
872 					      "The following option allows the version to be set manually"
873 					      " and to override the version if detected from RTP payload type:",
874 					      "The following option allows the version to be set manually"
875 					      " and to override the version if detected from RTP payload type:");
876 
877 	prefs_register_bool_preference(ismacryp_module,
878 				       "override_rtp_pt", "Override RTP payload type for version",
879 				       "Indicates whether or not the ISMACryp version deduced"
880 				       " from RTP payload type, if present, is used or whether the"
881 				       " version above is used",
882 				       &override_flag);
883 
884 	/* ISMACryp v11 parameters */
885 	prefs_register_static_text_preference(ismacryp_module,
886 					      "v11_parameters",
887 					      "ISMACryp v1.1 parameters:",
888 					      "ISMACryp v1.1 parameters declared in SDP");
889 
890 	prefs_register_uint_preference(ismacryp_module,
891 				       "iv_length", "ISMACrypIVLength (bytes)",
892 				       "Set the length of the IV in the ISMACryp AU Header in bytes",
893 				       10, &iv_length);
894 
895 	prefs_register_uint_preference(ismacryp_module,
896 				       "delta_iv_length", "ISMACrypDeltaIVLength (bytes)",
897 				       "Set the length of the Delta IV in the ISMACryp AU Header in bytes",
898 				       10, &delta_iv_length);
899 
900 	prefs_register_uint_preference(ismacryp_module,
901 				       "key_indicator_length", "ISMACrypKeyIndicatorLength (bytes)",
902 				       "Set the length of the Key Indicator in the ISMACryp AU Header in bytes",
903 				       10, &key_indicator_length);
904 
905 	prefs_register_bool_preference(ismacryp_module,
906 				       "key_indicator_per_au_flag", "ISMACrypKeyIndicatorPerAU (T/F)",
907 				       "Indicates whether or not the Key Indicator is present in all AU Headers (T/F)",
908 				       &key_indicator_per_au_flag);
909 
910 	prefs_register_bool_preference(ismacryp_module,
911 				       "selective_encryption", "ISMACrypSelectiveEncryption (T/F)",
912 				       "Indicates whether or not selective encryption is enabled (T/F)",
913 				       &selective_encryption);
914 
915 	/* ISMACryp v20 parameters */
916 	prefs_register_static_text_preference(ismacryp_module,
917 					      "v20_parameters",
918 					      "ISMACryp v2.0 parameters:",
919 					      "ISMACryp v2.0 parameters declared in SDP");
920 
921 	prefs_register_bool_preference(ismacryp_module,
922 				       "slice_indication", "ISMACrypSliceIndication (T/F)",
923 				       "Indicates whether or not slice start / end is present (T/F)",
924 				       &slice_indication);
925 
926 	prefs_register_bool_preference(ismacryp_module,
927 				       "padding_indication", "ISMACrypPaddingIndication (T/F)",
928 				       "Indicates whether or not padding information is present (T/F)",
929 				       &padding_indication);
930 
931 	/* RFC3640 mode - ISMACryp v11 */
932 	prefs_register_static_text_preference(ismacryp_module,
933 					      "codec_modes",
934 					      "Codec mode selection (RFC3640 for ISMACryp v1.1 only):",
935 					      "AU parameters set according to RFC3640 mode or user defined");
936 
937 	prefs_register_enum_preference(ismacryp_module,
938 				       "rfc3640_mode",
939 				       "RFC3640 mode",
940 				       "RFC3640 mode",
941 				       &mode, mode_types, TRUE);
942 
943 	/* User defined mode */
944 	prefs_register_bool_preference(ismacryp_module,
945 				       "user_mode", "User mode (T/F)",
946 				       "Indicates use of user mode instead of RFC3640 modes (T/F)",
947 				       &pref_user_mode);
948 
949 	/* following preference values only used if user mode is selected above */
950 	prefs_register_static_text_preference(ismacryp_module,
951 					      "user_defined_modes",
952 					      "Following parameters only valid and used for user mode:",
953 					      "AU parameters defined by the user");
954 
955 	/* ideally would grey this out or disable this if in user mode */
956 	prefs_register_uint_preference(ismacryp_module,
957 				       "au_size_length", "User mode: SizeLength (bits)",
958 				       "Set the length of the AU size in the AU Header in bits",
959 				       10, &pref_au_size_length);
960 
961 	prefs_register_uint_preference(ismacryp_module,
962 				       "au_index_length", "User mode: IndexLength (bits)",
963 				       "Set the length of the AU index in the AU Header in bits",
964 				       10, &pref_au_index_length);
965 
966 	prefs_register_uint_preference(ismacryp_module,
967 				       "au_index_delta_length", "User mode: IndexDeltaLength (bits)",
968 				       "Set the length of the AU delta index in the AU Header in bits",
969 				       10, &pref_au_index_delta_length);
970 
971 	prefs_register_uint_preference(ismacryp_module,
972 				       "cts_delta_length", "User mode: CTSDeltaLength (bits)",
973 				       "Set the length of the CTS delta field in the AU Header in bits",
974 				       10, &pref_cts_delta_length);
975 
976 	prefs_register_uint_preference(ismacryp_module,
977 				       "dts_delta_length", "User mode: DTSDeltaLength (bits)",
978 				       "Set the length of the DTS delta field in the AU Header in bits",
979 				       10, &pref_dts_delta_length);
980 
981 	prefs_register_bool_preference(ismacryp_module,
982 				       "random_access_indication", "User mode: RandomAccessIndication (T/F)",
983 				       "Indicates whether or not the RAP field is present in the AU Header (T/F)",
984 				       &pref_random_access_indication);
985 
986 	prefs_register_uint_preference(ismacryp_module,
987 				       "stream_state_indication", "User mode: StreamStateIndication (number of bits)",
988 				       "Indicates the number of bits on which the stream state field is encoded"
989 				       " in the AU Header (bits)",
990 				       10, &pref_stream_state_indication);
991 
992 }
993 
proto_reg_handoff_ismacryp(void)994 void proto_reg_handoff_ismacryp(void)
995 {
996 	static gboolean ismacryp_prefs_initialized = FALSE;
997 	static dissector_handle_t ismacryp_handle;
998 	static range_t *dynamic_payload_type_range;
999 
1000 	if (!ismacryp_prefs_initialized) {
1001 		dissector_handle_t ismacryp_v11_handle;
1002 		dissector_handle_t ismacryp_v20_handle;
1003 		ismacryp_handle = create_dissector_handle(dissect_ismacryp, proto_ismacryp);
1004 		ismacryp_v11_handle = create_dissector_handle(dissect_ismacryp_v11, proto_ismacryp_v11);
1005 		ismacryp_v20_handle = create_dissector_handle(dissect_ismacryp_v20, proto_ismacryp_v20);
1006 		ismacryp_prefs_initialized = TRUE;
1007 		dissector_add_string("rtp_dyn_payload_type", "ISMACRYP", ismacryp_handle);
1008 		dissector_add_string("rtp_dyn_payload_type", "enc-mpeg4-generic", ismacryp_v11_handle);
1009 		dissector_add_string("rtp_dyn_payload_type", "enc-isoff-generic", ismacryp_v20_handle);
1010 	  }
1011 	else { /* ismacryp_prefs_initialized = TRUE */
1012 		/* delete existing association of ismacryp with payload_type */
1013 		dissector_delete_uint_range("rtp.pt", dynamic_payload_type_range, ismacryp_handle);
1014 		wmem_free(wmem_epan_scope(), dynamic_payload_type_range);
1015 	}
1016 	/* always do the following */
1017 	/* update payload_type to new value */
1018 	dynamic_payload_type_range = range_copy(wmem_epan_scope(), pref_dynamic_payload_type_range);
1019 	range_remove_value(wmem_epan_scope(), &dynamic_payload_type_range, 0);
1020 	dissector_add_uint_range("rtp.pt", dynamic_payload_type_range, ismacryp_handle);
1021 
1022 }
1023 
1024 /*
1025  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1026  *
1027  * Local variables:
1028  * c-basic-offset: 8
1029  * tab-width: 8
1030  * indent-tabs-mode: t
1031  * End:
1032  *
1033  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1034  * :indentSize=8:tabSize=8:noTabs=false:
1035  */
1036