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 3939b60..0082912 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 dd93493..dfcb22d 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 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel