aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/random.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2018-09-11 23:05:10 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2018-09-21 01:24:50 -0400
commita5e9f557098e54af44ade5d501379be18435bfbf (patch)
tree4410647aaa269fd9a4e304851b06f83251b12853 /drivers/char/random.c
parent78105c7e769b8cfa4a4d59027807882b560a2634 (diff)
crypto: chacha20 - Fix chacha20_block() keystream alignment (again)
In commit 9f480faec58c ("crypto: chacha20 - Fix keystream alignment for chacha20_block()"), I had missed that chacha20_block() can be called directly on the buffer passed to get_random_bytes(), which can have any alignment. So, while my commit didn't break anything, it didn't fully solve the alignment problems. Revert my solution and just update chacha20_block() to use put_unaligned_le32(), so the output buffer need not be aligned. This is simpler, and on many CPUs it's the same speed. But, I kept the 'tmp' buffers in extract_crng_user() and _get_random_bytes() 4-byte aligned, since that alignment is actually needed for _crng_backtrack_protect() too. Reported-by: Stephan Müller <smueller@chronox.de> Cc: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r--drivers/char/random.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index bf5f99fc36f1..d22d967c50f0 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -433,9 +433,9 @@ static int crng_init_cnt = 0;
433static unsigned long crng_global_init_time = 0; 433static unsigned long crng_global_init_time = 0;
434#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) 434#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
435static void _extract_crng(struct crng_state *crng, 435static void _extract_crng(struct crng_state *crng,
436 __u32 out[CHACHA20_BLOCK_WORDS]); 436 __u8 out[CHACHA20_BLOCK_SIZE]);
437static void _crng_backtrack_protect(struct crng_state *crng, 437static void _crng_backtrack_protect(struct crng_state *crng,
438 __u32 tmp[CHACHA20_BLOCK_WORDS], int used); 438 __u8 tmp[CHACHA20_BLOCK_SIZE], int used);
439static void process_random_ready_list(void); 439static void process_random_ready_list(void);
440static void _get_random_bytes(void *buf, int nbytes); 440static void _get_random_bytes(void *buf, int nbytes);
441 441
@@ -921,7 +921,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
921 unsigned long flags; 921 unsigned long flags;
922 int i, num; 922 int i, num;
923 union { 923 union {
924 __u32 block[CHACHA20_BLOCK_WORDS]; 924 __u8 block[CHACHA20_BLOCK_SIZE];
925 __u32 key[8]; 925 __u32 key[8];
926 } buf; 926 } buf;
927 927
@@ -968,7 +968,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
968} 968}
969 969
970static void _extract_crng(struct crng_state *crng, 970static void _extract_crng(struct crng_state *crng,
971 __u32 out[CHACHA20_BLOCK_WORDS]) 971 __u8 out[CHACHA20_BLOCK_SIZE])
972{ 972{
973 unsigned long v, flags; 973 unsigned long v, flags;
974 974
@@ -985,7 +985,7 @@ static void _extract_crng(struct crng_state *crng,
985 spin_unlock_irqrestore(&crng->lock, flags); 985 spin_unlock_irqrestore(&crng->lock, flags);
986} 986}
987 987
988static void extract_crng(__u32 out[CHACHA20_BLOCK_WORDS]) 988static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
989{ 989{
990 struct crng_state *crng = NULL; 990 struct crng_state *crng = NULL;
991 991
@@ -1003,7 +1003,7 @@ static void extract_crng(__u32 out[CHACHA20_BLOCK_WORDS])
1003 * enough) to mutate the CRNG key to provide backtracking protection. 1003 * enough) to mutate the CRNG key to provide backtracking protection.
1004 */ 1004 */
1005static void _crng_backtrack_protect(struct crng_state *crng, 1005static void _crng_backtrack_protect(struct crng_state *crng,
1006 __u32 tmp[CHACHA20_BLOCK_WORDS], int used) 1006 __u8 tmp[CHACHA20_BLOCK_SIZE], int used)
1007{ 1007{
1008 unsigned long flags; 1008 unsigned long flags;
1009 __u32 *s, *d; 1009 __u32 *s, *d;
@@ -1015,14 +1015,14 @@ static void _crng_backtrack_protect(struct crng_state *crng,
1015 used = 0; 1015 used = 0;
1016 } 1016 }
1017 spin_lock_irqsave(&crng->lock, flags); 1017 spin_lock_irqsave(&crng->lock, flags);
1018 s = &tmp[used / sizeof(__u32)]; 1018 s = (__u32 *) &tmp[used];
1019 d = &crng->state[4]; 1019 d = &crng->state[4];
1020 for (i=0; i < 8; i++) 1020 for (i=0; i < 8; i++)
1021 *d++ ^= *s++; 1021 *d++ ^= *s++;
1022 spin_unlock_irqrestore(&crng->lock, flags); 1022 spin_unlock_irqrestore(&crng->lock, flags);
1023} 1023}
1024 1024
1025static void crng_backtrack_protect(__u32 tmp[CHACHA20_BLOCK_WORDS], int used) 1025static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used)
1026{ 1026{
1027 struct crng_state *crng = NULL; 1027 struct crng_state *crng = NULL;
1028 1028
@@ -1038,7 +1038,7 @@ static void crng_backtrack_protect(__u32 tmp[CHACHA20_BLOCK_WORDS], int used)
1038static ssize_t extract_crng_user(void __user *buf, size_t nbytes) 1038static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
1039{ 1039{
1040 ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE; 1040 ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE;
1041 __u32 tmp[CHACHA20_BLOCK_WORDS]; 1041 __u8 tmp[CHACHA20_BLOCK_SIZE] __aligned(4);
1042 int large_request = (nbytes > 256); 1042 int large_request = (nbytes > 256);
1043 1043
1044 while (nbytes) { 1044 while (nbytes) {
@@ -1617,7 +1617,7 @@ static void _warn_unseeded_randomness(const char *func_name, void *caller,
1617 */ 1617 */
1618static void _get_random_bytes(void *buf, int nbytes) 1618static void _get_random_bytes(void *buf, int nbytes)
1619{ 1619{
1620 __u32 tmp[CHACHA20_BLOCK_WORDS]; 1620 __u8 tmp[CHACHA20_BLOCK_SIZE] __aligned(4);
1621 1621
1622 trace_get_random_bytes(nbytes, _RET_IP_); 1622 trace_get_random_bytes(nbytes, _RET_IP_);
1623 1623
@@ -2243,7 +2243,7 @@ u64 get_random_u64(void)
2243 if (use_lock) 2243 if (use_lock)
2244 read_lock_irqsave(&batched_entropy_reset_lock, flags); 2244 read_lock_irqsave(&batched_entropy_reset_lock, flags);
2245 if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) { 2245 if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
2246 extract_crng((__u32 *)batch->entropy_u64); 2246 extract_crng((u8 *)batch->entropy_u64);
2247 batch->position = 0; 2247 batch->position = 0;
2248 } 2248 }
2249 ret = batch->entropy_u64[batch->position++]; 2249 ret = batch->entropy_u64[batch->position++];
@@ -2273,7 +2273,7 @@ u32 get_random_u32(void)
2273 if (use_lock) 2273 if (use_lock)
2274 read_lock_irqsave(&batched_entropy_reset_lock, flags); 2274 read_lock_irqsave(&batched_entropy_reset_lock, flags);
2275 if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) { 2275 if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
2276 extract_crng(batch->entropy_u32); 2276 extract_crng((u8 *)batch->entropy_u32);
2277 batch->position = 0; 2277 batch->position = 0;
2278 } 2278 }
2279 ret = batch->entropy_u32[batch->position++]; 2279 ret = batch->entropy_u32[batch->position++];