From mboxrd@z Thu Jan 1 00:00:00 1970 From: "C, Ramalingam" Subject: Re: [PATCH v9 12/39] drm/i915: Implement HDCP2.2 repeater authentication Date: Thu, 13 Dec 2018 16:48:55 +0530 Message-ID: <5c7fc023-6af0-1acd-8b3f-5cc80d87fef6@intel.com> References: <1544673701-6353-1-git-send-email-ramalingam.c@intel.com> <1544673701-6353-13-git-send-email-ramalingam.c@intel.com> <5B8DA87D05A7694D9FA63FD143655C1B9DA51DD6@hasmsx108.ger.corp.intel.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1908602400==" Return-path: In-Reply-To: <5B8DA87D05A7694D9FA63FD143655C1B9DA51DD6@hasmsx108.ger.corp.intel.com> Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: "Winkler, Tomas" , "intel-gfx@lists.freedesktop.org" , "dri-devel@lists.freedesktop.org" , "seanpaul@chromium.org" , "daniel.vetter@ffwll.ch" , "Shankar, Uma" List-Id: dri-devel@lists.freedesktop.org This is a multi-part message in MIME format. --===============1908602400== Content-Type: multipart/alternative; boundary="------------23148E6636DA6AFEE3E5B5DC" Content-Language: en-US This is a multi-part message in MIME format. --------------23148E6636DA6AFEE3E5B5DC Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit On 12/13/2018 1:52 PM, Winkler, Tomas wrote: >> Implements the HDCP2.2 repeaters authentication steps such as verifying the >> downstream topology and sending stream management information. >> >> v2: Rebased. >> v3: >> -EINVAL is returned for topology error and rollover scenario. >> Endianness conversion func from drm_hdcp.h is used [Uma] >> v4: >> Rebased as part of patches reordering. >> Defined the mei service functions [Daniel] >> v5: >> Redefined the mei service functions as per comp redesign. >> v6: >> %s/uintxx_t/uxx >> Check for comp_master is removed. >> v7: >> Adjust to the new mei interface. >> style issue fixed. >> v8: >> drm_hdcp.h change is moved into separate patch [Daniel] >> >> Signed-off-by: Ramalingam C >> --- >> drivers/gpu/drm/i915/intel_hdcp.c | 123 >> +++++++++++++++++++++++++++++++++++++- >> 1 file changed, 121 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c >> b/drivers/gpu/drm/i915/intel_hdcp.c >> index f1f0ef294e20..b52da5c3159d 100644 >> --- a/drivers/gpu/drm/i915/intel_hdcp.c >> +++ b/drivers/gpu/drm/i915/intel_hdcp.c >> @@ -978,7 +978,7 @@ static int hdcp2_prepare_skey(struct intel_connector >> *connector, >> return ret; >> } >> >> -static __attribute__((unused)) int >> +static int >> hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector, >> struct hdcp2_rep_send_receiverid_list >> >> *rep_topology, >> @@ -999,7 +999,7 @@ hdcp2_verify_rep_topology_prepare_ack(struct >> intel_connector *connector, >> return ret; >> } >> >> -static __attribute__((unused)) int >> +static int >> hdcp2_verify_mprime(struct intel_connector *connector, >> struct hdcp2_rep_stream_ready *stream_ready) { @@ - >> 1182,6 +1182,119 @@ static int hdcp2_session_key_exchange(struct >> intel_connector *connector) >> return 0; >> } >> >> +static >> +int hdcp2_propagate_stream_management_info(struct intel_connector >> +*connector) { >> + struct intel_digital_port *intel_dig_port = >> conn_to_dig_port(connector); >> + struct intel_hdcp *hdcp = &connector->hdcp; >> + union { >> + struct hdcp2_rep_stream_manage stream_manage; >> + struct hdcp2_rep_stream_ready stream_ready; >> + } msgs; >> + const struct intel_hdcp_shim *shim = hdcp->shim; >> + int ret; >> + >> + /* Prepare RepeaterAuth_Stream_Manage msg */ >> + msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE; >> + drm_hdcp2_u32_to_seq_num(msgs.stream_manage.seq_num_m, >> +hdcp->seq_num_m); >> + >> + /* K no of streams is fixed as 1. Stored as big-endian. */ >> + msgs.stream_manage.k = __swab16(1); > cpu_to_be16(1); Sure. Tomas. That will suit better. BTW, whether current mei- i915 interface suits to your preference? Thanks Ram >> + >> + /* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */ >> + msgs.stream_manage.streams[0].stream_id = 0; >> + msgs.stream_manage.streams[0].stream_type = hdcp->content_type; >> + >> + /* Send it to Repeater */ >> + ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage, >> + sizeof(msgs.stream_manage)); >> + if (ret < 0) >> + return ret; >> + >> + ret = shim->read_2_2_msg(intel_dig_port, >> HDCP_2_2_REP_STREAM_READY, >> + &msgs.stream_ready, >> sizeof(msgs.stream_ready)); >> + if (ret < 0) >> + return ret; >> + >> + hdcp->port_data.seq_num_m = hdcp->seq_num_m; >> + hdcp->port_data.streams[0].stream_type = hdcp->content_type; >> + >> + ret = hdcp2_verify_mprime(connector, &msgs.stream_ready); >> + if (ret < 0) >> + return ret; >> + >> + hdcp->seq_num_m++; >> + >> + if (hdcp->seq_num_m > HDCP_2_2_SEQ_NUM_MAX) { >> + DRM_DEBUG_KMS("seq_num_m roll over.\n"); >> + return -1; >> + } >> + >> + return 0; >> +} >> + >> +static >> +int hdcp2_authenticate_repeater_topology(struct intel_connector >> +*connector) { >> + struct intel_digital_port *intel_dig_port = >> conn_to_dig_port(connector); >> + struct intel_hdcp *hdcp = &connector->hdcp; >> + union { >> + struct hdcp2_rep_send_receiverid_list recvid_list; >> + struct hdcp2_rep_send_ack rep_ack; >> + } msgs; >> + const struct intel_hdcp_shim *shim = hdcp->shim; >> + u8 *rx_info; >> + u32 seq_num_v; >> + int ret; >> + >> + ret = shim->read_2_2_msg(intel_dig_port, >> HDCP_2_2_REP_SEND_RECVID_LIST, >> + &msgs.recvid_list, sizeof(msgs.recvid_list)); >> + if (ret < 0) >> + return ret; >> + >> + rx_info = msgs.recvid_list.rx_info; >> + >> + if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) || >> + HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) { >> + DRM_DEBUG_KMS("Topology Max Size Exceeded\n"); >> + return -EINVAL; >> + } >> + >> + /* Converting and Storing the seq_num_v to local variable as DWORD >> */ >> + drm_hdcp2_seq_num_to_u32(&seq_num_v, >> msgs.recvid_list.seq_num_v); >> + >> + if (seq_num_v < hdcp->seq_num_v) { >> + /* Roll over of the seq_num_v from repeater. Reauthenticate. >> */ >> + DRM_DEBUG_KMS("Seq_num_v roll over.\n"); >> + return -EINVAL; >> + } >> + >> + ret = hdcp2_verify_rep_topology_prepare_ack(connector, >> + &msgs.recvid_list, >> + &msgs.rep_ack); >> + if (ret < 0) >> + return ret; >> + >> + hdcp->seq_num_v = seq_num_v; >> + ret = shim->write_2_2_msg(intel_dig_port, &msgs.rep_ack, >> + sizeof(msgs.rep_ack)); >> + if (ret < 0) >> + return ret; >> + >> + return 0; >> +} >> + >> +static int hdcp2_authenticate_repeater(struct intel_connector >> +*connector) { >> + int ret; >> + >> + ret = hdcp2_authenticate_repeater_topology(connector); >> + if (ret < 0) >> + return ret; >> + >> + return hdcp2_propagate_stream_management_info(connector); >> +} >> + >> static int hdcp2_authenticate_sink(struct intel_connector *connector) { >> struct intel_digital_port *intel_dig_port = >> conn_to_dig_port(connector); @@ -1223,6 +1336,12 @@ static int >> hdcp2_authenticate_sink(struct intel_connector *connector) >> sizeof(stream_type_msg)); >> if (ret < 0) >> return ret; >> + } else if (hdcp->is_repeater) { >> + ret = hdcp2_authenticate_repeater(connector); >> + if (ret < 0) { >> + DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n", >> ret); >> + return ret; >> + } >> } >> >> hdcp->port_data.streams[0].stream_type = hdcp->content_type; >> -- >> 2.7.4 --------------23148E6636DA6AFEE3E5B5DC Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 7bit


On 12/13/2018 1:52 PM, Winkler, Tomas wrote:
Implements the HDCP2.2 repeaters authentication steps such as verifying the
downstream topology and sending stream management information.

v2: Rebased.
v3:
  -EINVAL is returned for topology error and rollover scenario.
  Endianness conversion func from drm_hdcp.h is used [Uma]
v4:
  Rebased as part of patches reordering.
  Defined the mei service functions [Daniel]
v5:
  Redefined the mei service functions as per comp redesign.
v6:
  %s/uintxx_t/uxx
  Check for comp_master is removed.
v7:
  Adjust to the new mei interface.
  style issue fixed.
v8:
  drm_hdcp.h change is moved into separate patch [Daniel]

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_hdcp.c | 123
+++++++++++++++++++++++++++++++++++++-
 1 file changed, 121 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c
b/drivers/gpu/drm/i915/intel_hdcp.c
index f1f0ef294e20..b52da5c3159d 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -978,7 +978,7 @@ static int hdcp2_prepare_skey(struct intel_connector
*connector,
 	return ret;
 }

-static __attribute__((unused)) int
+static int
 hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
 				      struct hdcp2_rep_send_receiverid_list

	*rep_topology,
@@ -999,7 +999,7 @@ hdcp2_verify_rep_topology_prepare_ack(struct
intel_connector *connector,
 	return ret;
 }

-static __attribute__((unused)) int
+static int
 hdcp2_verify_mprime(struct intel_connector *connector,
 		    struct hdcp2_rep_stream_ready *stream_ready)  { @@ -
1182,6 +1182,119 @@ static int hdcp2_session_key_exchange(struct
intel_connector *connector)
 	return 0;
 }

+static
+int hdcp2_propagate_stream_management_info(struct intel_connector
+*connector) {
+	struct intel_digital_port *intel_dig_port =
conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	union {
+		struct hdcp2_rep_stream_manage stream_manage;
+		struct hdcp2_rep_stream_ready stream_ready;
+	} msgs;
+	const struct intel_hdcp_shim *shim = hdcp->shim;
+	int ret;
+
+	/* Prepare RepeaterAuth_Stream_Manage msg */
+	msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
+	drm_hdcp2_u32_to_seq_num(msgs.stream_manage.seq_num_m,
+hdcp->seq_num_m);
+
+	/* K no of streams is fixed as 1. Stored as big-endian. */
+	msgs.stream_manage.k = __swab16(1);
                                                       cpu_to_be16(1);
Sure. Tomas. That will suit better.
BTW, whether current mei- i915 interface suits to your preference?
Thanks
Ram
+
+	/* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
+	msgs.stream_manage.streams[0].stream_id = 0;
+	msgs.stream_manage.streams[0].stream_type = hdcp->content_type;
+
+	/* Send it to Repeater */
+	ret = shim->write_2_2_msg(intel_dig_port, &msgs.stream_manage,
+				  sizeof(msgs.stream_manage));
+	if (ret < 0)
+		return ret;
+
+	ret = shim->read_2_2_msg(intel_dig_port,
HDCP_2_2_REP_STREAM_READY,
+				 &msgs.stream_ready,
sizeof(msgs.stream_ready));
+	if (ret < 0)
+		return ret;
+
+	hdcp->port_data.seq_num_m = hdcp->seq_num_m;
+	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
+
+	ret = hdcp2_verify_mprime(connector, &msgs.stream_ready);
+	if (ret < 0)
+		return ret;
+
+	hdcp->seq_num_m++;
+
+	if (hdcp->seq_num_m > HDCP_2_2_SEQ_NUM_MAX) {
+		DRM_DEBUG_KMS("seq_num_m roll over.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static
+int hdcp2_authenticate_repeater_topology(struct intel_connector
+*connector) {
+	struct intel_digital_port *intel_dig_port =
conn_to_dig_port(connector);
+	struct intel_hdcp *hdcp = &connector->hdcp;
+	union {
+		struct hdcp2_rep_send_receiverid_list recvid_list;
+		struct hdcp2_rep_send_ack rep_ack;
+	} msgs;
+	const struct intel_hdcp_shim *shim = hdcp->shim;
+	u8 *rx_info;
+	u32 seq_num_v;
+	int ret;
+
+	ret = shim->read_2_2_msg(intel_dig_port,
HDCP_2_2_REP_SEND_RECVID_LIST,
+				 &msgs.recvid_list, sizeof(msgs.recvid_list));
+	if (ret < 0)
+		return ret;
+
+	rx_info = msgs.recvid_list.rx_info;
+
+	if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
+	    HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
+		DRM_DEBUG_KMS("Topology Max Size Exceeded\n");
+		return -EINVAL;
+	}
+
+	/* Converting and Storing the seq_num_v to local variable as DWORD
*/
+	drm_hdcp2_seq_num_to_u32(&seq_num_v,
msgs.recvid_list.seq_num_v);
+
+	if (seq_num_v < hdcp->seq_num_v) {
+		/* Roll over of the seq_num_v from repeater. Reauthenticate.
*/
+		DRM_DEBUG_KMS("Seq_num_v roll over.\n");
+		return -EINVAL;
+	}
+
+	ret = hdcp2_verify_rep_topology_prepare_ack(connector,
+						    &msgs.recvid_list,
+						    &msgs.rep_ack);
+	if (ret < 0)
+		return ret;
+
+	hdcp->seq_num_v = seq_num_v;
+	ret = shim->write_2_2_msg(intel_dig_port, &msgs.rep_ack,
+				  sizeof(msgs.rep_ack));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int hdcp2_authenticate_repeater(struct intel_connector
+*connector) {
+	int ret;
+
+	ret = hdcp2_authenticate_repeater_topology(connector);
+	if (ret < 0)
+		return ret;
+
+	return hdcp2_propagate_stream_management_info(connector);
+}
+
 static int hdcp2_authenticate_sink(struct intel_connector *connector)  {
 	struct intel_digital_port *intel_dig_port =
conn_to_dig_port(connector); @@ -1223,6 +1336,12 @@ static int
hdcp2_authenticate_sink(struct intel_connector *connector)
 					       sizeof(stream_type_msg));
 		if (ret < 0)
 			return ret;
+	} else if (hdcp->is_repeater) {
+		ret = hdcp2_authenticate_repeater(connector);
+		if (ret < 0) {
+			DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n",
ret);
+			return ret;
+		}
 	}

 	hdcp->port_data.streams[0].stream_type = hdcp->content_type;
--
2.7.4

    
--------------23148E6636DA6AFEE3E5B5DC-- --===============1908602400== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KSW50ZWwtZ2Z4 IG1haWxpbmcgbGlzdApJbnRlbC1nZnhAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlz dHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vaW50ZWwtZ2Z4Cg== --===============1908602400==--