aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-27 18:11:55 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-27 18:11:55 -0400
commit818e607b57c94ade9824dad63a96c2ea6b21baf3 (patch)
tree2c83a38a1d090da464c435486e4a2e6f4afbacd2 /lib
parentff9a082fda424257976f08fce942609f358015e0 (diff)
parent86a574de4590ffe6fd3f3ca34cdcf655a78e36ec (diff)
Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random
Pull random driver updates from Ted Ts'o: "A number of improvements for the /dev/random driver; the most important is the use of a ChaCha20-based CRNG for /dev/urandom, which is faster, more efficient, and easier to make scalable for silly/abusive userspace programs that want to read from /dev/urandom in a tight loop on NUMA systems. This set of patches also improves entropy gathering on VM's running on Microsoft Azure, and will take advantage of a hw random number generator (if present) to initialize the /dev/urandom pool" (It turns out that the random tree hadn't been in linux-next this time around, because it had been dropped earlier as being too quiet. Oh well). * tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random: random: strengthen input validation for RNDADDTOENTCNT random: add backtracking protection to the CRNG random: make /dev/urandom scalable for silly userspace programs random: replace non-blocking pool with a Chacha20-based CRNG random: properly align get_random_int_hash random: add interrupt callback to VMBus IRQ handler random: print a warning for the first ten uninitialized random users random: initialize the non-blocking pool via add_hwgenerator_randomness()
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile2
-rw-r--r--lib/chacha20.c79
2 files changed, 80 insertions, 1 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 07d06a8b9788..cfa68eb269e4 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -19,7 +19,7 @@ KCOV_INSTRUMENT_dynamic_debug.o := n
19lib-y := ctype.o string.o vsprintf.o cmdline.o \ 19lib-y := ctype.o string.o vsprintf.o cmdline.o \
20 rbtree.o radix-tree.o dump_stack.o timerqueue.o\ 20 rbtree.o radix-tree.o dump_stack.o timerqueue.o\
21 idr.o int_sqrt.o extable.o \ 21 idr.o int_sqrt.o extable.o \
22 sha1.o md5.o irq_regs.o argv_split.o \ 22 sha1.o chacha20.o md5.o irq_regs.o argv_split.o \
23 flex_proportions.o ratelimit.o show_mem.o \ 23 flex_proportions.o ratelimit.o show_mem.o \
24 is_single_threaded.o plist.o decompress.o kobject_uevent.o \ 24 is_single_threaded.o plist.o decompress.o kobject_uevent.o \
25 earlycpio.o seq_buf.o nmi_backtrace.o nodemask.o 25 earlycpio.o seq_buf.o nmi_backtrace.o nodemask.o
diff --git a/lib/chacha20.c b/lib/chacha20.c
new file mode 100644
index 000000000000..250ceed9ec9a
--- /dev/null
+++ b/lib/chacha20.c
@@ -0,0 +1,79 @@
1/*
2 * ChaCha20 256-bit cipher algorithm, RFC7539
3 *
4 * Copyright (C) 2015 Martin Willi
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/export.h>
14#include <linux/bitops.h>
15#include <linux/cryptohash.h>
16#include <asm/unaligned.h>
17#include <crypto/chacha20.h>
18
19static inline u32 rotl32(u32 v, u8 n)
20{
21 return (v << n) | (v >> (sizeof(v) * 8 - n));
22}
23
24extern void chacha20_block(u32 *state, void *stream)
25{
26 u32 x[16], *out = stream;
27 int i;
28
29 for (i = 0; i < ARRAY_SIZE(x); i++)
30 x[i] = state[i];
31
32 for (i = 0; i < 20; i += 2) {
33 x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 16);
34 x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 16);
35 x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 16);
36 x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 16);
37
38 x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 12);
39 x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 12);
40 x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 12);
41 x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 12);
42
43 x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 8);
44 x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 8);
45 x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 8);
46 x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 8);
47
48 x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 7);
49 x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 7);
50 x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 7);
51 x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 7);
52
53 x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 16);
54 x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 16);
55 x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 16);
56 x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 16);
57
58 x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 12);
59 x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 12);
60 x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 12);
61 x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 12);
62
63 x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 8);
64 x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 8);
65 x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 8);
66 x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 8);
67
68 x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 7);
69 x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 7);
70 x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 7);
71 x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 7);
72 }
73
74 for (i = 0; i < ARRAY_SIZE(x); i++)
75 out[i] = cpu_to_le32(x[i] + state[i]);
76
77 state[12]++;
78}
79EXPORT_SYMBOL(chacha20_block);