Source: linux Version: 3.16.36-1+deb8u1 Severity: important Tags: patch Control: fixed -1 4.1.1-1~exp1 User: debian-ad...@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 <jcris...@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 <aure...@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 <shur...@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 <shur...@sectorb.msk.ru> +Cc: stable <sta...@vger.kernel.org> +Signed-off-by: Greg Kroah-Hartman <gre...@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 <jcris...@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....@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....@collabora.com> +Signed-off-by: Herbert Xu <herb...@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....@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....@collabora.com> +Signed-off-by: Herbert Xu <herb...@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 <kei...@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 <oneu...@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 <kei...@keithp.com> +Cc: Oliver Neukum <oneu...@suse.de> +Signed-off-by: Greg Kroah-Hartman <gre...@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 <kei...@keithp.com> ++L: linux-...@vger.kernel.org ++S: Maintained ++F: drivers/usb/misc/chaoskey.c ++ + USB CYPRESS C67X00 DRIVER + M: Peter Korsgaard <jac...@sunsite.dk> + L: linux-...@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 <kei...@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, kei...@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 <kei...@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 <kei...@keithp.com> +Signed-off-by: Greg Kroah-Hartman <gre...@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 <oneu...@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 <oneu...@suse.com> +Signed-off-by: Keith Packard <kei...@keithp.com> +Signed-off-by: Greg Kroah-Hartman <gre...@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 <oneu...@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 <oneu...@suse.com> +Signed-off-by: Keith Packard <kei...@keithp.com> +Signed-off-by: Greg Kroah-Hartman <gre...@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 <rdun...@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 <rdun...@infradead.org> +Signed-off-by: Greg Kroah-Hartman <gre...@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