diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-27 18:11:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-27 18:11:55 -0400 |
commit | 818e607b57c94ade9824dad63a96c2ea6b21baf3 (patch) | |
tree | 2c83a38a1d090da464c435486e4a2e6f4afbacd2 /lib | |
parent | ff9a082fda424257976f08fce942609f358015e0 (diff) | |
parent | 86a574de4590ffe6fd3f3ca34cdcf655a78e36ec (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/Makefile | 2 | ||||
-rw-r--r-- | lib/chacha20.c | 79 |
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 | |||
19 | lib-y := ctype.o string.o vsprintf.o cmdline.o \ | 19 | lib-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 | |||
19 | static inline u32 rotl32(u32 v, u8 n) | ||
20 | { | ||
21 | return (v << n) | (v >> (sizeof(v) * 8 - n)); | ||
22 | } | ||
23 | |||
24 | extern 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 | } | ||
79 | EXPORT_SYMBOL(chacha20_block); | ||