[PATCH] cipher-gcm-riscv-zbb-zbc: add POLYVAL acceleration

Jussi Kivilinna jussi.kivilinna at iki.fi
Tue Aug 19 07:59:36 CEST 2025


* cipher/cipher-gcm-riscv-zbb-zbc.c (_gcry_ghash_riscv_zbb_zbc): Rename to ...
(ghash_polyval_riscv_zbb_zbc): ... this; Add 'is_polyval' argument.
(_gcry_ghash_riscv_zbb_zbc): New.
(ghash_polyval_riscv_zbb_zbc): New.
* cipher/cipher-gcm.c [GCM_USE_RISCV_ZBB_ZBC]
(ghash_polyval_riscv_zbb_zbc): New.
(setupM) [GCM_USE_RISCV_ZBB_ZBC]: Add setup for 'c->u_mode.gcm.polyval_fn'.
--

Benchmark on SpacemiT K1:

 Before:
 AES            |  nanosecs/byte   mebibytes/sec   cycles/byte  auto Mhz
   GCM-SIV auth |      3.65 ns/B     261.4 MiB/s      5.84 c/B      1600

 After:
 AES            |  nanosecs/byte   mebibytes/sec   cycles/byte  auto Mhz
   GCM-SIV auth |     0.861 ns/B      1108 MiB/s      1.38 c/B      1600

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 cipher/cipher-gcm-riscv-zbb-zbc.c | 24 +++++++++++++++++++-----
 cipher/cipher-gcm.c               |  5 +++++
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/cipher/cipher-gcm-riscv-zbb-zbc.c b/cipher/cipher-gcm-riscv-zbb-zbc.c
index 61539274..e32bfafe 100644
--- a/cipher/cipher-gcm-riscv-zbb-zbc.c
+++ b/cipher/cipher-gcm-riscv-zbb-zbc.c
@@ -190,9 +190,9 @@ reduction(u64x2x2 r0r1)
   return veor_u64x2(r0, r1);
 }
 
-ASM_FUNC_ATTR_NOINLINE unsigned int
-_gcry_ghash_riscv_zbb_zbc(gcry_cipher_hd_t c, byte *result, const byte *buf,
-			  size_t nblocks)
+static ASM_FUNC_ATTR_INLINE unsigned int
+ghash_polyval_riscv_zbb_zbc(gcry_cipher_hd_t c, byte *result, const byte *buf,
+			    size_t nblocks, int is_polyval)
 {
   u64x2 rhash;
   u64x2 rh1;
@@ -211,7 +211,7 @@ _gcry_ghash_riscv_zbb_zbc(gcry_cipher_hd_t c, byte *result, const byte *buf,
   buf += 16;
   nblocks--;
 
-  rbuf = byteswap_u64x2(rbuf);
+  rbuf = is_polyval ? rbuf : byteswap_u64x2(rbuf);
 
   rhash = veor_u64x2(rhash, rbuf);
 
@@ -223,7 +223,7 @@ _gcry_ghash_riscv_zbb_zbc(gcry_cipher_hd_t c, byte *result, const byte *buf,
 
       rr0rr1 = pmul_128x128(rhash, rh1);
 
-      rbuf = byteswap_u64x2(rbuf);
+      rbuf = is_polyval ? rbuf : byteswap_u64x2(rbuf);
 
       rhash = reduction(rr0rr1);
 
@@ -240,6 +240,20 @@ _gcry_ghash_riscv_zbb_zbc(gcry_cipher_hd_t c, byte *result, const byte *buf,
   return 0;
 }
 
+ASM_FUNC_ATTR_NOINLINE unsigned int
+_gcry_ghash_riscv_zbb_zbc(gcry_cipher_hd_t c, byte *result, const byte *buf,
+			  size_t nblocks)
+{
+  return ghash_polyval_riscv_zbb_zbc(c, result, buf, nblocks, 0);
+}
+
+ASM_FUNC_ATTR_NOINLINE unsigned int
+_gcry_polyval_riscv_zbb_zbc(gcry_cipher_hd_t c, byte *result, const byte *buf,
+			    size_t nblocks)
+{
+  return ghash_polyval_riscv_zbb_zbc(c, result, buf, nblocks, 1);
+}
+
 static ASM_FUNC_ATTR_INLINE void
 gcm_lsh_1(void *r_out, u64x2 i)
 {
diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c
index 4c9f9ff5..a9c48551 100644
--- a/cipher/cipher-gcm.c
+++ b/cipher/cipher-gcm.c
@@ -107,6 +107,10 @@ extern void _gcry_ghash_setup_riscv_zbb_zbc(gcry_cipher_hd_t c);
 
 extern unsigned int _gcry_ghash_riscv_zbb_zbc(gcry_cipher_hd_t c, byte *result,
 					      const byte *buf, size_t nblocks);
+
+extern unsigned int _gcry_polyval_riscv_zbb_zbc(gcry_cipher_hd_t c,
+						byte *result, const byte *buf,
+						size_t nblocks);
 #endif /* GCM_USE_RISCV_ZBB_ZBC */
 
 #ifdef GCM_USE_RISCV_ZVKG
@@ -655,6 +659,7 @@ setupM (gcry_cipher_hd_t c)
 	   && (features & HWF_RISCV_ZBC))
     {
       c->u_mode.gcm.ghash_fn = _gcry_ghash_riscv_zbb_zbc;
+      c->u_mode.gcm.polyval_fn = _gcry_polyval_riscv_zbb_zbc;
       _gcry_ghash_setup_riscv_zbb_zbc (c);
     }
 #endif
-- 
2.48.1




More information about the Gcrypt-devel mailing list