aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2015-03-19 23:36:49 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-26 05:47:11 -0400
commit66e3e591891da9899a8990792da080432531ffd4 (patch)
treed54303288c4261218e78587c48f9e376d8118f77 /drivers/usb/misc
parent1fcefbdf06708a5811ffa8acc949714aee60ae13 (diff)
usb: Add driver for Altus Metrum ChaosKey device (v2)
This is a hardware random number generator. The driver provides both a /dev/chaoskeyX entry and hooks the entropy source up to the kernel hwrng interface. More information about the device can be found at http://chaoskey.org The USB ID for ChaosKey was allocated from the OpenMoko USB vendor space and is visible as 'USBtrng' here: http://wiki.openmoko.org/wiki/USB_Product_IDs v2: Respond to review from Oliver Neukum <oneukum@suse.de> * Delete extensive debug infrastructure and replace it with calls to dev_dbg. * Allocate I/O buffer separately from device structure to obey requirements for non-coherant architectures. * Initialize mutexes before registering device to ensure that open cannot be invoked before the device is ready to proceed. * Return number of bytes read instead of -EINTR when partial read operation is aborted due to a signal. * Make sure device mutex is unlocked in read error paths. * Add MAINTAINERS entry for the driver Signed-off-by: Keith Packard <keithp@keithp.com> Cc: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r--drivers/usb/misc/Kconfig12
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/chaoskey.c530
3 files changed, 543 insertions, 0 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 76d77206e011..8c331f1dfd23 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -255,3 +255,15 @@ config USB_LINK_LAYER_TEST
255 This driver is for generating specific traffic for Super Speed Link 255 This driver is for generating specific traffic for Super Speed Link
256 Layer Test Device. Say Y only when you want to conduct USB Super Speed 256 Layer Test Device. Say Y only when you want to conduct USB Super Speed
257 Link Layer Test for host controllers. 257 Link Layer Test for host controllers.
258
259config USB_CHAOSKEY
260 tristate "ChaosKey random number generator driver support"
261 help
262 Say Y here if you want to connect an AltusMetrum ChaosKey to
263 your computer's USB port. The ChaosKey is a hardware random
264 number generator which hooks into the kernel entropy pool to
265 ensure a large supply of entropy for /dev/random and
266 /dev/urandom and also provides direct access via /dev/chaoskeyX
267
268 To compile this driver as a module, choose M here: the
269 module will be called chaoskey.
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 65b0402c1ca1..45fd4ac39d3e 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_USB_USS720) += uss720.o
25obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o 25obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o
26obj-$(CONFIG_USB_YUREX) += yurex.o 26obj-$(CONFIG_USB_YUREX) += yurex.o
27obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o 27obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o
28obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o
28 29
29obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ 30obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/
30obj-$(CONFIG_USB_LINK_LAYER_TEST) += lvstest.o 31obj-$(CONFIG_USB_LINK_LAYER_TEST) += lvstest.o
diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
new file mode 100644
index 000000000000..ef80ce9452a4
--- /dev/null
+++ b/drivers/usb/misc/chaoskey.c
@@ -0,0 +1,530 @@
1/*
2 * chaoskey - driver for ChaosKey device from Altus Metrum.
3 *
4 * This device provides true random numbers using a noise source based
5 * on a reverse-biased p-n junction in avalanche breakdown. More
6 * details can be found at http://chaoskey.org
7 *
8 * The driver connects to the kernel hardware RNG interface to provide
9 * entropy for /dev/random and other kernel activities. It also offers
10 * a separate /dev/ entry to allow for direct access to the random
11 * bit stream.
12 *
13 * Copyright © 2015 Keith Packard <keithp@keithp.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; version 2 of the License.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 */
24
25#include <linux/module.h>
26#include <linux/slab.h>
27#include <linux/usb.h>
28#include <linux/wait.h>
29#include <linux/hw_random.h>
30
31static struct usb_driver chaoskey_driver;
32static struct usb_class_driver chaoskey_class;
33static int chaoskey_rng_read(struct hwrng *rng, void *data,
34 size_t max, bool wait);
35
36#define usb_dbg(usb_if, format, arg...) \
37 dev_dbg(&(usb_if)->dev, format, ## arg)
38
39#define usb_err(usb_if, format, arg...) \
40 dev_err(&(usb_if)->dev, format, ## arg)
41
42/* Version Information */
43#define DRIVER_VERSION "v0.1"
44#define DRIVER_AUTHOR "Keith Packard, keithp@keithp.com"
45#define DRIVER_DESC "Altus Metrum ChaosKey driver"
46#define DRIVER_SHORT "chaoskey"
47
48MODULE_VERSION(DRIVER_VERSION);
49MODULE_AUTHOR(DRIVER_AUTHOR);
50MODULE_DESCRIPTION(DRIVER_DESC);
51MODULE_LICENSE("GPL");
52
53#define CHAOSKEY_VENDOR_ID 0x1d50 /* OpenMoko */
54#define CHAOSKEY_PRODUCT_ID 0x60c6 /* ChaosKey */
55
56#define CHAOSKEY_BUF_LEN 64 /* max size of USB full speed packet */
57
58#define NAK_TIMEOUT (HZ) /* stall/wait timeout for device */
59
60#ifdef CONFIG_USB_DYNAMIC_MINORS
61#define USB_CHAOSKEY_MINOR_BASE 0
62#else
63
64/* IOWARRIOR_MINOR_BASE + 16, not official yet */
65#define USB_CHAOSKEY_MINOR_BASE 224
66#endif
67
68static const struct usb_device_id chaoskey_table[] = {
69 { USB_DEVICE(CHAOSKEY_VENDOR_ID, CHAOSKEY_PRODUCT_ID) },
70 { },
71};
72MODULE_DEVICE_TABLE(usb, chaoskey_table);
73
74/* Driver-local specific stuff */
75struct chaoskey {
76 struct usb_interface *interface;
77 char in_ep;
78 struct mutex lock;
79 struct mutex rng_lock;
80 int open; /* open count */
81 int present; /* device not disconnected */
82 int size; /* size of buf */
83 int valid; /* bytes of buf read */
84 int used; /* bytes of buf consumed */
85 char *name; /* product + serial */
86 struct hwrng hwrng; /* Embedded struct for hwrng */
87 int hwrng_registered; /* registered with hwrng API */
88 wait_queue_head_t wait_q; /* for timeouts */
89 char *buf;
90};
91
92static void chaoskey_free(struct chaoskey *dev)
93{
94 usb_dbg(dev->interface, "free");
95 kfree(dev->name);
96 kfree(dev->buf);
97 kfree(dev);
98}
99
100static int chaoskey_probe(struct usb_interface *interface,
101 const struct usb_device_id *id)
102{
103 struct usb_device *udev = interface_to_usbdev(interface);
104 struct usb_host_interface *altsetting = interface->cur_altsetting;
105 int i;
106 int in_ep = -1;
107 struct chaoskey *dev;
108 int result;
109 int size;
110
111 usb_dbg(interface, "probe %s-%s", udev->product, udev->serial);
112
113 /* Find the first bulk IN endpoint and its packet size */
114 for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
115 if (usb_endpoint_is_bulk_in(&altsetting->endpoint[i].desc)) {
116 in_ep = altsetting->endpoint[i].desc.bEndpointAddress;
117 size = altsetting->endpoint[i].desc.wMaxPacketSize;
118 break;
119 }
120 }
121
122 /* Validate endpoint and size */
123 if (in_ep == -1) {
124 usb_dbg(interface, "no IN endpoint found");
125 return -ENODEV;
126 }
127 if (size <= 0) {
128 usb_dbg(interface, "invalid size (%d)", size);
129 return -ENODEV;
130 }
131
132 if (size > CHAOSKEY_BUF_LEN) {
133 usb_dbg(interface, "size reduced from %d to %d\n",
134 size, CHAOSKEY_BUF_LEN);
135 size = CHAOSKEY_BUF_LEN;
136 }
137
138 /* Looks good, allocate and initialize */
139
140 dev = kzalloc(sizeof(struct chaoskey), GFP_KERNEL);
141
142 if (dev == NULL)
143 return -ENOMEM;
144
145 dev->buf = kmalloc(size, GFP_KERNEL);
146
147 if (dev->buf == NULL) {
148 kfree(dev);
149 return -ENOMEM;
150 }
151
152 /* Construct a name using the product and serial values. Each
153 * device needs a unique name for the hwrng code
154 */
155
156 if (udev->product && udev->serial) {
157 dev->name = kmalloc(strlen(udev->product) + 1 +
158 strlen(udev->serial) + 1, GFP_KERNEL);
159 if (dev->name == NULL) {
160 kfree(dev->buf);
161 kfree(dev);
162 return -ENOMEM;
163 }
164
165 strcpy(dev->name, udev->product);
166 strcat(dev->name, "-");
167 strcat(dev->name, udev->serial);
168 }
169
170 dev->interface = interface;
171
172 dev->in_ep = in_ep;
173
174 dev->size = size;
175 dev->present = 1;
176
177 init_waitqueue_head(&dev->wait_q);
178
179 mutex_init(&dev->lock);
180 mutex_init(&dev->rng_lock);
181
182 usb_set_intfdata(interface, dev);
183
184 result = usb_register_dev(interface, &chaoskey_class);
185 if (result) {
186 usb_err(interface, "Unable to allocate minor number.");
187 usb_set_intfdata(interface, NULL);
188 chaoskey_free(dev);
189 return result;
190 }
191
192 dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name;
193 dev->hwrng.read = chaoskey_rng_read;
194
195 /* Set the 'quality' metric. Quality is measured in units of
196 * 1/1024's of a bit ("mills"). This should be set to 1024,
197 * but there is a bug in the hwrng core which masks it with
198 * 1023.
199 *
200 * The patch that has been merged to the crypto development
201 * tree for that bug limits the value to 1024 at most, so by
202 * setting this to 1024 + 1023, we get 1023 before the fix is
203 * merged and 1024 afterwards. We'll patch this driver once
204 * both bits of code are in the same tree.
205 */
206 dev->hwrng.quality = 1024 + 1023;
207
208 dev->hwrng_registered = (hwrng_register(&dev->hwrng) == 0);
209 if (!dev->hwrng_registered)
210 usb_err(interface, "Unable to register with hwrng");
211
212 usb_enable_autosuspend(udev);
213
214 usb_dbg(interface, "chaoskey probe success, size %d", dev->size);
215 return 0;
216}
217
218static void chaoskey_disconnect(struct usb_interface *interface)
219{
220 struct chaoskey *dev;
221
222 usb_dbg(interface, "disconnect");
223 dev = usb_get_intfdata(interface);
224 if (!dev) {
225 usb_dbg(interface, "disconnect failed - no dev");
226 return;
227 }
228
229 if (dev->hwrng_registered)
230 hwrng_unregister(&dev->hwrng);
231
232 usb_deregister_dev(interface, &chaoskey_class);
233
234 usb_set_intfdata(interface, NULL);
235 mutex_lock(&dev->lock);
236
237 dev->present = 0;
238
239 if (!dev->open) {
240 mutex_unlock(&dev->lock);
241 chaoskey_free(dev);
242 } else
243 mutex_unlock(&dev->lock);
244
245 usb_dbg(interface, "disconnect done");
246}
247
248static int chaoskey_open(struct inode *inode, struct file *file)
249{
250 struct chaoskey *dev;
251 struct usb_interface *interface;
252
253 /* get the interface from minor number and driver information */
254 interface = usb_find_interface(&chaoskey_driver, iminor(inode));
255 if (!interface)
256 return -ENODEV;
257
258 usb_dbg(interface, "open");
259
260 dev = usb_get_intfdata(interface);
261 if (!dev) {
262 usb_dbg(interface, "open (dev)");
263 return -ENODEV;
264 }
265
266 file->private_data = dev;
267 mutex_lock(&dev->lock);
268 ++dev->open;
269 mutex_unlock(&dev->lock);
270
271 usb_dbg(interface, "open success");
272 return 0;
273}
274
275static int chaoskey_release(struct inode *inode, struct file *file)
276{
277 struct chaoskey *dev = file->private_data;
278 struct usb_interface *interface;
279
280 if (dev == NULL)
281 return -ENODEV;
282
283 interface = dev->interface;
284
285 usb_dbg(interface, "release");
286
287 mutex_lock(&dev->lock);
288
289 usb_dbg(interface, "open count at release is %d", dev->open);
290
291 if (dev->open <= 0) {
292 usb_dbg(interface, "invalid open count (%d)", dev->open);
293 mutex_unlock(&dev->lock);
294 return -ENODEV;
295 }
296
297 --dev->open;
298
299 if (!dev->present) {
300 if (dev->open == 0) {
301 mutex_unlock(&dev->lock);
302 chaoskey_free(dev);
303 } else
304 mutex_unlock(&dev->lock);
305 } else
306 mutex_unlock(&dev->lock);
307
308 usb_dbg(interface, "release success");
309 return 0;
310}
311
312/* Fill the buffer. Called with dev->lock held
313 */
314static int _chaoskey_fill(struct chaoskey *dev)
315{
316 DEFINE_WAIT(wait);
317 int result;
318 int this_read;
319 struct usb_device *udev = interface_to_usbdev(dev->interface);
320
321 usb_dbg(dev->interface, "fill");
322
323 /* Return immediately if someone called before the buffer was
324 * empty */
325 if (dev->valid != dev->used) {
326 usb_dbg(dev->interface, "not empty yet (valid %d used %d)",
327 dev->valid, dev->used);
328 return 0;
329 }
330
331 /* Bail if the device has been removed */
332 if (!dev->present) {
333 usb_dbg(dev->interface, "device not present");
334 return -ENODEV;
335 }
336
337 /* Make sure the device is awake */
338 result = usb_autopm_get_interface(dev->interface);
339 if (result) {
340 usb_dbg(dev->interface, "wakeup failed (result %d)", result);
341 return result;
342 }
343
344 result = usb_bulk_msg(udev,
345 usb_rcvbulkpipe(udev, dev->in_ep),
346 dev->buf, dev->size, &this_read,
347 NAK_TIMEOUT);
348
349 /* Let the device go back to sleep eventually */
350 usb_autopm_put_interface(dev->interface);
351
352 if (result == 0) {
353 dev->valid = this_read;
354 dev->used = 0;
355 }
356
357 usb_dbg(dev->interface, "bulk_msg result %d this_read %d",
358 result, this_read);
359
360 return result;
361}
362
363static ssize_t chaoskey_read(struct file *file,
364 char __user *buffer,
365 size_t count,
366 loff_t *ppos)
367{
368 struct chaoskey *dev;
369 ssize_t read_count = 0;
370 int this_time;
371 int result = 0;
372 unsigned long remain;
373
374 dev = file->private_data;
375
376 if (dev == NULL || !dev->present)
377 return -ENODEV;
378
379 usb_dbg(dev->interface, "read %zu", count);
380
381 while (count > 0) {
382
383 /* Grab the rng_lock briefly to ensure that the hwrng interface
384 * gets priority over other user access
385 */
386 result = mutex_lock_interruptible(&dev->rng_lock);
387 if (result)
388 goto bail;
389 mutex_unlock(&dev->rng_lock);
390
391 result = mutex_lock_interruptible(&dev->lock);
392 if (result)
393 goto bail;
394 if (dev->valid == dev->used) {
395 result = _chaoskey_fill(dev);
396 if (result) {
397 mutex_unlock(&dev->lock);
398 goto bail;
399 }
400
401 /* Read returned zero bytes */
402 if (dev->used == dev->valid) {
403 mutex_unlock(&dev->lock);
404 goto bail;
405 }
406 }
407
408 this_time = dev->valid - dev->used;
409 if (this_time > count)
410 this_time = count;
411
412 remain = copy_to_user(buffer, dev->buf + dev->used, this_time);
413 if (remain) {
414 result = -EFAULT;
415
416 /* Consume the bytes that were copied so we don't leak
417 * data to user space
418 */
419 dev->used += this_time - remain;
420 mutex_unlock(&dev->lock);
421 goto bail;
422 }
423
424 count -= this_time;
425 read_count += this_time;
426 buffer += this_time;
427 dev->used += this_time;
428 mutex_unlock(&dev->lock);
429 }
430bail:
431 if (read_count) {
432 usb_dbg(dev->interface, "read %zu bytes", read_count);
433 return read_count;
434 }
435 usb_dbg(dev->interface, "empty read, result %d", result);
436 return result;
437}
438
439static int chaoskey_rng_read(struct hwrng *rng, void *data,
440 size_t max, bool wait)
441{
442 struct chaoskey *dev = container_of(rng, struct chaoskey, hwrng);
443 int this_time;
444
445 usb_dbg(dev->interface, "rng_read max %zu wait %d", max, wait);
446
447 if (!dev->present) {
448 usb_dbg(dev->interface, "device not present");
449 return 0;
450 }
451
452 /* Hold the rng_lock until we acquire the device lock so that
453 * this operation gets priority over other user access to the
454 * device
455 */
456 mutex_lock(&dev->rng_lock);
457
458 mutex_lock(&dev->lock);
459
460 mutex_unlock(&dev->rng_lock);
461
462 /* Try to fill the buffer if empty. It doesn't actually matter
463 * if _chaoskey_fill works; we'll just return zero bytes as
464 * the buffer will still be empty
465 */
466 if (dev->valid == dev->used)
467 (void) _chaoskey_fill(dev);
468
469 this_time = dev->valid - dev->used;
470 if (this_time > max)
471 this_time = max;
472
473 memcpy(data, dev->buf, this_time);
474
475 dev->used += this_time;
476
477 mutex_unlock(&dev->lock);
478
479 usb_dbg(dev->interface, "rng_read this_time %d\n", this_time);
480 return this_time;
481}
482
483#ifdef CONFIG_PM
484static int chaoskey_suspend(struct usb_interface *interface,
485 pm_message_t message)
486{
487 usb_dbg(interface, "suspend");
488 return 0;
489}
490
491static int chaoskey_resume(struct usb_interface *interface)
492{
493 usb_dbg(interface, "resume");
494 return 0;
495}
496#else
497#define chaoskey_suspend NULL
498#define chaoskey_resume NULL
499#endif
500
501/* file operation pointers */
502static const struct file_operations chaoskey_fops = {
503 .owner = THIS_MODULE,
504 .read = chaoskey_read,
505 .open = chaoskey_open,
506 .release = chaoskey_release,
507 .llseek = default_llseek,
508};
509
510/* class driver information */
511static struct usb_class_driver chaoskey_class = {
512 .name = "chaoskey%d",
513 .fops = &chaoskey_fops,
514 .minor_base = USB_CHAOSKEY_MINOR_BASE,
515};
516
517/* usb specific object needed to register this driver with the usb subsystem */
518static struct usb_driver chaoskey_driver = {
519 .name = DRIVER_SHORT,
520 .probe = chaoskey_probe,
521 .disconnect = chaoskey_disconnect,
522 .suspend = chaoskey_suspend,
523 .resume = chaoskey_resume,
524 .reset_resume = chaoskey_resume,
525 .id_table = chaoskey_table,
526 .supports_autosuspend = 1,
527};
528
529module_usb_driver(chaoskey_driver);
530