[PATCH] cipher-gcm-ppc: add big-endian support

Jussi Kivilinna jussi.kivilinna at iki.fi
Sat Mar 27 11:40:33 CET 2021


* 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 at iki.fi>
---
 cipher/cipher-gcm-ppc.c  | 45 +++++++++++++++++++++++-----------------
 cipher/cipher-gcm.c      |  8 +++----
 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 */
-- 
2.27.0




More information about the Gcrypt-devel mailing list