SRM blob with hdcp2 id is parsed and parsed list of revoked ids is
used in the authentication process to identify the compromised HDCP
sinks.

Signed-off-by: Ramalingam C <ramalinga...@intel.com>
---
 drivers/gpu/drm/i915/intel_hdcp.c | 86 +++++++++++++++++++++++++++++++++++++--
 include/drm/drm_hdcp.h            | 20 +++++++++
 2 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c 
b/drivers/gpu/drm/i915/intel_hdcp.c
index 7d007de984d7..b92fc0383788 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -1244,6 +1244,12 @@ static int hdcp2_authentication_key_exchange(struct 
intel_connector *connector)
 
        hdcp->is_repeater = HDCP_2_2_RX_REPEATER(msgs.send_cert.rx_caps[2]);
 
+       if (intel_hdcp_ksvs_revocated(hdcp,
+                                     msgs.send_cert.cert_rx.receiver_id, 1)) {
+               DRM_ERROR("Receiver ID is revocated\n");
+               return -EPERM;
+       }
+
        /*
         * Here msgs.no_stored_km will hold msgs corresponding to the km
         * stored also.
@@ -1402,7 +1408,7 @@ int hdcp2_authenticate_repeater_topology(struct 
intel_connector *connector)
        } msgs;
        const struct intel_hdcp_shim *shim = hdcp->shim;
        u8 *rx_info;
-       u32 seq_num_v;
+       u32 seq_num_v, device_cnt;
        int ret;
 
        ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_SEND_RECVID_LIST,
@@ -1427,6 +1433,14 @@ int hdcp2_authenticate_repeater_topology(struct 
intel_connector *connector)
                return -EINVAL;
        }
 
+       device_cnt = HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 ||
+                       HDCP_2_2_DEV_COUNT_LO(rx_info[1]);
+       if (intel_hdcp_ksvs_revocated(hdcp, msgs.recvid_list.receiver_ids,
+                                     device_cnt)) {
+               DRM_ERROR("Revoked receiver ID(s) is in list\n");
+               return -EPERM;
+       }
+
        ret = hdcp2_verify_rep_topology_prepare_ack(connector,
                                                    &msgs.recvid_list,
                                                    &msgs.rep_ack);
@@ -1982,12 +1996,72 @@ static int intel_hdcp_parse_srm(struct drm_connector 
*connector,
        return 0;
 }
 
+static int intel_hdcp2_parse_srm(struct drm_connector *connector,
+                                struct drm_property_blob *blob)
+{
+       struct intel_hdcp *hdcp = &(to_intel_connector(connector)->hdcp);
+       struct hdcp2_srm_header *header;
+       u32 vrl_length, ksv_count, ksv_sz;
+       u8 *buf;
+
+       if (blob->length < (sizeof(struct hdcp2_srm_header) +
+           DRM_HDCP_2_VRL_LENGTH_SIZE + DRM_HDCP_2_DCP_SIG_SIZE)) {
+               DRM_ERROR("Invalid blob length\n");
+               return -EINVAL;
+       }
+
+       header = (struct hdcp2_srm_header *)blob->data;
+       DRM_DEBUG_KMS("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n",
+                     header->spec_indicator.srm_id,
+                     __swab16(header->srm_version), header->srm_gen_no);
+       WARN_ON(header->spec_indicator.reserved);
+       buf = blob->data + sizeof(*header);
+
+       vrl_length = (*buf << 16 | *(buf + 1) << 8 | *(buf + 2));
+       if (blob->length < (sizeof(struct hdcp2_srm_header) + vrl_length) ||
+           vrl_length < (DRM_HDCP_2_VRL_LENGTH_SIZE +
+                         DRM_HDCP_2_DCP_SIG_SIZE)) {
+               DRM_ERROR("Invalid blob length or vrl length\n");
+               return -EINVAL;
+       }
+
+       /* Length of the all vrls combined */
+       vrl_length -= (DRM_HDCP_2_VRL_LENGTH_SIZE + DRM_HDCP_2_DCP_SIG_SIZE);
+       if (!vrl_length) {
+               DRM_ERROR("No vrl found\n");
+               return -EINVAL;
+       }
+
+       buf += DRM_HDCP_2_VRL_LENGTH_SIZE;
+       ksv_count = (*buf << 2) | DRM_HDCP_2_KSV_COUNT_2_LSBITS(*(buf + 1));
+       if (!ksv_count)
+               return 0;
+
+       kfree(hdcp->revocated_ksv_list);
+       hdcp->revocated_ksv_list = kzalloc(ksv_count * DRM_HDCP_KSV_LEN,
+                                          GFP_KERNEL);
+       if (!hdcp->revocated_ksv_list) {
+               DRM_ERROR("Out of Memory\n");
+               return -ENOMEM;
+       }
+
+       ksv_sz = ksv_count * DRM_HDCP_KSV_LEN;
+       buf += DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ;
+
+       DRM_DEBUG_KMS("Revoked KSVs: %d\n", ksv_count);
+       memcpy(hdcp->revocated_ksv_list, buf, ksv_sz);
+       hdcp->revocated_ksv_cnt = ksv_count;
+
+       return 0;
+}
+
 static void intel_hdcp_update_srm(struct intel_connector *intel_connector,
                                  u32 srm_blob_id)
 {
        struct drm_connector *connector = &intel_connector->base;
        struct intel_hdcp *hdcp = &intel_connector->hdcp;
        struct drm_property_blob *blob;
+       u8 srm_id;
 
        DRM_DEBUG_KMS("srm_blob_id %u\n", srm_blob_id);
 
@@ -2002,8 +2076,14 @@ static void intel_hdcp_update_srm(struct intel_connector 
*intel_connector,
        if (!blob || !blob->data)
                return;
 
-       if (!intel_hdcp_parse_srm(connector, blob))
-               hdcp->srm_blob_id = srm_blob_id;
+       srm_id = *((u8 *)blob->data);
+       if (srm_id == DRM_HDCP_SRM_ID) {
+               if (!intel_hdcp_parse_srm(connector, blob))
+                       hdcp->srm_blob_id = srm_blob_id;
+       } else if (srm_id == DRM_HDCP2_SRM_ID) {
+               if (!intel_hdcp2_parse_srm(connector, blob))
+                       hdcp->srm_blob_id = srm_blob_id;
+       }
 
        drm_property_blob_put(blob);
 }
diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
index 1ccae47fcff5..1e630a593b73 100644
--- a/include/drm/drm_hdcp.h
+++ b/include/drm/drm_hdcp.h
@@ -279,4 +279,24 @@ struct hdcp_srm_header {
        u8 srm_gen_no;
 } __packed;
 
+#define DRM_HDCP_2_SRM_ID                      0x9
+#define DRM_HDCP_2_INDICATOR                   0x1
+#define DRM_HDCP_2_VRL_LENGTH_SIZE             3
+#define DRM_HDCP_2_DCP_SIG_SIZE                        384
+#define DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ  4
+
+#define DRM_HDCP_2_KSV_COUNT_2_LSBITS(byte)    (((byte) & 0xC) >> 6)
+#define DRM_HDCP_SRM_ID                                0x80
+#define DRM_HDCP2_SRM_ID                       0x91
+
+struct hdcp2_srm_header {
+       struct {
+               u8 hdcp2_indicator:4;
+               u8 srm_id:4;
+               u8 reserved;
+       } spec_indicator;
+       u16 srm_version;
+       u8 srm_gen_no;
+} __packed;
+
 #endif
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to