From Didier Gautheron:
[obnox/wireshark/wip.git] / epan / dissectors / packet-zrtp.c
1 /* packet-zrtp.c
2  * Routines for zrtp packet dissection
3  * IETF draft draft-zimmermann-avt-zrtp-15x
4  * Copyright 2007, Sagar Pai <sagar@gmail.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from packet-pop.c
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <stdio.h>
34
35 #include <string.h>
36 #include <glib.h>
37 #include <epan/packet.h>
38 #include <epan/strutil.h>
39 #include <epan/crc32.h>
40
41 /*
42   RTP header
43 */
44 static int proto_zrtp = -1;
45 static int hf_zrtp_rtpversion = -1;
46 static int hf_zrtp_rtppadding = -1;
47 static int hf_zrtp_rtpextension = -1;
48 static int hf_zrtp_id = -1;
49 static int hf_zrtp_sequence = -1;
50 static int hf_zrtp_cookie = -1;
51 static int hf_zrtp_source_id = -1;
52
53 /*
54   ZRTP header
55 */
56 static int hf_zrtp_signature = -1;
57 static int hf_zrtp_msg_length = -1;
58 static int hf_zrtp_msg_type = -1;
59 static int hf_zrtp_msg_version = -1;
60
61 /*
62   Hello Data
63 */
64 static int hf_zrtp_msg_client_id = -1;
65 static int hf_zrtp_msg_zid = -1;
66 static int hf_zrtp_msg_mitm = -1;
67 static int hf_zrtp_msg_passive = -1;
68 static int hf_zrtp_msg_hash_count = -1;
69 static int hf_zrtp_msg_cipher_count = -1;
70 static int hf_zrtp_msg_authtag_count = -1;
71 static int hf_zrtp_msg_key_count = -1;
72 static int hf_zrtp_msg_sas_count = -1;
73 static int hf_zrtp_msg_hash = -1;
74 static int hf_zrtp_msg_cipher = -1;
75 static int hf_zrtp_msg_at = -1;
76 static int hf_zrtp_msg_keya = -1;
77 static int hf_zrtp_msg_sas = -1;
78 static int hf_zrtp_msg_hash_image = -1;
79
80 /*
81   Commit Data
82 */
83 static int hf_zrtp_msg_hvi = -1;
84 static int hf_zrtp_msg_nonce = -1;
85 static int hf_zrtp_msg_key_id = -1;
86
87 /*
88   DHParts Data
89 */
90 static int hf_zrtp_msg_rs1ID = -1;
91 static int hf_zrtp_msg_rs2ID = -1;
92 static int hf_zrtp_msg_auxs = -1;
93 static int hf_zrtp_msg_pbxs = -1;
94
95 /*
96   Confirm Data
97 */
98 static int hf_zrtp_msg_hmac = -1;
99 static int hf_zrtp_msg_cfb = -1;
100
101 /*
102   Error Data
103 */
104 static int hf_zrtp_msg_error = -1;
105
106 /*
107   Ping Data
108 */
109 static int hf_zrtp_msg_ping_version = -1;
110 static int hf_zrtp_msg_ping_endpointhash = -1;
111 static int hf_zrtp_msg_pingack_endpointhash = -1;
112 static int hf_zrtp_msg_ping_ssrc = -1;
113
114 /*
115   Checksum Data
116 */
117 static int hf_zrtp_checksum = -1;
118 static int hf_zrtp_checksum_good = -1;
119 static int hf_zrtp_checksum_bad = -1;
120
121 /*
122   Sub-Tree
123 */
124 static gint ett_zrtp = -1;
125 static gint ett_zrtp_msg = -1;
126 static gint ett_zrtp_msg_data = -1;
127
128 static gint ett_zrtp_msg_encrypted = -1;
129 static gint ett_zrtp_msg_pvr = -1;
130 static gint ett_zrtp_msg_hc = -1;
131 static gint ett_zrtp_msg_kc = -1;
132 static gint ett_zrtp_msg_ac = -1;
133 static gint ett_zrtp_msg_cc = -1;
134 static gint ett_zrtp_msg_sc = -1;
135
136 static gint ett_zrtp_checksum = -1;
137
138 /*
139   Definitions
140 */
141 #define ZRTP_ERR_10 0x10
142 #define ZRTP_ERR_20 0x20
143 #define ZRTP_ERR_30 0x30
144 #define ZRTP_ERR_40 0x40
145 #define ZRTP_ERR_51 0x51
146 #define ZRTP_ERR_52 0x52
147 #define ZRTP_ERR_53 0x53
148 #define ZRTP_ERR_54 0x54
149 #define ZRTP_ERR_55 0x55
150 #define ZRTP_ERR_56 0x56
151 #define ZRTP_ERR_61 0x61
152 #define ZRTP_ERR_62 0x62
153 #define ZRTP_ERR_63 0x63
154 #define ZRTP_ERR_70 0x70
155 #define ZRTP_ERR_80 0x80
156 #define ZRTP_ERR_90 0x90
157 #define ZRTP_ERR_A0 0xA0
158 #define ZRTP_ERR_100 0x100
159
160 /*
161   Text for Display
162 */
163 typedef struct _value_zrtp_versions {
164   const gchar *version;
165 } value_zrtp_versions;
166
167
168 typedef struct _value_string_keyval {
169   const gchar *key;
170   const gchar *val;
171 } value_string_keyval;
172
173
174 const value_zrtp_versions valid_zrtp_versions[]=
175   {
176     {"1.1x"},
177     {"1.0x"},
178     {"0.95"},
179     {"0.90"},
180     {"0.85"},
181     {NULL}
182   };
183
184 const value_string_keyval zrtp_hash_type_vals[] =
185   {
186     { "S256",   "SHA-256 Hash"},
187     { NULL,             NULL }
188   };
189
190 const value_string_keyval zrtp_cipher_type_vals[] =
191   {
192     { "AES1",   "AES-CM with 128 bit keys"},
193     { "AES2",   "AES-CM with 192 bit keys"},
194     { "AES3",   "AES-CM with 256 bit keys"},
195     { "2FS1",   "TwoFish with 128 bit keys"},
196     { "2FS2",   "TwoFish with 192 bit keys"},
197     { "2FS3",   "TwoFish with 256 bit keys"},
198     { "CAM1",   "Camellia with 128 bit keys"},
199     { "CAM2",   "Camellia with 192 bit keys"},
200     { "CAM3",   "Camellia with 256 bit keys"},
201     { NULL,             NULL }
202   };
203
204 const value_string_keyval zrtp_auth_tag_vals[] =
205   {
206     { "HS32",   "HMAC-SHA1 32 bit authentication tag"},
207     { "HS80",   "HMAC-SHA1 80 bit authentication tag"},
208     { NULL,             NULL }
209   };
210
211 const value_string_keyval zrtp_sas_type_vals[] =
212   {
213     { "B32 ",   "Short authentication string using base 32"},
214     { "B256",   "Short authentication string using base 256"},
215     { NULL,             NULL }
216   };
217
218 const value_string_keyval zrtp_key_agreement_vals[] =
219   {
220     { "DH2k",   "DH mode with p=2048 bit prime"},
221     { "DH3k",   "DH mode with p=3072 bit prime"},
222     { "DH4k",   "DH mode with p=4096 bit prime"},
223     { "Prsh",   "Preshared non-DH mode using shared secret"},
224     { "EC25",   "Elliptic Curve DH-256"},
225     { "EC38",   "Elliptic Curve DH-384"},
226     { "EC52",   "Elliptic Curve DH-521"},
227     { "Mult",   "Multistream mode"},
228     { NULL,             NULL }
229   };
230
231 const value_string zrtp_error_vals[] =
232   {
233     { ZRTP_ERR_10, "Malformed Packet (CRC OK but wrong structure)"},
234     { ZRTP_ERR_20, "Critical Software Error"},
235     { ZRTP_ERR_30, "Unsupported ZRTP version"},
236     { ZRTP_ERR_40, "Hello Components mismatch"},
237     { ZRTP_ERR_51, "Hash type unsupported"},
238     { ZRTP_ERR_52, "Cipher type not supported"},
239     { ZRTP_ERR_53, "Public key exchange not supported"},
240     { ZRTP_ERR_54, "SRTP auth. tag not supported"},
241     { ZRTP_ERR_55, "SAS scheme not supported"},
242     { ZRTP_ERR_56, "No shared secret available, DH mode required"},
243     { ZRTP_ERR_61, "DH Error: bad pv for initiator/responder value is (1,0,p-1)"},
244     { ZRTP_ERR_62, "DH Error: bad hash commitment (hvi != hashed data)"},
245     { ZRTP_ERR_63, "Received relayed SAS from untrusted MiTM"},
246     { ZRTP_ERR_70, "Auth. Error Bad Confirm Packet HMAC"},
247     { ZRTP_ERR_80, "Nonce is reused"},
248     { ZRTP_ERR_90, "Equal ZID's in Hello"},
249     { ZRTP_ERR_A0, "Service unavailable"},
250     { ZRTP_ERR_100, "GoClear packet received, but not allowed"},
251     { 0, NULL}
252   };
253
254 static void
255 dissect_Hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
256 static void
257 dissect_ErrorACK(packet_info *pinfo);
258 static void
259 dissect_Commit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
260 static void
261 dissect_ClearACK( packet_info *pinfo);
262 static void
263 dissect_Conf2ACK(packet_info *pinfo);
264 static void
265 dissect_HelloACK( packet_info *pinfo);
266 static void
267 dissect_GoClear(tvbuff_t *tvb,packet_info *pinfo, proto_tree *zrtp_tree);
268 static void
269 dissect_Error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
270 static void
271 dissect_Confirm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree,int part);
272 static void
273 dissect_DHPart(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree,int part);
274 static void
275 dissect_SASrelay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
276 static void
277 dissect_RelayACK(packet_info *pinfo);
278 static void
279 dissect_Ping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
280 static void
281 dissect_PingACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
282
283
284 static const gchar *
285 key_to_val(const gchar *key, int keylen, const value_string_keyval *kv, const gchar *fmt){
286   int i=0;
287   while (kv[i].key) {
288     if (!strncmp(kv[i].key, key, keylen)){
289       return(kv[i].val);
290     }
291     i++;
292   }
293   return ep_strdup_printf(fmt, key);
294 }
295
296 static const gchar *
297 check_valid_version(const gchar *version){
298   int i=0;
299   int match_size = (version[0] == '0') ? 4 : 3;
300   while (valid_zrtp_versions[i].version) {
301     if (!strncmp(valid_zrtp_versions[i].version, version, match_size)){
302       return(valid_zrtp_versions[i].version);
303     }
304     i++;
305   }
306   return NULL;
307 }
308
309
310 static void
311 dissect_zrtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
312 {
313   proto_tree   *zrtp_tree;
314   proto_tree   *zrtp_msg_tree;
315   proto_tree   *zrtp_msg_data_tree;
316   proto_tree   *checksum_tree;
317   proto_item   *ti;
318   int          linelen;
319   int          checksum_offset;
320   unsigned char message_type[9];
321   unsigned int prime_offset = 0;
322   unsigned int msg_offset = 12;
323   guint32      sent_crc, calc_crc;
324
325   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZRTP");
326
327   if (check_col(pinfo->cinfo, COL_INFO))
328     col_set_str(pinfo->cinfo, COL_INFO, "Unknown ZRTP Packet");
329
330   ti = proto_tree_add_protocol_format(tree,proto_zrtp,tvb,0,-1,"ZRTP protocol");
331   zrtp_tree = proto_item_add_subtree(ti,ett_zrtp);
332
333   proto_tree_add_item(zrtp_tree,hf_zrtp_rtpversion,tvb,prime_offset+0,1,FALSE);
334   proto_tree_add_item(zrtp_tree,hf_zrtp_rtppadding,tvb,prime_offset+0,1,FALSE);
335   proto_tree_add_item(zrtp_tree,hf_zrtp_rtpextension,tvb,prime_offset+0,1,FALSE);
336
337   proto_tree_add_item(zrtp_tree,hf_zrtp_sequence,tvb,prime_offset+2,2,FALSE);
338
339   proto_tree_add_item(zrtp_tree,hf_zrtp_cookie,tvb,prime_offset+4,4,FALSE);
340
341   proto_tree_add_item(zrtp_tree,hf_zrtp_source_id,tvb,prime_offset+8,4,FALSE);
342
343   linelen = tvb_reported_length_remaining(tvb,msg_offset);
344   checksum_offset = linelen-4;
345
346   ti = proto_tree_add_protocol_format(zrtp_tree,proto_zrtp,tvb,msg_offset,linelen-4,"Message");
347   zrtp_msg_tree = proto_item_add_subtree(ti,ett_zrtp_msg);
348
349   proto_tree_add_item(zrtp_msg_tree,hf_zrtp_signature,tvb,msg_offset+0,2,FALSE);
350
351   proto_tree_add_item(zrtp_msg_tree,hf_zrtp_msg_length,tvb,msg_offset+2,2,FALSE);
352
353   tvb_memcpy(tvb,(void *)message_type,msg_offset+4,8);
354   message_type[8] = '\0';
355   proto_tree_add_item(zrtp_msg_tree,hf_zrtp_msg_type,tvb,msg_offset+4,8,FALSE);
356
357   linelen = tvb_reported_length_remaining(tvb,msg_offset+12);
358
359   if (!strncmp(message_type,"Hello   ",8)){
360     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
361     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
362     dissect_Hello(tvb,pinfo,zrtp_msg_data_tree);
363   } else if (!strncmp(message_type,"HelloACK",8)){
364     dissect_HelloACK(pinfo);
365   } else if (!strncmp(message_type,"Commit  ",8)){
366     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
367     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
368     dissect_Commit(tvb,pinfo,zrtp_msg_data_tree);
369   } else if (!strncmp(message_type,"DHPart1 ",8)){
370     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
371     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
372     dissect_DHPart(tvb,pinfo,zrtp_msg_data_tree,1);
373   } else if (!strncmp(message_type,"DHPart2 ",8)){
374     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
375     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
376     dissect_DHPart(tvb,pinfo,zrtp_msg_data_tree,2);
377   } else if (!strncmp(message_type,"Confirm1",8)){
378     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
379     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
380     dissect_Confirm(tvb,pinfo,zrtp_msg_data_tree,1);
381   } else if (!strncmp(message_type,"Confirm2",8)){
382     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
383     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
384     dissect_Confirm(tvb,pinfo,zrtp_msg_data_tree,2);
385   } else if (!strncmp(message_type,"Conf2ACK",8)){
386     dissect_Conf2ACK(pinfo);
387   } else if (!strncmp(message_type,"Error   ",8)){
388     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
389     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
390     dissect_Error(tvb,pinfo,zrtp_msg_data_tree);
391   } else if (!strncmp(message_type,"ErrorACK",8)){
392     dissect_ErrorACK(pinfo);
393   } else if (!strncmp(message_type,"GoClear ",8)){
394     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
395     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
396     dissect_GoClear(tvb,pinfo,zrtp_msg_data_tree);
397   } else if (!strncmp(message_type,"ClearACK",8)){
398     dissect_ClearACK(pinfo);
399   } else if (!strncmp(message_type,"SASrelay",8)){
400     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
401     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
402     dissect_SASrelay(tvb,pinfo,zrtp_msg_data_tree);
403   } else if (!strncmp(message_type,"RelayACK",8)){
404     dissect_RelayACK(pinfo);
405   } else if (!strncmp(message_type,"Ping    ",8)){
406     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
407     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
408     dissect_Ping(tvb,pinfo,zrtp_msg_data_tree);
409   } else if (!strncmp(message_type,"PingACK ",8)){
410     ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data");
411     zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data);
412     dissect_PingACK(tvb,pinfo,zrtp_msg_data_tree);
413   }
414
415   sent_crc = tvb_get_ntohl(tvb,msg_offset+checksum_offset);
416   calc_crc = ~crc32c_calculate(tvb_get_ptr(tvb,0,msg_offset+checksum_offset),msg_offset+checksum_offset,CRC32C_PRELOAD);
417
418   if (sent_crc == calc_crc) {
419     ti = proto_tree_add_uint_format_value(zrtp_tree, hf_zrtp_checksum, tvb, msg_offset+checksum_offset, 4, sent_crc,
420                                           "0x%04x [correct]", sent_crc);
421     checksum_tree = proto_item_add_subtree(ti, ett_zrtp_checksum);
422     ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_good, tvb, msg_offset+checksum_offset, 4, TRUE);
423     PROTO_ITEM_SET_GENERATED(ti);
424     ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_bad, tvb, msg_offset+checksum_offset, 4, FALSE);
425     PROTO_ITEM_SET_GENERATED(ti);
426   } else {
427     ti = proto_tree_add_uint_format_value(zrtp_tree, hf_zrtp_checksum, tvb, msg_offset+checksum_offset, 4, sent_crc,
428                                           "0x%04x [incorrect, should be 0x%04x]", sent_crc, calc_crc);
429     checksum_tree = proto_item_add_subtree(ti, ett_zrtp_checksum);
430     ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_good, tvb, msg_offset+checksum_offset, 4, FALSE);
431     PROTO_ITEM_SET_GENERATED(ti);
432     ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_bad, tvb, msg_offset+checksum_offset, 4, TRUE);
433     PROTO_ITEM_SET_GENERATED(ti);
434   }
435
436 }
437
438 static void
439 dissect_ErrorACK(packet_info *pinfo) {
440   col_set_str(pinfo->cinfo, COL_INFO, "ErrorACK Packet");
441 }
442
443 static void
444 dissect_ClearACK(packet_info *pinfo) {
445   col_set_str(pinfo->cinfo, COL_INFO, "ClearACK Packet");
446 }
447
448 static void
449 dissect_RelayACK(packet_info *pinfo) {
450   col_set_str(pinfo->cinfo, COL_INFO, "RelayACK Packet");
451 }
452
453 static void
454 dissect_Conf2ACK(packet_info *pinfo) {
455   col_set_str(pinfo->cinfo, COL_INFO, "Conf2ACK Packet");
456 }
457
458 static void
459 dissect_HelloACK(packet_info *pinfo) {
460   col_set_str(pinfo->cinfo, COL_INFO, "HelloACK Packet");
461 }
462
463 static void
464 dissect_Ping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
465   unsigned int data_offset=24;
466
467   col_set_str(pinfo->cinfo, COL_INFO, "Ping Packet");
468
469   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_ping_version,tvb,data_offset,4,FALSE);
470   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_ping_endpointhash,tvb,data_offset+4,8,FALSE);
471 }
472
473 static void
474 dissect_PingACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
475   unsigned int data_offset=24;
476
477   col_set_str(pinfo->cinfo, COL_INFO, "PingACK Packet");
478
479   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_ping_version,tvb,data_offset,4,FALSE);
480   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_pingack_endpointhash,tvb,data_offset+4,8,FALSE);
481   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_ping_endpointhash,tvb,data_offset+12,8,FALSE);
482   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_ping_ssrc,tvb,data_offset+20,4,FALSE);
483 }
484
485 static void
486 dissect_GoClear(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
487   unsigned int data_offset=24;
488
489   col_set_str(pinfo->cinfo, COL_INFO, "GoClear Packet");
490
491   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+0,8,FALSE);
492 }
493
494 static void
495 dissect_Error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
496   unsigned int data_offset=24;
497
498   col_set_str(pinfo->cinfo, COL_INFO, "Error Packet");
499
500   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_error,tvb,data_offset,4,FALSE);
501 }
502
503 static void
504 dissect_Confirm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree,int part) {
505   proto_item   *ti;
506   unsigned int data_offset=24;
507   proto_tree *zrtp_msg_encrypted_tree;
508   int linelen;
509
510   if (check_col(pinfo->cinfo, COL_INFO)) {
511     col_add_fstr(pinfo->cinfo, COL_INFO, (part == 1) ? "Confirm1 Packet" : "Confirm2 Packet");
512   }
513
514   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+0,8,FALSE);
515   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_cfb,tvb,data_offset+8,16,FALSE);
516   linelen = tvb_reported_length_remaining(tvb,data_offset+24);
517   ti = proto_tree_add_protocol_format(zrtp_tree,proto_zrtp,tvb,data_offset+24,linelen-4,"Encrypted Data");
518   zrtp_msg_encrypted_tree = proto_item_add_subtree(ti,ett_zrtp_msg_encrypted);
519 }
520
521 static void
522 dissect_SASrelay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
523   proto_item   *ti;
524   unsigned int data_offset=24;
525   proto_tree *zrtp_msg_encrypted_tree;
526   int linelen;
527
528   col_set_str(pinfo->cinfo, COL_INFO, "SASrelay Packet");
529
530   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+0,8,FALSE);
531   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_cfb,tvb,data_offset+8,16,FALSE);
532   linelen = tvb_reported_length_remaining(tvb,data_offset+24);
533   ti = proto_tree_add_protocol_format(zrtp_tree,proto_zrtp,tvb,data_offset+24,linelen-4,"Encrypted Data");
534   zrtp_msg_encrypted_tree = proto_item_add_subtree(ti,ett_zrtp_msg_encrypted);
535 }
536
537 static void
538 dissect_DHPart(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree,int part) {
539   proto_item   *ti;
540   unsigned int msg_offset=12;
541   unsigned int data_offset=56;
542   proto_tree *zrtp_msg_pvr_tree;
543   int linelen, pvr_len;
544
545   if (check_col(pinfo->cinfo, COL_INFO)) {
546     col_add_fstr(pinfo->cinfo, COL_INFO, (part == 1) ? "DHPart1 Packet" : "DHPart2 Packet");
547   }
548
549   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hash_image,tvb,msg_offset+12,32,FALSE);
550   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_rs1ID,tvb,data_offset+0,8,FALSE);
551   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_rs2ID,tvb,data_offset+8,8,FALSE);
552   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_auxs,tvb,data_offset+16,8,FALSE);
553   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_pbxs,tvb,data_offset+24,8,FALSE);
554   linelen = tvb_reported_length_remaining(tvb,data_offset+32);
555   pvr_len = linelen-8-4;
556   ti = proto_tree_add_protocol_format(zrtp_tree,proto_zrtp,tvb,data_offset+32,pvr_len,(part==1)?"pvr Data":"pvi Data");
557   zrtp_msg_pvr_tree = proto_item_add_subtree(ti,ett_zrtp_msg_pvr);
558   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+32+pvr_len,8,FALSE);
559 }
560
561 static void
562 dissect_Commit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
563   unsigned int msg_offset=12;
564   unsigned int data_offset=56;
565   unsigned char value[5];
566   int key_type = 0;
567   /*
568     0 - other type
569     1 - "Mult"
570     2 - "Prsh"
571   */
572   unsigned int offset;
573
574   col_set_str(pinfo->cinfo, COL_INFO, "Commit Packet");
575
576   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hash_image,tvb,msg_offset+12,32,FALSE);
577   /* ZID */
578   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_zid,tvb,data_offset+0,12,FALSE);
579   tvb_memcpy(tvb,(void *)value,data_offset+12,4);
580   value[4]='\0';
581   proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_hash,tvb,data_offset+12,4,value,
582                                   "Hash: %s",key_to_val(value,4,zrtp_hash_type_vals,"Unknown hash type %s"));
583   tvb_memcpy(tvb,(void *)value,data_offset+16,4);
584   value[4]='\0';
585   proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_cipher,tvb,data_offset+16,4,value,"Cipher: %s",
586                                   key_to_val(value,4,zrtp_cipher_type_vals,"Unknown cipher type %s"));
587   tvb_memcpy(tvb,(void *)value,data_offset+20,4);
588   value[4]='\0';
589   proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_at,tvb,data_offset+20,4,value,
590                                   "Auth tag: %s",key_to_val(value,4,zrtp_auth_tag_vals,"Unknown auth tag %s"));
591   tvb_memcpy(tvb,(void *)value,data_offset+24,4);
592   value[4]='\0';
593   proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_keya,tvb,data_offset+24,4,value,
594                                   "Key agreement: %s",key_to_val(value,4,zrtp_key_agreement_vals,"Unknown key agreement %s"));
595
596   if(!strncmp(value, "Mult", 4)){
597     key_type = 1;
598   } else if (!strncmp(value, "Prsh", 4)){
599     key_type = 2;
600   }
601   tvb_memcpy(tvb,(void *)value,data_offset+28,4);
602   value[4]='\0';
603   proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_sas,tvb,data_offset+28,4,value,
604                                   "SAS type: %s",key_to_val(value,4,zrtp_sas_type_vals,"Unknown SAS type %s"));
605
606   switch(key_type){
607   case 1: /*
608              Mult
609           */
610     proto_tree_add_item(zrtp_tree,hf_zrtp_msg_nonce,tvb,data_offset+32,16,FALSE);
611     offset = 48;
612     break;
613   case 2: /*
614             Prsh
615           */
616     proto_tree_add_item(zrtp_tree,hf_zrtp_msg_nonce,tvb,data_offset+32,16,FALSE);
617     proto_tree_add_item(zrtp_tree,hf_zrtp_msg_key_id,tvb,data_offset+48,8,FALSE);
618     offset = 56;
619     break;
620   default: /*
621              other
622            */
623     proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hvi,tvb,data_offset+32, 32, FALSE);
624     offset = 64;
625     break;
626   }
627
628   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+offset,8,FALSE);
629 }
630
631 static void
632 dissect_Hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
633   proto_item   *ti;
634   unsigned int msg_offset = 12;
635   unsigned int data_offset = 88;
636   guint8       val_b;
637   unsigned int i;
638   unsigned int run_offset;
639   unsigned int hc,cc,ac,kc,sc;
640   unsigned int vhc,vcc,vac,vkc,vsc;
641   unsigned char value[5];
642   unsigned char version_str[5];
643   proto_tree *tmp_tree;
644
645   col_set_str(pinfo->cinfo, COL_INFO, "Hello Packet");
646
647   tvb_memcpy(tvb,version_str,msg_offset+12,4);
648   version_str[4]='\0';
649   if (check_valid_version(version_str) == NULL){
650     col_set_str(pinfo->cinfo, COL_INFO, "Unsupported version of ZRTP protocol");
651   }
652   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_version,tvb,msg_offset+12,4,FALSE);
653   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_client_id,tvb,msg_offset+16,16,FALSE);
654   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hash_image,tvb,msg_offset+32,32,FALSE);
655   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_zid,tvb,msg_offset+64,12,FALSE);
656   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_mitm,tvb,data_offset+0,1,FALSE);
657   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_passive,tvb,data_offset+0,1,FALSE);
658
659   val_b = tvb_get_guint8(tvb,data_offset+1);
660   hc = val_b & 0x0F;
661   vhc = hc;
662
663   val_b = tvb_get_guint8(tvb,data_offset+2);
664   cc = val_b & 0xF0;
665   ac = val_b & 0x0F;
666   vcc = cc >> 4;
667   vac = ac;
668
669   val_b = tvb_get_guint8(tvb,data_offset+3);
670   kc = val_b & 0xF0;
671   sc = val_b & 0x0F;
672   vkc = kc >> 4;
673   vsc = sc;
674
675   ti=proto_tree_add_uint_format(zrtp_tree,hf_zrtp_msg_hash_count,tvb,data_offset+1,1,hc,"Hash type count = %d",vhc);
676   tmp_tree = proto_item_add_subtree(ti,ett_zrtp_msg_hc);
677   run_offset = data_offset+4;
678   for(i=0;i<vhc;i++){
679     tvb_memcpy(tvb,(void *)value,run_offset,4);
680     value[4]='\0';
681     proto_tree_add_string_format(tmp_tree,hf_zrtp_msg_hash,tvb,run_offset,4,value,
682                                     "Hash[%d]: %s",i,key_to_val(value,4,zrtp_hash_type_vals,"Unknown hash type %s"));
683     run_offset+=4;
684   }
685   ti=proto_tree_add_uint_format(zrtp_tree,hf_zrtp_msg_cipher_count,tvb,data_offset+2,1,cc,"Cipher type count = %d",vcc);
686   tmp_tree = proto_item_add_subtree(ti,ett_zrtp_msg_cc);
687   for(i=0;i<vcc;i++){
688     tvb_memcpy(tvb,(void *)value,run_offset,4);
689     value[4]='\0';
690     proto_tree_add_string_format(tmp_tree,hf_zrtp_msg_cipher,tvb,run_offset,4,value,"Cipher[%d]: %s",i,
691                                     key_to_val(value,4,zrtp_cipher_type_vals,"Unknown cipher type %s"));
692     run_offset+=4;
693   }
694   ti=proto_tree_add_uint_format(zrtp_tree,hf_zrtp_msg_authtag_count,tvb,data_offset+2,1,ac,"Auth tag count = %d",vac);
695   tmp_tree = proto_item_add_subtree(ti,ett_zrtp_msg_ac);
696   for(i=0;i<vac;i++){
697     tvb_memcpy(tvb,(void *)value,run_offset,4);
698     value[4]='\0';
699     proto_tree_add_string_format(tmp_tree,hf_zrtp_msg_at,tvb,run_offset,4,value,
700                                     "Auth tag[%d]: %s",i,key_to_val(value,4,zrtp_auth_tag_vals,"Unknown auth tag %s"));
701     run_offset+=4;
702   }
703   ti=proto_tree_add_uint_format(zrtp_tree,hf_zrtp_msg_key_count,tvb,data_offset+3,1,kc,"Key agreement type count = %d",vkc);
704   tmp_tree = proto_item_add_subtree(ti,ett_zrtp_msg_kc);
705   for(i=0;i<vkc;i++){
706     tvb_memcpy(tvb,(void *)value,run_offset,4);
707     value[4]='\0';
708     proto_tree_add_string_format(tmp_tree,hf_zrtp_msg_keya,tvb,run_offset,4,value,
709                                     "Key agreement[%d]: %s",i,key_to_val(value,4,zrtp_key_agreement_vals,"Unknown key agreement %s"));
710     run_offset+=4;
711   }
712   ti=proto_tree_add_uint_format(zrtp_tree,hf_zrtp_msg_sas_count,tvb,data_offset+3,1,sc,"SAS type count = %d",vsc);
713   tmp_tree = proto_item_add_subtree(ti,ett_zrtp_msg_sc);
714   for(i=0;i<vsc;i++){
715     tvb_memcpy(tvb,(void *)value,run_offset,4);
716     value[4]='\0';
717     proto_tree_add_string_format(tmp_tree,hf_zrtp_msg_sas,tvb,run_offset,4,value,
718                                     "SAS type[%d]: %s",i,key_to_val(value,4,zrtp_sas_type_vals,"Unknown SAS type %s"));
719     run_offset+=4;
720   }
721
722   proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,run_offset,8,FALSE);
723 }
724
725 void
726 proto_register_zrtp(void)
727 {
728   static hf_register_info hf[] = {
729     {&hf_zrtp_rtpversion,
730      {
731        "RTP Version", "zrtp.rtpversion",
732        FT_UINT8, BASE_DEC,
733        NULL, 0xC0,
734        NULL, HFILL
735      }
736     },
737
738     {&hf_zrtp_rtppadding,
739      {
740        "RTP padding", "zrtp.rtppadding",
741        FT_BOOLEAN, 8,
742        NULL, 0x20,
743        NULL, HFILL
744      }
745     },
746
747     {&hf_zrtp_rtpextension,
748      {
749        "RTP Extension", "zrtp.rtpextension",
750        FT_BOOLEAN, 8,
751        NULL, 0x10,
752        NULL, HFILL
753      }
754     },
755
756     {&hf_zrtp_id,
757      {
758        "ID", "zrtp.id",
759        FT_UINT8, BASE_HEX,
760        NULL, 0x0,
761        NULL, HFILL
762      }
763     },
764
765     {&hf_zrtp_sequence,
766      {
767        "Sequence", "zrtp.sequence",
768        FT_UINT16, BASE_DEC,
769        NULL, 0x0,
770        NULL, HFILL
771      }
772     },
773
774     {&hf_zrtp_cookie,
775      {
776        "Magic Cookie", "zrtp.cookie",
777        FT_STRING, BASE_NONE,
778        NULL, 0x0,
779        NULL, HFILL
780      }
781     },
782
783     {&hf_zrtp_source_id,
784      {
785        "Source Identifier", "zrtp.source_id",
786        FT_UINT32, BASE_HEX,
787        NULL, 0x0,
788        NULL, HFILL
789      }
790     },
791
792     /*
793        Message Types
794     */
795     {&hf_zrtp_signature,
796      {
797        "Signature", "zrtp.signature",
798        FT_UINT16, BASE_HEX,
799        NULL, 0x0,
800        NULL, HFILL
801      }
802     },
803
804     {&hf_zrtp_msg_length,
805      {
806        "Length", "zrtp.length",
807        FT_UINT16, BASE_DEC,
808        NULL, 0x0,
809        NULL, HFILL
810      }
811     },
812
813     {&hf_zrtp_msg_type,
814      {
815        "Type", "zrtp.type",
816        FT_STRING, BASE_NONE,
817        NULL, 0x0,
818        NULL, HFILL
819      }
820     },
821
822     {&hf_zrtp_msg_version,
823      {
824        "ZRTP protocol version", "zrtp.version",
825        FT_STRING, BASE_NONE,
826        NULL, 0x0,
827        NULL, HFILL
828      }
829     },
830
831     {&hf_zrtp_msg_client_id,
832      {
833        "Client Identifier", "zrtp.client_source_id",
834        FT_STRING, BASE_NONE,
835        NULL, 0x0,
836        NULL, HFILL
837      }
838     },
839
840     {&hf_zrtp_msg_hash_image,
841      {
842        "Hash Image", "zrtp.hash_image",
843        FT_BYTES, BASE_NONE,
844        NULL, 0x0,
845        NULL, HFILL
846      }
847     },
848
849     {&hf_zrtp_msg_zid,
850      {
851        "ZID", "zrtp.zid",
852        FT_BYTES, BASE_NONE,
853        NULL, 0x0,
854        NULL, HFILL
855      }
856     },
857
858     {&hf_zrtp_msg_mitm,
859      {
860        "MiTM", "zrtp.mitm",
861        FT_BOOLEAN, 8,
862        NULL, 0x20,
863        NULL, HFILL
864      }
865     },
866
867     {&hf_zrtp_msg_passive,
868      {
869        "Passive", "zrtp.passive",
870        FT_BOOLEAN, 8,
871        NULL, 0x10,
872        NULL, HFILL
873      }
874     },
875
876     {&hf_zrtp_msg_hash_count,
877      {
878        "Hash Count", "zrtp.hc",
879        FT_UINT8, BASE_DEC,
880        NULL, 0x0F,
881        NULL, HFILL
882      }
883     },
884
885     {&hf_zrtp_msg_cipher_count,
886      {
887        "Cipher Count", "zrtp.cc",
888        FT_UINT8, BASE_DEC,
889        NULL, 0xF0,
890        NULL, HFILL
891      }
892     },
893
894     {&hf_zrtp_msg_authtag_count,
895      {
896        "Auth tag Count", "zrtp.ac",
897        FT_UINT8, BASE_DEC,
898        NULL, 0x0F,
899        NULL, HFILL
900      }
901     },
902
903     {&hf_zrtp_msg_key_count,
904      {
905        "Key Agreement Count", "zrtp.kc",
906        FT_UINT8, BASE_DEC,
907        NULL, 0xF0,
908        NULL, HFILL
909      }
910     },
911
912     {&hf_zrtp_msg_sas_count,
913      {
914        "SAS Count", "zrtp.sc",
915        FT_UINT8, BASE_DEC,
916        NULL, 0x0F,
917        NULL, HFILL
918      }
919     },
920
921     {&hf_zrtp_msg_hash,
922      {
923        "Hash", "zrtp.hash",
924        FT_STRING, BASE_NONE,
925        NULL, 0x0,
926        NULL, HFILL
927      }
928     },
929
930     {&hf_zrtp_msg_cipher,
931      {
932        "Cipher", "zrtp.cipher",
933        FT_STRING, BASE_NONE,
934        NULL, 0x0,
935        NULL, HFILL
936      }
937     },
938
939     {&hf_zrtp_msg_at,
940      {
941        "AT", "zrtp.at",
942        FT_STRING, BASE_NONE,
943        NULL, 0x0,
944        NULL, HFILL
945      }
946     },
947
948     {&hf_zrtp_msg_keya,
949      {
950        "Key Agreement", "zrtp.keya",
951        FT_STRING, BASE_NONE,
952        NULL, 0x0,
953        NULL, HFILL
954      }
955     },
956
957     {&hf_zrtp_msg_sas,
958      {
959        "SAS", "zrtp.sas",
960        FT_STRING, BASE_NONE,
961        NULL, 0x0,
962        NULL, HFILL
963      }
964     },
965
966     {&hf_zrtp_msg_rs1ID,
967      {
968        "rs1ID", "zrtp.rs1id",
969        FT_BYTES, BASE_NONE,
970        NULL, 0x0,
971        NULL, HFILL
972      }
973     },
974
975     {&hf_zrtp_msg_rs2ID,
976      {
977        "rs2ID", "zrtp.rs2id",
978        FT_BYTES, BASE_NONE,
979        NULL, 0x0,
980        NULL, HFILL
981      }
982     },
983
984     {&hf_zrtp_msg_auxs,
985      {
986        "auxs", "zrtp.auxs",
987        FT_BYTES, BASE_NONE,
988        NULL, 0x0,
989        NULL, HFILL
990      }
991     },
992
993     {&hf_zrtp_msg_pbxs,
994      {
995        "pbxs", "zrtp.pbxs",
996        FT_BYTES, BASE_NONE,
997        NULL, 0x0,
998        NULL, HFILL
999      }
1000     },
1001
1002     {&hf_zrtp_msg_hmac,
1003      {
1004        "HMAC", "zrtp.hmac",
1005        FT_BYTES, BASE_NONE,
1006        NULL, 0x0,
1007        NULL, HFILL
1008      }
1009     },
1010
1011     {&hf_zrtp_msg_cfb,
1012      {
1013        "CFB", "zrtp.cfb",
1014        FT_BYTES, BASE_NONE,
1015        NULL, 0x0,
1016        NULL, HFILL
1017      }
1018     },
1019
1020     {&hf_zrtp_msg_error,
1021      {
1022        "Error", "zrtp.error",
1023        FT_UINT32, BASE_DEC,
1024        VALS(zrtp_error_vals), 0x0,
1025        NULL, HFILL
1026      }
1027     },
1028
1029     {&hf_zrtp_msg_ping_version,
1030      {
1031        "Ping Version", "zrtp.ping_version",
1032        FT_STRING, BASE_NONE,
1033        NULL, 0x0,
1034        NULL, HFILL
1035      }
1036     },
1037
1038     {&hf_zrtp_msg_ping_endpointhash,
1039      {
1040        "Ping Endpoint Hash", "zrtp.ping_endpointhash",
1041        FT_UINT64, BASE_HEX,
1042        NULL, 0x0,
1043        NULL, HFILL
1044      }
1045     },
1046
1047     {&hf_zrtp_msg_pingack_endpointhash,
1048      {
1049        "PingAck Endpoint Hash", "zrtp.pingack_endpointhash",
1050        FT_UINT64, BASE_HEX,
1051        NULL, 0x0,
1052        NULL, HFILL
1053      }
1054     },
1055
1056     {&hf_zrtp_msg_ping_ssrc,
1057      {
1058        "Ping SSRC", "zrtp.ping_ssrc",
1059        FT_UINT32, BASE_HEX,
1060        NULL, 0x0,
1061        NULL, HFILL
1062      }
1063     },
1064
1065     {&hf_zrtp_checksum,
1066      {
1067        "Checksum", "zrtp.checksum",
1068        FT_UINT32, BASE_HEX,
1069        NULL, 0x0,
1070        NULL, HFILL
1071      }
1072     },
1073
1074     {&hf_zrtp_checksum_good,
1075      {
1076        "Good", "zrtp.checksum_good",
1077        FT_BOOLEAN, BASE_NONE,
1078        NULL, 0x0,
1079        "True: checksum matches packet content; False: doesn't match content", HFILL
1080      }
1081     },
1082
1083     {&hf_zrtp_checksum_bad,
1084      {
1085        "Bad", "zrtp.checksum_bad",
1086        FT_BOOLEAN, BASE_NONE,
1087        NULL, 0x0,
1088        "True: checksum doesn't match packet content; False: matches content", HFILL
1089      }
1090     },
1091
1092     {&hf_zrtp_msg_hvi,
1093      {
1094        "hvi", "zrtp.hvi",
1095        FT_BYTES, BASE_NONE,
1096        NULL, 0x0,
1097        NULL, HFILL
1098      }
1099     },
1100
1101     {&hf_zrtp_msg_nonce,
1102      {
1103        "nonce", "zrtp.nonce",
1104        FT_BYTES, BASE_NONE,
1105        NULL, 0x0,
1106        NULL, HFILL
1107      }
1108     },
1109
1110     {&hf_zrtp_msg_key_id,
1111      {
1112        "key ID", "zrtp.key_id",
1113        FT_BYTES, BASE_NONE,
1114        NULL, 0x0,
1115        NULL, HFILL
1116      }
1117     }
1118   };
1119
1120   static gint *ett[] = {
1121     &ett_zrtp,
1122     &ett_zrtp_msg,
1123     &ett_zrtp_msg_data,
1124     &ett_zrtp_msg_encrypted,
1125     &ett_zrtp_msg_pvr,
1126     &ett_zrtp_msg_hc,
1127     &ett_zrtp_msg_kc,
1128     &ett_zrtp_msg_ac,
1129     &ett_zrtp_msg_cc,
1130     &ett_zrtp_msg_sc,
1131     &ett_zrtp_checksum
1132   };
1133
1134   proto_zrtp = proto_register_protocol("ZRTP", "ZRTP", "zrtp");
1135   proto_register_field_array(proto_zrtp, hf, array_length(hf));
1136   proto_register_subtree_array(ett, array_length(ett));
1137   register_dissector("zrtp", dissect_zrtp, proto_zrtp);
1138 }
1139
1140 void
1141 proto_reg_handoff_zrtp(void)
1142 {
1143   dissector_handle_t zrtp_handle;
1144
1145   zrtp_handle = find_dissector("zrtp");
1146   dissector_add_handle("udp.port", zrtp_handle);
1147 }