| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Sat, 14 Jul 2018 23:55:57 -0400 |
| Subject: random: mix rdrand with entropy sent in from userspace |
| |
| commit 81e69df38e2911b642ec121dec319fad2a4782f3 upstream. |
| |
| Fedora has integrated the jitter entropy daemon to work around slow |
| boot problems, especially on VM's that don't support virtio-rng: |
| |
| https://bugzilla.redhat.com/show_bug.cgi?id=1572944 |
| |
| It's understandable why they did this, but the Jitter entropy daemon |
| works fundamentally on the principle: "the CPU microarchitecture is |
| **so** complicated and we can't figure it out, so it *must* be |
| random". Yes, it uses statistical tests to "prove" it is secure, but |
| AES_ENCRYPT(NSA_KEY, COUNTER++) will also pass statistical tests with |
| flying colors. |
| |
| So if RDRAND is available, mix it into entropy submitted from |
| userspace. It can't hurt, and if you believe the NSA has backdoored |
| RDRAND, then they probably have enough details about the Intel |
| microarchitecture that they can reverse engineer how the Jitter |
| entropy daemon affects the microarchitecture, and attack its output |
| stream. And if RDRAND is in fact an honest DRNG, it will immeasurably |
| improve on what the Jitter entropy daemon might produce. |
| |
| This also provides some protection against someone who is able to read |
| or set the entropy seed file. |
| |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Cc: Arnd Bergmann <arnd@arndb.de> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/char/random.c | 10 +++++++++- |
| 1 file changed, 9 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/char/random.c |
| +++ b/drivers/char/random.c |
| @@ -1418,14 +1418,22 @@ static int |
| write_pool(struct entropy_store *r, const char __user *buffer, size_t count) |
| { |
| size_t bytes; |
| - __u32 buf[16]; |
| + __u32 t, buf[16]; |
| const char __user *p = buffer; |
| |
| while (count > 0) { |
| + int b, i = 0; |
| + |
| bytes = min(count, sizeof(buf)); |
| if (copy_from_user(&buf, p, bytes)) |
| return -EFAULT; |
| |
| + for (b = bytes ; b > 0 ; b -= sizeof(__u32), i++) { |
| + if (!arch_get_random_int(&t)) |
| + break; |
| + buf[i] ^= t; |
| + } |
| + |
| count -= bytes; |
| p += bytes; |
| |