cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hdcp_msg.c (12485B)


      1/*
      2 * Copyright 2019 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25
     26#include <linux/slab.h>
     27
     28#include "dm_services.h"
     29#include "dm_helpers.h"
     30#include "include/hdcp_types.h"
     31#include "include/i2caux_interface.h"
     32#include "include/signal_types.h"
     33#include "core_types.h"
     34#include "dc_link_ddc.h"
     35#include "link_hwss.h"
     36#include "inc/link_dpcd.h"
     37
     38#define DC_LOGGER \
     39	link->ctx->logger
     40#define HDCP14_KSV_SIZE 5
     41#define HDCP14_MAX_KSV_FIFO_SIZE 127*HDCP14_KSV_SIZE
     42
     43static const bool hdcp_cmd_is_read[HDCP_MESSAGE_ID_MAX] = {
     44	[HDCP_MESSAGE_ID_READ_BKSV] = true,
     45	[HDCP_MESSAGE_ID_READ_RI_R0] = true,
     46	[HDCP_MESSAGE_ID_READ_PJ] = true,
     47	[HDCP_MESSAGE_ID_WRITE_AKSV] = false,
     48	[HDCP_MESSAGE_ID_WRITE_AINFO] = false,
     49	[HDCP_MESSAGE_ID_WRITE_AN] = false,
     50	[HDCP_MESSAGE_ID_READ_VH_X] = true,
     51	[HDCP_MESSAGE_ID_READ_VH_0] = true,
     52	[HDCP_MESSAGE_ID_READ_VH_1] = true,
     53	[HDCP_MESSAGE_ID_READ_VH_2] = true,
     54	[HDCP_MESSAGE_ID_READ_VH_3] = true,
     55	[HDCP_MESSAGE_ID_READ_VH_4] = true,
     56	[HDCP_MESSAGE_ID_READ_BCAPS] = true,
     57	[HDCP_MESSAGE_ID_READ_BSTATUS] = true,
     58	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = true,
     59	[HDCP_MESSAGE_ID_READ_BINFO] = true,
     60	[HDCP_MESSAGE_ID_HDCP2VERSION] = true,
     61	[HDCP_MESSAGE_ID_RX_CAPS] = true,
     62	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = false,
     63	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = true,
     64	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = false,
     65	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = false,
     66	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = true,
     67	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = true,
     68	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = false,
     69	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = true,
     70	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = false,
     71	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = true,
     72	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = false,
     73	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = false,
     74	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = true,
     75	[HDCP_MESSAGE_ID_READ_RXSTATUS] = true,
     76	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = false
     77};
     78
     79static const uint8_t hdcp_i2c_offsets[HDCP_MESSAGE_ID_MAX] = {
     80	[HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
     81	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
     82	[HDCP_MESSAGE_ID_READ_PJ] = 0xA,
     83	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
     84	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
     85	[HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
     86	[HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
     87	[HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
     88	[HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
     89	[HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
     90	[HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
     91	[HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
     92	[HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
     93	[HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
     94	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
     95	[HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
     96	[HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,
     97	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,
     98	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,
     99	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,
    100	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,
    101	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,
    102	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,
    103	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,
    104	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,
    105	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,
    106	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,
    107	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,
    108	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,
    109	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,
    110	[HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70,
    111	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x0,
    112};
    113
    114struct protection_properties {
    115	bool supported;
    116	bool (*process_transaction)(
    117		struct dc_link *link,
    118		struct hdcp_protection_message *message_info);
    119};
    120
    121static const struct protection_properties non_supported_protection = {
    122	.supported = false
    123};
    124
    125static bool hdmi_14_process_transaction(
    126	struct dc_link *link,
    127	struct hdcp_protection_message *message_info)
    128{
    129	uint8_t *buff = NULL;
    130	bool result;
    131	const uint8_t hdcp_i2c_addr_link_primary = 0x3a; /* 0x74 >> 1*/
    132	const uint8_t hdcp_i2c_addr_link_secondary = 0x3b; /* 0x76 >> 1*/
    133	struct i2c_command i2c_command;
    134	uint8_t offset = hdcp_i2c_offsets[message_info->msg_id];
    135	struct i2c_payload i2c_payloads[] = {
    136		{ true, 0, 1, &offset },
    137		/* actual hdcp payload, will be filled later, zeroed for now*/
    138		{ 0 }
    139	};
    140
    141	switch (message_info->link) {
    142	case HDCP_LINK_SECONDARY:
    143		i2c_payloads[0].address = hdcp_i2c_addr_link_secondary;
    144		i2c_payloads[1].address = hdcp_i2c_addr_link_secondary;
    145		break;
    146	case HDCP_LINK_PRIMARY:
    147	default:
    148		i2c_payloads[0].address = hdcp_i2c_addr_link_primary;
    149		i2c_payloads[1].address = hdcp_i2c_addr_link_primary;
    150		break;
    151	}
    152
    153	if (hdcp_cmd_is_read[message_info->msg_id]) {
    154		i2c_payloads[1].write = false;
    155		i2c_command.number_of_payloads = ARRAY_SIZE(i2c_payloads);
    156		i2c_payloads[1].length = message_info->length;
    157		i2c_payloads[1].data = message_info->data;
    158	} else {
    159		i2c_command.number_of_payloads = 1;
    160		buff = kzalloc(message_info->length + 1, GFP_KERNEL);
    161
    162		if (!buff)
    163			return false;
    164
    165		buff[0] = offset;
    166		memmove(&buff[1], message_info->data, message_info->length);
    167		i2c_payloads[0].length = message_info->length + 1;
    168		i2c_payloads[0].data = buff;
    169	}
    170
    171	i2c_command.payloads = i2c_payloads;
    172	i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW
    173	i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;
    174
    175	result = dm_helpers_submit_i2c(
    176			link->ctx,
    177			link,
    178			&i2c_command);
    179	kfree(buff);
    180
    181	return result;
    182}
    183
    184static const struct protection_properties hdmi_14_protection = {
    185	.supported = true,
    186	.process_transaction = hdmi_14_process_transaction
    187};
    188
    189static const uint32_t hdcp_dpcd_addrs[HDCP_MESSAGE_ID_MAX] = {
    190	[HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
    191	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
    192	[HDCP_MESSAGE_ID_READ_PJ] = 0xFFFFFFFF,
    193	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
    194	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
    195	[HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
    196	[HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
    197	[HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
    198	[HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
    199	[HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
    200	[HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
    201	[HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
    202	[HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
    203	[HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
    204	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
    205	[HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
    206	[HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
    207	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
    208	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
    209	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
    210	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
    211	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
    212	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
    213	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
    214	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
    215	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
    216	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,
    217	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,
    218	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,
    219	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,
    220	[HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,
    221	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494
    222};
    223
    224static bool dpcd_access_helper(
    225	struct dc_link *link,
    226	uint32_t length,
    227	uint8_t *data,
    228	uint32_t dpcd_addr,
    229	bool is_read)
    230{
    231	enum dc_status status;
    232	uint32_t cur_length = 0;
    233	uint32_t offset = 0;
    234	uint32_t ksv_read_size = 0x6803b - 0x6802c;
    235
    236	/* Read KSV, need repeatedly handle */
    237	if (dpcd_addr == 0x6802c) {
    238		if (length % HDCP14_KSV_SIZE) {
    239			DC_LOG_ERROR("%s: KsvFifo Size(%d) is not a multiple of HDCP14_KSV_SIZE(%d)\n",
    240				__func__,
    241				length,
    242				HDCP14_KSV_SIZE);
    243		}
    244		if (length > HDCP14_MAX_KSV_FIFO_SIZE) {
    245			DC_LOG_ERROR("%s: KsvFifo Size(%d) is greater than HDCP14_MAX_KSV_FIFO_SIZE(%d)\n",
    246				__func__,
    247				length,
    248				HDCP14_MAX_KSV_FIFO_SIZE);
    249		}
    250
    251		DC_LOG_ERROR("%s: Reading %d Ksv(s) from KsvFifo\n",
    252			__func__,
    253			length / HDCP14_KSV_SIZE);
    254
    255		while (length > 0) {
    256			if (length > ksv_read_size) {
    257				status = core_link_read_dpcd(
    258					link,
    259					dpcd_addr + offset,
    260					data + offset,
    261					ksv_read_size);
    262
    263				data += ksv_read_size;
    264				length -= ksv_read_size;
    265			} else {
    266				status = core_link_read_dpcd(
    267					link,
    268					dpcd_addr + offset,
    269					data + offset,
    270					length);
    271
    272				data += length;
    273				length = 0;
    274			}
    275
    276			if (status != DC_OK)
    277				return false;
    278		}
    279	} else {
    280		while (length > 0) {
    281			if (length > DEFAULT_AUX_MAX_DATA_SIZE)
    282				cur_length = DEFAULT_AUX_MAX_DATA_SIZE;
    283			else
    284				cur_length = length;
    285
    286			if (is_read) {
    287				status = core_link_read_dpcd(
    288					link,
    289					dpcd_addr + offset,
    290					data + offset,
    291					cur_length);
    292			} else {
    293				status = core_link_write_dpcd(
    294					link,
    295					dpcd_addr + offset,
    296					data + offset,
    297					cur_length);
    298			}
    299
    300			if (status != DC_OK)
    301				return false;
    302
    303			length -= cur_length;
    304			offset += cur_length;
    305		}
    306	}
    307	return true;
    308}
    309
    310static bool dp_11_process_transaction(
    311	struct dc_link *link,
    312	struct hdcp_protection_message *message_info)
    313{
    314	return dpcd_access_helper(
    315		link,
    316		message_info->length,
    317		message_info->data,
    318		hdcp_dpcd_addrs[message_info->msg_id],
    319		hdcp_cmd_is_read[message_info->msg_id]);
    320}
    321
    322static const struct protection_properties dp_11_protection = {
    323	.supported = true,
    324	.process_transaction = dp_11_process_transaction
    325};
    326
    327static const struct protection_properties *get_protection_properties_by_signal(
    328	struct dc_link *link,
    329	enum signal_type st,
    330	enum hdcp_version version)
    331{
    332	switch (version) {
    333	case HDCP_VERSION_14:
    334		switch (st) {
    335		case SIGNAL_TYPE_DVI_SINGLE_LINK:
    336		case SIGNAL_TYPE_DVI_DUAL_LINK:
    337		case SIGNAL_TYPE_HDMI_TYPE_A:
    338			return &hdmi_14_protection;
    339		case SIGNAL_TYPE_DISPLAY_PORT:
    340			if (link &&
    341				(link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
    342				link->dpcd_caps.dongle_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER)) {
    343				return &non_supported_protection;
    344			}
    345			return &dp_11_protection;
    346		case SIGNAL_TYPE_DISPLAY_PORT_MST:
    347		case SIGNAL_TYPE_EDP:
    348			return &dp_11_protection;
    349		default:
    350			return &non_supported_protection;
    351		}
    352		break;
    353	case HDCP_VERSION_22:
    354		switch (st) {
    355		case SIGNAL_TYPE_DVI_SINGLE_LINK:
    356		case SIGNAL_TYPE_DVI_DUAL_LINK:
    357		case SIGNAL_TYPE_HDMI_TYPE_A:
    358			return &hdmi_14_protection; //todo version2.2
    359		case SIGNAL_TYPE_DISPLAY_PORT:
    360		case SIGNAL_TYPE_DISPLAY_PORT_MST:
    361		case SIGNAL_TYPE_EDP:
    362			return &dp_11_protection;  //todo version2.2
    363		default:
    364			return &non_supported_protection;
    365		}
    366		break;
    367	default:
    368		return &non_supported_protection;
    369	}
    370}
    371
    372enum hdcp_message_status dc_process_hdcp_msg(
    373	enum signal_type signal,
    374	struct dc_link *link,
    375	struct hdcp_protection_message *message_info)
    376{
    377	enum hdcp_message_status status = HDCP_MESSAGE_FAILURE;
    378	uint32_t i = 0;
    379
    380	const struct protection_properties *protection_props;
    381
    382	if (!message_info)
    383		return HDCP_MESSAGE_UNSUPPORTED;
    384
    385	if (message_info->msg_id < HDCP_MESSAGE_ID_READ_BKSV ||
    386		message_info->msg_id >= HDCP_MESSAGE_ID_MAX)
    387		return HDCP_MESSAGE_UNSUPPORTED;
    388
    389	protection_props =
    390		get_protection_properties_by_signal(
    391			link,
    392			signal,
    393			message_info->version);
    394
    395	if (!protection_props->supported)
    396		return HDCP_MESSAGE_UNSUPPORTED;
    397
    398	if (protection_props->process_transaction(
    399		link,
    400		message_info)) {
    401		status = HDCP_MESSAGE_SUCCESS;
    402	} else {
    403		for (i = 0; i < message_info->max_retries; i++) {
    404			if (protection_props->process_transaction(
    405						link,
    406						message_info)) {
    407				status = HDCP_MESSAGE_SUCCESS;
    408				break;
    409			}
    410		}
    411	}
    412
    413	return status;
    414}
    415