From f67cf491175a315ca86c9b349708bfed7b1f40c1 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 6 Jun 2017 15:25:16 +0300 Subject: thunderbolt: Add support for Internal Connection Manager (ICM) Starting from Intel Falcon Ridge the internal connection manager running on the Thunderbolt host controller has been supporting 4 security levels. One reason for this is to prevent DMA attacks and only allow connecting devices the user trusts. The internal connection manager (ICM) is the preferred way of connecting Thunderbolt devices over software only implementation typically used on Macs. The driver communicates with ICM using special Thunderbolt ring 0 (control channel) messages. In order to handle these messages we add support for the ICM messages to the control channel. The security levels are as follows: none - No security, all tunnels are created automatically user - User needs to approve the device before tunnels are created secure - User need to approve the device before tunnels are created. The device is sent a challenge on future connects to be able to verify it is actually the approved device. dponly - Only Display Port and USB tunnels can be created and those are created automatically. The security levels are typically configurable from the system BIOS and by default it is set to "user" on many systems. In this patch each Thunderbolt device will have either one or two new sysfs attributes: authorized and key. The latter appears for devices that support secure connect. In order to identify the device the user can read identication information, including UUID and name of the device from sysfs and based on that make a decision to authorize the device. The device is authorized by simply writing 1 to the "authorized" sysfs attribute. This is following the USB bus device authorization mechanism. The secure connect requires an additional challenge step (writing 2 to the "authorized" attribute) in future connects when the key has already been stored to the NVM of the device. Non-ICM systems (before Alpine Ridge) continue to use the existing functionality and the security level is set to none. For systems with Alpine Ridge, even on Apple hardware, we will use ICM. This code is based on the work done by Amir Levy and Michael Jamet. Signed-off-by: Michael Jamet Signed-off-by: Mika Westerberg Reviewed-by: Yehezkel Bernat Reviewed-by: Andy Shevchenko Signed-off-by: Andreas Noever Signed-off-by: Greg Kroah-Hartman --- drivers/thunderbolt/tb_msgs.h | 152 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) (limited to 'drivers/thunderbolt/tb_msgs.h') diff --git a/drivers/thunderbolt/tb_msgs.h b/drivers/thunderbolt/tb_msgs.h index 761d56287149..85b6d33c0919 100644 --- a/drivers/thunderbolt/tb_msgs.h +++ b/drivers/thunderbolt/tb_msgs.h @@ -13,6 +13,7 @@ #define _TB_MSGS #include +#include enum tb_cfg_pkg_type { TB_CFG_PKG_READ = 1, @@ -24,6 +25,9 @@ enum tb_cfg_pkg_type { TB_CFG_PKG_XDOMAIN_RESP = 7, TB_CFG_PKG_OVERRIDE = 8, TB_CFG_PKG_RESET = 9, + TB_CFG_PKG_ICM_EVENT = 10, + TB_CFG_PKG_ICM_CMD = 11, + TB_CFG_PKG_ICM_RESP = 12, TB_CFG_PKG_PREPARE_TO_SLEEP = 0xd, }; @@ -105,4 +109,152 @@ struct cfg_pts_pkg { u32 data; } __packed; +/* ICM messages */ + +enum icm_pkg_code { + ICM_GET_TOPOLOGY = 0x1, + ICM_DRIVER_READY = 0x3, + ICM_APPROVE_DEVICE = 0x4, + ICM_CHALLENGE_DEVICE = 0x5, + ICM_ADD_DEVICE_KEY = 0x6, + ICM_GET_ROUTE = 0xa, +}; + +enum icm_event_code { + ICM_EVENT_DEVICE_CONNECTED = 3, + ICM_EVENT_DEVICE_DISCONNECTED = 4, +}; + +struct icm_pkg_header { + u8 code; + u8 flags; + u8 packet_id; + u8 total_packets; +} __packed; + +#define ICM_FLAGS_ERROR BIT(0) +#define ICM_FLAGS_NO_KEY BIT(1) +#define ICM_FLAGS_SLEVEL_SHIFT 3 +#define ICM_FLAGS_SLEVEL_MASK GENMASK(4, 3) + +struct icm_pkg_driver_ready { + struct icm_pkg_header hdr; +} __packed; + +struct icm_pkg_driver_ready_response { + struct icm_pkg_header hdr; + u8 romver; + u8 ramver; + u16 security_level; +} __packed; + +/* Falcon Ridge & Alpine Ridge common messages */ + +struct icm_fr_pkg_get_topology { + struct icm_pkg_header hdr; +} __packed; + +#define ICM_GET_TOPOLOGY_PACKETS 14 + +struct icm_fr_pkg_get_topology_response { + struct icm_pkg_header hdr; + u32 route_lo; + u32 route_hi; + u8 first_data; + u8 second_data; + u8 drom_i2c_address_index; + u8 switch_index; + u32 reserved[2]; + u32 ports[16]; + u32 port_hop_info[16]; +} __packed; + +#define ICM_SWITCH_USED BIT(0) +#define ICM_SWITCH_UPSTREAM_PORT_MASK GENMASK(7, 1) +#define ICM_SWITCH_UPSTREAM_PORT_SHIFT 1 + +#define ICM_PORT_TYPE_MASK GENMASK(23, 0) +#define ICM_PORT_INDEX_SHIFT 24 +#define ICM_PORT_INDEX_MASK GENMASK(31, 24) + +struct icm_fr_event_device_connected { + struct icm_pkg_header hdr; + uuid_be ep_uuid; + u8 connection_key; + u8 connection_id; + u16 link_info; + u32 ep_name[55]; +} __packed; + +#define ICM_LINK_INFO_LINK_MASK 0x7 +#define ICM_LINK_INFO_DEPTH_SHIFT 4 +#define ICM_LINK_INFO_DEPTH_MASK GENMASK(7, 4) +#define ICM_LINK_INFO_APPROVED BIT(8) + +struct icm_fr_pkg_approve_device { + struct icm_pkg_header hdr; + uuid_be ep_uuid; + u8 connection_key; + u8 connection_id; + u16 reserved; +} __packed; + +struct icm_fr_event_device_disconnected { + struct icm_pkg_header hdr; + u16 reserved; + u16 link_info; +} __packed; + +struct icm_fr_pkg_add_device_key { + struct icm_pkg_header hdr; + uuid_be ep_uuid; + u8 connection_key; + u8 connection_id; + u16 reserved; + u32 key[8]; +} __packed; + +struct icm_fr_pkg_add_device_key_response { + struct icm_pkg_header hdr; + uuid_be ep_uuid; + u8 connection_key; + u8 connection_id; + u16 reserved; +} __packed; + +struct icm_fr_pkg_challenge_device { + struct icm_pkg_header hdr; + uuid_be ep_uuid; + u8 connection_key; + u8 connection_id; + u16 reserved; + u32 challenge[8]; +} __packed; + +struct icm_fr_pkg_challenge_device_response { + struct icm_pkg_header hdr; + uuid_be ep_uuid; + u8 connection_key; + u8 connection_id; + u16 reserved; + u32 challenge[8]; + u32 response[8]; +} __packed; + +/* Alpine Ridge only messages */ + +struct icm_ar_pkg_get_route { + struct icm_pkg_header hdr; + u16 reserved; + u16 link_info; +} __packed; + +struct icm_ar_pkg_get_route_response { + struct icm_pkg_header hdr; + u16 reserved; + u16 link_info; + u32 route_hi; + u32 route_lo; +} __packed; + #endif -- cgit v1.2.3