2 * ISMACryp 1.1 & 2.0 protocol as defined in ISMA Encryption and Authentication see http://www.isma.tv
4 * David Castleford, Orange Labs / France Telecom R&D
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
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?
21 #include <epan/packet.h>
22 #include <epan/prefs.h>
23 #include <epan/unit_strings.h>
25 void proto_register_ismacryp(void);
26 void proto_reg_handoff_ismacryp(void);
28 static dissector_handle_t ismacryp_handle
;
29 static dissector_handle_t ismacryp_v11_handle
;
30 static dissector_handle_t ismacryp_v20_handle
;
32 /* keeps track of current position in buffer in terms of bit and byte offset */
33 typedef struct Toffset_struct
40 static void dissect_ismacryp_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned ismacryp_version
);
41 static offset_struct
* dissect_auheader( tvbuff_t
*tvb
, offset_struct
*poffset
, packet_info
*pinfo
, proto_tree
*tree
, unsigned set_version
);
42 static void add_bits(offset_struct
* poffset
, int len_bits
);
44 #define PROTO_TAG_ISMACRYP "ISMACRYP"
45 #define PROTO_TAG_ISMACRYP_11 "ISMACryp_11"
46 #define PROTO_TAG_ISMACRYP_20 "ISMACryp_20"
49 #define AAC_HBR_MODE 0
50 #define MPEG4_VIDEO_MODE 1
51 #define AVC_VIDEO_MODE 2
52 /* #define USERMODE 3 */
53 #define DEFAULT_SELECTIVE_ENCRYPTION true
54 #define DEFAULT_SLICE_INDICATION false
55 #define DEFAULT_PADDING_INDICATION false
56 #define DEFAULT_IV_LENGTH 4
57 #define DEFAULT_DELTA_IV_LENGTH 0
58 #define DEFAULT_KEY_INDICATOR_LENGTH 0
59 #define DEFAULT_KEY_INDICATOR_PER_AU false
60 #define AU_HEADERS_LENGTH_SIZE 2 /* size in bytes */
61 #define DEFAULT_AU_SIZE_LENGTH 0
62 #define DEFAULT_AU_INDEX_LENGTH 0
63 #define DEFAULT_AU_INDEX_DELTA_LENGTH 0
64 #define DEFAULT_CTS_DELTA_LENGTH 0
65 #define DEFAULT_DTS_DELTA_LENGTH 0
66 #define DEFAULT_RANDOM_ACCESS_INDICATION false
67 #define DEFAULT_STREAM_STATE_INDICATION 0
69 /* Wireshark ID of the ISMACRYP protocol */
70 static int proto_ismacryp
;
71 static int proto_ismacryp_v11
;
72 static int proto_ismacryp_v20
;
74 /* parameters set in preferences */
75 static unsigned pref_au_size_length
= DEFAULT_AU_SIZE_LENGTH
; /* default Au size length */
76 static unsigned pref_au_index_length
= DEFAULT_AU_INDEX_LENGTH
; /* default Au index length */
77 static unsigned pref_au_index_delta_length
= DEFAULT_AU_INDEX_DELTA_LENGTH
; /* default Au index delta length */
78 static unsigned pref_cts_delta_length
= DEFAULT_CTS_DELTA_LENGTH
; /* default CTS delta length */
79 static unsigned pref_dts_delta_length
= DEFAULT_DTS_DELTA_LENGTH
; /* default DTS delta length */
80 static bool pref_random_access_indication
= DEFAULT_RANDOM_ACCESS_INDICATION
; /* default random access indication */
81 static unsigned pref_stream_state_indication
= DEFAULT_STREAM_STATE_INDICATION
; /* default stream state indication */
82 static unsigned version_type
= V11
; /* default to ISMACryp 1.1 */
83 static unsigned mode
= AVC_VIDEO_MODE
; /* default codec mode */
84 static bool selective_encryption
= DEFAULT_SELECTIVE_ENCRYPTION
; /* default selective encryption flag */
85 static bool slice_indication
= DEFAULT_SLICE_INDICATION
; /* default slice indication */
86 static bool padding_indication
= DEFAULT_PADDING_INDICATION
; /* default padding indication */
87 static unsigned key_indicator_length
= DEFAULT_KEY_INDICATOR_LENGTH
; /* default key indicator length */
88 static bool key_indicator_per_au_flag
= DEFAULT_KEY_INDICATOR_PER_AU
; /* default key indicator per au */
89 static unsigned iv_length
= DEFAULT_IV_LENGTH
; /* default IV length */
90 static unsigned delta_iv_length
= DEFAULT_DELTA_IV_LENGTH
; /* default delta IV length */
91 static bool pref_user_mode
; /* preference user mode instead of RFC3640 mode? */
92 static bool override_flag
; /* override use of RTP payload type to deduce ISMACryp version */
96 static unsigned au_size_length
= DEFAULT_AU_SIZE_LENGTH
; /* default Au size length */
97 static unsigned au_index_length
= DEFAULT_AU_INDEX_LENGTH
; /* default Au index length */
98 static unsigned au_index_delta_length
= DEFAULT_AU_INDEX_DELTA_LENGTH
; /* default Au index delta length */
99 static unsigned cts_delta_length
= DEFAULT_CTS_DELTA_LENGTH
; /* default CTS delta length */
100 static unsigned dts_delta_length
= DEFAULT_DTS_DELTA_LENGTH
; /* default DTS delta length */
101 static bool random_access_indication
= DEFAULT_RANDOM_ACCESS_INDICATION
; /* default random access indication */
102 static unsigned stream_state_indication
= DEFAULT_STREAM_STATE_INDICATION
; /* default stream state indication */
103 static bool user_mode
; /* selected user mode instead of RFC3640 mode? */
105 /*static const value_string messagetypenames[] = {}; */
107 /* ismacryp Parameter Types */
108 /*static const value_string parametertypenames[] = {}; */
109 static const value_string modetypenames
[] = {
110 { AAC_HBR_MODE
, "aac-hbr" },
111 { MPEG4_VIDEO_MODE
, "mpeg4-video" },
112 { AVC_VIDEO_MODE
, "avc-video" },
115 /* The following hf_* variables are used to hold the Wireshark IDs of
116 * our header fields; they are filled out when we call
117 * proto_register_field_array() in proto_register_ismacryp()
119 /** Kts attempt at defining the protocol */
120 /* static int hf_ismacryp; */
121 static int hf_ismacryp_header
;
122 static int hf_ismacryp_au_headers_length
;
123 /* static int hf_ismacryp_header_length; */
124 static int hf_ismacryp_header_byte
;
125 /* static int hf_ismacryp_version; */
126 /* static int hf_ismacryp_length; */
127 /* static int hf_ismacryp_message_type; */
128 /* static int hf_ismacryp_message_length; */
129 static int hf_ismacryp_message
;
130 /* static int hf_ismacryp_parameter; */
131 /* static int hf_ismacryp_parameter_type; */
132 /* static int hf_ismacryp_parameter_length; */
133 /* static int hf_ismacryp_parameter_value; */
134 static int hf_ismacryp_iv
;
135 static int hf_ismacryp_delta_iv
;
136 static int hf_ismacryp_key_indicator
;
137 /* static int hf_ismacryp_delta_iv_length; */
138 static int hf_ismacryp_au_size
;
139 static int hf_ismacryp_au_index
;
140 static int hf_ismacryp_au_index_delta
;
141 static int hf_ismacryp_cts_delta
;
142 static int hf_ismacryp_cts_flag
;
143 static int hf_ismacryp_dts_flag
;
144 static int hf_ismacryp_dts_delta
;
145 static int hf_ismacryp_rap_flag
;
146 static int hf_ismacryp_au_is_encrypted
;
147 static int hf_ismacryp_slice_start
;
148 static int hf_ismacryp_slice_end
;
149 static int hf_ismacryp_padding_bitcount
;
150 static int hf_ismacryp_padding
;
151 static int hf_ismacryp_reserved_bits
;
152 static int hf_ismacryp_unused_bits
;
153 static int hf_ismacryp_stream_state
;
155 /* These are the ids of the subtrees that we may be creating */
156 static int ett_ismacryp
;
157 static int ett_ismacryp_header
;
158 static int ett_ismacryp_header_byte
;
159 static int ett_ismacryp_message
;
161 /* Informative tree structure is shown here:
163 * AU Headers Length (2 bytes) - total length of AU header(s)
165 * HEADER BYTE (if present - 1 byte)
166 * -AU_is_encrypted (1 bit)
167 * -Slice_start (1 bit)
169 * -Padding_bitcount (3 bits)
171 * IV (variable length)
172 * Key Indicator (variable length)
173 * AU size (if present - variable length)
174 * AU index (if present - variable length)
175 * CTS delta (if present - variable length)
176 * DTS delta (if present - variable length)
177 * RAP flag (if present - 1 bit)
178 * Stream State Indication (if present - variable length)
179 * - HEADER2 if 2nd header present (depends on AU headers length)
180 * Header Byte (if present - 1 byte)
181 * -AU_is_encrypted (1 bit)
182 * -Slice_start (1 bit)
184 * -Padding_bitcount (3 bits)
186 * IV (variable length)
187 * Key Indicator (variable length)
188 * AU size (if present - variable length)
189 * AU index delta(if present - variable length)
190 * CTS delta (if present - variable length)
191 * DTS delta (if present - variable length)
192 * RAP flag (if present - 1 bit)
193 * Stream State Indication (if present - variable length)
194 * - more HEADERS if present
197 * End informative tree structure
200 /* Note that check coherence of total AU headers length and that calculated from size of parameters defined by default or preferences.
201 * These are found in SDP and vary e.g. between audio and video and depend on ISMACryp encoding parameters
202 * hence if these values are incorrect displayed values will be strange and can see errors
203 * this could be improved of course
206 /* dissect_ismacryp_v11 gets called if rtp_dyn_payload_type = "enc-mpeg4-generic" i.e. is set via SDP */
207 static int dissect_ismacryp_v11(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
209 /* display ISMACryp version */
210 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PROTO_TAG_ISMACRYP_11
);
212 /* display RTP payload type */
213 col_set_str(pinfo
->cinfo
, COL_INFO
, "(PT=enc-mpeg4-generic)");
215 dissect_ismacryp_common( tvb
, pinfo
, tree
, V11
);
216 return tvb_captured_length(tvb
);
219 /* dissect_ismacryp_v20 gets called if rtp_dyn_payload_type = "enc-isoff-generic" i.e. is set via SDP */
220 static int dissect_ismacryp_v20(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
222 /* display ISMACryp version */
223 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PROTO_TAG_ISMACRYP_20
);
225 /* display RTP payload type */
226 col_set_str(pinfo
->cinfo
, COL_INFO
, "(PT=enc-isoff-generic)");
228 dissect_ismacryp_common( tvb
, pinfo
, tree
, V20
);
229 return tvb_captured_length(tvb
);
232 static int dissect_ismacryp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
234 col_set_str(pinfo
->cinfo
, COL_INFO
, "Manual version");
235 dissect_ismacryp_common( tvb
, pinfo
, tree
, version_type
); /* Unknown version type: Use preference */
236 return tvb_captured_length(tvb
);
239 static void dissect_ismacryp_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned ismacryp_version
)
241 unsigned set_version
; /* ISMACryp version used during dissection */
242 proto_item
*ismacryp_item
;
243 proto_tree
*ismacryp_tree
;
244 proto_tree
*ismacryp_message_tree
;
246 /* select and display ISMACryp version */
247 if ((ismacryp_version
!= version_type
) && override_flag
) {
248 /* override -> use manual preference setting */
249 col_append_str(pinfo
->cinfo
, COL_INFO
, " Manual version");
250 set_version
= version_type
; /* set to preference value */
253 set_version
= ismacryp_version
;
256 if (set_version
== V11
) {
257 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PROTO_TAG_ISMACRYP_11
);
259 if (pref_user_mode
== false) {
260 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", %s", val_to_str_const(mode
, modetypenames
, "user mode"));
262 col_append_str(pinfo
->cinfo
, COL_INFO
, ", user mode");
264 user_mode
= pref_user_mode
;
266 if (set_version
== V20
) {
267 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PROTO_TAG_ISMACRYP_20
);
270 col_append_str(pinfo
->cinfo
, COL_INFO
, ", user mode");
272 /* select correct AU values depending on version & selected mode in preferences menu if not in user_mode */
273 if (user_mode
== true) { /* use values set in preference menu */
274 au_size_length
= pref_au_size_length
;
275 au_index_length
= pref_au_index_length
;
276 au_index_delta_length
= pref_au_index_delta_length
;
277 cts_delta_length
= pref_cts_delta_length
;
278 dts_delta_length
= pref_dts_delta_length
;
279 random_access_indication
= pref_random_access_indication
;
280 stream_state_indication
= pref_stream_state_indication
;
281 } /* end if user_mode == true */
282 if (user_mode
== false) {
287 au_index_delta_length
= 3;
288 cts_delta_length
= 0;
289 dts_delta_length
= 0;
290 random_access_indication
= false;
291 stream_state_indication
= 0;
293 case MPEG4_VIDEO_MODE
:
296 au_index_delta_length
= 0;
297 cts_delta_length
= 0;
298 dts_delta_length
= 22;
299 random_access_indication
= true;
300 stream_state_indication
= 0;
305 au_index_delta_length
= 0;
306 cts_delta_length
= 0;
307 dts_delta_length
= 22;
308 random_access_indication
= true;
309 stream_state_indication
= 0;
312 DISSECTOR_ASSERT_NOT_REACHED();
315 } /* end if user_mode == false */
317 /* navigate through buffer */
319 uint16_t au_headers_length
; /* total length of AU headers */
320 uint16_t totalbits
; /* keeps track of total number of AU header bits treated (used to determine end of AU headers) */
321 int deltabits
; /* keeps track of extra bits per AU header treated (used to determine end of AU headers ) */
322 offset_struct s_offset
;
323 offset_struct
* poffset
;
324 uint16_t nbmessage_bytes
; /*nb of message data bytes */
325 s_offset
.offset_bytes
= 0; /* initialise byte offset */
326 s_offset
.offset_bits
= 0; /* initialise bit offset */
329 ismacryp_item
= proto_tree_add_item(tree
, proto_ismacryp
, tvb
, 0, -1, ENC_NA
);
330 ismacryp_tree
= proto_item_add_subtree(ismacryp_item
, ett_ismacryp
);
331 proto_item_append_text(tree
, ", %s", "ismacryp packet"); /* add text to tree */
333 /* ismacryp_tree analysis */
334 /* get total length of AU headers (first 2 bytes) */
335 proto_tree_add_item(ismacryp_tree
, hf_ismacryp_au_headers_length
,
336 tvb
, poffset
->offset_bytes
, AU_HEADERS_LENGTH_SIZE
, ENC_BIG_ENDIAN
);
337 au_headers_length
= tvb_get_ntohs(tvb
, poffset
->offset_bytes
); /* 2 byte au headers length */
338 poffset
->offset_bytes
+= AU_HEADERS_LENGTH_SIZE
;
339 /* ADD HEADER(S) BRANCH */
342 totalbits
= (poffset
->offset_bytes
*8) + poffset
->offset_bits
;
344 while( ((totalbits
- 8*AU_HEADERS_LENGTH_SIZE
)<au_headers_length
) && deltabits
!= 0 ) /* subtract AU headers length bits*/
346 poffset
= dissect_auheader( tvb
, poffset
, pinfo
, ismacryp_tree
, set_version
);
347 deltabits
= (poffset
->offset_bytes
*8) + poffset
->offset_bits
- totalbits
; /* if zero this means no actual AU header so exit while loop */
348 totalbits
+= deltabits
;
350 /* reached end of AU Header(s) */
351 /* sanity check if actual total AU headers length in bits i.e. totalbits is */
352 /* the same as expected AU headers length from 2 bytes at start of buffer */
353 if ( (totalbits
- 8*AU_HEADERS_LENGTH_SIZE
) != au_headers_length
) /* something wrong */
355 proto_item_append_text(ismacryp_item
,
356 " Error - expected total AU headers size (%d bits) "
357 "does not match calculated size (%d bits) - check parameters!",
358 au_headers_length
, (totalbits
- 8*AU_HEADERS_LENGTH_SIZE
));
360 /* add padding if need to byte align */
361 if (poffset
->offset_bits
!= 0)
363 uint16_t totalbit_offset
; /* total offset in bits*/
364 int nbpadding_bits
; /* number of padding bits*/
365 totalbit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
366 nbpadding_bits
= (8 - poffset
->offset_bits
); /* number of padding bits for byte alignment */
367 ismacryp_item
= proto_tree_add_bits_item(ismacryp_tree
, hf_ismacryp_padding
,
368 tvb
, totalbit_offset
, nbpadding_bits
, ENC_BIG_ENDIAN
); /* padding bits */
369 proto_item_append_text(ismacryp_item
, ": Length=%d bits", nbpadding_bits
); /* add padding info */
370 add_bits(poffset
, nbpadding_bits
);
372 /* ADD MESSAGE BRANCH */
373 ismacryp_item
= proto_tree_add_item( ismacryp_tree
, hf_ismacryp_message
,
374 tvb
, poffset
->offset_bytes
, -1, ENC_NA
);
375 ismacryp_message_tree
= proto_item_add_subtree(ismacryp_item
, ett_ismacryp_message
);
376 proto_item_append_text(ismacryp_item
, ", %s", "Encrypted data"); /* add text to Message tree */
377 nbmessage_bytes
= tvb_reported_length_remaining(tvb
, poffset
->offset_bytes
);
378 proto_item_append_text(ismacryp_item
, ", Length= %d bytes", nbmessage_bytes
); /* add length of message */
380 /* ismacryp message tree analysis (encrypted AUs) */
381 if (ismacryp_message_tree
)
383 poffset
->offset_bytes
+= nbmessage_bytes
; /* */
387 /* AU Header dissection */
388 static offset_struct
* dissect_auheader( tvbuff_t
*tvb
, offset_struct
*poffset
, packet_info
*pinfo
, proto_tree
*ismacryp_tree
, unsigned set_version
)
390 proto_item
*ismacryp_item
;
391 proto_tree
*ismacryp_header_tree
;
392 proto_tree
*ismacryp_header_byte_tree
;
394 uint16_t header_len_bytes
= 0; /* total length of non-first AU header in bytes (rounded up) */
395 int header_len
= 0; /* length of AU headers in bits */
398 bool first_au_flag
= false;
401 /*first determine total AU header length */
402 /* calculate each AU header length in bits first */
403 switch (set_version
) {
405 if (selective_encryption
)
406 header_len
+= 8; /* add one byte to header length */
409 if (selective_encryption
|| slice_indication
|| padding_indication
)
410 header_len
+= 8; /* add one byte to header length */
413 DISSECTOR_ASSERT_NOT_REACHED();
416 header_len
+= au_size_length
; /* add au size length */
418 if (poffset
->offset_bytes
== AU_HEADERS_LENGTH_SIZE
) { /*first AU */
419 header_len
+= 8*(iv_length
); /* add IV length */
420 header_len
+= 8*key_indicator_length
; /* add key indicator length */
421 header_len
+= au_index_length
; /* add AU index length */
422 first_au_flag
= true;
424 else { /* not the first AU */
425 if (key_indicator_per_au_flag
== true)
426 header_len
+= 8*key_indicator_length
; /* add key indicator length */
427 header_len
+= 8*(delta_iv_length
); /* add delta IV length */
428 header_len
+= au_index_delta_length
; /* add AU delta index length */
430 /* CTS flag is present? */
431 if (cts_delta_length
!= 0) { /* need to test whether cts_delta_flag is true or false */
432 cts_flag
= tvb_get_bits8(tvb
, AU_HEADERS_LENGTH_SIZE
*8 + header_len
, 1); /*fetch 1 bit CTS flag */
433 header_len
+= 1; /* add CTS flag bit */
435 header_len
+= cts_delta_length
; /* add CTS delta length bits if CTS flag SET */
437 /* DTS flag is present? */
438 if (dts_delta_length
!= 0) { /* need to test whether dts_delta_flag is true or false */
439 dts_flag
= tvb_get_bits8(tvb
, AU_HEADERS_LENGTH_SIZE
*8 + header_len
, 1); /*fetch 1 bit DTS flag */
440 header_len
+= 1; /* add DTS flag bit */
442 header_len
+= dts_delta_length
; /* add DTS delta length bits if DTS flag SET */
444 /* RAP flag present? */
445 if (random_access_indication
!= false)
446 header_len
+= 1; /* add 1 bit RAP flag */
448 /* stream state indication present */
449 if (stream_state_indication
!=0)
450 header_len
+= stream_state_indication
; /* add stream state indication bits */
452 /* convert header_len to bytes (rounded up) */
453 if (header_len
% 8 != 0)
455 header_len_bytes
= ((header_len
)/8) + 1; /*add 1 */
458 header_len_bytes
= ((header_len
)/8);
460 /* add AU header tree */
461 ismacryp_item
= proto_tree_add_item(ismacryp_tree
, hf_ismacryp_header
, tvb
, poffset
->offset_bytes
, header_len_bytes
, ENC_NA
);
462 proto_item_append_text(ismacryp_item
, ": Length=%d bits", header_len
); /* add text to Header tree indicating length */
463 /* sanity check if actual AU header length is zero bits, which indicates an error */
464 if ( header_len
== 0) /* something wrong */
466 proto_item_append_text(ismacryp_item
, " Error - zero bit AU header size - check parameters!");
468 ismacryp_header_tree
= proto_item_add_subtree(ismacryp_item
, ett_ismacryp_header
);
470 /* ismacryp header analysis */
472 /* Extra 1 Byte Header? */
474 if ((set_version
== V20
&& (selective_encryption
|| slice_indication
|| padding_indication
))
475 || (set_version
== V11
&& selective_encryption
)) {
477 /* add header byte tree */
478 ismacryp_item
= proto_tree_add_item(ismacryp_header_tree
, hf_ismacryp_header_byte
,
479 tvb
, poffset
->offset_bytes
, 1, ENC_NA
);
480 proto_item_append_text(ismacryp_item
, ": Length=8 bits"); /* add text to Header byte tree indicating length */
481 ismacryp_header_byte_tree
= proto_item_add_subtree(ismacryp_item
, ett_ismacryp_header_byte
);
483 /*ismacryp_header_byte_tree */
484 /* tvb is network order, so get MSB bits first, so shift 8 bits and work "backwards" */
485 add_bits(poffset
, 7); /*shift 7 bits to get correct bit */
486 /* AU_is_encrypted bit */
487 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
488 if (selective_encryption
) { /* bit used */
489 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_au_is_encrypted
,
490 tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
); /*fetch 1 bit AU_is_encrypted */
492 else { /* bit unused */
493 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_unused_bits
,
494 tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
); /*fetch 1 bit unused */
496 switch (set_version
) { /* ISMACryp version? */
499 add_bits(poffset
, -7); /* move back 7 bits for reserved bits */
500 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
501 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_reserved_bits
,
502 tvb
, bit_offset
, 7, ENC_BIG_ENDIAN
); /*fetch 7 bits reserved */
503 add_bits(poffset
, 8); /* offset to next byte */
506 /* Slice_start bit */
507 add_bits(poffset
, -1); /* move back 1 bit for slice_start */
508 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
509 if (slice_indication
) {
510 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_slice_start
,
511 tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
); /*fetch 1 bit slice_start */
513 else { /* bit unused */
514 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_unused_bits
,
515 tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
); /*fetch 1 bit unused */
517 add_bits(poffset
, -1); /* move back 1 bit for slice_end */
520 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
521 if (slice_indication
) {
522 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_slice_end
,
523 tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
); /*fetch 1 bit Slice_end */
525 else { /* bit unused */
526 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_unused_bits
,
527 tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
); /*fetch 1 bit unused */
529 add_bits(poffset
, -3); /* move back 3 bits for padding_bitcount */
531 /* Padding_bitcount bits */
532 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
533 if (padding_indication
) {
534 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_padding_bitcount
,
535 tvb
, bit_offset
, 3, ENC_BIG_ENDIAN
); /*fetch 3 bits padding_bitcount */
537 else { /* bits unused */
538 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_unused_bits
,
539 tvb
, bit_offset
, 3, ENC_BIG_ENDIAN
); /*fetch 3 bits unused */
541 add_bits(poffset
, -2); /* move back 2 bits for reserved bits */
544 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
545 proto_tree_add_bits_item(ismacryp_header_byte_tree
, hf_ismacryp_reserved_bits
,
546 tvb
, bit_offset
, 2, ENC_BIG_ENDIAN
); /*fetch 2 bits reserved */
547 add_bits(poffset
, 8); /* offset to next byte */
550 DISSECTOR_ASSERT_NOT_REACHED();
552 } /* end switch set_version */
553 } /* end selective encryption */
555 if (first_au_flag
== true && iv_length
!= 0)
557 ismacryp_item
= proto_tree_add_item(ismacryp_header_tree
, hf_ismacryp_iv
, tvb
, poffset
->offset_bytes
, iv_length
, ENC_NA
);
558 proto_item_append_text(ismacryp_item
, ": Length=%d bytes", iv_length
); /* add IV info */
559 col_append_fstr( pinfo
->cinfo
, COL_INFO
,
560 ", IV=0x%s", tvb_bytes_to_str_punct(pinfo
->pool
, tvb
, poffset
->offset_bytes
, iv_length
, ' '));
562 poffset
->offset_bytes
+= iv_length
; /* add IV length to offset_bytes */
565 if (first_au_flag
== false && delta_iv_length
!= 0)
567 ismacryp_item
= proto_tree_add_item(ismacryp_header_tree
, hf_ismacryp_delta_iv
,
568 tvb
, poffset
->offset_bytes
, delta_iv_length
, ENC_NA
);
569 proto_item_append_text(ismacryp_item
, ": Length=%d bytes", delta_iv_length
); /* add delta IV info */
570 col_append_fstr( pinfo
->cinfo
, COL_INFO
,
571 ", Delta IV=0x%s", tvb_bytes_to_str_punct(pinfo
->pool
, tvb
, poffset
->offset_bytes
, delta_iv_length
, ' '));
572 poffset
->offset_bytes
+= delta_iv_length
; /* add IV length to offset_bytes */
575 if ( key_indicator_length
!= 0 && ( first_au_flag
== true || key_indicator_per_au_flag
== true) )
577 /* (first AU or KI for each AU) and non-zero KeyIndicator size */
578 ismacryp_item
= proto_tree_add_item(ismacryp_header_tree
, hf_ismacryp_key_indicator
,
579 tvb
, poffset
->offset_bytes
, key_indicator_length
, ENC_NA
);
580 proto_item_append_text(ismacryp_item
, ": Length=%d bytes", key_indicator_length
); /* add KI info */
581 col_append_fstr( pinfo
->cinfo
, COL_INFO
,
582 ", KI=0x%s", tvb_bytes_to_str_punct(pinfo
->pool
, tvb
, poffset
->offset_bytes
, key_indicator_length
, ' '));
583 poffset
->offset_bytes
+= key_indicator_length
; /* add KI length to offset_bytes */
586 if (au_size_length
!= 0) /* in bits */
588 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
589 ismacryp_item
= proto_tree_add_bits_item(ismacryp_header_tree
, hf_ismacryp_au_size
,
590 tvb
, bit_offset
, au_size_length
, ENC_BIG_ENDIAN
);
591 proto_item_append_text(ismacryp_item
, " bytes: Length=%d bits", au_size_length
); /* add AU size info */
592 /*bit_offset += au_size_length;*/
593 add_bits(poffset
, au_size_length
);
596 if (first_au_flag
== true && au_index_length
!= 0) /* first AU and non-zero AU size */
598 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
599 ismacryp_item
= proto_tree_add_bits_item(ismacryp_header_tree
, hf_ismacryp_au_index
,
600 tvb
, bit_offset
, au_index_length
, ENC_BIG_ENDIAN
);
601 proto_item_append_text(ismacryp_item
, " bits: Length=%d bits", au_index_length
); /* add AU index info */
602 /*bit_offset += au_index_length;*/
603 add_bits(poffset
, au_index_length
);
606 if (first_au_flag
== false && au_index_delta_length
!= 0) /* not first AU and non-zero AU delta size */
608 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
609 ismacryp_item
= proto_tree_add_bits_item(ismacryp_header_tree
, hf_ismacryp_au_index_delta
,
610 tvb
, bit_offset
, au_index_delta_length
, ENC_BIG_ENDIAN
);
611 proto_item_append_text(ismacryp_item
, ": Length=%d bits", au_index_delta_length
); /* add AU index info */
612 /*bit_offset += au_index_delta_length;*/
613 add_bits(poffset
, au_index_delta_length
);
615 /* CTS delta value */
616 if (cts_delta_length
!= 0)
618 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
619 proto_tree_add_bits_item(ismacryp_header_tree
, hf_ismacryp_cts_flag
,
620 tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
); /* read CTS flag */
621 add_bits(poffset
, 1);
624 /* now fetch CTS delta value (remember offset 1 bit due to CTS flag) */
625 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
626 ismacryp_item
= proto_tree_add_bits_item(ismacryp_header_tree
, hf_ismacryp_cts_delta
,
627 tvb
, bit_offset
, cts_delta_length
, ENC_BIG_ENDIAN
); /* read CTS delta value */
628 proto_item_append_text(ismacryp_item
, ": Length=%d bits", cts_delta_length
); /* add CTS delta info */
629 add_bits(poffset
, cts_delta_length
);
632 /* DTS delta value */
633 if (dts_delta_length
!= 0)
635 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
636 proto_tree_add_bits_item(ismacryp_header_tree
, hf_ismacryp_dts_flag
,
637 tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
); /* read DTS flag */
638 add_bits(poffset
, 1);
640 /* now fetch DTS delta value (remember offset x bits due to DTS flag) */
643 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
644 ismacryp_item
= proto_tree_add_bits_item(ismacryp_header_tree
, hf_ismacryp_dts_delta
,
645 tvb
, bit_offset
, dts_delta_length
, ENC_BIG_ENDIAN
); /* read DTS delta value */
646 proto_item_append_text(ismacryp_item
, ": Length=%d bits", dts_delta_length
); /* add DTS delta info */
647 add_bits(poffset
, dts_delta_length
);
651 if (random_access_indication
!= false)
653 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
654 proto_tree_add_bits_item(ismacryp_header_tree
, hf_ismacryp_rap_flag
,
655 tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
); /* read RAP flag */
656 add_bits(poffset
, 1);
659 if (stream_state_indication
!= 0)
661 bit_offset
= (poffset
->offset_bytes
)*8 + poffset
->offset_bits
; /* offset in bits */
662 proto_tree_add_bits_item(ismacryp_header_tree
, hf_ismacryp_stream_state
,
663 tvb
, bit_offset
, stream_state_indication
, ENC_BIG_ENDIAN
); /* read stream state */
664 add_bits(poffset
, stream_state_indication
);
669 /* add len_bits to offset bits and bytes, handling bits overflow */
670 static void add_bits(offset_struct
* poffset
, int len_bits
)
673 nbbitstotal
= poffset
->offset_bytes
*8 + (poffset
->offset_bits
) + len_bits
; /* total offset in bits */
674 /* now calculate bytes and bit offsets */
675 poffset
->offset_bytes
= (nbbitstotal
/ 8); /* add integer no. of bytes */
676 poffset
->offset_bits
= (nbbitstotal
% 8); /* add remaining bits */
679 void proto_register_ismacryp (void)
681 /* A header field is something you can search/filter on.
683 * We create a structure to register our fields. It consists of an
684 * array of hf_register_info structures, each of which are of the format
685 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
687 static hf_register_info hf
[] = {
690 { "Data", "ismacryp.data", FT_NONE
, BASE_NONE
, NULL
, 0x0,
695 { &hf_ismacryp_length
,
696 { "Total Length", "ismacryp.len", FT_UINT16
, BASE_DEC
, NULL
, 0x0, /* length 2 bytes, print as decimal value */
700 { &hf_ismacryp_header
,
701 { "AU Header", "ismacryp.header", FT_NONE
, BASE_NONE
, NULL
, 0x0,
705 { &hf_ismacryp_header_length
,
706 { "Header Length", "ismacryp.header.length", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
710 { &hf_ismacryp_au_headers_length
,
711 { "AU Headers Length", "ismacryp.au_headers.length", FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_bit_bits
), 0x0,
714 { &hf_ismacryp_header_byte
,
715 { "Header Byte", "ismacryp.header.byte", FT_NONE
, BASE_NONE
, NULL
, 0x0, /* 1 byte */
719 { &hf_ismacryp_version
,
720 { "Version", "ismacryp.version", FT_UINT8
, BASE_HEX
, NULL
, 0x0, /* version 1 byte */
724 { &hf_ismacryp_message
,
725 { "Message", "ismacryp.message", FT_NONE
, BASE_NONE
, NULL
, 0x0,
729 { &hf_ismacryp_message_length
,
730 { "Message Length", "ismacryp.message.len", FT_UINT16
, BASE_DEC
, NULL
, 0x0, /* length 2 bytes, print as decimal value */
735 { &hf_ismacryp_parameter
,
736 { "Parameter", "ismacryp.parameter", FT_NONE
, BASE_NONE
, NULL
, 0x0,
741 { &hf_ismacryp_parameter_length
,
742 { "Parameter Length", "ismacryp.parameter.len", FT_UINT16
, BASE_DEC
, NULL
, 0x0, /* length 2 bytes, print as decimal value */
747 { "IV", "ismacryp.iv", FT_BYTES
, BASE_NONE
, NULL
, 0x0, /* variable length */
750 { &hf_ismacryp_delta_iv
,
751 { "Delta IV", "ismacryp.delta_iv", FT_BYTES
, BASE_NONE
, NULL
, 0x0, /* variable length */
754 { &hf_ismacryp_key_indicator
,
755 { "Key Indicator", "ismacryp.key_indicator", FT_BYTES
, BASE_NONE
, NULL
, 0x0, /* variable length */
759 { &hf_ismacryp_parameter_value
,
760 { "Parameter Value", "ismacryp.parameter.value", FT_NONE
, BASE_NONE
, NULL
, 0x0,
764 { &hf_ismacryp_au_size
,
765 { "AU size", "ismacryp.au.size", FT_UINT64
, BASE_DEC
, NULL
, 0x0,
768 { &hf_ismacryp_au_index
,
769 { "AU index", "ismacryp.au.index", FT_UINT64
, BASE_DEC
, NULL
, 0x0,
772 { &hf_ismacryp_au_index_delta
,
773 { "AU index delta", "ismacryp.au.index_delta", FT_UINT64
, BASE_DEC
, NULL
, 0x0,
776 { &hf_ismacryp_cts_delta
,
777 { "CTS delta", "ismacryp.cts_delta", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
780 { &hf_ismacryp_cts_flag
,
781 { "CTS flag", "ismacryp.cts_flag", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
784 { &hf_ismacryp_dts_delta
,
785 { "DTS delta", "ismacryp.dts_delta", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
788 { &hf_ismacryp_dts_flag
,
789 { "DTS flag", "ismacryp.dts_flag", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
792 { &hf_ismacryp_rap_flag
,
793 { "RAP flag", "ismacryp.rap_flag", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
796 { &hf_ismacryp_stream_state
,
797 { "Stream state", "ismacryp.stream_state", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
800 { &hf_ismacryp_au_is_encrypted
,
801 { "AU_is_encrypted flag", "ismacryp.au_is_encrypted", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
804 { &hf_ismacryp_slice_start
,
805 { "Slice_start flag", "ismacryp.slice_start", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
808 { &hf_ismacryp_slice_end
,
809 { "Slice_end flag", "ismacryp.slice_end", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
812 { &hf_ismacryp_padding_bitcount
,
813 { "Padding_bitcount bits", "ismacryp.padding_bitcount", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
816 { &hf_ismacryp_padding
,
817 { "Padding bits", "ismacryp.padding", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
820 { &hf_ismacryp_reserved_bits
,
821 { "Reserved bits", "ismacryp.reserved", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
824 { &hf_ismacryp_unused_bits
,
825 { "Unused bits", "ismacryp.unused", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
832 &ett_ismacryp_header
,
833 &ett_ismacryp_header_byte
,
834 &ett_ismacryp_message
837 static const enum_val_t version_types
[] = {
838 {PROTO_TAG_ISMACRYP_11
, "ISMACryp v1.1", V11
},
839 {PROTO_TAG_ISMACRYP_20
, "ISMACryp v2.0", V20
},
843 static const enum_val_t mode_types
[] = {
844 {"aac-hbr", "aac-hbr", AAC_HBR_MODE
},
845 {"mpeg4-video", "mpeg4-video", MPEG4_VIDEO_MODE
},
846 {"avc-video", "avc-video", AVC_VIDEO_MODE
},
850 module_t
*ismacryp_module
;
852 proto_ismacryp
= proto_register_protocol ("ISMACryp Protocol", "ISMACRYP", "ismacryp");
853 proto_ismacryp_v11
= proto_register_protocol_in_name_only ("ISMACryp Protocol v1.1",
854 "ISMACRYP 1.1", "ismacryp_v11", proto_ismacryp
, FT_PROTOCOL
);
855 proto_ismacryp_v20
= proto_register_protocol_in_name_only ("ISMACryp Protocol v2.0",
856 "ISMACRYP 2.0", "ismacryp_v20", proto_ismacryp
, FT_PROTOCOL
);
857 proto_register_field_array (proto_ismacryp
, hf
, array_length (hf
));
858 proto_register_subtree_array (ett
, array_length (ett
));
860 ismacryp_handle
= register_dissector("ismacryp", dissect_ismacryp
, proto_ismacryp
);
861 ismacryp_v11_handle
= register_dissector("ismacryp_v11", dissect_ismacryp_v11
, proto_ismacryp_v11
);
862 ismacryp_v20_handle
= register_dissector("ismacryp_v20", dissect_ismacryp_v20
, proto_ismacryp_v20
);
864 /* Register our configuration options for ismacryp */
865 ismacryp_module
= prefs_register_protocol(proto_ismacryp
, NULL
);
867 prefs_register_obsolete_preference(ismacryp_module
, "dynamic.payload.type");
869 prefs_register_enum_preference(ismacryp_module
, "version",
872 &version_type
, version_types
, true);
874 prefs_register_static_text_preference(ismacryp_module
, "text_override",
875 "The following option allows the version to be set manually"
876 " and to override the version if detected from RTP payload type:",
877 "The following option allows the version to be set manually"
878 " and to override the version if detected from RTP payload type:");
880 prefs_register_bool_preference(ismacryp_module
,
881 "override_rtp_pt", "Override RTP payload type for version",
882 "Indicates whether or not the ISMACryp version deduced"
883 " from RTP payload type, if present, is used or whether the"
884 " version above is used",
887 /* ISMACryp v11 parameters */
888 prefs_register_static_text_preference(ismacryp_module
,
890 "ISMACryp v1.1 parameters:",
891 "ISMACryp v1.1 parameters declared in SDP");
893 prefs_register_uint_preference(ismacryp_module
,
894 "iv_length", "ISMACrypIVLength (bytes)",
895 "Set the length of the IV in the ISMACryp AU Header in bytes",
898 prefs_register_uint_preference(ismacryp_module
,
899 "delta_iv_length", "ISMACrypDeltaIVLength (bytes)",
900 "Set the length of the Delta IV in the ISMACryp AU Header in bytes",
901 10, &delta_iv_length
);
903 prefs_register_uint_preference(ismacryp_module
,
904 "key_indicator_length", "ISMACrypKeyIndicatorLength (bytes)",
905 "Set the length of the Key Indicator in the ISMACryp AU Header in bytes",
906 10, &key_indicator_length
);
908 prefs_register_bool_preference(ismacryp_module
,
909 "key_indicator_per_au_flag", "ISMACrypKeyIndicatorPerAU (T/F)",
910 "Indicates whether or not the Key Indicator is present in all AU Headers (T/F)",
911 &key_indicator_per_au_flag
);
913 prefs_register_bool_preference(ismacryp_module
,
914 "selective_encryption", "ISMACrypSelectiveEncryption (T/F)",
915 "Indicates whether or not selective encryption is enabled (T/F)",
916 &selective_encryption
);
918 /* ISMACryp v20 parameters */
919 prefs_register_static_text_preference(ismacryp_module
,
921 "ISMACryp v2.0 parameters:",
922 "ISMACryp v2.0 parameters declared in SDP");
924 prefs_register_bool_preference(ismacryp_module
,
925 "slice_indication", "ISMACrypSliceIndication (T/F)",
926 "Indicates whether or not slice start / end is present (T/F)",
929 prefs_register_bool_preference(ismacryp_module
,
930 "padding_indication", "ISMACrypPaddingIndication (T/F)",
931 "Indicates whether or not padding information is present (T/F)",
932 &padding_indication
);
934 /* RFC3640 mode - ISMACryp v11 */
935 prefs_register_static_text_preference(ismacryp_module
,
937 "Codec mode selection (RFC3640 for ISMACryp v1.1 only):",
938 "AU parameters set according to RFC3640 mode or user defined");
940 prefs_register_enum_preference(ismacryp_module
,
944 &mode
, mode_types
, true);
946 /* User defined mode */
947 prefs_register_bool_preference(ismacryp_module
,
948 "user_mode", "User mode (T/F)",
949 "Indicates use of user mode instead of RFC3640 modes (T/F)",
952 /* following preference values only used if user mode is selected above */
953 prefs_register_static_text_preference(ismacryp_module
,
954 "user_defined_modes",
955 "Following parameters only valid and used for user mode:",
956 "AU parameters defined by the user");
958 /* ideally would grey this out or disable this if in user mode */
959 prefs_register_uint_preference(ismacryp_module
,
960 "au_size_length", "User mode: SizeLength (bits)",
961 "Set the length of the AU size in the AU Header in bits",
962 10, &pref_au_size_length
);
964 prefs_register_uint_preference(ismacryp_module
,
965 "au_index_length", "User mode: IndexLength (bits)",
966 "Set the length of the AU index in the AU Header in bits",
967 10, &pref_au_index_length
);
969 prefs_register_uint_preference(ismacryp_module
,
970 "au_index_delta_length", "User mode: IndexDeltaLength (bits)",
971 "Set the length of the AU delta index in the AU Header in bits",
972 10, &pref_au_index_delta_length
);
974 prefs_register_uint_preference(ismacryp_module
,
975 "cts_delta_length", "User mode: CTSDeltaLength (bits)",
976 "Set the length of the CTS delta field in the AU Header in bits",
977 10, &pref_cts_delta_length
);
979 prefs_register_uint_preference(ismacryp_module
,
980 "dts_delta_length", "User mode: DTSDeltaLength (bits)",
981 "Set the length of the DTS delta field in the AU Header in bits",
982 10, &pref_dts_delta_length
);
984 prefs_register_bool_preference(ismacryp_module
,
985 "random_access_indication", "User mode: RandomAccessIndication (T/F)",
986 "Indicates whether or not the RAP field is present in the AU Header (T/F)",
987 &pref_random_access_indication
);
989 prefs_register_uint_preference(ismacryp_module
,
990 "stream_state_indication", "User mode: StreamStateIndication (number of bits)",
991 "Indicates the number of bits on which the stream state field is encoded"
992 " in the AU Header (bits)",
993 10, &pref_stream_state_indication
);
996 void proto_reg_handoff_ismacryp(void)
998 dissector_add_string("rtp_dyn_payload_type", "ISMACRYP", ismacryp_handle
);
999 dissector_add_string("rtp_dyn_payload_type", "enc-mpeg4-generic", ismacryp_v11_handle
);
1000 dissector_add_string("rtp_dyn_payload_type", "enc-isoff-generic", ismacryp_v20_handle
);
1001 dissector_add_uint_range_with_preference("rtp.pt", "", ismacryp_handle
);
1006 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1011 * indent-tabs-mode: t
1014 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1015 * :indentSize=8:tabSize=8:noTabs=false: