Running completely virtualised, system Z severely lacks good true random sources.
Gathering entropy in a virtual environment is difficult. To compensate, there is
specialised crypto hardware which includes a source for hardware randomness;
the zcrypt driver is able to access this random source. This patch adds a kernel
thread that feeds the random bits via the interface created with the previous patch.
Signed-off-by: Torsten Duwe <[email protected]>
---
zcrypt_api.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -38,6 +38,8 @@
#include <linux/atomic.h>
#include <asm/uaccess.h>
#include <linux/hw_random.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
#include <linux/debugfs.h>
#include <asm/debug.h>
@@ -99,6 +99,13 @@ static ssize_t zcrypt_online_store(struc
if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1)
return -EINVAL;
+ if (zdev->ops->rng) {
+ if (zdev->online == 0 && online == 1)
+ zcrypt_rng_device_add();
+ if (zdev->online == 1 && online == 0)
+ zcrypt_rng_device_remove();
+
+ }
zdev->online = online;
ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dman", zdev->ap_dev->qid,
zdev->online);
@@ -1117,6 +1119,7 @@ static int zcrypt_rng_device_count;
static u32 *zcrypt_rng_buffer;
static int zcrypt_rng_buffer_index;
static DEFINE_MUTEX(zcrypt_rng_mutex);
+static struct task_struct *zcrypt_hwrng_fill;
static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data)
{
@@ -1141,6 +1144,36 @@ static struct hwrng zcrypt_rng_dev = {
.data_read = zcrypt_rng_data_read,
};
+static int zcrypt_hwrng_fillfn(void *unused)
+{
+ long rc;
+
+ while (!kthread_should_stop()) {
+ rc = zcrypt_rng((char *)zcrypt_rng_buffer);
+ if (rc == -ENODEV || rc == -EINVAL || rc == -ENOMEM) {
+ pr_err("zcrypt_rng unavailable: %ld\n", rc);
+ break;
+ }
+ if (rc == -EAGAIN || rc == -ERESTARTSYS) {
+ pr_info("zcrypt_rng interrupted: %ld\n", rc);
+ msleep_interruptible(1000);
+ continue;
+ }
+ if (rc == 0) {
+ pr_err("zcrypt_rng: no data available\n");
+ msleep_interruptible(10000);
+ continue;
+ }
+ if (rc < 0) {
+ pr_err("zcrypt_rng unknown error: %ld\n", rc);
+ break;
+ }
+ add_hwgenerator_randomness((void *)zcrypt_rng_buffer, rc);
+ }
+ zcrypt_hwrng_fill = 0;
+ return 0;
+}
+
static int zcrypt_rng_device_add(void)
{
int rc = 0;
@@ -1157,6 +1189,12 @@ static int zcrypt_rng_device_add(void)
if (rc)
goto out_free;
zcrypt_rng_device_count = 1;
+ zcrypt_hwrng_fill = kthread_run(zcrypt_hwrng_fillfn,
+ NULL, "zc_hwrng");
+ if (zcrypt_hwrng_fill == ERR_PTR(-ENOMEM)) {
+ pr_err("zcrypt_hwrng_fill thread creation failed\n");
+ zcrypt_hwrng_fill = 0;
+ }
} else
zcrypt_rng_device_count++;
mutex_unlock(&zcrypt_rng_mutex);
@@ -1174,6 +1211,10 @@ static void zcrypt_rng_device_remove(voi
mutex_lock(&zcrypt_rng_mutex);
zcrypt_rng_device_count--;
if (zcrypt_rng_device_count == 0) {
+ if (zcrypt_hwrng_fill) {
+ kthread_stop(zcrypt_hwrng_fill);
+ zcrypt_hwrng_fill = 0;
+ }
hwrng_unregister(&zcrypt_rng_dev);
free_page((unsigned long) zcrypt_rng_buffer);
}
On 09/12/2013 02:41 AM, Torsten Duwe wrote:
>
> Running completely virtualised, system Z severely lacks good true random sources.
> Gathering entropy in a virtual environment is difficult. To compensate, there is
> specialised crypto hardware which includes a source for hardware randomness;
> the zcrypt driver is able to access this random source. This patch adds a kernel
> thread that feeds the random bits via the interface created with the previous patch.
>
> Signed-off-by: Torsten Duwe <[email protected]>
>From what I can gather from the patch this is too heavyweight (need
locks and so on) to use as arch_get_random*(). There has been a lot of
discussion about the pros and cons of allowing the kernel to bypass
rngd, but I would think that any such plumbing -- once it gets past the
fully synchronous low latency properties of arch_get_random*() -- really
should be implemented as an option in the existing hwrng device
infrastructure.
In other words, start by implementing a hwrng device. That will work
right now with rngd running. Then we can consider if we want to allow
bypass of rngd for certain hwrng devices -- which may include zcrypt,
virtio_rng and so on.
-hpa
On Thu, 12 Sep 2013, H. Peter Anvin wrote:
> From what I can gather from the patch this is too heavyweight (need
> locks and so on) to use as arch_get_random*(). There has been a lot of
Alas, I can see there's only x86 that currently has this implemented?
> discussion about the pros and cons of allowing the kernel to bypass
> rngd, but I would think that any such plumbing -- once it gets past the
> fully synchronous low latency properties of arch_get_random*() -- really
> should be implemented as an option in the existing hwrng device
> infrastructure.
As I wrote in the intro, the problem to solve is slow startup when ASLR is
in effect; in that case: until rngd or haveged is finally running.
> In other words, start by implementing a hwrng device. That will work
> right now with rngd running. Then we can consider if we want to allow
That's already there, thanks to the IBM guys :)
> bypass of rngd for certain hwrng devices -- which may include zcrypt,
> virtio_rng and so on.
I'm currently thinking about some kind of buffer in zcrypt, where
arch_get_random can get a long or int quickly, as "designed" after x86.
Device init or low water would trigger a work item to refill the buffer.
It might tun out though, that every device on every architecture that does
not quite match the x86 approach implements its own buffer.
What do you think?
Besides that, as you wrote, a generic mechanism to mix hwrngs into the
input pool would be nice, triggered by user space policy. As far as I can
see, some mixing of arch_get_random is done, but no entropy credited?
Torsten
By the way, haveged is... worthy of suspicion (I doubt it is malicious, but still). Its self-tests are completely useless (replace the entropy source with a constant "1" and they still pass) and there is as far as I know no analysis about the randomness other than "it passes some tests."
Torsten Duwe <[email protected]> wrote:
>
>
>On Thu, 12 Sep 2013, H. Peter Anvin wrote:
>
>> From what I can gather from the patch this is too heavyweight (need
>> locks and so on) to use as arch_get_random*(). There has been a lot
>of
>
>Alas, I can see there's only x86 that currently has this implemented?
>
>> discussion about the pros and cons of allowing the kernel to bypass
>> rngd, but I would think that any such plumbing -- once it gets past
>the
>> fully synchronous low latency properties of arch_get_random*() --
>really
>> should be implemented as an option in the existing hwrng device
>> infrastructure.
>
>As I wrote in the intro, the problem to solve is slow startup when ASLR
>is
>in effect; in that case: until rngd or haveged is finally running.
>
>> In other words, start by implementing a hwrng device. That will work
>> right now with rngd running. Then we can consider if we want to
>allow
>
>That's already there, thanks to the IBM guys :)
>
>> bypass of rngd for certain hwrng devices -- which may include zcrypt,
>> virtio_rng and so on.
>
>I'm currently thinking about some kind of buffer in zcrypt, where
>arch_get_random can get a long or int quickly, as "designed" after x86.
>Device init or low water would trigger a work item to refill the
>buffer.
>It might tun out though, that every device on every architecture that
>does
>not quite match the x86 approach implements its own buffer.
>
>What do you think?
>
>Besides that, as you wrote, a generic mechanism to mix hwrngs into the
>input pool would be nice, triggered by user space policy. As far as I
>can
>see, some mixing of arch_get_random is done, but no entropy credited?
>
> Torsten
--
Sent from my mobile phone. Please pardon brevity and lack of formatting.
As I said, the option of doing feed from hwrng directly via a kernel thread seems the most logical thing to me, assuming you can convince Ted & co. rngd doesn't really add much value for a whitened source.
Torsten Duwe <[email protected]> wrote:
>
>
>On Thu, 12 Sep 2013, H. Peter Anvin wrote:
>
>> From what I can gather from the patch this is too heavyweight (need
>> locks and so on) to use as arch_get_random*(). There has been a lot
>of
>
>Alas, I can see there's only x86 that currently has this implemented?
>
>> discussion about the pros and cons of allowing the kernel to bypass
>> rngd, but I would think that any such plumbing -- once it gets past
>the
>> fully synchronous low latency properties of arch_get_random*() --
>really
>> should be implemented as an option in the existing hwrng device
>> infrastructure.
>
>As I wrote in the intro, the problem to solve is slow startup when ASLR
>is
>in effect; in that case: until rngd or haveged is finally running.
>
>> In other words, start by implementing a hwrng device. That will work
>> right now with rngd running. Then we can consider if we want to
>allow
>
>That's already there, thanks to the IBM guys :)
>
>> bypass of rngd for certain hwrng devices -- which may include zcrypt,
>> virtio_rng and so on.
>
>I'm currently thinking about some kind of buffer in zcrypt, where
>arch_get_random can get a long or int quickly, as "designed" after x86.
>Device init or low water would trigger a work item to refill the
>buffer.
>It might tun out though, that every device on every architecture that
>does
>not quite match the x86 approach implements its own buffer.
>
>What do you think?
>
>Besides that, as you wrote, a generic mechanism to mix hwrngs into the
>input pool would be nice, triggered by user space policy. As far as I
>can
>see, some mixing of arch_get_random is done, but no entropy credited?
>
> Torsten
--
Sent from my mobile phone. Please pardon brevity and lack of formatting.