diff options
author | Eric Biggers <ebiggers@google.com> | 2017-11-22 14:51:39 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2017-11-29 01:33:33 -0500 |
commit | 9f480faec58cd6197a007ea1dcac6b7c3daf1139 (patch) | |
tree | bd5107e627a9013bbbfc290ceccea218d9393f66 /drivers/char/random.c | |
parent | 796c99fbd7e20a8d78189fc0166a524d78f635a0 (diff) |
crypto: chacha20 - Fix keystream alignment for chacha20_block()
When chacha20_block() outputs the keystream block, it uses 'u32' stores
directly. However, the callers (crypto/chacha20_generic.c and
drivers/char/random.c) declare the keystream buffer as a 'u8' array,
which is not guaranteed to have the needed alignment.
Fix it by having both callers declare the keystream as a 'u32' array.
For now this is preferable to switching over to the unaligned access
macros because chacha20_block() is only being used in cases where we can
easily control the alignment (stack buffers).
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 ec42c8bb9b0d..11304bbc78cc 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -431,9 +431,9 @@ static int crng_init = 0; | |||
431 | static int crng_init_cnt = 0; | 431 | static int crng_init_cnt = 0; |
432 | #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) | 432 | #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) |
433 | static void _extract_crng(struct crng_state *crng, | 433 | static void _extract_crng(struct crng_state *crng, |
434 | __u8 out[CHACHA20_BLOCK_SIZE]); | 434 | __u32 out[CHACHA20_BLOCK_WORDS]); |
435 | static void _crng_backtrack_protect(struct crng_state *crng, | 435 | static void _crng_backtrack_protect(struct crng_state *crng, |
436 | __u8 tmp[CHACHA20_BLOCK_SIZE], int used); | 436 | __u32 tmp[CHACHA20_BLOCK_WORDS], int used); |
437 | static void process_random_ready_list(void); | 437 | static void process_random_ready_list(void); |
438 | static void _get_random_bytes(void *buf, int nbytes); | 438 | static void _get_random_bytes(void *buf, int nbytes); |
439 | 439 | ||
@@ -817,7 +817,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) | |||
817 | unsigned long flags; | 817 | unsigned long flags; |
818 | int i, num; | 818 | int i, num; |
819 | union { | 819 | union { |
820 | __u8 block[CHACHA20_BLOCK_SIZE]; | 820 | __u32 block[CHACHA20_BLOCK_WORDS]; |
821 | __u32 key[8]; | 821 | __u32 key[8]; |
822 | } buf; | 822 | } buf; |
823 | 823 | ||
@@ -851,7 +851,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) | |||
851 | } | 851 | } |
852 | 852 | ||
853 | static void _extract_crng(struct crng_state *crng, | 853 | static void _extract_crng(struct crng_state *crng, |
854 | __u8 out[CHACHA20_BLOCK_SIZE]) | 854 | __u32 out[CHACHA20_BLOCK_WORDS]) |
855 | { | 855 | { |
856 | unsigned long v, flags; | 856 | unsigned long v, flags; |
857 | 857 | ||
@@ -867,7 +867,7 @@ static void _extract_crng(struct crng_state *crng, | |||
867 | spin_unlock_irqrestore(&crng->lock, flags); | 867 | spin_unlock_irqrestore(&crng->lock, flags); |
868 | } | 868 | } |
869 | 869 | ||
870 | static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) | 870 | static void extract_crng(__u32 out[CHACHA20_BLOCK_WORDS]) |
871 | { | 871 | { |
872 | struct crng_state *crng = NULL; | 872 | struct crng_state *crng = NULL; |
873 | 873 | ||
@@ -885,7 +885,7 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) | |||
885 | * enough) to mutate the CRNG key to provide backtracking protection. | 885 | * enough) to mutate the CRNG key to provide backtracking protection. |
886 | */ | 886 | */ |
887 | static void _crng_backtrack_protect(struct crng_state *crng, | 887 | static void _crng_backtrack_protect(struct crng_state *crng, |
888 | __u8 tmp[CHACHA20_BLOCK_SIZE], int used) | 888 | __u32 tmp[CHACHA20_BLOCK_WORDS], int used) |
889 | { | 889 | { |
890 | unsigned long flags; | 890 | unsigned long flags; |
891 | __u32 *s, *d; | 891 | __u32 *s, *d; |
@@ -897,14 +897,14 @@ static void _crng_backtrack_protect(struct crng_state *crng, | |||
897 | used = 0; | 897 | used = 0; |
898 | } | 898 | } |
899 | spin_lock_irqsave(&crng->lock, flags); | 899 | spin_lock_irqsave(&crng->lock, flags); |
900 | s = (__u32 *) &tmp[used]; | 900 | s = &tmp[used / sizeof(__u32)]; |
901 | d = &crng->state[4]; | 901 | d = &crng->state[4]; |
902 | for (i=0; i < 8; i++) | 902 | for (i=0; i < 8; i++) |
903 | *d++ ^= *s++; | 903 | *d++ ^= *s++; |
904 | spin_unlock_irqrestore(&crng->lock, flags); | 904 | spin_unlock_irqrestore(&crng->lock, flags); |
905 | } | 905 | } |
906 | 906 | ||
907 | static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used) | 907 | static void crng_backtrack_protect(__u32 tmp[CHACHA20_BLOCK_WORDS], int used) |
908 | { | 908 | { |
909 | struct crng_state *crng = NULL; | 909 | struct crng_state *crng = NULL; |
910 | 910 | ||
@@ -920,7 +920,7 @@ static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used) | |||
920 | static ssize_t extract_crng_user(void __user *buf, size_t nbytes) | 920 | static ssize_t extract_crng_user(void __user *buf, size_t nbytes) |
921 | { | 921 | { |
922 | ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE; | 922 | ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE; |
923 | __u8 tmp[CHACHA20_BLOCK_SIZE]; | 923 | __u32 tmp[CHACHA20_BLOCK_WORDS]; |
924 | int large_request = (nbytes > 256); | 924 | int large_request = (nbytes > 256); |
925 | 925 | ||
926 | while (nbytes) { | 926 | while (nbytes) { |
@@ -1507,7 +1507,7 @@ static void _warn_unseeded_randomness(const char *func_name, void *caller, | |||
1507 | */ | 1507 | */ |
1508 | static void _get_random_bytes(void *buf, int nbytes) | 1508 | static void _get_random_bytes(void *buf, int nbytes) |
1509 | { | 1509 | { |
1510 | __u8 tmp[CHACHA20_BLOCK_SIZE]; | 1510 | __u32 tmp[CHACHA20_BLOCK_WORDS]; |
1511 | 1511 | ||
1512 | trace_get_random_bytes(nbytes, _RET_IP_); | 1512 | trace_get_random_bytes(nbytes, _RET_IP_); |
1513 | 1513 | ||
@@ -2114,7 +2114,7 @@ u64 get_random_u64(void) | |||
2114 | if (use_lock) | 2114 | if (use_lock) |
2115 | read_lock_irqsave(&batched_entropy_reset_lock, flags); | 2115 | read_lock_irqsave(&batched_entropy_reset_lock, flags); |
2116 | if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) { | 2116 | if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) { |
2117 | extract_crng((u8 *)batch->entropy_u64); | 2117 | extract_crng((__u32 *)batch->entropy_u64); |
2118 | batch->position = 0; | 2118 | batch->position = 0; |
2119 | } | 2119 | } |
2120 | ret = batch->entropy_u64[batch->position++]; | 2120 | ret = batch->entropy_u64[batch->position++]; |
@@ -2144,7 +2144,7 @@ u32 get_random_u32(void) | |||
2144 | if (use_lock) | 2144 | if (use_lock) |
2145 | read_lock_irqsave(&batched_entropy_reset_lock, flags); | 2145 | read_lock_irqsave(&batched_entropy_reset_lock, flags); |
2146 | if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) { | 2146 | if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) { |
2147 | extract_crng((u8 *)batch->entropy_u32); | 2147 | extract_crng(batch->entropy_u32); |
2148 | batch->position = 0; | 2148 | batch->position = 0; |
2149 | } | 2149 | } |
2150 | ret = batch->entropy_u32[batch->position++]; | 2150 | ret = batch->entropy_u32[batch->position++]; |