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 202 /* ignore errors or packets without data */ 203 if (ret < offsetof(struct u2f_hid_msg, init.data)) 204 return 0; 205 206 /* only take the minimum amount of data it is safe to take */ 207 actual_length = min3((size_t)ret - offsetof(struct u2f_hid_msg, 208 init.data), U2F_HID_MSG_LEN(resp), max); 209 210 memcpy(data, resp.init.data, actual_length); 211 212 return actual_length; 213 } 214 215 static int u2fzero_init_led(struct u2fzero_device *dev, 216 unsigned int minor) 217 { 218 dev->led_name = devm_kasprintf(&dev->hdev->dev, GFP_KERNEL, 219 "%s%u", DRIVER_SHORT, minor); 220 if (dev->led_name == NULL) 221 return -ENOMEM; 222 223 dev->ldev.name = dev->led_name; 224 dev->ldev.max_brightness = LED_ON; 225 dev->ldev.flags = LED_HW_PLUGGABLE; 226 dev->ldev.brightness_set_blocking = u2fzero_brightness_set; 227 228 return devm_led_classdev_register(&dev->hdev->dev, &dev->ldev); 229 } 230 231 static int u2fzero_init_hwrng(struct u2fzero_device *dev, 232 unsigned int minor) 233 { 234 dev->rng_name = devm_kasprintf(&dev->hdev->dev, GFP_KERNEL, 235 "%s-rng%u", DRIVER_SHORT, minor); 236 if (dev->rng_name == NULL) 237 return -ENOMEM; 238 239 dev->hwrng.name = dev->rng_name; 240 dev->hwrng.read = u2fzero_rng_read; 241 dev->hwrng.quality = 1; 242 243 return devm_hwrng_register(&dev->hdev->dev, &dev->hwrng); 244 } 245 246 static int u2fzero_fill_in_urb(struct u2fzero_device *dev) 247 { 248 struct hid_device *hdev = dev->hdev; 249 struct usb_device *udev; 250 struct usbhid_device *usbhid = hdev->driver_data; 251 unsigned int pipe_in; 252 struct usb_host_endpoint *ep; 253 254 if (dev->hdev->bus != BUS_USB) 255 return -EINVAL; 256 257 udev = hid_to_usb_dev(hdev); 258 259 if (!usbhid->urbout || !usbhid->urbin) 260 return -ENODEV; 261 262 ep = usb_pipe_endpoint(udev, usbhid->urbin->pipe); 263 if (!ep) 264 return -ENODEV; 265 266 dev->urb = usb_alloc_urb(0, GFP_KERNEL); 267 if (!dev->urb) 268 return -ENOMEM; 269 270 pipe_in = (usbhid->urbin->pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); 271 272 usb_fill_int_urb(dev->urb, 273 udev, 274 pipe_in, 275 dev->buf_in, 276 HID_REPORT_SIZE, 277 u2fzero_read_callback, 278 NULL, 279 ep->desc.bInterval); 280 281 return 0; 282 } 283 284 static int u2fzero_probe(struct hid_device *hdev, 285 const struct hid_device_id *id) 286 { 287 struct u2fzero_device *dev; 288 unsigned int minor; 289 int ret; 290 291 if (!hid_is_using_ll_driver(hdev, &usb_hid_driver)) 292 return -EINVAL; 293 294 dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); 295 if (dev == NULL) 296 return -ENOMEM; 297 298 dev->buf_out = devm_kmalloc(&hdev->dev, 299 sizeof(struct u2f_hid_report), GFP_KERNEL); 300 if (dev->buf_out == NULL) 301 return -ENOMEM; 302 303 dev->buf_in = devm_kmalloc(&hdev->dev, 304 sizeof(struct u2f_hid_msg), GFP_KERNEL); 305 if (dev->buf_in == NULL) 306 return -ENOMEM; 307 308 ret = hid_parse(hdev); 309 if (ret) 310 return ret; 311 312 dev->hdev = hdev; 313 hid_set_drvdata(hdev, dev); 314 mutex_init(&dev->lock); 315 316 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); 317 if (ret) 318 return ret; 319 320 u2fzero_fill_in_urb(dev); 321 322 dev->present = true; 323 324 minor = ((struct hidraw *) hdev->hidraw)->minor; 325 326 ret = u2fzero_init_led(dev, minor); 327 if (ret) { 328 hid_hw_stop(hdev); 329 return ret; 330 } 331 332 hid_info(hdev, "U2F Zero LED initialised\n"); 333 334 ret = u2fzero_init_hwrng(dev, minor); 335 if (ret) { 336 hid_hw_stop(hdev); 337 return ret; 338 } 339 340 hid_info(hdev, "U2F Zero RNG initialised\n"); 341 342 return 0; 343 } 344 345 static void u2fzero_remove(struct hid_device *hdev) 346 { 347 struct u2fzero_device *dev = hid_get_drvdata(hdev); 348 349 mutex_lock(&dev->lock); 350 dev->present = false; 351 mutex_unlock(&dev->lock); 352 353 hid_hw_stop(hdev); 354 usb_poison_urb(dev->urb); 355 usb_free_urb(dev->urb); 356 } 357 358 static const struct hid_device_id u2fzero_table[] = { 359 { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, 360 USB_DEVICE_ID_U2F_ZERO) }, 361 { } 362 }; 363 MODULE_DEVICE_TABLE(hid, u2fzero_table); 364 365 static struct hid_driver u2fzero_driver = { 366 .name = "hid-" DRIVER_SHORT, 367 .probe = u2fzero_probe, 368 .remove = u2fzero_remove, 369 .id_table = u2fzero_table, 370 }; 371 372 module_hid_driver(u2fzero_driver); 373 374 MODULE_LICENSE("GPL"); 375 MODULE_AUTHOR("Andrej Shadura <andrew@shadura.me>"); 376 MODULE_DESCRIPTION("U2F Zero LED and RNG driver"); 377