Bug#839616: linux: add support for chaoskey
Source: linux
Version: 3.16.36-1+deb8u1
Severity: important
Tags: patch
Control: fixed -1 4.1.1-1~exp1
User: debian-admin@lists.debian.org
Usertags: needed-by-DSA-Team
Hi,
the attached patch adds the chaoskey driver
(http://altusmetrum.org/ChaosKey/). I've smoke tested it in qemu (with
usb passthrough). This should include all patches touching
drivers/usb/misc/chaoskey.c since its introduction, with the only diff
from the upstream patches being context in Kconfig; there's an extra
patch to deal with the absence of
0f734e6e768b4b66737b3d3e13f1769a12ecff86 in 3.16.
Applies on top of 3.16.36-1+deb8u1, because the tip of the jessie branch
doesn't seem to build.
Cheers,
Julien
>From e9060d88141e2978d4acf31716a0502534fdf7b5 Mon Sep 17 00:00:00 2001
From: Julien Cristau <jcristau@debian.org>
Date: Sun, 2 Oct 2016 18:32:04 +0200
Subject: [PATCH] Add chaoskey driver, backported from 4.8.
---
debian/changelog | 7 +
debian/config/config | 1 +
.../chaoskey/USB-chaoskey-read-offset-bug.patch | 31 +
.../chaoskey/chaoskey-3.16-no-hwrng-quality.patch | 28 +
...key-Add-support-for-Araneus-Alea-I-USB-RN.patch | 64 +++
...key-Fix-URB-warning-due-to-timeout-on-Ale.patch | 105 ++++
...river-for-Altus-Metrum-ChaosKey-device-v2.patch | 627 +++++++++++++++++++++
.../usb-Fix-warnings-in-chaoskey-driver.patch | 57 ++
...misc-chaoskey-Cleanup-probe-failure-paths.patch | 103 ++++
...aoskey-introduce-an-URB-for-asynchronous-.patch | 187 ++++++
...b-misc-fix-chaoskey-build-needs-HW_RANDOM.patch | 33 ++
debian/patches/series | 11 +
12 files changed, 1254 insertions(+)
create mode 100644 debian/patches/features/all/chaoskey/USB-chaoskey-read-offset-bug.patch
create mode 100644 debian/patches/features/all/chaoskey/chaoskey-3.16-no-hwrng-quality.patch
create mode 100644 debian/patches/features/all/chaoskey/hwrng-chaoskey-Add-support-for-Araneus-Alea-I-USB-RN.patch
create mode 100644 debian/patches/features/all/chaoskey/hwrng-chaoskey-Fix-URB-warning-due-to-timeout-on-Ale.patch
create mode 100644 debian/patches/features/all/chaoskey/usb-Add-driver-for-Altus-Metrum-ChaosKey-device-v2.patch
create mode 100644 debian/patches/features/all/chaoskey/usb-Fix-warnings-in-chaoskey-driver.patch
create mode 100644 debian/patches/features/all/chaoskey/usb-misc-chaoskey-Cleanup-probe-failure-paths.patch
create mode 100644 debian/patches/features/all/chaoskey/usb-misc-chaoskey-introduce-an-URB-for-asynchronous-.patch
create mode 100644 debian/patches/features/all/chaoskey/usb-misc-fix-chaoskey-build-needs-HW_RANDOM.patch
diff --git a/debian/changelog b/debian/changelog
index dcf2adc..5cdf3b2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+linux (3.16.36-2) UNRELEASED; urgency=medium
+
+ [ Julien Cristau ]
+ * Add chaoskey driver, backported from 4.8.
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 09 Aug 2016 22:05:53 +0200
+
linux (3.16.36-1+deb8u1) jessie-security; urgency=high
[ Ben Hutchings ]
diff --git a/debian/config/config b/debian/config/config
index 0b70520..cc363ae 100644
--- a/debian/config/config
+++ b/debian/config/config
@@ -4107,6 +4107,7 @@ CONFIG_USB_EHSET_TEST_FIXTURE=m
CONFIG_USB_ISIGHTFW=m
CONFIG_USB_YUREX=m
# CONFIG_USB_HSIC_USB3503 is not set
+CONFIG_USB_CHAOSKEY=m
##
## file: drivers/usb/misc/sisusbvga/Kconfig
diff --git a/debian/patches/features/all/chaoskey/USB-chaoskey-read-offset-bug.patch b/debian/patches/features/all/chaoskey/USB-chaoskey-read-offset-bug.patch
new file mode 100644
index 0000000..9ff8e32
--- /dev/null
+++ b/debian/patches/features/all/chaoskey/USB-chaoskey-read-offset-bug.patch
@@ -0,0 +1,31 @@
+From 1d5c47f555c5ae050fad22e4a99f88856cae5d05 Mon Sep 17 00:00:00 2001
+From: Alexander Inyukhin <shurick@sectorb.msk.ru>
+Date: Sat, 26 Sep 2015 15:24:21 +0300
+Subject: [PATCH] USB: chaoskey read offset bug
+
+Rng reads in chaoskey driver could return the same data under
+the certain conditions.
+
+Signed-off-by: Alexander Inyukhin <shurick@sectorb.msk.ru>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/chaoskey.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
+index 3ad5d19..23c7948 100644
+--- a/drivers/usb/misc/chaoskey.c
++++ b/drivers/usb/misc/chaoskey.c
+@@ -472,7 +472,7 @@ static int chaoskey_rng_read(struct hwrng *rng, void *data,
+ if (this_time > max)
+ this_time = max;
+
+- memcpy(data, dev->buf, this_time);
++ memcpy(data, dev->buf + dev->used, this_time);
+
+ dev->used += this_time;
+
+--
+2.9.3
+
diff --git a/debian/patches/features/all/chaoskey/chaoskey-3.16-no-hwrng-quality.patch b/debian/patches/features/all/chaoskey/chaoskey-3.16-no-hwrng-quality.patch
new file mode 100644
index 0000000..b20fdb0
--- /dev/null
+++ b/debian/patches/features/all/chaoskey/chaoskey-3.16-no-hwrng-quality.patch
@@ -0,0 +1,28 @@
+From: Julien Cristau <jcristau@debian.org>
+Date: Sun, 02 Oct 2016 17:52:02 +0000
+Subject: [PATCH] hwrng: chaoskey - don't set quality field
+
+struct hwrng doesn't have that field in 3.16.
+
+--- a/drivers/usb/misc/chaoskey.c 2016-10-02 17:01:56.419883204 +0000
++++ b/drivers/usb/misc/chaoskey.c 2016-10-02 17:50:44.605990596 +0000
+@@ -216,19 +216,6 @@
+ dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name;
+ dev->hwrng.read = chaoskey_rng_read;
+
+- /* Set the 'quality' metric. Quality is measured in units of
+- * 1/1024's of a bit ("mills"). This should be set to 1024,
+- * but there is a bug in the hwrng core which masks it with
+- * 1023.
+- *
+- * The patch that has been merged to the crypto development
+- * tree for that bug limits the value to 1024 at most, so by
+- * setting this to 1024 + 1023, we get 1023 before the fix is
+- * merged and 1024 afterwards. We'll patch this driver once
+- * both bits of code are in the same tree.
+- */
+- dev->hwrng.quality = 1024 + 1023;
+-
+ dev->hwrng_registered = (hwrng_register(&dev->hwrng) == 0);
+ if (!dev->hwrng_registered)
+ usb_err(interface, "Unable to register with hwrng");
diff --git a/debian/patches/features/all/chaoskey/hwrng-chaoskey-Add-support-for-Araneus-Alea-I-USB-RN.patch b/debian/patches/features/all/chaoskey/hwrng-chaoskey-Add-support-for-Araneus-Alea-I-USB-RN.patch
new file mode 100644
index 0000000..2d8afb8
--- /dev/null
+++ b/debian/patches/features/all/chaoskey/hwrng-chaoskey-Add-support-for-Araneus-Alea-I-USB-RN.patch
@@ -0,0 +1,64 @@
+From d3ede2dba3d800912523838a6db35d562e042101 Mon Sep 17 00:00:00 2001
+From: Bob Ham <bob.ham@collabora.com>
+Date: Fri, 3 Jun 2016 12:13:07 +0100
+Subject: [PATCH] hwrng: chaoskey - Add support for Araneus Alea I USB RNG
+
+Adds support for the Araneus Alea I USB hardware Random Number
+Generator which is interfaced with in exactly the same way as the
+Altus Metrum ChaosKey. We just add the appropriate device ID and
+modify the config help text.
+
+Signed-off-by: Bob Ham <bob.ham@collabora.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/usb/misc/Kconfig | 11 ++++++-----
+ drivers/usb/misc/chaoskey.c | 4 ++++
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
+index e9e5ae5..6e70597 100644
+--- a/drivers/usb/misc/Kconfig
++++ b/drivers/usb/misc/Kconfig
+@@ -260,11 +260,12 @@ config USB_CHAOSKEY
+ tristate "ChaosKey random number generator driver support"
+ depends on HW_RANDOM
+ help
+- Say Y here if you want to connect an AltusMetrum ChaosKey to
+- your computer's USB port. The ChaosKey is a hardware random
+- number generator which hooks into the kernel entropy pool to
+- ensure a large supply of entropy for /dev/random and
+- /dev/urandom and also provides direct access via /dev/chaoskeyX
++ Say Y here if you want to connect an AltusMetrum ChaosKey or
++ Araneus Alea I to your computer's USB port. These devices
++ are hardware random number generators which hook into the
++ kernel entropy pool to ensure a large supply of entropy for
++ /dev/random and /dev/urandom and also provides direct access
++ via /dev/chaoskeyX
+
+ To compile this driver as a module, choose M here: the
+ module will be called chaoskey.
+diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
+index 76350e4..9aef46b 100644
+--- a/drivers/usb/misc/chaoskey.c
++++ b/drivers/usb/misc/chaoskey.c
+@@ -55,6 +55,9 @@ MODULE_LICENSE("GPL");
+ #define CHAOSKEY_VENDOR_ID 0x1d50 /* OpenMoko */
+ #define CHAOSKEY_PRODUCT_ID 0x60c6 /* ChaosKey */
+
++#define ALEA_VENDOR_ID 0x12d8 /* Araneus */
++#define ALEA_PRODUCT_ID 0x0001 /* Alea I */
++
+ #define CHAOSKEY_BUF_LEN 64 /* max size of USB full speed packet */
+
+ #define NAK_TIMEOUT (HZ) /* stall/wait timeout for device */
+@@ -69,6 +72,7 @@ MODULE_LICENSE("GPL");
+
+ static const struct usb_device_id chaoskey_table[] = {
+ { USB_DEVICE(CHAOSKEY_VENDOR_ID, CHAOSKEY_PRODUCT_ID) },
++ { USB_DEVICE(ALEA_VENDOR_ID, ALEA_PRODUCT_ID) },
+ { },
+ };
+ MODULE_DEVICE_TABLE(usb, chaoskey_table);
+--
+2.9.3
+
diff --git a/debian/patches/features/all/chaoskey/hwrng-chaoskey-Fix-URB-warning-due-to-timeout-on-Ale.patch b/debian/patches/features/all/chaoskey/hwrng-chaoskey-Fix-URB-warning-due-to-timeout-on-Ale.patch
new file mode 100644
index 0000000..bfe99aa
--- /dev/null
+++ b/debian/patches/features/all/chaoskey/hwrng-chaoskey-Fix-URB-warning-due-to-timeout-on-Ale.patch
@@ -0,0 +1,105 @@
+From e4a886e811cd07dd5c6f389eae4d35870ec2a483 Mon Sep 17 00:00:00 2001
+From: Bob Ham <bob.ham@collabora.com>
+Date: Fri, 3 Jun 2016 12:13:08 +0100
+Subject: [PATCH] hwrng: chaoskey - Fix URB warning due to timeout on Alea
+
+The first read on an Alea takes about 1.8 seconds, more than the
+timeout value waiting for the read. As a consequence, later URB reuse
+causes the warning given below. To avoid this, we increase the wait
+time for the first read on the Alea.
+
+[ 78.293247] WARNING: CPU: 3 PID: 1892 at drivers/usb/core/urb.c:338 usb_submit_urb+0x2b4/0x580 [usbcore]
+[ 78.293250] URB ffff8802135be3c0 submitted while active
+[ 78.293252] Modules linked in: chaoskey(+) rng_core rfcomm binfmt_misc bnep cfg80211 nfsd auth_rpcgss oid_registry nfs_acl nfs lockd grace fscache sunrpc bridge stp llc tun snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic iTCO_wdt iTCO_vendor_support nls_utf8 nls_cp437 vfat fat intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel efi_pstore kvm irqbypass pcspkr btusb btrtl btbcm btintel uvcvideo joydev bluetooth videobuf2_vmalloc videobuf2_memops efivars videobuf2_v4l2 serio_raw i2c_i801 videobuf2_core videodev cdc_mbim media lpc_ich shpchp mfd_core cdc_ncm usbnet mii cdc_wdm cdc_acm evdev snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core i915 snd_pcm snd_timer i2c_algo_bit drm_kms_helper wmi thinkpad_acpi drm nvram mei_me mei snd soundcore rfkill ac battery i2c_core
+[ 78.293335] video button tpm_tis tpm fuse parport_pc ppdev lp parport autofs4 ext4 crc16 jbd2 mbcache algif_skcipher af_alg hid_generic usbhid hid dm_crypt dm_mod sg sr_mod cdrom sd_mod crct10dif_pclmul crc32_pclmul crc32c_intel jitterentropy_rng sha256_generic hmac drbg aesni_intel xhci_pci aes_x86_64 ahci glue_helper xhci_hcd ehci_pci lrw libahci gf128mul ablk_helper cryptd libata sdhci_pci psmouse sdhci scsi_mod ehci_hcd mmc_core usbcore usb_common thermal
+[ 78.293402] CPU: 3 PID: 1892 Comm: hwrng Not tainted 4.7.0-rc1-linux-14+ #16
+[ 78.293405] Hardware name: LENOVO 232577G/232577G, BIOS G2ET92WW (2.52 ) 02/22/2013
+[ 78.293408] 0000000000000000 ffffffff812dfa0f ffff8801fa5b3d68 0000000000000000
+[ 78.293413] ffffffff81072224 ffff8802135be3c0 ffff8801fa5b3db8 ffff880212e44210
+[ 78.293418] 0000000000000040 ffff880209fb32c0 ffff880212e44200 ffffffff8107228f
+[ 78.293422] Call Trace:
+[ 78.293432] [<ffffffff812dfa0f>] ? dump_stack+0x5c/0x7d
+[ 78.293437] [<ffffffff81072224>] ? __warn+0xc4/0xe0
+[ 78.293441] [<ffffffff8107228f>] ? warn_slowpath_fmt+0x4f/0x60
+[ 78.293451] [<ffffffff810a46a2>] ? enqueue_task_fair+0xcd2/0x1260
+[ 78.293463] [<ffffffffa001ec54>] ? usb_submit_urb+0x2b4/0x580 [usbcore]
+[ 78.293474] [<ffffffff8140c2e5>] ? __pm_runtime_resume+0x55/0x70
+[ 78.293484] [<ffffffffa0825212>] ? _chaoskey_fill+0x132/0x250 [chaoskey]
+[ 78.293485] usbcore: registered new interface driver chaoskey
+[ 78.293493] [<ffffffff810aed50>] ? wait_woken+0x90/0x90
+[ 78.293500] [<ffffffffa06448c0>] ? devm_hwrng_register+0x80/0x80 [rng_core]
+[ 78.293505] [<ffffffffa0825907>] ? chaoskey_rng_read+0x127/0x140 [chaoskey]
+[ 78.293511] [<ffffffffa06448c0>] ? devm_hwrng_register+0x80/0x80 [rng_core]
+[ 78.293515] [<ffffffffa064492e>] ? hwrng_fillfn+0x6e/0x120 [rng_core]
+[ 78.293520] [<ffffffff8108fb5f>] ? kthread+0xcf/0xf0
+[ 78.293529] [<ffffffff81596d5f>] ? ret_from_fork+0x1f/0x40
+[ 78.293535] [<ffffffff8108fa90>] ? kthread_park+0x50/0x50
+
+Signed-off-by: Bob Ham <bob.ham@collabora.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/usb/misc/chaoskey.c | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
+index 9aef46b..6ddd08a 100644
+--- a/drivers/usb/misc/chaoskey.c
++++ b/drivers/usb/misc/chaoskey.c
+@@ -60,7 +60,8 @@ MODULE_LICENSE("GPL");
+
+ #define CHAOSKEY_BUF_LEN 64 /* max size of USB full speed packet */
+
+-#define NAK_TIMEOUT (HZ) /* stall/wait timeout for device */
++#define NAK_TIMEOUT (HZ) /* normal stall/wait timeout */
++#define ALEA_FIRST_TIMEOUT (HZ*3) /* first stall/wait timeout for Alea */
+
+ #ifdef CONFIG_USB_DYNAMIC_MINORS
+ #define USB_CHAOSKEY_MINOR_BASE 0
+@@ -88,6 +89,7 @@ struct chaoskey {
+ int open; /* open count */
+ bool present; /* device not disconnected */
+ bool reading; /* ongoing IO */
++ bool reads_started; /* track first read for Alea */
+ int size; /* size of buf */
+ int valid; /* bytes of buf read */
+ int used; /* bytes of buf consumed */
+@@ -192,6 +194,9 @@ static int chaoskey_probe(struct usb_interface *interface,
+
+ dev->in_ep = in_ep;
+
++ if (udev->descriptor.idVendor != ALEA_VENDOR_ID)
++ dev->reads_started = 1;
++
+ dev->size = size;
+ dev->present = 1;
+
+@@ -361,6 +366,7 @@ static int _chaoskey_fill(struct chaoskey *dev)
+ {
+ DEFINE_WAIT(wait);
+ int result;
++ bool started;
+
+ usb_dbg(dev->interface, "fill");
+
+@@ -393,10 +399,17 @@ static int _chaoskey_fill(struct chaoskey *dev)
+ goto out;
+ }
+
++ /* The first read on the Alea takes a little under 2 seconds.
++ * Reads after the first read take only a few microseconds
++ * though. Presumably the entropy-generating circuit needs
++ * time to ramp up. So, we wait longer on the first read.
++ */
++ started = dev->reads_started;
++ dev->reads_started = true;
+ result = wait_event_interruptible_timeout(
+ dev->wait_q,
+ !dev->reading,
+- NAK_TIMEOUT);
++ (started ? NAK_TIMEOUT : ALEA_FIRST_TIMEOUT) );
+
+ if (result < 0)
+ goto out;
+--
+2.9.3
+
diff --git a/debian/patches/features/all/chaoskey/usb-Add-driver-for-Altus-Metrum-ChaosKey-device-v2.patch b/debian/patches/features/all/chaoskey/usb-Add-driver-for-Altus-Metrum-ChaosKey-device-v2.patch
new file mode 100644
index 0000000..c618084
--- /dev/null
+++ b/debian/patches/features/all/chaoskey/usb-Add-driver-for-Altus-Metrum-ChaosKey-device-v2.patch
@@ -0,0 +1,627 @@
+From 66e3e591891da9899a8990792da080432531ffd4 Mon Sep 17 00:00:00 2001
+From: Keith Packard <keithp@keithp.com>
+Date: Thu, 19 Mar 2015 20:36:49 -0700
+Subject: [PATCH] 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>
+---
+ MAINTAINERS | 6 +
+ drivers/usb/misc/Kconfig | 12 +
+ drivers/usb/misc/Makefile | 1 +
+ drivers/usb/misc/chaoskey.c | 530 ++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 549 insertions(+)
+ create mode 100644 drivers/usb/misc/chaoskey.c
+
+Index: linux/MAINTAINERS
+===================================================================
+--- linux.orig/MAINTAINERS
++++ linux/MAINTAINERS
+@@ -9414,6 +9414,12 @@ S: Maintained
+ F: drivers/net/usb/cdc_*.c
+ F: include/uapi/linux/usb/cdc.h
+
++USB CHAOSKEY DRIVER
++M: Keith Packard <keithp@keithp.com>
++L: linux-usb@vger.kernel.org
++S: Maintained
++F: drivers/usb/misc/chaoskey.c
++
+ USB CYPRESS C67X00 DRIVER
+ M: Peter Korsgaard <jacmet@sunsite.dk>
+ L: linux-usb@vger.kernel.org
+Index: linux/drivers/usb/misc/Kconfig
+===================================================================
+--- linux.orig/drivers/usb/misc/Kconfig
++++ linux/drivers/usb/misc/Kconfig
+@@ -248,3 +248,15 @@ config USB_HSIC_USB3503
+ select REGMAP_I2C
+ help
+ This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.
++
++config USB_CHAOSKEY
++ tristate "ChaosKey random number generator driver support"
++ help
++ Say Y here if you want to connect an AltusMetrum ChaosKey to
++ your computer's USB port. The ChaosKey is a hardware random
++ number generator which hooks into the kernel entropy pool to
++ ensure a large supply of entropy for /dev/random and
++ /dev/urandom and also provides direct access via /dev/chaoskeyX
++
++ To compile this driver as a module, choose M here: the
++ module will be called chaoskey.
+Index: linux/drivers/usb/misc/Makefile
+===================================================================
+--- linux.orig/drivers/usb/misc/Makefile
++++ linux/drivers/usb/misc/Makefile
+@@ -25,5 +25,6 @@ obj-$(CONFIG_USB_USS720) += uss720.o
+ obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o
+ obj-$(CONFIG_USB_YUREX) += yurex.o
+ obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o
++obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o
+
+ obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/
+Index: linux/drivers/usb/misc/chaoskey.c
+===================================================================
+--- /dev/null
++++ linux/drivers/usb/misc/chaoskey.c
+@@ -0,0 +1,530 @@
++/*
++ * chaoskey - driver for ChaosKey device from Altus Metrum.
++ *
++ * This device provides true random numbers using a noise source based
++ * on a reverse-biased p-n junction in avalanche breakdown. More
++ * details can be found at http://chaoskey.org
++ *
++ * The driver connects to the kernel hardware RNG interface to provide
++ * entropy for /dev/random and other kernel activities. It also offers
++ * a separate /dev/ entry to allow for direct access to the random
++ * bit stream.
++ *
++ * Copyright © 2015 Keith Packard <keithp@keithp.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/usb.h>
++#include <linux/wait.h>
++#include <linux/hw_random.h>
++
++static struct usb_driver chaoskey_driver;
++static struct usb_class_driver chaoskey_class;
++static int chaoskey_rng_read(struct hwrng *rng, void *data,
++ size_t max, bool wait);
++
++#define usb_dbg(usb_if, format, arg...) \
++ dev_dbg(&(usb_if)->dev, format, ## arg)
++
++#define usb_err(usb_if, format, arg...) \
++ dev_err(&(usb_if)->dev, format, ## arg)
++
++/* Version Information */
++#define DRIVER_VERSION "v0.1"
++#define DRIVER_AUTHOR "Keith Packard, keithp@keithp.com"
++#define DRIVER_DESC "Altus Metrum ChaosKey driver"
++#define DRIVER_SHORT "chaoskey"
++
++MODULE_VERSION(DRIVER_VERSION);
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
++
++#define CHAOSKEY_VENDOR_ID 0x1d50 /* OpenMoko */
++#define CHAOSKEY_PRODUCT_ID 0x60c6 /* ChaosKey */
++
++#define CHAOSKEY_BUF_LEN 64 /* max size of USB full speed packet */
++
++#define NAK_TIMEOUT (HZ) /* stall/wait timeout for device */
++
++#ifdef CONFIG_USB_DYNAMIC_MINORS
++#define USB_CHAOSKEY_MINOR_BASE 0
++#else
++
++/* IOWARRIOR_MINOR_BASE + 16, not official yet */
++#define USB_CHAOSKEY_MINOR_BASE 224
++#endif
++
++static const struct usb_device_id chaoskey_table[] = {
++ { USB_DEVICE(CHAOSKEY_VENDOR_ID, CHAOSKEY_PRODUCT_ID) },
++ { },
++};
++MODULE_DEVICE_TABLE(usb, chaoskey_table);
++
++/* Driver-local specific stuff */
++struct chaoskey {
++ struct usb_interface *interface;
++ char in_ep;
++ struct mutex lock;
++ struct mutex rng_lock;
++ int open; /* open count */
++ int present; /* device not disconnected */
++ int size; /* size of buf */
++ int valid; /* bytes of buf read */
++ int used; /* bytes of buf consumed */
++ char *name; /* product + serial */
++ struct hwrng hwrng; /* Embedded struct for hwrng */
++ int hwrng_registered; /* registered with hwrng API */
++ wait_queue_head_t wait_q; /* for timeouts */
++ char *buf;
++};
++
++static void chaoskey_free(struct chaoskey *dev)
++{
++ usb_dbg(dev->interface, "free");
++ kfree(dev->name);
++ kfree(dev->buf);
++ kfree(dev);
++}
++
++static int chaoskey_probe(struct usb_interface *interface,
++ const struct usb_device_id *id)
++{
++ struct usb_device *udev = interface_to_usbdev(interface);
++ struct usb_host_interface *altsetting = interface->cur_altsetting;
++ int i;
++ int in_ep = -1;
++ struct chaoskey *dev;
++ int result;
++ int size;
++
++ usb_dbg(interface, "probe %s-%s", udev->product, udev->serial);
++
++ /* Find the first bulk IN endpoint and its packet size */
++ for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
++ if (usb_endpoint_is_bulk_in(&altsetting->endpoint[i].desc)) {
++ in_ep = altsetting->endpoint[i].desc.bEndpointAddress;
++ size = altsetting->endpoint[i].desc.wMaxPacketSize;
++ break;
++ }
++ }
++
++ /* Validate endpoint and size */
++ if (in_ep == -1) {
++ usb_dbg(interface, "no IN endpoint found");
++ return -ENODEV;
++ }
++ if (size <= 0) {
++ usb_dbg(interface, "invalid size (%d)", size);
++ return -ENODEV;
++ }
++
++ if (size > CHAOSKEY_BUF_LEN) {
++ usb_dbg(interface, "size reduced from %d to %d\n",
++ size, CHAOSKEY_BUF_LEN);
++ size = CHAOSKEY_BUF_LEN;
++ }
++
++ /* Looks good, allocate and initialize */
++
++ dev = kzalloc(sizeof(struct chaoskey), GFP_KERNEL);
++
++ if (dev == NULL)
++ return -ENOMEM;
++
++ dev->buf = kmalloc(size, GFP_KERNEL);
++
++ if (dev->buf == NULL) {
++ kfree(dev);
++ return -ENOMEM;
++ }
++
++ /* Construct a name using the product and serial values. Each
++ * device needs a unique name for the hwrng code
++ */
++
++ if (udev->product && udev->serial) {
++ dev->name = kmalloc(strlen(udev->product) + 1 +
++ strlen(udev->serial) + 1, GFP_KERNEL);
++ if (dev->name == NULL) {
++ kfree(dev->buf);
++ kfree(dev);
++ return -ENOMEM;
++ }
++
++ strcpy(dev->name, udev->product);
++ strcat(dev->name, "-");
++ strcat(dev->name, udev->serial);
++ }
++
++ dev->interface = interface;
++
++ dev->in_ep = in_ep;
++
++ dev->size = size;
++ dev->present = 1;
++
++ init_waitqueue_head(&dev->wait_q);
++
++ mutex_init(&dev->lock);
++ mutex_init(&dev->rng_lock);
++
++ usb_set_intfdata(interface, dev);
++
++ result = usb_register_dev(interface, &chaoskey_class);
++ if (result) {
++ usb_err(interface, "Unable to allocate minor number.");
++ usb_set_intfdata(interface, NULL);
++ chaoskey_free(dev);
++ return result;
++ }
++
++ dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name;
++ dev->hwrng.read = chaoskey_rng_read;
++
++ /* Set the 'quality' metric. Quality is measured in units of
++ * 1/1024's of a bit ("mills"). This should be set to 1024,
++ * but there is a bug in the hwrng core which masks it with
++ * 1023.
++ *
++ * The patch that has been merged to the crypto development
++ * tree for that bug limits the value to 1024 at most, so by
++ * setting this to 1024 + 1023, we get 1023 before the fix is
++ * merged and 1024 afterwards. We'll patch this driver once
++ * both bits of code are in the same tree.
++ */
++ dev->hwrng.quality = 1024 + 1023;
++
++ dev->hwrng_registered = (hwrng_register(&dev->hwrng) == 0);
++ if (!dev->hwrng_registered)
++ usb_err(interface, "Unable to register with hwrng");
++
++ usb_enable_autosuspend(udev);
++
++ usb_dbg(interface, "chaoskey probe success, size %d", dev->size);
++ return 0;
++}
++
++static void chaoskey_disconnect(struct usb_interface *interface)
++{
++ struct chaoskey *dev;
++
++ usb_dbg(interface, "disconnect");
++ dev = usb_get_intfdata(interface);
++ if (!dev) {
++ usb_dbg(interface, "disconnect failed - no dev");
++ return;
++ }
++
++ if (dev->hwrng_registered)
++ hwrng_unregister(&dev->hwrng);
++
++ usb_deregister_dev(interface, &chaoskey_class);
++
++ usb_set_intfdata(interface, NULL);
++ mutex_lock(&dev->lock);
++
++ dev->present = 0;
++
++ if (!dev->open) {
++ mutex_unlock(&dev->lock);
++ chaoskey_free(dev);
++ } else
++ mutex_unlock(&dev->lock);
++
++ usb_dbg(interface, "disconnect done");
++}
++
++static int chaoskey_open(struct inode *inode, struct file *file)
++{
++ struct chaoskey *dev;
++ struct usb_interface *interface;
++
++ /* get the interface from minor number and driver information */
++ interface = usb_find_interface(&chaoskey_driver, iminor(inode));
++ if (!interface)
++ return -ENODEV;
++
++ usb_dbg(interface, "open");
++
++ dev = usb_get_intfdata(interface);
++ if (!dev) {
++ usb_dbg(interface, "open (dev)");
++ return -ENODEV;
++ }
++
++ file->private_data = dev;
++ mutex_lock(&dev->lock);
++ ++dev->open;
++ mutex_unlock(&dev->lock);
++
++ usb_dbg(interface, "open success");
++ return 0;
++}
++
++static int chaoskey_release(struct inode *inode, struct file *file)
++{
++ struct chaoskey *dev = file->private_data;
++ struct usb_interface *interface;
++
++ if (dev == NULL)
++ return -ENODEV;
++
++ interface = dev->interface;
++
++ usb_dbg(interface, "release");
++
++ mutex_lock(&dev->lock);
++
++ usb_dbg(interface, "open count at release is %d", dev->open);
++
++ if (dev->open <= 0) {
++ usb_dbg(interface, "invalid open count (%d)", dev->open);
++ mutex_unlock(&dev->lock);
++ return -ENODEV;
++ }
++
++ --dev->open;
++
++ if (!dev->present) {
++ if (dev->open == 0) {
++ mutex_unlock(&dev->lock);
++ chaoskey_free(dev);
++ } else
++ mutex_unlock(&dev->lock);
++ } else
++ mutex_unlock(&dev->lock);
++
++ usb_dbg(interface, "release success");
++ return 0;
++}
++
++/* Fill the buffer. Called with dev->lock held
++ */
++static int _chaoskey_fill(struct chaoskey *dev)
++{
++ DEFINE_WAIT(wait);
++ int result;
++ int this_read;
++ struct usb_device *udev = interface_to_usbdev(dev->interface);
++
++ usb_dbg(dev->interface, "fill");
++
++ /* Return immediately if someone called before the buffer was
++ * empty */
++ if (dev->valid != dev->used) {
++ usb_dbg(dev->interface, "not empty yet (valid %d used %d)",
++ dev->valid, dev->used);
++ return 0;
++ }
++
++ /* Bail if the device has been removed */
++ if (!dev->present) {
++ usb_dbg(dev->interface, "device not present");
++ return -ENODEV;
++ }
++
++ /* Make sure the device is awake */
++ result = usb_autopm_get_interface(dev->interface);
++ if (result) {
++ usb_dbg(dev->interface, "wakeup failed (result %d)", result);
++ return result;
++ }
++
++ result = usb_bulk_msg(udev,
++ usb_rcvbulkpipe(udev, dev->in_ep),
++ dev->buf, dev->size, &this_read,
++ NAK_TIMEOUT);
++
++ /* Let the device go back to sleep eventually */
++ usb_autopm_put_interface(dev->interface);
++
++ if (result == 0) {
++ dev->valid = this_read;
++ dev->used = 0;
++ }
++
++ usb_dbg(dev->interface, "bulk_msg result %d this_read %d",
++ result, this_read);
++
++ return result;
++}
++
++static ssize_t chaoskey_read(struct file *file,
++ char __user *buffer,
++ size_t count,
++ loff_t *ppos)
++{
++ struct chaoskey *dev;
++ ssize_t read_count = 0;
++ int this_time;
++ int result = 0;
++ unsigned long remain;
++
++ dev = file->private_data;
++
++ if (dev == NULL || !dev->present)
++ return -ENODEV;
++
++ usb_dbg(dev->interface, "read %zu", count);
++
++ while (count > 0) {
++
++ /* Grab the rng_lock briefly to ensure that the hwrng interface
++ * gets priority over other user access
++ */
++ result = mutex_lock_interruptible(&dev->rng_lock);
++ if (result)
++ goto bail;
++ mutex_unlock(&dev->rng_lock);
++
++ result = mutex_lock_interruptible(&dev->lock);
++ if (result)
++ goto bail;
++ if (dev->valid == dev->used) {
++ result = _chaoskey_fill(dev);
++ if (result) {
++ mutex_unlock(&dev->lock);
++ goto bail;
++ }
++
++ /* Read returned zero bytes */
++ if (dev->used == dev->valid) {
++ mutex_unlock(&dev->lock);
++ goto bail;
++ }
++ }
++
++ this_time = dev->valid - dev->used;
++ if (this_time > count)
++ this_time = count;
++
++ remain = copy_to_user(buffer, dev->buf + dev->used, this_time);
++ if (remain) {
++ result = -EFAULT;
++
++ /* Consume the bytes that were copied so we don't leak
++ * data to user space
++ */
++ dev->used += this_time - remain;
++ mutex_unlock(&dev->lock);
++ goto bail;
++ }
++
++ count -= this_time;
++ read_count += this_time;
++ buffer += this_time;
++ dev->used += this_time;
++ mutex_unlock(&dev->lock);
++ }
++bail:
++ if (read_count) {
++ usb_dbg(dev->interface, "read %zu bytes", read_count);
++ return read_count;
++ }
++ usb_dbg(dev->interface, "empty read, result %d", result);
++ return result;
++}
++
++static int chaoskey_rng_read(struct hwrng *rng, void *data,
++ size_t max, bool wait)
++{
++ struct chaoskey *dev = container_of(rng, struct chaoskey, hwrng);
++ int this_time;
++
++ usb_dbg(dev->interface, "rng_read max %zu wait %d", max, wait);
++
++ if (!dev->present) {
++ usb_dbg(dev->interface, "device not present");
++ return 0;
++ }
++
++ /* Hold the rng_lock until we acquire the device lock so that
++ * this operation gets priority over other user access to the
++ * device
++ */
++ mutex_lock(&dev->rng_lock);
++
++ mutex_lock(&dev->lock);
++
++ mutex_unlock(&dev->rng_lock);
++
++ /* Try to fill the buffer if empty. It doesn't actually matter
++ * if _chaoskey_fill works; we'll just return zero bytes as
++ * the buffer will still be empty
++ */
++ if (dev->valid == dev->used)
++ (void) _chaoskey_fill(dev);
++
++ this_time = dev->valid - dev->used;
++ if (this_time > max)
++ this_time = max;
++
++ memcpy(data, dev->buf, this_time);
++
++ dev->used += this_time;
++
++ mutex_unlock(&dev->lock);
++
++ usb_dbg(dev->interface, "rng_read this_time %d\n", this_time);
++ return this_time;
++}
++
++#ifdef CONFIG_PM
++static int chaoskey_suspend(struct usb_interface *interface,
++ pm_message_t message)
++{
++ usb_dbg(interface, "suspend");
++ return 0;
++}
++
++static int chaoskey_resume(struct usb_interface *interface)
++{
++ usb_dbg(interface, "resume");
++ return 0;
++}
++#else
++#define chaoskey_suspend NULL
++#define chaoskey_resume NULL
++#endif
++
++/* file operation pointers */
++static const struct file_operations chaoskey_fops = {
++ .owner = THIS_MODULE,
++ .read = chaoskey_read,
++ .open = chaoskey_open,
++ .release = chaoskey_release,
++ .llseek = default_llseek,
++};
++
++/* class driver information */
++static struct usb_class_driver chaoskey_class = {
++ .name = "chaoskey%d",
++ .fops = &chaoskey_fops,
++ .minor_base = USB_CHAOSKEY_MINOR_BASE,
++};
++
++/* usb specific object needed to register this driver with the usb subsystem */
++static struct usb_driver chaoskey_driver = {
++ .name = DRIVER_SHORT,
++ .probe = chaoskey_probe,
++ .disconnect = chaoskey_disconnect,
++ .suspend = chaoskey_suspend,
++ .resume = chaoskey_resume,
++ .reset_resume = chaoskey_resume,
++ .id_table = chaoskey_table,
++ .supports_autosuspend = 1,
++};
++
++module_usb_driver(chaoskey_driver);
++
diff --git a/debian/patches/features/all/chaoskey/usb-Fix-warnings-in-chaoskey-driver.patch b/debian/patches/features/all/chaoskey/usb-Fix-warnings-in-chaoskey-driver.patch
new file mode 100644
index 0000000..9655b68
--- /dev/null
+++ b/debian/patches/features/all/chaoskey/usb-Fix-warnings-in-chaoskey-driver.patch
@@ -0,0 +1,57 @@
+From 8b86ed078a65433a60ff59091a136d23724bd6d3 Mon Sep 17 00:00:00 2001
+From: Keith Packard <keithp@keithp.com>
+Date: Thu, 26 Mar 2015 16:49:38 -0700
+Subject: [PATCH] usb: Fix warnings in chaoskey driver
+
+> drivers/usb/misc/chaoskey.c: In function 'chaoskey_read':
+> >> drivers/usb/misc/chaoskey.c:412:3: error: implicit declaration of function 'copy_to_user'
+> >> [-Werror=implicit-function-declaration]
+> remain = copy_to_user(buffer, dev->buf + dev->used, this_time);
+
+I was unable to reproduce this locally, but added an explicit
+
+ #include <linux/uaccess.h>
+
+which should ensure the definition on all architectures.
+
+> sparse warnings: (new ones prefixed by >>)
+>
+> >> drivers/usb/misc/chaoskey.c:117:30: sparse: incorrect type in assignment (different base types)
+> drivers/usb/misc/chaoskey.c:117:30: expected int [signed] size
+> drivers/usb/misc/chaoskey.c:117:30: got restricted __le16 [usertype] wMaxPacketSize
+
+Switched the code to using the USB descriptor accessor functions.
+
+Signed-off-by: Keith Packard <keithp@keithp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/chaoskey.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
+index ef80ce9..3ad5d19 100644
+--- a/drivers/usb/misc/chaoskey.c
++++ b/drivers/usb/misc/chaoskey.c
+@@ -27,6 +27,8 @@
+ #include <linux/usb.h>
+ #include <linux/wait.h>
+ #include <linux/hw_random.h>
++#include <linux/mutex.h>
++#include <linux/uaccess.h>
+
+ static struct usb_driver chaoskey_driver;
+ static struct usb_class_driver chaoskey_class;
+@@ -113,8 +115,8 @@ static int chaoskey_probe(struct usb_interface *interface,
+ /* Find the first bulk IN endpoint and its packet size */
+ for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+ if (usb_endpoint_is_bulk_in(&altsetting->endpoint[i].desc)) {
+- in_ep = altsetting->endpoint[i].desc.bEndpointAddress;
+- size = altsetting->endpoint[i].desc.wMaxPacketSize;
++ in_ep = usb_endpoint_num(&altsetting->endpoint[i].desc);
++ size = usb_endpoint_maxp(&altsetting->endpoint[i].desc);
+ break;
+ }
+ }
+--
+2.9.3
+
diff --git a/debian/patches/features/all/chaoskey/usb-misc-chaoskey-Cleanup-probe-failure-paths.patch b/debian/patches/features/all/chaoskey/usb-misc-chaoskey-Cleanup-probe-failure-paths.patch
new file mode 100644
index 0000000..eb426ae
--- /dev/null
+++ b/debian/patches/features/all/chaoskey/usb-misc-chaoskey-Cleanup-probe-failure-paths.patch
@@ -0,0 +1,103 @@
+From 0a15e24c2740b7db99fbe21642b33a3028700225 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Wed, 17 Feb 2016 09:58:11 -0800
+Subject: [PATCH] usb/misc/chaoskey: Cleanup probe failure paths
+
+Shares the cleanup code between all probe failure paths, instead of
+having per-failure cleanup at each point in the function.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Keith Packard <keithp@keithp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/chaoskey.c | 36 ++++++++++++++++++------------------
+ 1 file changed, 18 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
+index 23c7948..cb1c239 100644
+--- a/drivers/usb/misc/chaoskey.c
++++ b/drivers/usb/misc/chaoskey.c
+@@ -93,10 +93,12 @@ struct chaoskey {
+
+ static void chaoskey_free(struct chaoskey *dev)
+ {
+- usb_dbg(dev->interface, "free");
+- kfree(dev->name);
+- kfree(dev->buf);
+- kfree(dev);
++ if (dev) {
++ usb_dbg(dev->interface, "free");
++ kfree(dev->name);
++ kfree(dev->buf);
++ kfree(dev);
++ }
+ }
+
+ static int chaoskey_probe(struct usb_interface *interface,
+@@ -107,7 +109,7 @@ static int chaoskey_probe(struct usb_interface *interface,
+ int i;
+ int in_ep = -1;
+ struct chaoskey *dev;
+- int result;
++ int result = -ENOMEM;
+ int size;
+
+ usb_dbg(interface, "probe %s-%s", udev->product, udev->serial);
+@@ -142,14 +144,12 @@ static int chaoskey_probe(struct usb_interface *interface,
+ dev = kzalloc(sizeof(struct chaoskey), GFP_KERNEL);
+
+ if (dev == NULL)
+- return -ENOMEM;
++ goto out;
+
+ dev->buf = kmalloc(size, GFP_KERNEL);
+
+- if (dev->buf == NULL) {
+- kfree(dev);
+- return -ENOMEM;
+- }
++ if (dev->buf == NULL)
++ goto out;
+
+ /* Construct a name using the product and serial values. Each
+ * device needs a unique name for the hwrng code
+@@ -158,11 +158,8 @@ static int chaoskey_probe(struct usb_interface *interface,
+ if (udev->product && udev->serial) {
+ dev->name = kmalloc(strlen(udev->product) + 1 +
+ strlen(udev->serial) + 1, GFP_KERNEL);
+- if (dev->name == NULL) {
+- kfree(dev->buf);
+- kfree(dev);
+- return -ENOMEM;
+- }
++ if (dev->name == NULL)
++ goto out;
+
+ strcpy(dev->name, udev->product);
+ strcat(dev->name, "-");
+@@ -186,9 +183,7 @@ static int chaoskey_probe(struct usb_interface *interface,
+ result = usb_register_dev(interface, &chaoskey_class);
+ if (result) {
+ usb_err(interface, "Unable to allocate minor number.");
+- usb_set_intfdata(interface, NULL);
+- chaoskey_free(dev);
+- return result;
++ goto out;
+ }
+
+ dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name;
+@@ -215,6 +210,11 @@ static int chaoskey_probe(struct usb_interface *interface,
+
+ usb_dbg(interface, "chaoskey probe success, size %d", dev->size);
+ return 0;
++
++out:
++ usb_set_intfdata(interface, NULL);
++ chaoskey_free(dev);
++ return result;
+ }
+
+ static void chaoskey_disconnect(struct usb_interface *interface)
+--
+2.9.3
+
diff --git a/debian/patches/features/all/chaoskey/usb-misc-chaoskey-introduce-an-URB-for-asynchronous-.patch b/debian/patches/features/all/chaoskey/usb-misc-chaoskey-introduce-an-URB-for-asynchronous-.patch
new file mode 100644
index 0000000..3dd0883
--- /dev/null
+++ b/debian/patches/features/all/chaoskey/usb-misc-chaoskey-introduce-an-URB-for-asynchronous-.patch
@@ -0,0 +1,187 @@
+From 0ca10122ca08d21e375b8c85bd7b498b1aeaf55d Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Wed, 17 Feb 2016 10:01:33 -0800
+Subject: [PATCH] usb/misc/chaoskey: introduce an URB for asynchronous reads
+
+To allow for and clean handling of signals an URB is introduced.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Keith Packard <keithp@keithp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/chaoskey.c | 86 ++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 65 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
+index cb1c239..76350e4 100644
+--- a/drivers/usb/misc/chaoskey.c
++++ b/drivers/usb/misc/chaoskey.c
+@@ -73,6 +73,8 @@ static const struct usb_device_id chaoskey_table[] = {
+ };
+ MODULE_DEVICE_TABLE(usb, chaoskey_table);
+
++static void chaos_read_callback(struct urb *urb);
++
+ /* Driver-local specific stuff */
+ struct chaoskey {
+ struct usb_interface *interface;
+@@ -80,7 +82,8 @@ struct chaoskey {
+ struct mutex lock;
+ struct mutex rng_lock;
+ int open; /* open count */
+- int present; /* device not disconnected */
++ bool present; /* device not disconnected */
++ bool reading; /* ongoing IO */
+ int size; /* size of buf */
+ int valid; /* bytes of buf read */
+ int used; /* bytes of buf consumed */
+@@ -88,6 +91,7 @@ struct chaoskey {
+ struct hwrng hwrng; /* Embedded struct for hwrng */
+ int hwrng_registered; /* registered with hwrng API */
+ wait_queue_head_t wait_q; /* for timeouts */
++ struct urb *urb; /* for performing IO */
+ char *buf;
+ };
+
+@@ -95,6 +99,7 @@ static void chaoskey_free(struct chaoskey *dev)
+ {
+ if (dev) {
+ usb_dbg(dev->interface, "free");
++ usb_free_urb(dev->urb);
+ kfree(dev->name);
+ kfree(dev->buf);
+ kfree(dev);
+@@ -151,6 +156,19 @@ static int chaoskey_probe(struct usb_interface *interface,
+ if (dev->buf == NULL)
+ goto out;
+
++ dev->urb = usb_alloc_urb(0, GFP_KERNEL);
++
++ if (!dev->urb)
++ goto out;
++
++ usb_fill_bulk_urb(dev->urb,
++ udev,
++ usb_rcvbulkpipe(udev, in_ep),
++ dev->buf,
++ size,
++ chaos_read_callback,
++ dev);
++
+ /* Construct a name using the product and serial values. Each
+ * device needs a unique name for the hwrng code
+ */
+@@ -237,6 +255,7 @@ static void chaoskey_disconnect(struct usb_interface *interface)
+ mutex_lock(&dev->lock);
+
+ dev->present = 0;
++ usb_poison_urb(dev->urb);
+
+ if (!dev->open) {
+ mutex_unlock(&dev->lock);
+@@ -311,14 +330,33 @@ static int chaoskey_release(struct inode *inode, struct file *file)
+ return 0;
+ }
+
++static void chaos_read_callback(struct urb *urb)
++{
++ struct chaoskey *dev = urb->context;
++ int status = urb->status;
++
++ usb_dbg(dev->interface, "callback status (%d)", status);
++
++ if (status == 0)
++ dev->valid = urb->actual_length;
++ else
++ dev->valid = 0;
++
++ dev->used = 0;
++
++ /* must be seen first before validity is announced */
++ smp_wmb();
++
++ dev->reading = false;
++ wake_up(&dev->wait_q);
++}
++
+ /* Fill the buffer. Called with dev->lock held
+ */
+ static int _chaoskey_fill(struct chaoskey *dev)
+ {
+ DEFINE_WAIT(wait);
+ int result;
+- int this_read;
+- struct usb_device *udev = interface_to_usbdev(dev->interface);
+
+ usb_dbg(dev->interface, "fill");
+
+@@ -343,21 +381,31 @@ static int _chaoskey_fill(struct chaoskey *dev)
+ return result;
+ }
+
+- result = usb_bulk_msg(udev,
+- usb_rcvbulkpipe(udev, dev->in_ep),
+- dev->buf, dev->size, &this_read,
+- NAK_TIMEOUT);
++ dev->reading = true;
++ result = usb_submit_urb(dev->urb, GFP_KERNEL);
++ if (result < 0) {
++ result = usb_translate_errors(result);
++ dev->reading = false;
++ goto out;
++ }
++
++ result = wait_event_interruptible_timeout(
++ dev->wait_q,
++ !dev->reading,
++ NAK_TIMEOUT);
+
++ if (result < 0)
++ goto out;
++
++ if (result == 0)
++ result = -ETIMEDOUT;
++ else
++ result = dev->valid;
++out:
+ /* Let the device go back to sleep eventually */
+ usb_autopm_put_interface(dev->interface);
+
+- if (result == 0) {
+- dev->valid = this_read;
+- dev->used = 0;
+- }
+-
+- usb_dbg(dev->interface, "bulk_msg result %d this_read %d",
+- result, this_read);
++ usb_dbg(dev->interface, "read %d bytes", dev->valid);
+
+ return result;
+ }
+@@ -395,13 +443,7 @@ static ssize_t chaoskey_read(struct file *file,
+ goto bail;
+ if (dev->valid == dev->used) {
+ result = _chaoskey_fill(dev);
+- if (result) {
+- mutex_unlock(&dev->lock);
+- goto bail;
+- }
+-
+- /* Read returned zero bytes */
+- if (dev->used == dev->valid) {
++ if (result < 0) {
+ mutex_unlock(&dev->lock);
+ goto bail;
+ }
+@@ -435,6 +477,8 @@ bail:
+ return read_count;
+ }
+ usb_dbg(dev->interface, "empty read, result %d", result);
++ if (result == -ETIMEDOUT)
++ result = -EAGAIN;
+ return result;
+ }
+
+--
+2.9.3
+
diff --git a/debian/patches/features/all/chaoskey/usb-misc-fix-chaoskey-build-needs-HW_RANDOM.patch b/debian/patches/features/all/chaoskey/usb-misc-fix-chaoskey-build-needs-HW_RANDOM.patch
new file mode 100644
index 0000000..c4bff01
--- /dev/null
+++ b/debian/patches/features/all/chaoskey/usb-misc-fix-chaoskey-build-needs-HW_RANDOM.patch
@@ -0,0 +1,33 @@
+From d9aab404e60d122ded979fa0b81db42fb680d867 Mon Sep 17 00:00:00 2001
+From: Randy Dunlap <rdunlap@infradead.org>
+Date: Thu, 2 Apr 2015 17:10:55 -0700
+Subject: [PATCH] usb/misc: fix chaoskey build, needs HW_RANDOM
+
+Fix build errors when HW_RANDOM is not enabled:
+
+drivers/built-in.o: In function `chaoskey_disconnect':
+chaoskey.c:(.text+0x5f3f00): undefined reference to `hwrng_unregister'
+drivers/built-in.o: In function `chaoskey_probe':
+chaoskey.c:(.text+0x5f42a6): undefined reference to `hwrng_register'
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
+index 8c331f1..f7a7fc2 100644
+--- a/drivers/usb/misc/Kconfig
++++ b/drivers/usb/misc/Kconfig
+@@ -258,6 +258,7 @@ config USB_LINK_LAYER_TEST
+
+ config USB_CHAOSKEY
+ tristate "ChaosKey random number generator driver support"
++ depends on HW_RANDOM
+ help
+ Say Y here if you want to connect an AltusMetrum ChaosKey to
+ your computer's USB port. The ChaosKey is a hardware random
+--
+2.9.3
+
diff --git a/debian/patches/series b/debian/patches/series
index 3ab0d2d..75ade3f 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -637,6 +637,17 @@ features/x86/ALSA-hda_controller-Separate-stream_tag-for-input-an.patch
features/x86/ALSA-hda_intel-apply-the-Seperate-stream_tag-for-Sky.patch
features/x86/ALSA-hda_intel-apply-the-Seperate-stream_tag-for-Sun.patch
+# chaoskey driver
+features/all/chaoskey/usb-Add-driver-for-Altus-Metrum-ChaosKey-device-v2.patch
+features/all/chaoskey/usb-Fix-warnings-in-chaoskey-driver.patch
+features/all/chaoskey/usb-misc-fix-chaoskey-build-needs-HW_RANDOM.patch
+features/all/chaoskey/USB-chaoskey-read-offset-bug.patch
+features/all/chaoskey/usb-misc-chaoskey-Cleanup-probe-failure-paths.patch
+features/all/chaoskey/usb-misc-chaoskey-introduce-an-URB-for-asynchronous-.patch
+features/all/chaoskey/hwrng-chaoskey-Add-support-for-Araneus-Alea-I-USB-RN.patch
+features/all/chaoskey/hwrng-chaoskey-Fix-URB-warning-due-to-timeout-on-Ale.patch
+features/all/chaoskey/chaoskey-3.16-no-hwrng-quality.patch
+
# Security fixes
bugfix/all/usb-usbfs-fix-potential-infoleak-in-devio.patch
bugfix/all/alsa-timer-fix-leak-in-sndrv_timer_ioctl_params.patch
--
2.1.4
Reply to: