From 56c4ea978af3991a404c72d4358d40483922cd09 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 24 Sep 2018 21:25:13 +0200 Subject: hchacha20: keep in native endian in words --- src/crypto/include/zinc/chacha20.h | 10 ++++---- src/crypto/zinc/chacha20/chacha20-arm-glue.h | 8 +++--- src/crypto/zinc/chacha20/chacha20-arm.S | 4 +-- src/crypto/zinc/chacha20/chacha20-mips-glue.h | 7 ++++-- src/crypto/zinc/chacha20/chacha20-x86_64-glue.h | 8 +++--- src/crypto/zinc/chacha20/chacha20.c | 33 +++++++++++-------------- src/crypto/zinc/chacha20poly1305.c | 10 +++++--- src/crypto/zinc/selftest/chacha20.h | 8 +++--- 8 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/crypto/include/zinc/chacha20.h b/src/crypto/include/zinc/chacha20.h index 276bdba..34d577d 100644 --- a/src/crypto/include/zinc/chacha20.h +++ b/src/crypto/include/zinc/chacha20.h @@ -14,14 +14,14 @@ enum { CHACHA20_IV_SIZE = 16, CHACHA20_KEY_SIZE = 32, + CHACHA20_KEY_WORDS = CHACHA20_KEY_SIZE / sizeof(u32), CHACHA20_BLOCK_SIZE = 64, CHACHA20_BLOCK_WORDS = CHACHA20_BLOCK_SIZE / sizeof(u32), HCHACHA20_KEY_SIZE = 32, HCHACHA20_NONCE_SIZE = 16 }; -enum { - /* expand 32-byte k */ +enum { /* expand 32-byte k */ CHACHA20_CONSTANT_EXPA = 0x61707865U, CHACHA20_CONSTANT_ND_3 = 0x3320646eU, CHACHA20_CONSTANT_2_BY = 0x79622d32U, @@ -50,15 +50,15 @@ static inline void chacha20_init(struct chacha20_ctx *state, state->key[5] = get_unaligned_le32(key + 20); state->key[6] = get_unaligned_le32(key + 24); state->key[7] = get_unaligned_le32(key + 28); - state->counter[0] = state->counter[1] = 0; + state->counter[0] = 0; + state->counter[1] = 0; state->counter[2] = nonce & U32_MAX; state->counter[3] = nonce >> 32; } void chacha20(struct chacha20_ctx *state, u8 *dst, const u8 *src, u32 len, simd_context_t *simd_context); -/* Derived key should be 32-bit aligned */ -void hchacha20(u8 derived_key[CHACHA20_KEY_SIZE], +void hchacha20(u32 derived_key[CHACHA20_KEY_WORDS], const u8 nonce[HCHACHA20_NONCE_SIZE], const u8 key[HCHACHA20_KEY_SIZE], simd_context_t *simd_context); diff --git a/src/crypto/zinc/chacha20/chacha20-arm-glue.h b/src/crypto/zinc/chacha20/chacha20-arm-glue.h index 1f1add0..86cce85 100644 --- a/src/crypto/zinc/chacha20/chacha20-arm-glue.h +++ b/src/crypto/zinc/chacha20/chacha20-arm-glue.h @@ -57,8 +57,10 @@ static inline bool chacha20_arch(struct chacha20_ctx *state, u8 *dst, return true; } -static inline bool hchacha20_arch(u8 *derived_key, const u8 *nonce, - const u8 *key, simd_context_t *simd_context) +static inline bool hchacha20_arch(u32 derived_key[CHACHA20_KEY_WORDS], + const u8 nonce[HCHACHA20_NONCE_SIZE], + const u8 key[HCHACHA20_KEY_SIZE], + simd_context_t *simd_context) { #if defined(CONFIG_ARM) u32 x[] = { CHACHA20_CONSTANT_EXPA, @@ -78,7 +80,7 @@ static inline bool hchacha20_arch(u8 *derived_key, const u8 *nonce, get_unaligned_le32(nonce + 8), get_unaligned_le32(nonce + 12) }; - hchacha20_arm(x, (u32 *)derived_key); + hchacha20_arm(x, derived_key); return true; #else return false; diff --git a/src/crypto/zinc/chacha20/chacha20-arm.S b/src/crypto/zinc/chacha20/chacha20-arm.S index 7fbb631..5abedaf 100644 --- a/src/crypto/zinc/chacha20/chacha20-arm.S +++ b/src/crypto/zinc/chacha20/chacha20-arm.S @@ -457,9 +457,7 @@ ENTRY(hchacha20_arm) ror X14, X14, #drot ror X15, X15, #drot - // Store (x0-x3,x12-x15) to 'out' after byte swapping - _le32_bswap_4x X0, X1, X2, X3, X4, X5, X6 - _le32_bswap_4x X12, X13, X14, X15, X4, X5, X6 + // Store (x0-x3,x12-x15) to 'out' stm r4, {X0,X1,X2,X3,X12,X13,X14,X15} pop {r4-r11,pc} diff --git a/src/crypto/zinc/chacha20/chacha20-mips-glue.h b/src/crypto/zinc/chacha20/chacha20-mips-glue.h index 929ca12..6e70dd6 100644 --- a/src/crypto/zinc/chacha20/chacha20-mips-glue.h +++ b/src/crypto/zinc/chacha20/chacha20-mips-glue.h @@ -17,8 +17,11 @@ static inline bool chacha20_arch(struct chacha20_ctx *state, u8 *dst, return true; } -static inline bool hchacha20_arch(u8 *derived_key, const u8 *nonce, - const u8 *key, simd_context_t *simd_context) + +static inline bool hchacha20_arch(u32 derived_key[CHACHA20_KEY_WORDS], + const u8 nonce[HCHACHA20_NONCE_SIZE], + const u8 key[HCHACHA20_KEY_SIZE], + simd_context_t *simd_context) { return false; } diff --git a/src/crypto/zinc/chacha20/chacha20-x86_64-glue.h b/src/crypto/zinc/chacha20/chacha20-x86_64-glue.h index 77dacf6..1b7fc05 100644 --- a/src/crypto/zinc/chacha20/chacha20-x86_64-glue.h +++ b/src/crypto/zinc/chacha20/chacha20-x86_64-glue.h @@ -9,7 +9,7 @@ #include #ifdef CONFIG_AS_SSSE3 -asmlinkage void hchacha20_ssse3(u8 *derived_key, const u8 *nonce, +asmlinkage void hchacha20_ssse3(u32 *derived_key, const u8 *nonce, const u8 *key); asmlinkage void chacha20_ssse3(u8 *out, const u8 *in, const size_t len, const u32 key[8], const u32 counter[4]); @@ -92,8 +92,10 @@ success: return true; } -static inline bool hchacha20_arch(u8 *derived_key, const u8 *nonce, - const u8 *key, simd_context_t *simd_context) +static inline bool hchacha20_arch(u32 derived_key[CHACHA20_KEY_WORDS], + const u8 nonce[HCHACHA20_NONCE_SIZE], + const u8 key[HCHACHA20_KEY_SIZE], + simd_context_t *simd_context) { #if defined(CONFIG_AS_SSSE3) if (chacha20_use_ssse3 && simd_use(simd_context)) { diff --git a/src/crypto/zinc/chacha20/chacha20.c b/src/crypto/zinc/chacha20/chacha20.c index ca50d0e..dc9770b 100644 --- a/src/crypto/zinc/chacha20/chacha20.c +++ b/src/crypto/zinc/chacha20/chacha20.c @@ -30,8 +30,10 @@ static inline bool chacha20_arch(struct chacha20_ctx *state, u8 *out, { return false; } -static inline bool hchacha20_arch(u8 *derived_key, const u8 *nonce, - const u8 *key, simd_context_t *simd_context) +static inline bool hchacha20_arch(u32 derived_key[CHACHA20_KEY_WORDS], + const u8 nonce[HCHACHA20_NONCE_SIZE], + const u8 key[HCHACHA20_KEY_SIZE], + simd_context_t *simd_context) { return false; } @@ -118,43 +120,36 @@ void chacha20(struct chacha20_ctx *state, u8 *dst, const u8 *src, u32 len, } EXPORT_SYMBOL(chacha20); -static void hchacha20_generic(u8 derived_key[CHACHA20_KEY_SIZE], +static void hchacha20_generic(u32 derived_key[CHACHA20_KEY_WORDS], const u8 nonce[HCHACHA20_NONCE_SIZE], const u8 key[HCHACHA20_KEY_SIZE]) { - __le32 *out = (__force __le32 *)derived_key; u32 x[] = { CHACHA20_CONSTANT_EXPA, CHACHA20_CONSTANT_ND_3, CHACHA20_CONSTANT_2_BY, CHACHA20_CONSTANT_TE_K, - get_unaligned_le32(key + 0), - get_unaligned_le32(key + 4), - get_unaligned_le32(key + 8), + get_unaligned_le32(key + 0), + get_unaligned_le32(key + 4), + get_unaligned_le32(key + 8), get_unaligned_le32(key + 12), get_unaligned_le32(key + 16), get_unaligned_le32(key + 20), get_unaligned_le32(key + 24), get_unaligned_le32(key + 28), - get_unaligned_le32(nonce + 0), - get_unaligned_le32(nonce + 4), - get_unaligned_le32(nonce + 8), + get_unaligned_le32(nonce + 0), + get_unaligned_le32(nonce + 4), + get_unaligned_le32(nonce + 8), get_unaligned_le32(nonce + 12) }; TWENTY_ROUNDS(x); - out[0] = cpu_to_le32(x[0]); - out[1] = cpu_to_le32(x[1]); - out[2] = cpu_to_le32(x[2]); - out[3] = cpu_to_le32(x[3]); - out[4] = cpu_to_le32(x[12]); - out[5] = cpu_to_le32(x[13]); - out[6] = cpu_to_le32(x[14]); - out[7] = cpu_to_le32(x[15]); + memcpy(derived_key + 0, x + 0, sizeof(u32) * 4); + memcpy(derived_key + 4, x + 12, sizeof(u32) * 4); } /* Derived key should be 32-bit aligned */ -void hchacha20(u8 derived_key[CHACHA20_KEY_SIZE], +void hchacha20(u32 derived_key[CHACHA20_KEY_WORDS], const u8 nonce[HCHACHA20_NONCE_SIZE], const u8 key[HCHACHA20_KEY_SIZE], simd_context_t *simd_context) { diff --git a/src/crypto/zinc/chacha20poly1305.c b/src/crypto/zinc/chacha20poly1305.c index 2003cb1..f2d82a1 100644 --- a/src/crypto/zinc/chacha20poly1305.c +++ b/src/crypto/zinc/chacha20poly1305.c @@ -305,13 +305,14 @@ void xchacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len, const u8 key[CHACHA20POLY1305_KEYLEN]) { simd_context_t simd_context; - u8 derived_key[CHACHA20POLY1305_KEYLEN] __aligned(16); + u32 derived_key[CHACHA20_KEY_WORDS] __aligned(16); simd_get(&simd_context); hchacha20(derived_key, nonce, key, &simd_context); + cpu_to_le32_array(derived_key, ARRAY_SIZE(derived_key)); __chacha20poly1305_encrypt(dst, src, src_len, ad, ad_len, get_unaligned_le64(nonce + 16), - derived_key, &simd_context); + (u8 *)derived_key, &simd_context); memzero_explicit(derived_key, CHACHA20POLY1305_KEYLEN); simd_put(&simd_context); } @@ -324,13 +325,14 @@ bool xchacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, { bool ret; simd_context_t simd_context; - u8 derived_key[CHACHA20POLY1305_KEYLEN] __aligned(16); + u32 derived_key[CHACHA20_KEY_WORDS] __aligned(16); simd_get(&simd_context); hchacha20(derived_key, nonce, key, &simd_context); + cpu_to_le32_array(derived_key, ARRAY_SIZE(derived_key)); ret = __chacha20poly1305_decrypt(dst, src, src_len, ad, ad_len, get_unaligned_le64(nonce + 16), - derived_key, &simd_context); + (u8 *)derived_key, &simd_context); memzero_explicit(derived_key, CHACHA20POLY1305_KEYLEN); simd_put(&simd_context); return ret; diff --git a/src/crypto/zinc/selftest/chacha20.h b/src/crypto/zinc/selftest/chacha20.h index b20fd31..fefcb75 100644 --- a/src/crypto/zinc/selftest/chacha20.h +++ b/src/crypto/zinc/selftest/chacha20.h @@ -2518,6 +2518,7 @@ static bool __init chacha20_selftest(void) { enum { MAXIMUM_TEST_BUFFER_LEN = 1UL << 10 }; size_t i, j; + u32 derived_key[CHACHA20_KEY_WORDS]; u8 *offset_input = NULL, *computed_output = NULL; u8 offset_key[CHACHA20_KEY_SIZE + 1] __aligned(__alignof__(unsigned long)); @@ -2609,10 +2610,11 @@ next_test: } } for (i = 0; i < ARRAY_SIZE(hchacha20_testvecs); ++i) { - memset(computed_output, 0, MAXIMUM_TEST_BUFFER_LEN + 1); - hchacha20(computed_output, hchacha20_testvecs[i].nonce, + memset(&derived_key, 0, sizeof(derived_key)); + hchacha20(derived_key, hchacha20_testvecs[i].nonce, hchacha20_testvecs[i].key, &simd_context); - if (memcmp(computed_output, hchacha20_testvecs[i].output, + cpu_to_le32_array(derived_key, ARRAY_SIZE(derived_key)); + if (memcmp(derived_key, hchacha20_testvecs[i].output, CHACHA20_KEY_SIZE)) { pr_info("hchacha20 self-test %zu: FAIL\n", i + 1); success = false; -- cgit v1.2.3-59-g8ed1b