From be4000bc4644d027c519b6361f5ae3bbfc52c347 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Sat, 14 Jun 2014 23:46:03 -0400 Subject: hwrng: create filler thread This can be viewed as the in-kernel equivalent of hwrngd; like FUSE it is a good thing to have a mechanism in user land, but for some reasons (simplicity, secrecy, integrity, speed) it may be better to have it in kernel space. This patch creates a thread once a hwrng registers, and uses the previously established add_hwgenerator_randomness() to feed its data to the input pool as long as needed. A derating factor is used to bias the entropy estimation and to disable this mechanism entirely when set to zero. Signed-off-by: Torsten Duwe Signed-off-by: Theodore Ts'o Acked-by: H. Peter Anvin --- drivers/char/hw_random/core.c | 69 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 5 deletions(-) (limited to 'drivers/char/hw_random/core.c') diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 334601cc81cf..48b3c812b9ec 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -50,10 +51,18 @@ static struct hwrng *current_rng; +static struct task_struct *hwrng_fill; static LIST_HEAD(rng_list); static DEFINE_MUTEX(rng_mutex); static int data_avail; -static u8 *rng_buffer; +static u8 *rng_buffer, *rng_fillbuf; +static unsigned short current_quality = 700; /* an arbitrary 70% */ + +module_param(current_quality, ushort, 0644); +MODULE_PARM_DESC(current_quality, + "current hwrng entropy estimation per mill"); + +static void start_khwrngd(void); static size_t rng_buffer_size(void) { @@ -62,9 +71,18 @@ static size_t rng_buffer_size(void) static inline int hwrng_init(struct hwrng *rng) { - if (!rng->init) - return 0; - return rng->init(rng); + int err; + + if (rng->init) { + err = rng->init(rng); + if (err) + return err; + } + + if (current_quality > 0 && !hwrng_fill) + start_khwrngd(); + + return 0; } static inline void hwrng_cleanup(struct hwrng *rng) @@ -300,6 +318,36 @@ err_misc_dereg: goto out; } +static int hwrng_fillfn(void *unused) +{ + long rc; + + while (!kthread_should_stop()) { + if (!current_rng) + break; + rc = rng_get_data(current_rng, rng_fillbuf, + rng_buffer_size(), 1); + if (rc <= 0) { + pr_warn("hwrng: no data available\n"); + msleep_interruptible(10000); + continue; + } + add_hwgenerator_randomness((void *)rng_fillbuf, rc, + (rc*current_quality)>>10); + } + hwrng_fill = 0; + return 0; +} + +static void start_khwrngd(void) +{ + hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng"); + if (hwrng_fill == ERR_PTR(-ENOMEM)) { + pr_err("hwrng_fill thread creation failed"); + hwrng_fill = NULL; + } +} + int hwrng_register(struct hwrng *rng) { int err = -EINVAL; @@ -320,6 +368,13 @@ int hwrng_register(struct hwrng *rng) if (!rng_buffer) goto out_unlock; } + if (!rng_fillbuf) { + rng_fillbuf = kmalloc(rng_buffer_size(), GFP_KERNEL); + if (!rng_fillbuf) { + kfree(rng_buffer); + goto out_unlock; + } + } /* Must not register two RNGs with the same name. */ err = -EEXIST; @@ -375,8 +430,11 @@ void hwrng_unregister(struct hwrng *rng) current_rng = NULL; } } - if (list_empty(&rng_list)) + if (list_empty(&rng_list)) { unregister_miscdev(); + if (hwrng_fill) + kthread_stop(hwrng_fill); + } mutex_unlock(&rng_mutex); } @@ -387,6 +445,7 @@ static void __exit hwrng_exit(void) mutex_lock(&rng_mutex); BUG_ON(current_rng); kfree(rng_buffer); + kfree(rng_fillbuf); mutex_unlock(&rng_mutex); } -- cgit v1.2.3 From 0f734e6e768b4b66737b3d3e13f1769a12ecff86 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Sat, 14 Jun 2014 23:48:41 -0400 Subject: hwrng: add per-device entropy derating This patch introduces a derating factor to struct hwrng for the random bits going into the kernel input pool, and a common default derating for drivers which do not specify one. Signed-off-by: Torsten Duwe Signed-off-by: Theodore Ts'o Acked-by: H. Peter Anvin --- drivers/char/hw_random/core.c | 11 ++++++++++- include/linux/hw_random.h | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/char/hw_random/core.c') diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 48b3c812b9ec..3aaf97c774f1 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -56,11 +56,15 @@ static LIST_HEAD(rng_list); static DEFINE_MUTEX(rng_mutex); static int data_avail; static u8 *rng_buffer, *rng_fillbuf; -static unsigned short current_quality = 700; /* an arbitrary 70% */ +static unsigned short current_quality; +static unsigned short default_quality; /* = 0; default to "off" */ module_param(current_quality, ushort, 0644); MODULE_PARM_DESC(current_quality, "current hwrng entropy estimation per mill"); +module_param(default_quality, ushort, 0644); +MODULE_PARM_DESC(default_quality, + "default entropy content of hwrng per mill"); static void start_khwrngd(void); @@ -79,6 +83,11 @@ static inline int hwrng_init(struct hwrng *rng) return err; } + current_quality = rng->quality ? : default_quality; + current_quality &= 1023; + + if (current_quality == 0 && hwrng_fill) + kthread_stop(hwrng_fill); if (current_quality > 0 && !hwrng_fill) start_khwrngd(); diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h index 3f075ff00411..914bb08cd738 100644 --- a/include/linux/hw_random.h +++ b/include/linux/hw_random.h @@ -29,6 +29,8 @@ * @read: New API. drivers can fill up to max bytes of data * into the buffer. The buffer is aligned for any type. * @priv: Private data, for use by the RNG driver. + * @quality: Estimation of true entropy in RNG's bitstream + * (per mill). */ struct hwrng { const char *name; @@ -38,6 +40,7 @@ struct hwrng { int (*data_read)(struct hwrng *rng, u32 *data); int (*read)(struct hwrng *rng, void *data, size_t max, bool wait); unsigned long priv; + unsigned short quality; /* internal. */ struct list_head list; -- cgit v1.2.3 From 9dda727d37ff6ce1628dd2b8557ad011c49db377 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Mon, 16 Jun 2014 10:24:09 -0400 Subject: hw_random: fix sparse warning (NULL vs 0 for pointer) Signed-off-by: Torsten Duwe Signed-off-by: Theodore Ts'o --- drivers/char/hw_random/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char/hw_random/core.c') diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 3aaf97c774f1..349a3b852be9 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -344,7 +344,7 @@ static int hwrng_fillfn(void *unused) add_hwgenerator_randomness((void *)rng_fillbuf, rc, (rc*current_quality)>>10); } - hwrng_fill = 0; + hwrng_fill = NULL; return 0; } -- cgit v1.2.3 From eeec626366ffe558fc3d5685bd2b49a962acf57d Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Sun, 27 Jul 2014 07:35:01 +0930 Subject: Revert "hwrng: virtio - ensure reads happen after successful probe" This reverts commit e052dbf554610e2104c5a7518c4d8374bed701bb. Now that we use the virtio ->scan() function to register with the hwrng core, we will not get read requests till probe is successfully finished. So revert the workaround we had in place to refuse read requests while we were not yet setup completely. Signed-off-by: Amit Shah Signed-off-by: Rusty Russell --- drivers/char/hw_random/core.c | 6 ------ drivers/char/hw_random/virtio-rng.c | 9 --------- 2 files changed, 15 deletions(-) (limited to 'drivers/char/hw_random/core.c') diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index c4419ea1ab07..2a451b14b3cc 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -68,12 +68,6 @@ static void add_early_randomness(struct hwrng *rng) unsigned char bytes[16]; int bytes_read; - /* - * Currently only virtio-rng cannot return data during device - * probe, and that's handled in virtio-rng.c itself. If there - * are more such devices, this call to rng_get_data can be - * made conditional here instead of doing it per-device. - */ bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1); if (bytes_read > 0) add_device_randomness(bytes, bytes_read); diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index d9927eb4fa98..0027137daa56 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -38,7 +38,6 @@ struct virtrng_info { bool hwrng_register_done; }; -static bool probe_done; static void random_recv_done(struct virtqueue *vq) { @@ -69,13 +68,6 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) int ret; struct virtrng_info *vi = (struct virtrng_info *)rng->priv; - /* - * Don't ask host for data till we're setup. This call can - * happen during hwrng_register(), after commit d9e7972619. - */ - if (unlikely(!probe_done)) - return 0; - if (!vi->busy) { vi->busy = true; init_completion(&vi->have_data); @@ -137,7 +129,6 @@ static int probe_common(struct virtio_device *vdev) return err; } - probe_done = true; return 0; } -- cgit v1.2.3 From e02b876597777ab26288dd2611a97b597d14d661 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 25 Jul 2014 15:19:18 -0700 Subject: hwrng: Pass entropy to add_hwgenerator_randomness() in bits, not bytes rng_get_data() returns the number of bytes read from the hardware. The entropy argument to add_hwgenerator_randomness() is passed directly to credit_entropy_bits() so we should be passing the number of bits, not bytes here. Fixes: be4000bc464 "hwrng: create filler thread" Acked-by: Torsten Duwe Signed-off-by: Stephen Boyd Signed-off-by: Theodore Ts'o --- drivers/char/hw_random/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char/hw_random/core.c') diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 349a3b852be9..33fd6633586d 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -342,7 +342,7 @@ static int hwrng_fillfn(void *unused) continue; } add_hwgenerator_randomness((void *)rng_fillbuf, rc, - (rc*current_quality)>>10); + rc * current_quality * 8 >> 10); } hwrng_fill = NULL; return 0; -- cgit v1.2.3