From fc88f5558ad682448286614f2c303f50cc591896 Mon Sep 17 00:00:00 2001 From: Alexis La Goutte Date: Fri, 24 Feb 2012 07:57:48 +0000 Subject: From Martin Kaiser via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6838 Support HDCP version 1 over I2c the attached patch adds support for HDCP version 1. This is the authentication that runs between your DVD/Bluray player and your TV when they're connected via an HDMI cable. svn path=/trunk/; revision=41172 --- epan/dissectors/Makefile.common | 1 + epan/dissectors/packet-hdcp.c | 494 +++++++++++++++++++++++++++++++++------- epan/dissectors/packet-i2c.c | 10 +- 3 files changed, 420 insertions(+), 85 deletions(-) diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 2e32105f35..6e7a53df61 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -1231,6 +1231,7 @@ DISSECTOR_INCLUDES = \ packet-h450-ros.h \ packet-hci_h4.h \ packet-hclnfsd.h \ + packet-hdcp.h \ packet-hpext.h \ packet-http.h \ packet-i2c.h \ diff --git a/epan/dissectors/packet-hdcp.c b/epan/dissectors/packet-hdcp.c index 7b07993e30..27dc5ce866 100644 --- a/epan/dissectors/packet-hdcp.c +++ b/epan/dissectors/packet-hdcp.c @@ -1,6 +1,6 @@ /* packet-hdcp.c * Routines for HDCP dissection - * Copyright 2011, Martin Kaiser + * Copyright 2011-2012, Martin Kaiser * * $Id$ * @@ -23,8 +23,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* This dissector is based on the HDCP 2.1 specification. - It supports the most common authentication protocol messages. */ +/* This dissector supports HDCP 1.x over I2C and HDCP 2.x over TCP. + For now, only the most common authentication protocol messages are + recognized. */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -37,30 +38,69 @@ #include -static int proto_hdcp = -1; -static gboolean hdcp_enable_dissector = FALSE; +static int proto_hdcp = -1; +static int proto_hdcp2 = -1; -void proto_reg_handoff_hdcp(void); +static gboolean hdcp2_enable_dissector = FALSE; +static emem_tree_t *transactions = NULL; + +void proto_reg_handoff_hdcp2(void); + +/* etts are shared by hdcp and hdcp2 */ static gint ett_hdcp = -1; static gint ett_hdcp_cert = -1; -static int hf_hdcp_msg_id = -1; -static int hf_hdcp_r_tx = -1; +static int hf_hdcp_addr = -1; +static int hf_hdcp_reg = -1; +static int hf_hdcp_resp_in = -1; +static int hf_hdcp_resp_to = -1; +static int hf_hdcp_a_ksv = -1; +static int hf_hdcp_b_ksv = -1; +static int hf_hdcp_an = -1; +static int hf_hdcp_hdmi_reserved = -1; static int hf_hdcp_repeater = -1; -static int hf_hdcp_cert_rcv_id = -1; -static int hf_hdcp_cert_n = -1; -static int hf_hdcp_cert_e = -1; -static int hf_hdcp_cert_rcv_sig = -1; -static int hf_hdcp_e_kh_km = -1; -static int hf_hdcp_m = -1; -static int hf_hdcp_r_rx = -1; -static int hf_hdcp_h_prime = -1; -static int hf_hdcp_r_n = -1; -static int hf_hdcp_l_prime = -1; -static int hf_hdcp_e_dkey_ks = -1; -static int hf_hdcp_r_iv = -1; - +static int hf_hdcp_ksv_fifo = -1; +static int hf_hdcp_fast_trans = -1; +static int hf_hdcp_features = -1; +static int hf_hdcp_fast_reauth = -1; +static int hf_hdcp_hdmi_mode = -1; +static int hf_hdcp_max_casc_exc = -1; +static int hf_hdcp_depth = -1; +static int hf_hdcp_max_devs_exc = -1; +static int hf_hdcp_downstream = -1; +static int hf_hdcp_link_vfy = -1; +static int hf_hdcp2_msg_id = -1; +static int hf_hdcp2_r_tx = -1; +static int hf_hdcp2_repeater = -1; +static int hf_hdcp2_cert_rcv_id = -1; +static int hf_hdcp2_cert_n = -1; +static int hf_hdcp2_cert_e = -1; +static int hf_hdcp2_cert_rcv_sig = -1; +static int hf_hdcp2_e_kh_km = -1; +static int hf_hdcp2_m = -1; +static int hf_hdcp2_r_rx = -1; +static int hf_hdcp2_h_prime = -1; +static int hf_hdcp2_r_n = -1; +static int hf_hdcp2_l_prime = -1; +static int hf_hdcp2_e_dkey_ks = -1; +static int hf_hdcp2_r_iv = -1; + +/* the addresses used by this dissector are 8bit, including the direction bit + (to be in line with the HDCP specification) */ +#define ADDR8_HDCP_WRITE 0x74 /* transmitter->receiver */ +#define ADDR8_HDCP_READ 0x75 /* receiver->transmitter */ + +#define HDCP_ADDR8(x) (x==ADDR8_HDCP_WRITE || x==ADDR8_HDCP_READ) + +#define ADDR8_RCV "Receiver" +#define ADDR8_TRX "Transmitter" + +#define REG_BKSV 0x0 +#define REG_AKSV 0x10 +#define REG_AN 0x18 +#define REG_BCAPS 0x40 +#define REG_BSTATUS 0x41 #define ID_AKE_INIT 2 #define ID_AKE_SEND_CERT 3 @@ -79,6 +119,26 @@ static int hf_hdcp_r_iv = -1; #define CERT_RX_LEN (RCV_ID_LEN + N_LEN + E_LEN + 2 + RCV_SIG_LEN) +typedef struct _hdcp_transaction_t { + guint32 rqst_frame; + guint32 resp_frame; + guint8 rqst_type; +} hdcp_transaction_t; + +static const value_string hdcp_addr[] = { + { ADDR8_HDCP_WRITE, "transmitter writes data for receiver" }, + { ADDR8_HDCP_READ, "transmitter reads data from receiver" }, + { 0, NULL } +}; + +static const value_string hdcp_reg[] = { + { REG_BKSV, "B_ksv" }, + { REG_AKSV, "A_ksv" }, + { REG_AN, "An" }, + { REG_BCAPS, "B_caps"}, + { REG_BSTATUS, "B_status"}, + { 0, NULL } +}; static const value_string hdcp_msg_id[] = { { ID_AKE_INIT, "AKE_Init" }, @@ -108,17 +168,216 @@ static const msg_info_t msg_info[] = { { ID_LC_INIT, 8 }, { ID_LC_SEND_L_PRIME, 32 }, { ID_SKE_SEND_EKS, 24 } - }; +}; + + +gboolean +sub_check_hdcp(packet_info *pinfo _U_) +{ + /* by looking at the i2c_phdr only, we can't decide if this packet is HDCPv1 + this function is called when the user explicitly selected HDCPv1 + in the preferences + therefore, we always return TRUE and hand the data to the (new + style) dissector who will check if the packet is HDCPv1 */ + + return TRUE; +} + + +static void +hdcp_init(void) +{ + /* se_...() allocations are automatically cleared when a new capture starts, + so we should be safe to create the tree without any previous checks */ + transactions = se_tree_create_non_persistent( + EMEM_TREE_TYPE_RED_BLACK, "hdcp_transactions"); +} + static int dissect_hdcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - msg_info_t *mi; - proto_item *pi; - proto_tree *hdcp_tree = NULL, *cert_tree = NULL; - guint8 msg_id; - gboolean repeater; - guint16 reserved; + guint8 addr, reg; + proto_item *pi; + ptvcursor_t *cursor; + proto_tree *hdcp_tree = NULL; + hdcp_transaction_t *hdcp_trans; + proto_item *it; + guint64 a_ksv, b_ksv; + + addr = tvb_get_guint8(tvb, 0); + if (!HDCP_ADDR8(addr)) + return 0; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "HDCP"); + col_clear(pinfo->cinfo, COL_INFO); + + if (tree) { + pi = proto_tree_add_protocol_format(tree, proto_hdcp, + tvb, 0, tvb_reported_length(tvb), "HDCP"); + hdcp_tree = proto_item_add_subtree(pi, ett_hdcp); + } + + cursor = ptvcursor_new(hdcp_tree, tvb, 0); + /* all values in HDCP are little endian */ + ptvcursor_add(cursor, hf_hdcp_addr, 1, ENC_LITTLE_ENDIAN); + + if (addr==ADDR8_HDCP_WRITE) { + /* transmitter sends data to the receiver */ + SET_ADDRESS(&pinfo->src, AT_STRINGZ, (int)strlen(ADDR8_TRX)+1, ADDR8_TRX); + SET_ADDRESS(&pinfo->dst, AT_STRINGZ, (int)strlen(ADDR8_RCV)+1, ADDR8_RCV); + + reg = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); + ptvcursor_add(cursor, hf_hdcp_reg, 1, ENC_LITTLE_ENDIAN); + + if (tvb_reported_length_remaining(tvb, + ptvcursor_current_offset(cursor)) == 0) { + /* transmitter requests the content of a register */ + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "request %s", + val_to_str(reg, hdcp_reg, "unknown (0x%x)")); + + if (PINFO_FD_VISITED(pinfo)) { + /* we've already dissected the receiver's response */ + hdcp_trans = se_tree_lookup32(transactions, PINFO_FD_NUM(pinfo)); + if (hdcp_trans && hdcp_trans->rqst_frame==PINFO_FD_NUM(pinfo) && + hdcp_trans->resp_frame!=0) { + + it = proto_tree_add_uint_format(hdcp_tree, hf_hdcp_resp_in, + NULL, 0, 0, hdcp_trans->resp_frame, + "Request to get the content of register %s, " + "response in frame %d", + val_to_str_const(hdcp_trans->rqst_type, + hdcp_reg, "unknown (0x%x)"), + hdcp_trans->resp_frame); + PROTO_ITEM_SET_GENERATED(it); + } + } + else { + /* we've not yet dissected the response */ + if (transactions) { + hdcp_trans = se_alloc(sizeof(hdcp_transaction_t)); + hdcp_trans->rqst_frame = PINFO_FD_NUM(pinfo); + hdcp_trans->resp_frame = 0; + hdcp_trans->rqst_type = reg; + se_tree_insert32(transactions, + hdcp_trans->rqst_frame, (void *)hdcp_trans); + } + } + } + else { + /* transmitter actually sends protocol data */ + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "send %s", + val_to_str(reg, hdcp_reg, "unknown (0x%x)")); + switch (reg) { + case REG_AKSV: + a_ksv = tvb_get_letoh40(tvb, + ptvcursor_current_offset(cursor)); + proto_tree_add_uint64_format(hdcp_tree, hf_hdcp_a_ksv, + tvb, ptvcursor_current_offset(cursor), 5, + a_ksv, "A_ksv 0x%010" G_GINT64_MODIFIER "x", a_ksv); + ptvcursor_advance(cursor, 5); + break; + case REG_AN: + ptvcursor_add(cursor, hf_hdcp_an, 8, ENC_LITTLE_ENDIAN); + break; + default: + break; + } + } + } + else { + /* transmitter reads from receiver */ + SET_ADDRESS(&pinfo->src, AT_STRINGZ, (int)strlen(ADDR8_RCV)+1, ADDR8_RCV); + SET_ADDRESS(&pinfo->dst, AT_STRINGZ, (int)strlen(ADDR8_TRX)+1, ADDR8_TRX); + + if (transactions) { + hdcp_trans = se_tree_lookup32_le(transactions, PINFO_FD_NUM(pinfo)); + if (hdcp_trans) { + if (hdcp_trans->resp_frame==0) { + /* there's a pending request, this packet is the response */ + hdcp_trans->resp_frame = PINFO_FD_NUM(pinfo); + } + + if (hdcp_trans->resp_frame== PINFO_FD_NUM(pinfo)) { + /* we found the request that corresponds to our response */ + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "send %s", + val_to_str_const(hdcp_trans->rqst_type, + hdcp_reg, "unknown (0x%x)")); + it = proto_tree_add_uint_format(hdcp_tree, hf_hdcp_resp_to, + NULL, 0, 0, hdcp_trans->rqst_frame, + "Response to frame %d (content of register %s)", + hdcp_trans->rqst_frame, + val_to_str_const(hdcp_trans->rqst_type, + hdcp_reg, "unknown (0x%x)")); + PROTO_ITEM_SET_GENERATED(it); + switch (hdcp_trans->rqst_type) { + case REG_BKSV: + b_ksv = tvb_get_letoh40(tvb, + ptvcursor_current_offset(cursor)); + proto_tree_add_uint64_format(hdcp_tree, hf_hdcp_b_ksv, + tvb, ptvcursor_current_offset(cursor), 5, + b_ksv, "B_ksv 0x%010" G_GINT64_MODIFIER "x", + b_ksv); + ptvcursor_advance(cursor, 5); + break; + case REG_BCAPS: + ptvcursor_add_no_advance(cursor, + hf_hdcp_hdmi_reserved, 1, ENC_LITTLE_ENDIAN); + ptvcursor_add_no_advance(cursor, + hf_hdcp_repeater, 1, ENC_LITTLE_ENDIAN); + ptvcursor_add_no_advance(cursor, + hf_hdcp_ksv_fifo, 1, ENC_LITTLE_ENDIAN); + ptvcursor_add_no_advance(cursor, + hf_hdcp_fast_trans, 1, ENC_LITTLE_ENDIAN); + ptvcursor_add_no_advance(cursor, + hf_hdcp_features, 1, ENC_LITTLE_ENDIAN); + ptvcursor_add_no_advance(cursor, + hf_hdcp_fast_reauth, 1, ENC_LITTLE_ENDIAN); + break; + case REG_BSTATUS: + ptvcursor_add_no_advance(cursor, + hf_hdcp_hdmi_mode, 2, ENC_LITTLE_ENDIAN); + ptvcursor_add_no_advance(cursor, + hf_hdcp_max_casc_exc, 2, ENC_LITTLE_ENDIAN); + ptvcursor_add_no_advance(cursor, + hf_hdcp_depth, 2, ENC_LITTLE_ENDIAN); + ptvcursor_add_no_advance(cursor, + hf_hdcp_max_devs_exc, 2, ENC_LITTLE_ENDIAN); + ptvcursor_add_no_advance(cursor, + hf_hdcp_downstream, 2, ENC_LITTLE_ENDIAN); + break; + } + } + } + + if (!hdcp_trans || hdcp_trans->resp_frame!=PINFO_FD_NUM(pinfo)) { + /* the packet isn't a response to a request from the + * transmitter; it must be a link verification */ + if (tvb_reported_length_remaining( + tvb, ptvcursor_current_offset(cursor)) == 2) { + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, + "send link verification Ri'"); + ptvcursor_add_no_advance(cursor, + hf_hdcp_link_vfy, 2, ENC_LITTLE_ENDIAN); + } + } + } + } + + ptvcursor_free(cursor); + return tvb_reported_length(tvb); +} + + +static int +dissect_hdcp2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + msg_info_t *mi; + proto_item *pi; + proto_tree *hdcp_tree = NULL, *cert_tree = NULL; + guint8 msg_id; + gboolean repeater; + guint16 reserved; ptvcursor_t *cursor; /* do the plausibility checks before setting up anything */ @@ -137,32 +396,32 @@ dissect_hdcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) if (tree) { pi = proto_tree_add_protocol_format(tree, proto_hdcp, - tvb, 0, tvb_reported_length(tvb), "HDCP"); + tvb, 0, tvb_reported_length(tvb), "HDCPv2"); hdcp_tree = proto_item_add_subtree(pi, ett_hdcp); } cursor = ptvcursor_new(hdcp_tree, tvb, 0); col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(msg_id, hdcp_msg_id, "unknown (0x%x)")); - ptvcursor_add(cursor, hf_hdcp_msg_id, 1, ENC_BIG_ENDIAN); + ptvcursor_add(cursor, hf_hdcp2_msg_id, 1, ENC_BIG_ENDIAN); switch (msg_id) { case ID_AKE_INIT: - ptvcursor_add(cursor, hf_hdcp_r_tx, 8, ENC_BIG_ENDIAN); + ptvcursor_add(cursor, hf_hdcp2_r_tx, 8, ENC_BIG_ENDIAN); break; case ID_AKE_SEND_CERT: repeater = ((tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)) & 0x01) == 0x01); col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s", repeater ? "repeater" : "no repeater"); - ptvcursor_add(cursor, hf_hdcp_repeater, 1, ENC_BIG_ENDIAN); + ptvcursor_add(cursor, hf_hdcp2_repeater, 1, ENC_BIG_ENDIAN); if (hdcp_tree) { cert_tree = ptvcursor_add_text_with_subtree(cursor, CERT_RX_LEN, ett_hdcp_cert, "%s", "HDCP Certificate"); } - ptvcursor_add(cursor, hf_hdcp_cert_rcv_id, RCV_ID_LEN, ENC_NA); - ptvcursor_add(cursor, hf_hdcp_cert_n, N_LEN, ENC_NA); - ptvcursor_add(cursor, hf_hdcp_cert_e, E_LEN, ENC_BIG_ENDIAN); + ptvcursor_add(cursor, hf_hdcp2_cert_rcv_id, RCV_ID_LEN, ENC_NA); + ptvcursor_add(cursor, hf_hdcp2_cert_n, N_LEN, ENC_NA); + ptvcursor_add(cursor, hf_hdcp2_cert_e, E_LEN, ENC_BIG_ENDIAN); reserved = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); proto_tree_add_text(cert_tree, tvb, ptvcursor_current_offset(cursor), 2, "reserved bytes"); @@ -173,29 +432,29 @@ dissect_hdcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) "reserved bytes must be set to 0x0"); } ptvcursor_advance(cursor, 2); - ptvcursor_add(cursor, hf_hdcp_cert_rcv_sig, RCV_SIG_LEN, ENC_NA); + ptvcursor_add(cursor, hf_hdcp2_cert_rcv_sig, RCV_SIG_LEN, ENC_NA); if (cert_tree) ptvcursor_pop_subtree(cursor); break; case ID_AKE_STORED_KM: - ptvcursor_add(cursor, hf_hdcp_e_kh_km, 16, ENC_NA); - ptvcursor_add(cursor, hf_hdcp_m, 16, ENC_NA); + ptvcursor_add(cursor, hf_hdcp2_e_kh_km, 16, ENC_NA); + ptvcursor_add(cursor, hf_hdcp2_m, 16, ENC_NA); break; case ID_AKE_SEND_RRX: - ptvcursor_add(cursor, hf_hdcp_r_rx, 8, ENC_BIG_ENDIAN); + ptvcursor_add(cursor, hf_hdcp2_r_rx, 8, ENC_BIG_ENDIAN); break; case ID_AKE_SEND_H_PRIME: - ptvcursor_add(cursor, hf_hdcp_h_prime, 32, ENC_NA); + ptvcursor_add(cursor, hf_hdcp2_h_prime, 32, ENC_NA); break; case ID_LC_INIT: - ptvcursor_add(cursor, hf_hdcp_r_n, 8, ENC_BIG_ENDIAN); + ptvcursor_add(cursor, hf_hdcp2_r_n, 8, ENC_BIG_ENDIAN); break; case ID_LC_SEND_L_PRIME: - ptvcursor_add(cursor, hf_hdcp_l_prime, 32, ENC_NA); + ptvcursor_add(cursor, hf_hdcp2_l_prime, 32, ENC_NA); break; case ID_SKE_SEND_EKS: - ptvcursor_add(cursor, hf_hdcp_e_dkey_ks, 16, ENC_NA); - ptvcursor_add(cursor, hf_hdcp_r_iv, 8, ENC_BIG_ENDIAN); + ptvcursor_add(cursor, hf_hdcp2_e_dkey_ks, 16, ENC_NA); + ptvcursor_add(cursor, hf_hdcp2_r_iv, 8, ENC_BIG_ENDIAN); break; default: break; @@ -205,65 +464,125 @@ dissect_hdcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) return tvb_reported_length(tvb); } + + void proto_register_hdcp(void) { guint i; static hf_register_info hf[] = { - { &hf_hdcp_msg_id, - { "Message ID", "hdcp.msg_id", FT_UINT8, BASE_HEX, + { &hf_hdcp_addr, + { "8bit I2C address", "hdcp.addr", FT_UINT8, BASE_HEX, + VALS(hdcp_addr), 0, NULL, HFILL } }, + { &hf_hdcp_reg, + { "Register offset", "hdcp.reg", FT_UINT8, BASE_HEX, + VALS(hdcp_reg), 0, NULL, HFILL } }, + { &hf_hdcp_resp_in, + { "Response In", "hdcp.resp_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "The response to this request is in this frame", HFILL }}, + { &hf_hdcp_resp_to, + { "Response To", "hdcp.resp_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "This is the response to the request in this frame", HFILL }}, + /* actually, the KSVs are only 40bits, but there's no FT_UINT40 type */ + { &hf_hdcp_a_ksv, + { "Transmitter's key selection vector", "hdcp.a_ksv", FT_UINT64, + BASE_HEX, NULL, 0, NULL, HFILL } }, + { &hf_hdcp_b_ksv, + { "Receiver's key selection vector", "hdcp.b_ksv", FT_UINT64, + BASE_HEX, NULL, 0, NULL, HFILL } }, + { &hf_hdcp_an, + { "Random number for the session", "hdcp.an", FT_UINT64, + BASE_HEX, NULL, 0, NULL, HFILL } }, + { &hf_hdcp_hdmi_reserved, + { "HDMI reserved", "hdcp.hdmi_reserved", FT_UINT8, BASE_DEC, + NULL, 0x80, NULL, HFILL } }, + { &hf_hdcp_repeater, + { "Repeater", "hdcp.repeater", FT_UINT8, BASE_DEC, + NULL, 0x40, NULL, HFILL } }, + { &hf_hdcp_ksv_fifo, + { "KSV fifo ready", "hdcp.ksv_fifo", FT_UINT8, BASE_DEC, + NULL, 0x20, NULL, HFILL } }, + { &hf_hdcp_fast_trans, + { "Support for 400KHz transfers", "hdcp.fast_trans", + FT_UINT8, BASE_DEC, NULL, 0x10, NULL, HFILL } }, + { &hf_hdcp_features, + { "Support for additional features", "hdcp.features", + FT_UINT8, BASE_DEC, NULL, 0x02, NULL, HFILL } }, + { &hf_hdcp_fast_reauth, + { "Support for fast re-authentication", "hdcp.fast_reauth", + FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL } }, + { &hf_hdcp_hdmi_mode, + { "HDMI mode", "hdcp.hdmi_mode", + FT_UINT16, BASE_DEC, NULL, 0x1000, NULL, HFILL } }, + { &hf_hdcp_max_casc_exc, + { "Maximum cascading depth exceeded", "hdcp.max_casc_exc", + FT_UINT16, BASE_DEC, NULL, 0x0800, NULL, HFILL } }, + { &hf_hdcp_depth, + { "Repeater cascade depth", "hdcp.depth", + FT_UINT16, BASE_DEC, NULL, 0x0700, NULL, HFILL } }, + { &hf_hdcp_max_devs_exc, + { "Maximum number of devices exceeded", "hdcp.max_devs_exc", + FT_UINT16, BASE_DEC, NULL, 0x0080, NULL, HFILL } }, + { &hf_hdcp_downstream, + { "Number of downstream receivers", "hdcp.downstream", + FT_UINT16, BASE_DEC, NULL, 0x007F, NULL, HFILL } }, + { &hf_hdcp_link_vfy, + { "Link verification response Ri'", "hdcp.link_vfy", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, + { &hf_hdcp2_msg_id, + { "Message ID", "hdcp2.msg_id", FT_UINT8, BASE_HEX, VALS(hdcp_msg_id), 0, NULL, HFILL } }, - { &hf_hdcp_r_tx, - { "r_tx", "hdcp.r_tx", FT_UINT64, BASE_HEX, + { &hf_hdcp2_r_tx, + { "r_tx", "hdcp2.r_tx", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_repeater, - { "Repeater", "hdcp.repeater", FT_BOOLEAN, BASE_NONE, + { &hf_hdcp2_repeater, + { "Repeater", "hdcp2.repeater", FT_BOOLEAN, BASE_NONE, NULL, 0x1, NULL, HFILL } }, - { &hf_hdcp_cert_rcv_id, - { "Receiver ID", "hdcp.cert.rcv_id", FT_BYTES, BASE_NONE, + { &hf_hdcp2_cert_rcv_id, + { "Receiver ID", "hdcp2.cert.rcv_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_cert_n, - { "Receiver RSA key n", "hdcp.cert.n", FT_BYTES, BASE_NONE, + { &hf_hdcp2_cert_n, + { "Receiver RSA key n", "hdcp2.cert.n", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_cert_e, - { "Receiver RSA key e", "hdcp.cert.e", FT_UINT24, BASE_HEX, + { &hf_hdcp2_cert_e, + { "Receiver RSA key e", "hdcp2.cert.e", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_cert_rcv_sig, - { "Receiver signature", "hdcp.cert.rcv_sig", FT_BYTES, + { &hf_hdcp2_cert_rcv_sig, + { "Receiver signature", "hdcp2.cert.rcv_sig", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_e_kh_km, - { "E_kh_km", "hdcp.e_kh_km", FT_BYTES, BASE_NONE, + { &hf_hdcp2_e_kh_km, + { "E_kh_km", "hdcp2.e_kh_km", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_m, - { "m", "hdcp.m", FT_BYTES, BASE_NONE, + { &hf_hdcp2_m, + { "m", "hdcp2.m", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_r_rx, - { "r_rx", "hdcp.r_rx", FT_UINT64, BASE_HEX, + { &hf_hdcp2_r_rx, + { "r_rx", "hdcp2.r_rx", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_h_prime, - { "H'", "hdcp.h_prime", FT_BYTES, BASE_NONE, + { &hf_hdcp2_h_prime, + { "H'", "hdcp2.h_prime", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_r_n, - { "r_n", "hdcp.r_n", FT_UINT64, BASE_HEX, + { &hf_hdcp2_r_n, + { "r_n", "hdcp2.r_n", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_l_prime, - { "L'", "hdcp.l_prime", FT_BYTES, BASE_NONE, + { &hf_hdcp2_l_prime, + { "L'", "hdcp2.l_prime", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_e_dkey_ks, - { "E_dkey_ks", "hdcp.e_dkey_ks", FT_BYTES, BASE_NONE, + { &hf_hdcp2_e_dkey_ks, + { "E_dkey_ks", "hdcp2.e_dkey_ks", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, - { &hf_hdcp_r_iv, - { "r_iv", "hdcp.r_iv", FT_UINT64, BASE_HEX, + { &hf_hdcp2_r_iv, + { "r_iv", "hdcp2.r_iv", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } } - }; +}; static gint *ett[] = { &ett_hdcp, &ett_hdcp_cert }; - module_t *hdcp_module; + module_t *hdcp2_module; msg_table = g_hash_table_new(g_direct_hash, g_direct_equal); for(i=0; i #include "packet-i2c.h" +#include "packet-hdcp.h" static int proto_i2c = -1; @@ -48,6 +49,7 @@ static gint ett_i2c = -1; enum { SUB_DATA = 0, SUB_IPMB, + SUB_HDCP, SUB_MAX }; @@ -178,7 +180,8 @@ sub_check_ipmb(packet_info *pinfo) static sub_checkfunc_t sub_check[SUB_MAX] = { NULL, /* raw data */ - sub_check_ipmb /* IPMI */ + sub_check_ipmb, /* IPMI */ + sub_check_hdcp /* HDCP */ }; static void @@ -277,6 +280,7 @@ proto_register_i2c(void) static const enum_val_t sub_enum_vals[] = { { "none", "None (raw I2C)", SUB_DATA }, { "ipmb", "IPMB", SUB_IPMB }, + { "hdcp", "HDCP", SUB_HDCP }, { NULL, NULL, 0 } }; module_t *m; @@ -286,7 +290,8 @@ proto_register_i2c(void) proto_register_subtree_array(ett, array_length(ett)); m = prefs_register_protocol(proto_i2c, NULL); - prefs_register_enum_preference(m, "type", "Bus type", "How the I2C messages are interpreted", + prefs_register_enum_preference(m, "type", "Bus/Data type", + "How the I2C messages are interpreted", &sub_selected, sub_enum_vals, FALSE); } @@ -297,6 +302,7 @@ proto_reg_handoff_i2c(void) sub_handles[SUB_DATA] = find_dissector("data"); sub_handles[SUB_IPMB] = find_dissector("ipmi"); + sub_handles[SUB_HDCP] = find_dissector("hdcp"); i2c_handle = create_dissector_handle(dissect_i2c, proto_i2c); dissector_add_uint("wtap_encap", WTAP_ENCAP_I2C, i2c_handle); } -- cgit v1.2.1