diff options
author | Eric Biggers <ebiggers@google.com> | 2018-09-11 23:05:10 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2018-09-21 01:24:50 -0400 |
commit | a5e9f557098e54af44ade5d501379be18435bfbf (patch) | |
tree | 4410647aaa269fd9a4e304851b06f83251b12853 /drivers/char/random.c | |
parent | 78105c7e769b8cfa4a4d59027807882b560a2634 (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.c | 24 |
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; | |||
433 | static unsigned long crng_global_init_time = 0; | 433 | static 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) |
435 | static void _extract_crng(struct crng_state *crng, | 435 | static void _extract_crng(struct crng_state *crng, |
436 | __u32 out[CHACHA20_BLOCK_WORDS]); | 436 | __u8 out[CHACHA20_BLOCK_SIZE]); |
437 | static void _crng_backtrack_protect(struct crng_state *crng, | 437 | static void _crng_backtrack_protect(struct crng_state *crng, |
438 | __u32 tmp[CHACHA20_BLOCK_WORDS], int used); | 438 | __u8 tmp[CHACHA20_BLOCK_SIZE], int used); |
439 | static void process_random_ready_list(void); | 439 | static void process_random_ready_list(void); |
440 | static void _get_random_bytes(void *buf, int nbytes); | 440 | static 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 | ||
970 | static void _extract_crng(struct crng_state *crng, | 970 | static 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 | ||
988 | static void extract_crng(__u32 out[CHACHA20_BLOCK_WORDS]) | 988 | static 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 | */ |
1005 | static void _crng_backtrack_protect(struct crng_state *crng, | 1005 | static 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 | ||
1025 | static void crng_backtrack_protect(__u32 tmp[CHACHA20_BLOCK_WORDS], int used) | 1025 | static 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) | |||
1038 | static ssize_t extract_crng_user(void __user *buf, size_t nbytes) | 1038 | static 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 | */ |
1618 | static void _get_random_bytes(void *buf, int nbytes) | 1618 | static 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++]; |