[PATCH 3/7] staging: usbip: Pass session keys to the kernel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This extends the userspace code to write the generated session keys to
sysfs in hexadecimal encoding after establishing the connection.
The kernel code is modified to parse the session keys.

Signed-off-by: Dominik Paulus <dominik.paulus@xxxxxx>
Signed-off-by: Tobias Polzer <tobias.polzer@xxxxxx>
---
 drivers/staging/usbip/stub_dev.c                   | 26 +++++++++++++++++++-
 drivers/staging/usbip/usbip_common.h               | 10 ++++++++
 .../staging/usbip/userspace/libsrc/usbip_common.c  | 14 +++++++++++
 .../staging/usbip/userspace/libsrc/usbip_common.h  |  2 ++
 .../usbip/userspace/libsrc/usbip_host_driver.c     | 15 ++++++++----
 .../staging/usbip/userspace/libsrc/vhci_driver.c   |  8 ++++---
 drivers/staging/usbip/vhci_sysfs.c                 | 28 +++++++++++++++++++++-
 7 files changed, 94 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index c44d5f2..f7bc6e1 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -87,13 +87,37 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
 	int sockfd = 0;
 	struct socket *socket;
 	ssize_t err = -EINVAL;
+	char sendkey[USBIP_KEYSIZE], recvkey[USBIP_KEYSIZE];
+	char sendkey_hex[2 * USBIP_KEYSIZE + 1];
+	char recvkey_hex[2 * USBIP_KEYSIZE + 1];
 
 	if (!sdev) {
 		dev_err(dev, "sdev is null\n");
 		return -ENODEV;
 	}
 
-	sscanf(buf, "%d", &sockfd);
+	/*
+	 * Read symmetric crypto keys. They are randomly
+	 * generated by userspace and passed to the kernel
+	 * via sysfs (encoded in hexadecimal)
+	 */
+	if (sscanf(buf, "%d %d %32s %32s", &sockfd, &sdev->ud.use_crypto,
+			sendkey_hex, recvkey_hex) < 1) {
+		dev_err(dev, "Invalid write to sysfs: Invalid sockfd\n");
+		return -EINVAL;
+	}
+	if (sdev->ud.use_crypto) {
+		int i;
+		dev_info(dev, "Using encrypted data transport\n");
+		for (i = USBIP_KEYSIZE - 1; i >= 0; --i) {
+			sendkey_hex[2 * (i + 1)] = 0;
+			sscanf(sendkey_hex + (2 * i), "%2hhX", &sendkey[i]);
+		}
+		for (i = USBIP_KEYSIZE - 1; i >= 0; --i) {
+			recvkey_hex[2 * (i + 1)] = 0;
+			sscanf(recvkey_hex + (2 * i), "%2hhX", &recvkey[i]);
+		}
+	}
 
 	if (sockfd != -1) {
 		dev_info(dev, "stub up\n");
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index 7e6c543..96c87ee 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -32,6 +32,13 @@
 
 #define USBIP_VERSION "1.0.0"
 
+/*
+ * Length of symmetric keys. Currently, this should be fixed at 16 bytes.
+ * Will break code if changed, look at userspace and stub_dev.c/vhci_sysfs.c
+ * where this constant is used before changing.
+ */
+#define USBIP_KEYSIZE 16
+
 #undef pr_fmt
 
 #ifdef DEBUG
@@ -290,6 +297,9 @@ struct usbip_device {
 		void (*reset)(struct usbip_device *);
 		void (*unusable)(struct usbip_device *);
 	} eh_ops;
+
+	/* Crypto support */
+	int use_crypto;
 };
 
 #define kthread_get_run(threadfn, data, namefmt, ...)			   \
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.c b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
index 17e08e0..1ec9cc9 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_common.c
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
@@ -290,3 +290,17 @@ void usbip_names_get_class(char *buff, size_t size, uint8_t class,
 
 	snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol);
 }
+
+/*
+ * Converts a 16-byte key to hexadecimal to be pushed to kernelspace
+ *
+ * Output buffer must be at least 33 bytes long
+ */
+char *keytohex(unsigned char *key, char *out)
+{
+	int i;
+	out[32] = 0;
+	for (i = 0; i != 16; ++i)
+		sprintf(out + (2 * i), "%02X", key[i]);
+	return out;
+}
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.h b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
index f804c04..a5d4d21 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_common.h
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
@@ -168,4 +168,6 @@ void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
 void usbip_names_get_class(char *buff, size_t size, uint8_t class,
 			   uint8_t subclass, uint8_t protocol);
 
+char *keytohex(unsigned char *key, char *out);
+
 #endif /* __USBIP_COMMON_H */
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
index 60247f2..be08ad7 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
@@ -338,7 +338,7 @@ int usbip_host_export_device(struct usbip_exported_device *edev,
 	char attr_name[] = "usbip_sockfd";
 	char attr_path[SYSFS_PATH_MAX];
 	struct sysfs_attribute *attr;
-	char sockfd_buff[30];
+	char sockfd_buff[512];
 	int ret;
 
 	if (edev->status != SDEV_ST_AVAILABLE) {
@@ -367,10 +367,17 @@ int usbip_host_export_device(struct usbip_exported_device *edev,
 		return -1;
 	}
 
-	snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", conf->sockfd);
-	dbg("write: %s", sockfd_buff);
+	{
+		char key1[33], key2[33];
+		snprintf(sockfd_buff, sizeof(sockfd_buff), "%d %d %s %s\n",
+				conf->sockfd, conf->use_crypto,
+				keytohex(conf->key2, key2),
+				keytohex(conf->key1, key1));
+		dbg("write: %s", sockfd_buff);
+	}
 
-	ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff));
+	ret = sysfs_write_attribute(attr, (const char *) sockfd_buff,
+			strlen(sockfd_buff));
 	if (ret < 0) {
 		dbg("sysfs_write_attribute failed: sockfd %s to %s",
 		    sockfd_buff, attr_path);
diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
index d1d45bb..66cdfaf 100644
--- a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
@@ -470,7 +470,7 @@ int usbip_vhci_get_free_port(void)
 int usbip_vhci_attach_device(struct vhci_conf *conf)
 {
 	struct sysfs_attribute *attr_attach;
-	char buff[200]; /* what size should be ? */
+	char buff[512], key1[33], key2[33];
 	int ret;
 
 	attr_attach = sysfs_get_device_attr(vhci_driver->hc_device, "attach");
@@ -480,8 +480,10 @@ int usbip_vhci_attach_device(struct vhci_conf *conf)
 		return -1;
 	}
 
-	snprintf(buff, sizeof(buff), "%u %u %u %u",
-			conf->port, conf->sockfd, conf->devid, conf->speed);
+	snprintf(buff, sizeof(buff), "%u %u %u %u %d %s %s",
+			conf->port, conf->sockfd, conf->devid, conf->speed,
+			conf->use_crypto, keytohex(conf->key1, key1),
+			keytohex(conf->key2, key2));
 	dbg("writing: %s", buff);
 
 	ret = sysfs_write_attribute(attr_attach, buff, strlen(buff));
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
index 9b51586..1ef3f25 100644
--- a/drivers/staging/usbip/vhci_sysfs.c
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -174,14 +174,40 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 	struct socket *socket;
 	int sockfd = 0;
 	__u32 rhport = 0, devid = 0, speed = 0;
+	unsigned char sendkey[USBIP_KEYSIZE], recvkey[USBIP_KEYSIZE];
+	char sendkey_hex[2*USBIP_KEYSIZE+1], recvkey_hex[2*USBIP_KEYSIZE+1];
+	int use_crypto = 0;
 
 	/*
 	 * @rhport: port number of vhci_hcd
 	 * @sockfd: socket descriptor of an established TCP connection
 	 * @devid: unique device identifier in a remote host
 	 * @speed: usb device speed in a remote host
+	 * @use_crypto: Whether to use an encrypted connection
+	 * @recvkey_hex/@sendkey_hex: Hexadecimal encoded 128bit
+	 *              symmetric encryption keys to be used.
+	 *              Generated randomly for each connection
+	 *              by userspace.
 	 */
-	sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed);
+	sendkey_hex[0] = 0;
+	recvkey_hex[0] = 0;
+	sscanf(buf, "%u %u %u %u %d %32s %32s", &rhport, &sockfd,
+			&devid, &speed, &use_crypto, sendkey_hex,
+			recvkey_hex);
+	if (use_crypto && strlen(sendkey_hex) == 32 &&
+			strlen(recvkey_hex) == 32) {
+		int i;
+		dev_info(dev, "Using encrypted data transport\n");
+		/* Decode decimal representation */
+		for (i = USBIP_KEYSIZE - 1; i >= 0; --i) {
+			sendkey_hex[2 * (i + 1)] = 0;
+			sscanf(sendkey_hex + (2 * i), "%2hhX", &sendkey[i]);
+		}
+		for (i = USBIP_KEYSIZE - 1; i >= 0; --i) {
+			recvkey_hex[2 * (i + 1)] = 0;
+			sscanf(recvkey_hex + (2 * i), "%2hhX", &recvkey[i]);
+		}
+	}
 
 	usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n",
 			     rhport, sockfd, devid, speed);
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux