>-----Original Message----- >From: Intel-gfx [mailto:intel-gfx-bounces@xxxxxxxxxxxxxxxxxxxxx] On Behalf Of >Ramalingam C >Sent: Tuesday, April 3, 2018 7:28 PM >To: intel-gfx@xxxxxxxxxxxxxxxxxxxxx; dri-devel@xxxxxxxxxxxxxxxxxxxxx; >seanpaul@xxxxxxxxxxxx; daniel@xxxxxxxx; chris@xxxxxxxxxxxxxxxxxx; >jani.nikula@xxxxxxxxxxxxxxx; Winkler, Tomas <tomas.winkler@xxxxxxxxx>; >Usyskin, Alexander <alexander.usyskin@xxxxxxxxx> >Cc: Vivi, Rodrigo <rodrigo.vivi@xxxxxxxxx> >Subject: [Intel-gfx] [PATCH v3 23/40] drm/i915: Implement HDCP2.2 receiver >authentication > >Implements HDCP2.2 authentication for hdcp2.2 receivers, with following steps: > Authentication and Key enchange (AKE). Typo in exchange. > Locality Check (LC). > Session Key Exchange(SKE). > DP Errata for stream type confuguration for receivers. Typo in configuration. > >At AKE, the HDCP Receiver’s public key certificate is verified by the HDCP >Transmitter. A Master Key k m is exchanged. > >At LC, the HDCP Transmitter enforces locality on the content by requiring that the >Round Trip Time (RTT) between a pair of messages is not more than 20 ms. > >At SKE, The HDCP Transmitter exchanges Session Key ks with the HDCP Receiver. > >In DP HDCP2.2 encryption and decryption logics use the stream type as one of the >parameter. So Before enabling the Encryption DP HDCP2.2 receiver needs to be >communicated with stream type. This is added to spec as ERRATA. > >This generic implementation is complete only with the hdcp2_shim defined. > >v2: > Rebased. >v3: > No Changes. > >Signed-off-by: Ramalingam C <ramalingam.c@xxxxxxxxx> >--- > drivers/gpu/drm/i915/intel_hdcp.c | 184 >++++++++++++++++++++++++++++++++++++++ > 1 file changed, 184 insertions(+) > >diff --git a/drivers/gpu/drm/i915/intel_hdcp.c >b/drivers/gpu/drm/i915/intel_hdcp.c >index b4d56b21cf9b..ee9b7519fe73 100644 >--- a/drivers/gpu/drm/i915/intel_hdcp.c >+++ b/drivers/gpu/drm/i915/intel_hdcp.c >@@ -18,6 +18,7 @@ > #define GET_MEI_DDI_INDEX(port) (((port) == PORT_A) ? DDI_A : \ > (enum hdcp_physical_port) (port)) > #define KEY_LOAD_TRIES 5 >+#define HDCP2_LC_RETRY_CNT 3 > > static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port, > const struct intel_hdcp_shim *shim) @@ - >1011,3 +1012,186 @@ static inline int hdcp2_deauthenticate_port(struct >intel_hdcp *hdcp) { > return hdcp2_close_mei_session(hdcp); > } >+ >+static int hdcp2_authentication_key_exchange(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_ake_init ake_init; >+ struct hdcp2_ake_send_cert send_cert; >+ struct hdcp2_ake_no_stored_km no_stored_km; >+ struct hdcp2_ake_send_hprime send_hprime; >+ struct hdcp2_ake_send_pairing_info pairing_info; >+ } msgs; >+ const struct intel_hdcp_shim *shim = hdcp->hdcp_shim; >+ size_t size; >+ int ret; >+ >+ /* Init for seq_num */ >+ hdcp->seq_num_v = 0; >+ hdcp->seq_num_m = 0; >+ >+ ret = hdcp2_prepare_ake_init(hdcp, &msgs.ake_init); >+ if (ret < 0) >+ return ret; >+ >+ ret = shim->write_2_2_msg(intel_dig_port, &msgs.ake_init, >+ sizeof(msgs.ake_init)); >+ if (ret < 0) >+ return ret; >+ >+ ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_AKE_SEND_CERT, >+ &msgs.send_cert, sizeof(msgs.send_cert)); >+ if (ret < 0) >+ return ret; >+ >+ if (msgs.send_cert.rx_caps[0] != HDCP_2_2_RX_CAPS_VERSION_VAL) >+ return -EINVAL; >+ >+ hdcp->is_repeater = >HDCP_2_2_RX_REPEATER(msgs.send_cert.rx_caps[2]); >+ >+ /* >+ * Here msgs.no_stored_km will hold msgs corresponding to the km >+ * stored also. >+ */ >+ ret = hdcp2_verify_rx_cert_prepare_km(hdcp, &msgs.send_cert, >+ &hdcp->is_paired, >+ &msgs.no_stored_km, &size); >+ if (ret < 0) >+ return ret; >+ >+ ret = shim->write_2_2_msg(intel_dig_port, &msgs.no_stored_km, size); >+ if (ret < 0) >+ return ret; >+ >+ ret = shim->read_2_2_msg(intel_dig_port, >HDCP_2_2_AKE_SEND_HPRIME, >+ &msgs.send_hprime, >sizeof(msgs.send_hprime)); >+ if (ret < 0) >+ return ret; >+ >+ ret = hdcp2_verify_hprime(hdcp, &msgs.send_hprime); >+ if (ret < 0) >+ return ret; >+ >+ if (!hdcp->is_paired) { >+ /* Pairing is required */ >+ ret = shim->read_2_2_msg(intel_dig_port, >+ HDCP_2_2_AKE_SEND_PARING_INFO, >+ &msgs.pairing_info, >+ sizeof(msgs.pairing_info)); >+ if (ret < 0) >+ return ret; >+ >+ ret = hdcp2_store_paring_info(hdcp, &msgs.pairing_info); >+ if (ret < 0) >+ return ret; >+ hdcp->is_paired = true; >+ } Leave a blank line here. >+ return 0; >+} >+ >+static int hdcp2_locality_check(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_lc_init lc_init; >+ struct hdcp2_lc_send_lprime send_lprime; >+ } msgs; >+ const struct intel_hdcp_shim *shim = hdcp->hdcp_shim; >+ int tries = HDCP2_LC_RETRY_CNT, ret, i; >+ >+ for (i = 0; i < tries; i++) { >+ ret = hdcp2_prepare_lc_init(hdcp, &msgs.lc_init); >+ if (ret < 0) >+ continue; >+ >+ ret = shim->write_2_2_msg(intel_dig_port, &msgs.lc_init, >+ sizeof(msgs.lc_init)); >+ if (ret < 0) >+ continue; >+ >+ ret = shim->read_2_2_msg(intel_dig_port, >+ HDCP_2_2_LC_SEND_LPRIME, >+ &msgs.send_lprime, >+ sizeof(msgs.send_lprime)); >+ if (ret < 0) >+ continue; >+ >+ ret = hdcp2_verify_lprime(hdcp, &msgs.send_lprime); >+ if (!ret) >+ break; >+ } Leave a blank line. >+ return ret; >+} >+ >+static int hdcp2_session_key_exchange(struct intel_connector >+*connector) { >+ struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector); >+ struct intel_hdcp *hdcp = &connector->hdcp; >+ struct hdcp2_ske_send_eks send_eks; >+ int ret; >+ >+ ret = hdcp2_prepare_skey(hdcp, &send_eks); >+ if (ret < 0) >+ return ret; >+ >+ ret = hdcp->hdcp_shim->write_2_2_msg(intel_dig_port, &send_eks, >+ sizeof(send_eks)); >+ if (ret < 0) >+ return ret; >+ >+ return 0; >+} >+ >+static int hdcp2_authenticate_sink(struct intel_connector *connector) { >+ struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector); >+ struct intel_hdcp *hdcp = &connector->hdcp; >+ const struct intel_hdcp_shim *shim = hdcp->hdcp_shim; >+ struct hdcp2_dp_errata_stream_type stream_type_msg; >+ int ret; >+ >+ ret = hdcp2_authentication_key_exchange(connector); >+ if (ret < 0) { >+ DRM_DEBUG_KMS("AKE Failed. Err : %d\n", ret); >+ return ret; >+ } >+ >+ ret = hdcp2_locality_check(connector); >+ if (ret < 0) { >+ DRM_DEBUG_KMS("Locality Check failed. Err : %d\n", ret); >+ return ret; >+ } >+ >+ ret = hdcp2_session_key_exchange(connector); >+ if (ret < 0) { >+ DRM_DEBUG_KMS("SKE Failed. Err : %d\n", ret); >+ return ret; >+ } >+ >+ if (!hdcp->is_repeater && shim->config_stream_type) { >+ >+ /* Errata for DP: As Stream type is used for encryption, Incorrect multi line comment style. >+ * Receiver should be communicated with stream type for the >+ * decryption of the content. >+ * Repeater will be communicated with stream type as a >+ * part of it's auth in later in time Remove "in" >+ */ >+ stream_type_msg.msg_id = >HDCP_2_2_ERRATA_DP_STREAM_TYPE; >+ stream_type_msg.stream_type = hdcp->content_type; >+ >+ ret = shim->config_stream_type(intel_dig_port, >&stream_type_msg, >+ sizeof(stream_type_msg)); >+ if (ret < 0) >+ return ret; >+ } >+ >+ hdcp->mei_data.streams[0].stream_type = hdcp->content_type; >+ ret = hdcp2_authenticate_port(hdcp); >+ if (ret < 0) >+ return ret; >+ >+ return ret; >+} >-- >2.7.4 > >_______________________________________________ >Intel-gfx mailing list >Intel-gfx@xxxxxxxxxxxxxxxxxxxxx >https://lists.freedesktop.org/mailman/listinfo/intel-gfx _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel