diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2017-06-06 14:25:16 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-06-09 11:42:43 +0200 |
commit | f67cf491175a315ca86c9b349708bfed7b1f40c1 (patch) | |
tree | 7b9b16deadbf5941b14cc16086eababa2dc70523 /drivers/thunderbolt/tb_msgs.h | |
parent | thunderbolt: Do not touch the hardware if the NHI is gone on resume (diff) | |
download | linux-f67cf491175a315ca86c9b349708bfed7b1f40c1.tar.xz linux-f67cf491175a315ca86c9b349708bfed7b1f40c1.zip |
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 <michael.jamet@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Yehezkel Bernat <yehezkel.bernat@intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Andreas Noever <andreas.noever@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/thunderbolt/tb_msgs.h')
-rw-r--r-- | drivers/thunderbolt/tb_msgs.h | 152 |
1 files changed, 152 insertions, 0 deletions
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 <linux/types.h> +#include <linux/uuid.h> 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 |