1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * U2F Zero LED and RNG driver 4 * 5 * Copyright 2018 Andrej Shadura <andrew@shadura.me> 6 * Loosely based on drivers/hid/hid-led.c 7 * and drivers/usb/misc/chaoskey.c 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation, version 2. 12 */ 13 14 #include <linux/hid.h> 15 #include <linux/hidraw.h> 16 #include <linux/hw_random.h> 17 #include <linux/leds.h> 18 #include <linux/module.h> 19 #include <linux/mutex.h> 20 #include <linux/usb.h> 21 22 #include "usbhid/usbhid.h" 23 #include "hid-ids.h" 24 25 #define DRIVER_SHORT "u2fzero" 26 27 #define HID_REPORT_SIZE 64 28 29 /* We only use broadcast (CID-less) messages */ 30 #define CID_BROADCAST 0xffffffff 31 32 struct u2f_hid_msg { 33 u32 cid; 34 union { 35 struct { 36 u8 cmd; 37 u8 bcnth; 38 u8 bcntl; 39 u8 data[HID_REPORT_SIZE - 7]; 40 } init; 41 struct { 42 u8 seq; 43 u8 data[HID_REPORT_SIZE - 5]; 44 } cont; 45 }; 46 } __packed; 47 48 struct u2f_hid_report { 49 u8 report_type; 50 struct u2f_hid_msg msg; 51 } __packed; 52 53 #define U2F_HID_MSG_LEN(f) (size_t)(((f).init.bcnth << 8) + (f).init.bcntl) 54 55 /* Custom extensions to the U2FHID protocol */ 56 #define U2F_CUSTOM_GET_RNG 0x21 57 #define U2F_CUSTOM_WINK 0x24 58 59 struct u2fzero_device { 60 struct hid_device *hdev; 61 struct urb *urb; /* URB for the RNG data */ 62 struct led_classdev ldev; /* Embedded struct for led */ 63 struct hwrng hwrng; /* Embedded struct for hwrng */ 64 char *led_name; 65 char *rng_name; 66 u8 *buf_out; 67 u8 *buf_in; 68 struct mutex lock; 69 bool present; 70 }; 71 72 static int u2fzero_send(struct u2fzero_device *dev, struct u2f_hid_report *req) 73 { 74 int ret; 75 76 mutex_lock(&dev->lock); 77 78 memcpy(dev->buf_out, req, sizeof(struct u2f_hid_report)); 79 80 ret = hid_hw_output_report(dev->hdev, dev->buf_out, 81 sizeof(struct u2f_hid_msg)); 82 83 mutex_unlock(&dev->lock); 84 85 if (ret < 0) 86 return ret; 87 88 return ret == sizeof(struct u2f_hid_msg) ? 0 : -EMSGSIZE; 89 } 90 91 struct u2fzero_transfer_context { 92 struct completion done; 93 int status; 94 }; 95 96 static void u2fzero_read_callback(struct urb *urb) 97 { 98 struct u2fzero_transfer_context *ctx = urb->context; 99 100 ctx->status = urb->status; 101 complete(&ctx->done); 102 } 103 104 static int u2fzero_recv(struct u2fzero_device *dev, 105 struct u2f_hid_report *req, 106 struct u2f_hid_msg *resp) 107 { 108 int ret; 109 struct hid_device *hdev = dev->hdev; 110 struct u2fzero_transfer_context ctx; 111 112 mutex_lock(&dev->lock); 113 114 memcpy(dev->buf_out, req, sizeof(struct u2f_hid_report)); 115 116 dev->urb->context = &ctx; 117 init_completion(&ctx.done); 118 119 ret = usb_submit_urb(dev->urb, GFP_NOIO); 120 if (unlikely(ret)) { 121 hid_err(hdev, "usb_submit_urb failed: %d", ret); 122 goto err; 123 } 124 125 ret = hid_hw_output_report(dev->hdev, dev->buf_out, 126 sizeof(struct u2f_hid_msg)); 127 128 if (ret < 0) { 129 hid_err(hdev, "hid_hw_output_report failed: %d", ret); 130 goto err; 131 } 132 133 ret = (wait_for_completion_timeout( 134 &ctx.done, msecs_to_jiffies(USB_CTRL_SET_TIMEOUT))); 135 if (ret < 0) { 136 usb_kill_urb(dev->urb); 137 hid_err(hdev, "urb submission timed out"); 138 } else { 139 ret = dev->urb->actual_length; 140 memcpy(resp, dev->buf_in, ret); 141 } 142 143 err: 144 mutex_unlock(&dev->lock); 145 146 return ret; 147 } 148 149 static int u2fzero_blink(struct led_classdev *ldev) 150 { 151 struct u2fzero_device *dev = container_of(ldev, 152 struct u2fzero_device, ldev); 153 struct u2f_hid_report req = { 154 .report_type = 0, 155 .msg.cid = CID_BROADCAST, 156 .msg.init = { 157 .cmd = U2F_CUSTOM_WINK, 158 .bcnth = 0, 159 .bcntl = 0, 160 .data = {0}, 161 } 162 }; 163 return u2fzero_send(dev, &req); 164 } 165 166 static int u2fzero_brightness_set(struct led_classdev *ldev, 167 enum led_brightness brightness) 168 { 169 ldev->brightness = LED_OFF; 170 if (brightness) 171 return u2fzero_blink(ldev); 172 else 173 return 0; 174 } 175 176 static int u2fzero_rng_read(struct hwrng *rng, void *data, 177 size_t max, bool wait) 178 { 179 struct u2fzero_device *dev = container_of(rng, 180 struct u2fzero_device, hwrng); 181 struct u2f_hid_report req = { 182 .report_type = 0, 183 .msg.cid = CID_BROADCAST, 184 .msg.init = { 185 .cmd = U2F_CUSTOM_GET_RNG, 186 .bcnth = 0, 187 .bcntl = 0, 188 .data = {0}, 189 } 190 }; 191 struct u2f_hid_msg resp; 192 int ret; 193 size_t actual_length; 194 195 if (!dev->present) { 196 hid_dbg(dev->hdev, "device not present"); 197 return 0; 198 } 199 200 ret = u2fzero_recv(dev, &req, &resp); 201 if (ret < 0) 202 return 0; 203 204 /* only take the minimum amount of data it is safe to take */ 205 actual_length = min3((size_t)ret - offsetof(struct u2f_hid_msg, 206 init.data), U2F_HID_MSG_LEN(resp), max); 207 208 memcpy(data, resp.init.data, actual_length); 209 210 return actual_length; 211 } 212 213 static int u2fzero_init_led(struct u2fzero_device *dev, 214 unsigned int minor) 215 { 216 dev->led_name = devm_kasprintf(&dev->hdev->dev, GFP_KERNEL, 217 "%s%u", DRIVER_SHORT, minor); 218 if (dev->led_name == NULL) 219 return -ENOMEM; 220 221 dev->ldev.name = dev->led_name; 222 dev->ldev.max_brightness = LED_ON; 223 dev->ldev.flags = LED_HW_PLUGGABLE; 224 dev->ldev.brightness_set_blocking = u2fzero_brightness_set; 225 226 return devm_led_classdev_register(&dev->hdev->dev, &dev->ldev); 227 } 228 229 static int u2fzero_init_hwrng(struct u2fzero_device *dev, 230 unsigned int minor) 231 { 232 dev->rng_name = devm_kasprintf(&dev->hdev->dev, GFP_KERNEL, 233 "%s-rng%u", DRIVER_SHORT, minor); 234 if (dev->rng_name == NULL) 235 return -ENOMEM; 236 237 dev->hwrng.name = dev->rng_name; 238 dev->hwrng.read = u2fzero_rng_read; 239 dev->hwrng.quality = 1; 240 241 return devm_hwrng_register(&dev->hdev->dev, &dev->hwrng); 242 } 243 244 static int u2fzero_fill_in_urb(struct u2fzero_device *dev) 245 { 246 struct hid_device *hdev = dev->hdev; 247 struct usb_device *udev; 248 struct usbhid_device *usbhid = hdev->driver_data; 249 unsigned int pipe_in; 250 struct usb_host_endpoint *ep; 251 252 if (dev->hdev->bus != BUS_USB) 253 return -EINVAL; 254 255 udev = hid_to_usb_dev(hdev); 256 257 if (!usbhid->urbout || !usbhid->urbin) 258 return -ENODEV; 259 260 ep = usb_pipe_endpoint(udev, usbhid->urbin->pipe); 261 if (!ep) 262 return -ENODEV; 263 264 dev->urb = usb_alloc_urb(0, GFP_KERNEL); 265 if (!dev->urb) 266 return -ENOMEM; 267 268 pipe_in = (usbhid->urbin->pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); 269 270 usb_fill_int_urb(dev->urb, 271 udev, 272 pipe_in, 273 dev->buf_in, 274 HID_REPORT_SIZE, 275 u2fzero_read_callback, 276 NULL, 277 ep->desc.bInterval); 278 279 return 0; 280 } 281 282 static int u2fzero_probe(struct hid_device *hdev, 283 const struct hid_device_id *id) 284 { 285 struct u2fzero_device *dev; 286 unsigned int minor; 287 int ret; 288 289 if (!hid_is_using_ll_driver(hdev, &usb_hid_driver)) 290 return -EINVAL; 291 292 dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); 293 if (dev == NULL) 294 return -ENOMEM; 295 296 dev->buf_out = devm_kmalloc(&hdev->dev, 297 sizeof(struct u2f_hid_report), GFP_KERNEL); 298 if (dev->buf_out == NULL) 299 return -ENOMEM; 300 301 dev->buf_in = devm_kmalloc(&hdev->dev, 302 sizeof(struct u2f_hid_msg), GFP_KERNEL); 303 if (dev->buf_in == NULL) 304 return -ENOMEM; 305 306 ret = hid_parse(hdev); 307 if (ret) 308 return ret; 309 310 dev->hdev = hdev; 311 hid_set_drvdata(hdev, dev); 312 mutex_init(&dev->lock); 313 314 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); 315 if (ret) 316 return ret; 317 318 u2fzero_fill_in_urb(dev); 319 320 dev->present = true; 321 322 minor = ((struct hidraw *) hdev->hidraw)->minor; 323 324 ret = u2fzero_init_led(dev, minor); 325 if (ret) { 326 hid_hw_stop(hdev); 327 return ret; 328 } 329 330 hid_info(hdev, "U2F Zero LED initialised\n"); 331 332 ret = u2fzero_init_hwrng(dev, minor); 333 if (ret) { 334 hid_hw_stop(hdev); 335 return ret; 336 } 337 338 hid_info(hdev, "U2F Zero RNG initialised\n"); 339 340 return 0; 341 } 342 343 static void u2fzero_remove(struct hid_device *hdev) 344 { 345 struct u2fzero_device *dev = hid_get_drvdata(hdev); 346 347 mutex_lock(&dev->lock); 348 dev->present = false; 349 mutex_unlock(&dev->lock); 350 351 hid_hw_stop(hdev); 352 usb_poison_urb(dev->urb); 353 usb_free_urb(dev->urb); 354 } 355 356 static const struct hid_device_id u2fzero_table[] = { 357 { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, 358 USB_DEVICE_ID_U2F_ZERO) }, 359 { } 360 }; 361 MODULE_DEVICE_TABLE(hid, u2fzero_table); 362 363 static struct hid_driver u2fzero_driver = { 364 .name = "hid-" DRIVER_SHORT, 365 .probe = u2fzero_probe, 366 .remove = u2fzero_remove, 367 .id_table = u2fzero_table, 368 }; 369 370 module_hid_driver(u2fzero_driver); 371 372 MODULE_LICENSE("GPL"); 373 MODULE_AUTHOR("Andrej Shadura <andrew@shadura.me>"); 374 MODULE_DESCRIPTION("U2F Zero LED and RNG driver"); 375