diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2021-03-27 12:27:27 +0200 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2021-04-01 13:40:33 +0300 |
commit | aaa30381eac3cdb49a21e279b2d89ef6e695a138 (patch) | |
tree | 02835b8781d608486656fba37e9ae31185f84f59 | |
parent | 1cf5a568f2b2f2c3d83c154cdcf5a40aa1f83c50 (diff) | |
download | libgcrypt-aaa30381eac3cdb49a21e279b2d89ef6e695a138.tar.gz |
cipher-gcm-ppc: add big-endian support
* cipher/cipher-gcm-ppc.c (ALIGNED_16): New.
(vec_store_he, vec_load_he): Remove WORDS_BIGENDIAN ifdef.
(vec_dup_byte_elem): New.
(_gcry_ghash_setup_ppc_vpmsum): Match function declaration with
prototype in cipher-gcm.c; Load C2 with VEC_LOAD_BE; Use
vec_dup_byte_elem; Align constants to 16 bytes.
(_gcry_ghash_ppc_vpmsum): Match function declaration with
prototype in cipher-gcm.c; Align constant to 16 bytes.
* cipher/cipher-gcm.c (ghash_ppc_vpmsum): Return value from
_gcry_ghash_ppc_vpmsum.
* cipher/cipher-internal.h (GCM_USE_PPC_VPMSUM): Remove requirement
for !WORDS_BIGENDIAN.
--
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
-rw-r--r-- | cipher/cipher-gcm-ppc.c | 45 | ||||
-rw-r--r-- | cipher/cipher-gcm.c | 8 | ||||
-rw-r--r-- | cipher/cipher-internal.h | 2 |
3 files changed, 31 insertions, 24 deletions
diff --git a/cipher/cipher-gcm-ppc.c b/cipher/cipher-gcm-ppc.c index 2f60c09d..4f75e95c 100644 --- a/cipher/cipher-gcm-ppc.c +++ b/cipher/cipher-gcm-ppc.c @@ -88,6 +88,8 @@ #define ASM_FUNC_ATTR NO_INSTRUMENT_FUNCTION #define ASM_FUNC_ATTR_INLINE ASM_FUNC_ATTR ALWAYS_INLINE +#define ALIGNED_16 __attribute__ ((aligned (16))) + typedef vector unsigned char vector16x_u8; typedef vector signed char vector16x_s8; typedef vector unsigned long long vector2x_u64; @@ -182,7 +184,6 @@ asm_ashl_128(block a, vector16x_u8 shift) static ASM_FUNC_ATTR_INLINE void vec_store_he(block vec, unsigned long offset, unsigned char *ptr) { -#ifndef WORDS_BIGENDIAN /* GCC vec_vsx_ld is generating two instructions on little-endian. Use * lxvd2x directly instead. */ #if __GNUC__ >= 4 @@ -197,9 +198,6 @@ vec_store_he(block vec, unsigned long offset, unsigned char *ptr) : : "wa" (vec), "r" (offset), "r" ((uintptr_t)ptr) : "memory", "r0"); -#else - vec_vsx_st ((vector16x_u8)vec, offset, ptr); -#endif } #define VEC_LOAD_BE(in_ptr, bswap_const) \ @@ -208,7 +206,6 @@ vec_store_he(block vec, unsigned long offset, unsigned char *ptr) static ASM_FUNC_ATTR_INLINE block vec_load_he(unsigned long offset, const unsigned char *ptr) { -#ifndef WORDS_BIGENDIAN block vec; /* GCC vec_vsx_ld is generating two instructions on little-endian. Use * lxvd2x directly instead. */ @@ -225,9 +222,6 @@ vec_load_he(unsigned long offset, const unsigned char *ptr) : "r" (offset), "r" ((uintptr_t)ptr) : "memory", "r0"); return vec; -#else - return vec_vsx_ld (offset, ptr); -#endif } static ASM_FUNC_ATTR_INLINE block @@ -243,6 +237,15 @@ vec_be_swap(block vec, vector16x_u8 be_bswap_const) return vec; } +static ASM_FUNC_ATTR_INLINE block +vec_dup_byte_elem(block vec, int idx) +{ +#ifndef WORDS_BIGENDIAN + return (block)vec_splat((vector16x_s8)vec, idx); +#else + return (block)vec_splat((vector16x_s8)vec, (15 - idx) & 15); +#endif +} /* Power ghash based on papers: "The Galois/Counter Mode of Operation (GCM)"; David A. McGrew, John Viega @@ -259,31 +262,33 @@ vec_be_swap(block vec, vector16x_u8 be_bswap_const) The ghash "key" is a salt. */ void ASM_FUNC_ATTR -_gcry_ghash_setup_ppc_vpmsum (uint64_t *gcm_table, void *gcm_key) +_gcry_ghash_setup_ppc_vpmsum (void *gcm_table_arg, void *gcm_key) { - static const vector16x_u8 bswap_const = + static const vector16x_u8 bswap_const ALIGNED_16 = { ~7, ~6, ~5, ~4, ~3, ~2, ~1, ~0, ~15, ~14, ~13, ~12, ~11, ~10, ~9, ~8 }; - static const vector16x_u8 c2 = - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0b11000010 }; - static const vector16x_u8 one = + static const byte c2[16] ALIGNED_16 = + { 0xc2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + static const vector16x_u8 one ALIGNED_16 = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + uint64_t *gcm_table = gcm_table_arg; block T0, T1, T2; block C2, H, H1, H1l, H1h, H2, H2l, H2h; block H3l, H3, H3h, H4l, H4, H4h, T3, T4; vector16x_s8 most_sig_of_H, t7, carry; H = VEC_LOAD_BE(gcm_key, bswap_const); - most_sig_of_H = vec_splat((vector16x_s8)H, 15); + C2 = VEC_LOAD_BE(c2, bswap_const); + most_sig_of_H = (vector16x_s8)vec_dup_byte_elem(H, 15); t7 = vec_splat_s8(7); carry = most_sig_of_H >> t7; - carry &= c2; /* only interested in certain carries. */ + carry &= (vector16x_s8)C2; /* only interested in certain carries. */ H1 = asm_ashl_128(H, one); H1 ^= (block)carry; /* complete the <<< 1 */ T1 = asm_swap_u64 (H1); H1l = asm_rot_block_right (T1); H1h = asm_rot_block_left (T1); - C2 = asm_rot_block_right ((block)c2); + C2 = asm_rot_block_right (C2); STORE_TABLE (gcm_table, 0, C2); STORE_TABLE (gcm_table, 1, H1l); @@ -367,11 +372,11 @@ _gcry_ghash_setup_ppc_vpmsum (uint64_t *gcm_table, void *gcm_key) STORE_TABLE (gcm_table, 12, H4h); } -void ASM_FUNC_ATTR -_gcry_ghash_ppc_vpmsum (byte *result, const void *const gcm_table, +unsigned int ASM_FUNC_ATTR +_gcry_ghash_ppc_vpmsum (byte *result, void *gcm_table, const byte *buf, const size_t nblocks) { - static const vector16x_u8 bswap_const = + static const vector16x_u8 bswap_const ALIGNED_16 = { ~7, ~6, ~5, ~4, ~3, ~2, ~1, ~0, ~15, ~14, ~13, ~12, ~11, ~10, ~9, ~8 }; block c2, H0l, H0m, H0h, H4l, H4m, H4h, H2m, H3l, H3m, H3h, Hl; block Hm, Hh, in, in0, in1, in2, in3, Hm_right, Hl_rotate, cur; @@ -539,6 +544,8 @@ _gcry_ghash_ppc_vpmsum (byte *result, const void *const gcm_table, } vec_store_he (vec_be_swap (cur, bswap_const), 0, result); + + return 0; } #endif /* GCM_USE_PPC_VPMSUM */ diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 598ea5fb..4ce85408 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -119,16 +119,16 @@ extern unsigned int _gcry_ghash_ppc_vpmsum (byte *result, void *gcm_table, static void ghash_setup_ppc_vpmsum (gcry_cipher_hd_t c) { - _gcry_ghash_setup_ppc_vpmsum(c->u_mode.gcm.gcm_table, c->u_mode.gcm.u_ghash_key.key); + _gcry_ghash_setup_ppc_vpmsum(c->u_mode.gcm.gcm_table, + c->u_mode.gcm.u_ghash_key.key); } static unsigned int ghash_ppc_vpmsum (gcry_cipher_hd_t c, byte *result, const byte *buf, size_t nblocks) { - _gcry_ghash_ppc_vpmsum(result, c->u_mode.gcm.gcm_table, buf, - nblocks); - return 0; + return _gcry_ghash_ppc_vpmsum(result, c->u_mode.gcm.gcm_table, buf, + nblocks); } #endif /* GCM_USE_PPC_VPMSUM */ diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 1d62b11e..0e4a90fc 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -107,7 +107,7 @@ #undef GCM_USE_PPC_VPMSUM #if defined(GCM_USE_TABLES) #if defined(ENABLE_PPC_CRYPTO_SUPPORT) && defined(__powerpc64__) && \ - !defined(WORDS_BIGENDIAN) && defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \ + defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \ defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) && __GNUC__ >= 4 # define GCM_USE_PPC_VPMSUM 1 # define NEED_16BYTE_ALIGNED_CONTEXT 1 /* this also aligns gcm_table */ |