[Intel-gfx] [PATCH 06/10] drm/i915: SRM parsing and revocation check for HDCP2
Ramalingam C
ramalingam.c at intel.com
Tue Feb 26 07:36:05 UTC 2019
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 <ramalingam.c at 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
More information about the Intel-gfx
mailing list