This is a note to let you know that I've just added the patch titled crypto: chacha20 - Fix chacha20_block() keystream alignment (again) to the 4.14-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: crypto-chacha20-fix-chacha20_block-keystream-alignment-again.patch and it can be found in the queue-4.14 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From foo@baz Thu Jun 16 07:08:33 PM CEST 2022 From: Eric Biggers <ebiggers@xxxxxxxxxx> Date: Tue, 11 Sep 2018 20:05:10 -0700 Subject: crypto: chacha20 - Fix chacha20_block() keystream alignment (again) From: Eric Biggers <ebiggers@xxxxxxxxxx> [ Upstream commit a5e9f557098e54af44ade5d501379be18435bfbf ] 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@xxxxxxxxxx> Cc: Theodore Ts'o <tytso@xxxxxxx> Signed-off-by: Eric Biggers <ebiggers@xxxxxxxxxx> Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- crypto/chacha20_generic.c | 7 ++++--- drivers/char/random.c | 24 ++++++++++++------------ include/crypto/chacha20.h | 3 +-- lib/chacha20.c | 6 +++--- 4 files changed, 20 insertions(+), 20 deletions(-) --- a/crypto/chacha20_generic.c +++ b/crypto/chacha20_generic.c @@ -22,20 +22,21 @@ static inline u32 le32_to_cpuvp(const vo static void chacha20_docrypt(u32 *state, u8 *dst, const u8 *src, unsigned int bytes) { - u32 stream[CHACHA20_BLOCK_WORDS]; + /* aligned to potentially speed up crypto_xor() */ + u8 stream[CHACHA20_BLOCK_SIZE] __aligned(sizeof(long)); if (dst != src) memcpy(dst, src, bytes); while (bytes >= CHACHA20_BLOCK_SIZE) { chacha20_block(state, stream); - crypto_xor(dst, (const u8 *)stream, CHACHA20_BLOCK_SIZE); + crypto_xor(dst, stream, CHACHA20_BLOCK_SIZE); bytes -= CHACHA20_BLOCK_SIZE; dst += CHACHA20_BLOCK_SIZE; } if (bytes) { chacha20_block(state, stream); - crypto_xor(dst, (const u8 *)stream, bytes); + crypto_xor(dst, stream, bytes); } } --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -485,9 +485,9 @@ static int crng_init_cnt = 0; static unsigned long crng_global_init_time = 0; #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) static void _extract_crng(struct crng_state *crng, - __u32 out[CHACHA20_BLOCK_WORDS]); + __u8 out[CHACHA20_BLOCK_SIZE]); static void _crng_backtrack_protect(struct crng_state *crng, - __u32 tmp[CHACHA20_BLOCK_WORDS], int used); + __u8 tmp[CHACHA20_BLOCK_SIZE], int used); static void process_random_ready_list(void); static void _get_random_bytes(void *buf, int nbytes); @@ -986,7 +986,7 @@ static void crng_reseed(struct crng_stat unsigned long flags; int i, num; union { - __u32 block[CHACHA20_BLOCK_WORDS]; + __u8 block[CHACHA20_BLOCK_SIZE]; __u32 key[8]; } buf; @@ -1014,7 +1014,7 @@ static void crng_reseed(struct crng_stat } static void _extract_crng(struct crng_state *crng, - __u32 out[CHACHA20_BLOCK_WORDS]) + __u8 out[CHACHA20_BLOCK_SIZE]) { unsigned long flags, init_time; @@ -1032,7 +1032,7 @@ static void _extract_crng(struct crng_st spin_unlock_irqrestore(&crng->lock, flags); } -static void extract_crng(__u32 out[CHACHA20_BLOCK_WORDS]) +static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) { _extract_crng(select_crng(), out); } @@ -1042,7 +1042,7 @@ static void extract_crng(__u32 out[CHACH * enough) to mutate the CRNG key to provide backtracking protection. */ static void _crng_backtrack_protect(struct crng_state *crng, - __u32 tmp[CHACHA20_BLOCK_WORDS], int used) + __u8 tmp[CHACHA20_BLOCK_SIZE], int used) { unsigned long flags; __u32 *s, *d; @@ -1054,14 +1054,14 @@ static void _crng_backtrack_protect(stru used = 0; } spin_lock_irqsave(&crng->lock, flags); - s = &tmp[used / sizeof(__u32)]; + s = (__u32 *) &tmp[used]; d = &crng->state[4]; for (i=0; i < 8; i++) *d++ ^= *s++; spin_unlock_irqrestore(&crng->lock, flags); } -static void crng_backtrack_protect(__u32 tmp[CHACHA20_BLOCK_WORDS], int used) +static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used) { _crng_backtrack_protect(select_crng(), tmp, used); } @@ -1069,7 +1069,7 @@ static void crng_backtrack_protect(__u32 static ssize_t extract_crng_user(void __user *buf, size_t nbytes) { ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE; - __u32 tmp[CHACHA20_BLOCK_WORDS]; + __u8 tmp[CHACHA20_BLOCK_SIZE] __aligned(4); int large_request = (nbytes > 256); while (nbytes) { @@ -1529,7 +1529,7 @@ static void _warn_unseeded_randomness(co */ static void _get_random_bytes(void *buf, int nbytes) { - __u32 tmp[CHACHA20_BLOCK_WORDS]; + __u8 tmp[CHACHA20_BLOCK_SIZE] __aligned(4); trace_get_random_bytes(nbytes, _RET_IP_); @@ -2116,7 +2116,7 @@ u64 get_random_u64(void) batch = raw_cpu_ptr(&batched_entropy_u64); spin_lock_irqsave(&batch->batch_lock, flags); if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) { - extract_crng((__u32 *)batch->entropy_u64); + extract_crng((u8 *)batch->entropy_u64); batch->position = 0; } ret = batch->entropy_u64[batch->position++]; @@ -2140,7 +2140,7 @@ u32 get_random_u32(void) batch = raw_cpu_ptr(&batched_entropy_u32); spin_lock_irqsave(&batch->batch_lock, flags); if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) { - extract_crng(batch->entropy_u32); + extract_crng((u8 *)batch->entropy_u32); batch->position = 0; } ret = batch->entropy_u32[batch->position++]; --- a/include/crypto/chacha20.h +++ b/include/crypto/chacha20.h @@ -13,13 +13,12 @@ #define CHACHA20_IV_SIZE 16 #define CHACHA20_KEY_SIZE 32 #define CHACHA20_BLOCK_SIZE 64 -#define CHACHA20_BLOCK_WORDS (CHACHA20_BLOCK_SIZE / sizeof(u32)) struct chacha20_ctx { u32 key[8]; }; -void chacha20_block(u32 *state, u32 *stream); +void chacha20_block(u32 *state, u8 *stream); void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv); int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keysize); --- a/lib/chacha20.c +++ b/lib/chacha20.c @@ -21,9 +21,9 @@ static inline u32 rotl32(u32 v, u8 n) return (v << n) | (v >> (sizeof(v) * 8 - n)); } -void chacha20_block(u32 *state, u32 *stream) +void chacha20_block(u32 *state, u8 *stream) { - u32 x[16], *out = stream; + u32 x[16]; int i; for (i = 0; i < ARRAY_SIZE(x); i++) @@ -72,7 +72,7 @@ void chacha20_block(u32 *state, u32 *str } for (i = 0; i < ARRAY_SIZE(x); i++) - out[i] = cpu_to_le32(x[i] + state[i]); + put_unaligned_le32(x[i] + state[i], &stream[i * sizeof(u32)]); state[12]++; } Patches currently in stable-queue which might be from ebiggers@xxxxxxxxxx are queue-4.14/random-do-not-take-pool-spinlock-at-boot.patch queue-4.14/random-introduce-drain_entropy-helper-to-declutter-crng_reseed.patch queue-4.14/random-fix-locking-in-crng_fast_load.patch queue-4.14/random-group-userspace-read-write-functions.patch queue-4.14/random-make-credit_entropy_bits-always-safe.patch queue-4.14/crypto-chacha20-fix-chacha20_block-keystream-alignment-again.patch queue-4.14/random-pull-add_hwgenerator_randomness-declaration-into-random.h.patch queue-4.14/random-unify-early-init-crng-load-accounting.patch queue-4.14/random-use-blake2s-instead-of-sha1-in-extraction.patch queue-4.14/random-initialize-chacha20-constants-with-correct-endianness.patch queue-4.14/random-group-entropy-extraction-functions.patch queue-4.14/random-rewrite-header-introductory-comment.patch queue-4.14/random-remove-ifdef-d-out-interrupt-bench.patch queue-4.14/random-tie-batched-entropy-generation-to-base_crng-generation.patch queue-4.14/random-use-linear-min-entropy-accumulation-crediting.patch queue-4.14/random-remove-batched-entropy-locking.patch queue-4.14/random-inline-leaves-of-rand_initialize.patch queue-4.14/random-remove-use_input_pool-parameter-from-crng_reseed.patch queue-4.14/random-zero-buffer-after-reading-entropy-from-userspace.patch queue-4.14/random-remove-whitespace-and-reorder-includes.patch queue-4.14/random-simplify-entropy-debiting.patch queue-4.14/random-document-crng_fast_key_erasure-destination-possibility.patch queue-4.14/random-absorb-fast-pool-into-input-pool-after-fast-load.patch queue-4.14/random-use-rdseed-instead-of-rdrand-in-entropy-extraction.patch queue-4.14/random-remove-dead-code-left-over-from-blocking-pool.patch queue-4.14/random-use-computational-hash-for-entropy-extraction.patch queue-4.14/random-always-wake-up-entropy-writers-after-extraction.patch queue-4.14/random-do-not-xor-rdrand-when-writing-into-dev-random.patch queue-4.14/random-group-initialization-wait-functions.patch queue-4.14/random-remove-unused-tracepoints.patch queue-4.14/crypto-chacha20-fix-keystream-alignment-for-chacha20_block.patch queue-4.14/random-check-for-crng_init-0-in-add_device_randomness.patch queue-4.14/crypto-blake2s-include-linux-bug.h-instead-of-asm-bug.h.patch queue-4.14/random-group-entropy-collection-functions.patch queue-4.14/random-remove-useless-header-comment.patch queue-4.14/random-remove-outdated-int_max-6-check-in-urandom_read.patch queue-4.14/random-do-not-pretend-to-handle-premature-next-security-model.patch queue-4.14/random-avoid-arch_get_random_seed_long-when-collecting-irq-randomness.patch queue-4.14/random-reseed-more-often-immediately-after-booting.patch queue-4.14/random-ensure-early-rdseed-goes-through-mixer-on-init.patch queue-4.14/crypto-blake2s-adjust-include-guard-naming.patch queue-4.14/random-use-hash-function-for-crng_slow_load.patch