From e92395a3c2c9253f8d46e0c38d0a8cf40233c9f1 Mon Sep 17 00:00:00 2001 From: jake Date: Thu, 25 Sep 2008 22:06:58 +0000 Subject: [PATCH] From Sagar Pai: This is a dissector for ZRTP, the Zfone projects secure media protocol, developed by Phil Zimmermann. It is updated to the latest IETF draft draft-zimmermann-avt-zrtp-08. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@26274 f5534014-38df-0310-8fa8-9805f1628bb7 --- epan/dissectors/Makefile.common | 3 +- epan/dissectors/packet-rtp.c | 29 +- epan/dissectors/packet-zrtp.c | 1035 +++++++++++++++++++++++++++++++ 3 files changed, 1057 insertions(+), 10 deletions(-) create mode 100644 epan/dissectors/packet-zrtp.c diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 8f21e1c68c..3cacb34ef1 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -838,7 +838,8 @@ DISSECTOR_SRC = \ packet-yppasswd.c \ packet-ypserv.c \ packet-ypxfr.c \ - packet-zebra.c + packet-zebra.c \ + packet-zrtp.c # # Dissectors with warnings. diff --git a/epan/dissectors/packet-rtp.c b/epan/dissectors/packet-rtp.c index 51d5aec609..492314a69e 100644 --- a/epan/dissectors/packet-rtp.c +++ b/epan/dissectors/packet-rtp.c @@ -77,8 +77,6 @@ #include #include -#include "log.h" - /* uncomment this to enable debugging of fragment reassembly */ /* #define DEBUG_FRAGMENTS 1 */ @@ -138,6 +136,7 @@ static const fragment_items rtp_fragment_items = { static dissector_handle_t rtp_handle; static dissector_handle_t stun_handle; static dissector_handle_t t38_handle; +static dissector_handle_t zrtp_handle; static int rtp_tap = -1; @@ -208,7 +207,7 @@ static guint global_pkt_ccc_udp_port = 0; #define RTP0_T38 2 static enum_val_t rtp_version0_types[] = { - { "invalid", "Invalid RTP packets", RTP0_INVALID }, + { "invalid", "Invalid or ZRTP packets", RTP0_INVALID }, { "stun", "STUN packets", RTP0_STUN }, { "t38", "T.38 packets", RTP0_T38 }, { NULL, NULL, 0 } @@ -480,19 +479,25 @@ dissect_rtp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) version = RTP_VERSION( octet1 ); if (version == 0) { - switch (global_rtp_version0_type) { + if (!(tvb_memeql(tvb, 4, "ZRTP", 4))) + { + call_dissector(zrtp_handle, tvb, pinfo, tree); + return TRUE; + } else { + switch (global_rtp_version0_type) { case RTP0_STUN: call_dissector(stun_handle, tvb, pinfo, tree); return TRUE; - + case RTP0_T38: call_dissector(t38_handle, tvb, pinfo, tree); return TRUE; - + case RTP0_INVALID: - + default: return FALSE; /* Unknown or unsupported version */ + } } } else if (version != 2) { /* Unknown or unsupported version */ @@ -967,8 +972,13 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) return; case RTP0_INVALID: + if (!(tvb_memeql(tvb, 4, "ZRTP", 4))) + { + call_dissector(zrtp_handle,tvb,pinfo,tree); + return; + } default: - ; /* Unknown or unsupported version (let it fall through */ + ; /* Unknown or unsupported version (let it fall through) */ } } @@ -1911,7 +1921,7 @@ proto_register_rtp(void) prefs_register_enum_preference(rtp_module, "version0_type", "Treat RTP version 0 packets as", - "If an RTP version 0 packet is encountered, it can be treated as an invalid packet, a STUN packet, or a T.38 packet", + "If an RTP version 0 packet is encountered, it can be treated as an invalid or ZRTP packet, a STUN packet, or a T.38 packet", &global_rtp_version0_type, rtp_version0_types, FALSE); prefs_register_uint_preference(rtp_module, @@ -1942,6 +1952,7 @@ proto_reg_handoff_rtp(void) data_handle = find_dissector("data"); stun_handle = find_dissector("stun"); t38_handle = find_dissector("t38"); + zrtp_handle = find_dissector("zrtp"); rtp_prefs_initialized = TRUE; } else { diff --git a/epan/dissectors/packet-zrtp.c b/epan/dissectors/packet-zrtp.c new file mode 100644 index 0000000000..46547d09dc --- /dev/null +++ b/epan/dissectors/packet-zrtp.c @@ -0,0 +1,1035 @@ +/* packet-zrtp.c + * Routines for zrtp packet dissection + * IETF draft draft-zimmermann-avt-zrtp-08 + * Copyright 2007, Sagar Pai + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * Copied from packet-pop.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include +#include +#include + + +/* + RTP header +*/ +static int proto_zrtp = -1; +static int hf_zrtp_rtpversion = -1; +static int hf_zrtp_rtppadding = -1; +static int hf_zrtp_rtpextension = -1; +static int hf_zrtp_id = -1; +static int hf_zrtp_sequence = -1; +static int hf_zrtp_cookie = -1; +static int hf_zrtp_source_id = -1; + +/* + ZRTP header +*/ +static int hf_zrtp_signature = -1; +static int hf_zrtp_msg_length = -1; +static int hf_zrtp_msg_type = -1; +static int hf_zrtp_msg_version = -1; + +/* + Hello Data +*/ +static int hf_zrtp_msg_client_id = -1; +static int hf_zrtp_msg_zid = -1; +static int hf_zrtp_msg_mitm = -1; +static int hf_zrtp_msg_passive = -1; +static int hf_zrtp_msg_hash_count = -1; +static int hf_zrtp_msg_cipher_count = -1; +static int hf_zrtp_msg_authtag_count = -1; +static int hf_zrtp_msg_key_count = -1; +static int hf_zrtp_msg_sas_count = -1; +static int hf_zrtp_msg_hash = -1; +static int hf_zrtp_msg_cipher = -1; +static int hf_zrtp_msg_at = -1; +static int hf_zrtp_msg_keya = -1; +static int hf_zrtp_msg_sas = -1; +static int hf_zrtp_msg_hash_image = -1; + +/* + Commit Data +*/ +static int hf_zrtp_msg_hvi = -1; +static int hf_zrtp_msg_nonce = -1; +static int hf_zrtp_msg_key_id = -1; + +/* + DHParts Data +*/ +static int hf_zrtp_msg_rs1ID = -1; +static int hf_zrtp_msg_rs2ID = -1; +static int hf_zrtp_msg_auxs = -1; +static int hf_zrtp_msg_pbxs = -1; + +/* + Confirm Data +*/ +static int hf_zrtp_msg_hmac = -1; +static int hf_zrtp_msg_cfb = -1; + +/* + Error Data +*/ +static int hf_zrtp_msg_error = -1; + +/* + Checksum Data +*/ +static int hf_zrtp_checksum = -1; + +/* + Sub-Tree +*/ +static gint ett_zrtp = -1; +static gint ett_zrtp_msg = -1; +static gint ett_zrtp_msg_data = -1; + +static gint ett_zrtp_msg_encrypted = -1; +static gint ett_zrtp_msg_pvr = -1; +static gint ett_zrtp_msg_hc = -1; +static gint ett_zrtp_msg_kc = -1; +static gint ett_zrtp_msg_ac = -1; +static gint ett_zrtp_msg_cc = -1; +static gint ett_zrtp_msg_sc = -1; + + +/* + Definitions +*/ +#define ZRTP_ERR_10 0x10 +#define ZRTP_ERR_20 0x20 +#define ZRTP_ERR_30 0x30 +#define ZRTP_ERR_40 0x40 +#define ZRTP_ERR_51 0x51 +#define ZRTP_ERR_52 0x52 +#define ZRTP_ERR_53 0x53 +#define ZRTP_ERR_54 0x54 +#define ZRTP_ERR_55 0x55 +#define ZRTP_ERR_61 0x61 +#define ZRTP_ERR_62 0x62 +#define ZRTP_ERR_63 0x63 +#define ZRTP_ERR_70 0x70 +#define ZRTP_ERR_80 0x80 +#define ZRTP_ERR_90 0x90 + +/* + Text for Display +*/ +typedef struct _value_zrtp_versions { + const gchar *version; +} value_zrtp_versions; + + +typedef struct _value_string_keyval { + const gchar *key; + const gchar *val; +} value_string_keyval; + + +const value_zrtp_versions valid_zrtp_versions[]= + { + {"0.95"}, + {"0.90"}, + {"0.85"}, + {NULL} + }; + +const value_string_keyval zrtp_hash_type_vals[] = + { + { "S256", "SHA-256 Hash"}, + { NULL, NULL } + }; + +const value_string_keyval zrtp_cipher_type_vals[] = + { + { "AES1", "AES-CM with 128 bit Keys"}, + { "AES3", "AES-CM with 256 bit Keys"}, + { NULL, NULL } + }; + +const value_string_keyval zrtp_auth_tag_vals[] = + { + { "HS32", "HMAC-SHA1 32 bit authentication tag"}, + { "HS80", "HMAC-SHA1 80 bit authentication tag"}, + { NULL, NULL } + }; + +const value_string_keyval zrtp_sas_type_vals[] = + { + { "B32 ", "Short authentication string using base 32"}, + { "B256", "Short authentication string using base 256"}, + { NULL, NULL } + }; + +const value_string_keyval zrtp_key_agreement_vals[] = + { + { "DH3k", "DH mode with p=3072 bit prime"}, + { "DH4k", "DH mode with p=4096 bit prime"}, + { "Prsh", "Preshared non-DH mode using shared secret"}, + { "EC25", "Elliptic Curve DH-256"}, + { "EC38", "Elliptic Curve DH-384"}, + { "EC52", "Elliptic Curve DH-521"}, + { "Mult", "Multistream mode"}, + { NULL, NULL } + }; + +const value_string zrtp_error_vals[] = + { + { ZRTP_ERR_10, "Malformed Packet (CRC OK but wrong structure)"}, + { ZRTP_ERR_20, "Critical Software Error"}, + { ZRTP_ERR_30, "Unsupported ZRTP version"}, + { ZRTP_ERR_40, "Hello Components mismatch"}, + { ZRTP_ERR_51, "Hash type unsupported"}, + { ZRTP_ERR_52, "Cipher type not supported"}, + { ZRTP_ERR_53, "Public key exchange not supported"}, + { ZRTP_ERR_54, "SRTP auth. tag not supported"}, + { ZRTP_ERR_55, "SAS scheme not supported"}, + { ZRTP_ERR_61, "DH Error: bad pv for initiator/responder value is (1,0,p-1)"}, + { ZRTP_ERR_62, "DH Error: bad hash commitment (hvi != hashed data)"}, + { ZRTP_ERR_63, "Received relayed SAS from untrusted MiTM"}, + { ZRTP_ERR_70, "Auth. Error Bad Confirm Packet HMAC"}, + { ZRTP_ERR_80, "Nonce is reused"}, + { ZRTP_ERR_90, "Equal ZID's in Hello"}, + { 0, NULL} + }; + +static void +dissect_Hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree); +static void +dissect_ErrorACK(packet_info *pinfo); +static void +dissect_Commit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree); +static void +dissect_ClearACK( packet_info *pinfo); +static void +dissect_Conf2ACK(packet_info *pinfo); +static void +dissect_HelloACK( packet_info *pinfo); +static void +dissect_GoClear(tvbuff_t *tvb,packet_info *pinfo, proto_tree *zrtp_tree); +static void +dissect_Error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree); +static void +dissect_Confirm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree,int part); +static void +dissect_DHPart(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree,int part); +static void +dissect_SASrelay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree); +static void +dissect_RelayACK(packet_info *pinfo); + + +static const gchar * +key_to_val(const gchar *key, int keylen, const value_string_keyval *kv, const gchar *fmt){ + int i=0; + while (kv[i].key) { + if (!strncmp(kv[i].key, key, keylen)){ + return(kv[i].val); + } + i++; + } + return ep_strdup_printf(fmt, key); +} + +static const gchar * +check_valid_version(const gchar *version){ + int i=0; + while (valid_zrtp_versions[i].version) { + if (!strncmp(valid_zrtp_versions[i].version, version, 4)){ + return(valid_zrtp_versions[i].version); + } + i++; + } + return NULL; +} + + +static void +dissect_zrtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *zrtp_tree; + proto_tree *zrtp_msg_tree; + proto_tree *zrtp_msg_data_tree; + proto_item *ti; + int linelen; + int checksum_offset; + unsigned char message_type[9]; + unsigned int prime_offset = 0; + unsigned int msg_offset = 12; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZRTP"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ZRTP Packet"); + + ti = proto_tree_add_protocol_format(tree,proto_zrtp,tvb,0,-1,"ZRTP protocol"); + zrtp_tree = proto_item_add_subtree(ti,ett_zrtp); + + proto_tree_add_item(zrtp_tree,hf_zrtp_rtpversion,tvb,prime_offset+0,1,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_rtppadding,tvb,prime_offset+0,1,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_rtpextension,tvb,prime_offset+0,1,FALSE); + + proto_tree_add_item(zrtp_tree,hf_zrtp_sequence,tvb,prime_offset+2,2,FALSE); + + proto_tree_add_item(zrtp_tree,hf_zrtp_cookie,tvb,prime_offset+4,4,FALSE); + + proto_tree_add_item(zrtp_tree,hf_zrtp_source_id,tvb,prime_offset+8,4,FALSE); + + linelen = tvb_reported_length_remaining(tvb,msg_offset); + checksum_offset = linelen-4; + + ti = proto_tree_add_protocol_format(zrtp_tree,proto_zrtp,tvb,msg_offset,linelen-4,"Message"); + zrtp_msg_tree = proto_item_add_subtree(ti,ett_zrtp_msg); + + proto_tree_add_item(zrtp_msg_tree,hf_zrtp_signature,tvb,msg_offset+0,2,FALSE); + + proto_tree_add_item(zrtp_msg_tree,hf_zrtp_msg_length,tvb,msg_offset+2,2,FALSE); + + tvb_memcpy(tvb,(void *)message_type,msg_offset+4,8); + message_type[8] = 0; + proto_tree_add_item(zrtp_msg_tree,hf_zrtp_msg_type,tvb,msg_offset+4,8,FALSE); + + linelen = tvb_reported_length_remaining(tvb,msg_offset+12); + + if (!strncmp(message_type,"Hello ",8)){ + ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data"); + zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data); + dissect_Hello(tvb,pinfo,zrtp_msg_data_tree); + } else if (!strncmp(message_type,"HelloACK",8)){ + dissect_HelloACK(pinfo); + } else if (!strncmp(message_type,"Commit ",8)){ + ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data"); + zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data); + dissect_Commit(tvb,pinfo,zrtp_msg_data_tree); + } else if (!strncmp(message_type,"DHPart1 ",8)){ + ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data"); + zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data); + dissect_DHPart(tvb,pinfo,zrtp_msg_data_tree,1); + } else if (!strncmp(message_type,"DHPart2 ",8)){ + ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data"); + zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data); + dissect_DHPart(tvb,pinfo,zrtp_msg_data_tree,2); + } else if (!strncmp(message_type,"Confirm1",8)){ + ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data"); + zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data); + dissect_Confirm(tvb,pinfo,zrtp_msg_data_tree,1); + } else if (!strncmp(message_type,"Confirm2",8)){ + ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data"); + zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data); + dissect_Confirm(tvb,pinfo,zrtp_msg_data_tree,2); + } else if (!strncmp(message_type,"Conf2ACK",8)){ + dissect_Conf2ACK(pinfo); + } else if (!strncmp(message_type,"Error ",8)){ + ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data"); + zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data); + dissect_Error(tvb,pinfo,zrtp_msg_data_tree); + } else if (!strncmp(message_type,"ErrorACK",8)){ + dissect_ErrorACK(pinfo); + } else if (!strncmp(message_type,"GoClear ",8)){ + ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data"); + zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data); + dissect_GoClear(tvb,pinfo,zrtp_msg_data_tree); + } else if (!strncmp(message_type,"ClearACK",8)){ + dissect_ClearACK(pinfo); + } else if (!strncmp(message_type,"SASrelay",8)){ + ti = proto_tree_add_protocol_format(zrtp_msg_tree,proto_zrtp,tvb,msg_offset+12,linelen-4,"Data"); + zrtp_msg_data_tree = proto_item_add_subtree(ti,ett_zrtp_msg_data); + dissect_SASrelay(tvb,pinfo,zrtp_msg_data_tree); + } else if (!strncmp(message_type,"RelayACK",8)){ + dissect_RelayACK(pinfo); + } + + proto_tree_add_item(zrtp_tree,hf_zrtp_checksum,tvb,msg_offset+checksum_offset,4,FALSE); +} + +static void +dissect_ErrorACK(packet_info *pinfo) { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "ErrorACK Packet"); + } +} + +static void +dissect_ClearACK(packet_info *pinfo) { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "ClearACK Packet"); + } +} + +static void +dissect_RelayACK(packet_info *pinfo) { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "RelayACK Packet"); + } +} + +static void +dissect_Conf2ACK(packet_info *pinfo) { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "Conf2ACK Packet"); + } +} + +static void +dissect_HelloACK(packet_info *pinfo) { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "HelloACK Packet"); + } +} + +static void +dissect_GoClear(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) { + unsigned int data_offset=24; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "GoClear Packet"); + } + + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+0,8,FALSE); +} + +static void +dissect_Error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) { + unsigned int data_offset=24; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "Error Packet"); + } + + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_error,tvb,data_offset,4,FALSE); +} + +static void +dissect_Confirm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree,int part) { + proto_item *ti; + unsigned int data_offset=24; + proto_tree *zrtp_msg_encrypted_tree; + int linelen; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, (part == 1) ? "Confirm1 Packet" : "Confirm2 Packet"); + } + + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+0,8,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_cfb,tvb,data_offset+8,16,FALSE); + linelen = tvb_reported_length_remaining(tvb,data_offset+24); + ti = proto_tree_add_protocol_format(zrtp_tree,proto_zrtp,tvb,data_offset+24,linelen-4,"Encrypted Data"); + zrtp_msg_encrypted_tree = proto_item_add_subtree(ti,ett_zrtp_msg_encrypted); +} + +static void +dissect_SASrelay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) { + proto_item *ti; + unsigned int data_offset=24; + proto_tree *zrtp_msg_encrypted_tree; + int linelen; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "SASrelay Packet"); + } + + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+0,8,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_cfb,tvb,data_offset+8,16,FALSE); + linelen = tvb_reported_length_remaining(tvb,data_offset+24); + ti = proto_tree_add_protocol_format(zrtp_tree,proto_zrtp,tvb,data_offset+24,linelen-4,"Encrypted Data"); + zrtp_msg_encrypted_tree = proto_item_add_subtree(ti,ett_zrtp_msg_encrypted); +} + +static void +dissect_DHPart(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree,int part) { + proto_item *ti; + unsigned int msg_offset=12; + unsigned int data_offset=56; + proto_tree *zrtp_msg_pvr_tree; + int linelen, pvr_len; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, (part == 1) ? "DHPart1 Packet" : "DHPart2 Packet"); + } + + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hash_image,tvb,msg_offset+12,32,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_rs1ID,tvb,data_offset+0,8,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_rs2ID,tvb,data_offset+8,8,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_auxs,tvb,data_offset+16,8,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_pbxs,tvb,data_offset+24,8,FALSE); + linelen = tvb_reported_length_remaining(tvb,data_offset+32); + pvr_len = linelen-8-4; + ti = proto_tree_add_protocol_format(zrtp_tree,proto_zrtp,tvb,data_offset+32,pvr_len,"pvr/nouncer Data"); + zrtp_msg_pvr_tree = proto_item_add_subtree(ti,ett_zrtp_msg_pvr); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+32+pvr_len,8,FALSE); +} + +static void +dissect_Commit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) { + unsigned int msg_offset=12; + unsigned int data_offset=56; + unsigned char value[5]; + int key_type = 0; + /* + 0 - other type + 1 - "Mult" + 2 - "Prsh" + */ + unsigned int offset; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "Commit Packet"); + } + + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hash_image,tvb,msg_offset+12,32,FALSE); + /* ZID */ + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_zid,tvb,data_offset+0,12,FALSE); + tvb_memcpy(tvb,(void *)value,data_offset+12,4); + value[4]=0; + proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_hash,tvb,data_offset+12,4,value, + "Hash: %s",key_to_val(value,4,zrtp_hash_type_vals,"Unknown hash type %s")); + tvb_memcpy(tvb,(void *)value,data_offset+16,4); + value[4]=0; + proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_cipher,tvb,data_offset+16,4,value,"Cipher: %s", + key_to_val(value,4,zrtp_cipher_type_vals,"Unknown cipher type %s")); + tvb_memcpy(tvb,(void *)value,data_offset+20,4); + value[4]=0; + proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_at,tvb,data_offset+20,4,value, + "Auth tag: %s",key_to_val(value,4,zrtp_auth_tag_vals,"Unknown auth tag %s")); + tvb_memcpy(tvb,(void *)value,data_offset+24,4); + value[4]=0; + proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_keya,tvb,data_offset+24,4,value, + "Key agreement: %s",key_to_val(value,4,zrtp_key_agreement_vals,"Unknown key agreement %s")); + + if(!strncmp(value, "Mult", 4)){ + key_type = 1; + } else if (!strncmp(value, "Prsh", 4)){ + key_type = 2; + } + tvb_memcpy(tvb,(void *)value,data_offset+28,4); + value[4]=0; + proto_tree_add_string_format(zrtp_tree,hf_zrtp_msg_sas,tvb,data_offset+28,4,value, + "Sas type: %s",key_to_val(value,4,zrtp_sas_type_vals,"Unknown sas type %s")); + + switch(key_type){ + case 1: /* + Mult + */ + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_nonce,tvb,data_offset+32,16,FALSE); + offset = 48; + break; + case 2: /* + Prsh + */ + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_nonce,tvb,data_offset+32,16,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_key_id,tvb,data_offset+48,8,FALSE); + offset = 56; + break; + default: /* + other + */ + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hvi,tvb,data_offset+32, 32, FALSE); + offset = 64; + break; + } + + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hmac,tvb,data_offset+offset,8,FALSE); +} + +static void +dissect_Hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) { + proto_item *ti; + unsigned int msg_offset = 12; + unsigned int data_offset = 88; + guint8 val_b; + unsigned int i; + unsigned int run_offset; + unsigned int hc,cc,ac,kc,sc; + unsigned int vhc,vcc,vac,vkc,vsc; + unsigned char value[5]; + unsigned char version_str[5]; + proto_tree *tmp_tree; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "Hello Packet"); + } + + tvb_memcpy(tvb,version_str,msg_offset+12,4); + version_str[4]='\0'; + if (check_valid_version(version_str) == NULL){ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_fstr(pinfo->cinfo, COL_INFO, "Unsupported version of ZRTP protocol"); + } + } + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_version,tvb,msg_offset+12,4,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_client_id,tvb,msg_offset+16,16,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_hash_image,tvb,msg_offset+32,32,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_zid,tvb,msg_offset+64,12,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_mitm,tvb,data_offset+0,1,FALSE); + proto_tree_add_item(zrtp_tree,hf_zrtp_msg_passive,tvb,data_offset+0,1,FALSE); + + val_b = tvb_get_guint8(tvb,data_offset+1); + hc = val_b & 0x0F; + vhc = hc; + + val_b = tvb_get_guint8(tvb,data_offset+2); + cc = val_b & 0xF0; + ac = val_b & 0x0F; + vcc = cc >> 4; + vac = ac; + + val_b = tvb_get_guint8(tvb,data_offset+3); + kc = val_b & 0xF0; + sc = val_b & 0x0F; + vkc = kc >> 4; + vsc = sc; + + ti=proto_tree_add_uint_format(zrtp_tree,hf_zrtp_msg_hash_count,tvb,data_offset+1,1,hc,"Hash type count = %d",vhc); + tmp_tree = proto_item_add_subtree(ti,ett_zrtp_msg_hc); + run_offset = data_offset+4; + for(i=0;i