crypto: chacha20 - Use unaligned access macros when loading key and IV
authorEric Biggers <ebiggers@google.com>
Wed, 22 Nov 2017 19:51:36 +0000 (11:51 -0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Wed, 29 Nov 2017 06:33:32 +0000 (17:33 +1100)
The generic ChaCha20 implementation has a cra_alignmask of 3, which
ensures that the key passed into crypto_chacha20_setkey() and the IV
passed into crypto_chacha20_init() are 4-byte aligned.  However, these
functions are also called from the ARM and ARM64 implementations of
ChaCha20, which intentionally do not have a cra_alignmask set.  This is
broken because 32-bit words are being loaded from potentially-unaligned
buffers without the unaligned access macros.

Fix it by using the unaligned access macros when loading the key and IV.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/chacha20_generic.c

index ec84e7837aac023efc2016a1c1a76aabdc2e2139..b5a10ebf1b8281542b92b26ebb1008470ab55ba2 100644 (file)
@@ -9,16 +9,12 @@
  * (at your option) any later version.
  */
 
+#include <asm/unaligned.h>
 #include <crypto/algapi.h>
 #include <crypto/chacha20.h>
 #include <crypto/internal/skcipher.h>
 #include <linux/module.h>
 
-static inline u32 le32_to_cpuvp(const void *p)
-{
-       return le32_to_cpup(p);
-}
-
 static void chacha20_docrypt(u32 *state, u8 *dst, const u8 *src,
                             unsigned int bytes)
 {
@@ -53,10 +49,10 @@ void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv)
        state[9]  = ctx->key[5];
        state[10] = ctx->key[6];
        state[11] = ctx->key[7];
-       state[12] = le32_to_cpuvp(iv +  0);
-       state[13] = le32_to_cpuvp(iv +  4);
-       state[14] = le32_to_cpuvp(iv +  8);
-       state[15] = le32_to_cpuvp(iv + 12);
+       state[12] = get_unaligned_le32(iv +  0);
+       state[13] = get_unaligned_le32(iv +  4);
+       state[14] = get_unaligned_le32(iv +  8);
+       state[15] = get_unaligned_le32(iv + 12);
 }
 EXPORT_SYMBOL_GPL(crypto_chacha20_init);
 
@@ -70,7 +66,7 @@ int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
                return -EINVAL;
 
        for (i = 0; i < ARRAY_SIZE(ctx->key); i++)
-               ctx->key[i] = le32_to_cpuvp(key + i * sizeof(u32));
+               ctx->key[i] = get_unaligned_le32(key + i * sizeof(u32));
 
        return 0;
 }