From 82cec1ce8971eaf24d6e37debdcd5eee9479519c Mon Sep 17 00:00:00 2001 From: Anders Broman Date: Sun, 8 Jan 2012 15:34:23 +0000 Subject: [PATCH] From Martin Kaiser: DVB-CI / CI+ decrypt SAC messages. https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6700 svn path=/trunk/; revision=40407 --- epan/dissectors/packet-dvbci.c | 159 +++++++++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 8 deletions(-) diff --git a/epan/dissectors/packet-dvbci.c b/epan/dissectors/packet-dvbci.c index 38391c1834..ee7cf8d28c 100644 --- a/epan/dissectors/packet-dvbci.c +++ b/epan/dissectors/packet-dvbci.c @@ -46,6 +46,13 @@ #include "packet-ber.h" +#ifdef HAVE_LIBGCRYPT +#include +#endif + + +#define AES_BLOCK_LEN 16 +#define AES_KEY_LEN 16 /* event byte in the pseudo-header */ #define DATA_CAM_TO_HOST 0xFF @@ -365,6 +372,9 @@ typedef struct _apdu_info_t { tvbuff_t *, gint, packet_info *, proto_tree *); } apdu_info_t; + +void proto_reg_handoff_dvbci(void); + static void dissect_dvbci_payload_rm(guint32 tag, gint len_field, tvbuff_t *tvb, gint offset, packet_info *pinfo, @@ -706,9 +716,11 @@ static const value_string dvbci_apdu_tag[] = { /* convert a byte that contains two 4bit BCD digits into a decimal value */ #define BCD44_TO_DEC(x) (((x&0xf0) >> 4) * 10 + (x&0x0f)) - static int proto_dvbci = -1; +static gchar* dvbci_sek = NULL; +static gchar* dvbci_siv = NULL; + static gint ett_dvbci = -1; static gint ett_dvbci_hdr = -1; static gint ett_dvbci_cis = -1; @@ -830,7 +842,7 @@ static int hf_dvbci_sac_auth_cip = -1; static int hf_dvbci_sac_payload_enc = -1; static int hf_dvbci_sac_enc_cip = -1; static int hf_dvbci_sac_payload_len = -1; -static int hf_dvbci_sac_body = -1; +static int hf_dvbci_sac_enc_body = -1; static int hf_dvbci_rating = -1; static int hf_dvbci_capability_field = -1; static int hf_dvbci_pin_chg_time = -1; @@ -1679,6 +1691,109 @@ dissect_cc_item(tvbuff_t *tvb, gint offset, } +#ifdef HAVE_LIBGCRYPT +/* convert a 0-terminated preference key_string that contains a hex number + * into its binary representation + * e.g. key_string "abcd" will be converted into two bytes 0xab, 0xcd + * return the number of binary bytes or -1 for error */ +static gint +pref_key_string_to_bin(const gchar *key_string, unsigned char **key_bin) +{ + int key_string_len; + int i, j; + char input[2]; + + if (!key_string || !key_bin) + return -1; + key_string_len = (int)strlen(key_string); + if (key_string_len != 2*AES_KEY_LEN) + return -1; + *key_bin = (unsigned char*)g_malloc(key_string_len/2); + + j=0; + for (i=0; icinfo, COL_INFO, NULL, "encrypted"); offset++; + enc_cip = (tvb_get_guint8(tvb, offset)&0xE0) >> 5; proto_tree_add_item( tree, hf_dvbci_sac_enc_cip, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; @@ -2618,9 +2735,25 @@ dissect_dvbci_payload_cc(guint32 tag, gint len_field _U_, offset += 2; if (tvb_reported_length_remaining(tvb, offset) < 0) break; - /* please note that payload != body */ - proto_tree_add_item(tree, hf_dvbci_sac_body, tvb, offset, - tvb_reported_length_remaining(tvb, offset), ENC_NA); + if (!enc_flag) { + pi = proto_tree_add_text(tree, tvb, offset, + tvb_reported_length_remaining(tvb, offset), + "Invalid CI+ SAC message body"); + expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, + "SAC message body must always be encrypted"); + break; + } + + clear_sac_body_tvb = decrypt_sac_msg_body(enc_cip, + tvb, offset, tvb_reported_length_remaining(tvb, offset)); + if (!clear_sac_body_tvb) { + /* we could not decrypt the sac message body */ + proto_tree_add_item(tree, hf_dvbci_sac_enc_body, tvb, offset, + tvb_reported_length_remaining(tvb, offset), ENC_NA); + break; + } + add_new_data_source(pinfo, clear_sac_body_tvb, + "Clear SAC message body"); break; case T_CC_PIN_CAPABILITIES_REPLY: proto_tree_add_item(tree, hf_dvbci_capability_field, @@ -3972,6 +4105,7 @@ void proto_register_dvbci(void) { guint i; + module_t *dvbci_module; static gint *ett[] = { &ett_dvbci, @@ -4304,8 +4438,8 @@ proto_register_dvbci(void) { &hf_dvbci_sac_payload_len, { "Payload length", "dvb-ci.cc.sac.payload_len", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, - { &hf_dvbci_sac_body, - { "SAC body", "dvb-ci.cc.sac_body", FT_BYTES, + { &hf_dvbci_sac_enc_body, + { "Encrypted SAC body", "dvb-ci.cc.sac.enc_body", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_dvbci_rating, { "Rating", "dvb-ci.cc.rating", FT_UINT8, BASE_DEC, @@ -4578,6 +4712,15 @@ proto_register_dvbci(void) proto_register_field_array(proto_dvbci, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); + dvbci_module = prefs_register_protocol( + proto_dvbci, proto_reg_handoff_dvbci); + prefs_register_string_preference(dvbci_module, + "sek", "SAC Encryption Key", "SAC Encryption Key (16 hex bytes)", + (const gchar **)&dvbci_sek); + prefs_register_string_preference(dvbci_module, + "siv", "SAC Init Vector", "SAC Init Vector (16 hex bytes)", + (const gchar **)&dvbci_siv); + register_init_routine(dvbci_init); }