[PATCH 3/5] twofish: add bulk CTR32LE mode for GCM-SIV
Jussi Kivilinna
jussi.kivilinna at iki.fi
Thu Oct 22 19:38:42 CEST 2026
* cipher/twofish.c (_gcry_twofish_ctr32le_enc): New.
(twofish_setkey): Setup 'ctr32le_enc' bulk function.
--
Benchmark on AMD Ryzen 9 9950X3D (zen5):
Before:
TWOFISH | nanosecs/byte mebibytes/sec cycles/byte auto Mhz
GCM-SIV enc | 2.37 ns/B 401.7 MiB/s 13.10 c/B 5520
GCM-SIV dec | 2.36 ns/B 404.4 MiB/s 13.03 c/B 5526±1
After:
TWOFISH | nanosecs/byte mebibytes/sec cycles/byte auto Mhz
GCM-SIV enc | 1.54 ns/B 618.4 MiB/s 8.51 c/B 5521
GCM-SIV dec | 1.54 ns/B 617.5 MiB/s 8.53 c/B 5526
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
cipher/twofish.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/cipher/twofish.c b/cipher/twofish.c
index 4341a7fb..61a5f787 100644
--- a/cipher/twofish.c
+++ b/cipher/twofish.c
@@ -104,6 +104,9 @@ static size_t _gcry_twofish_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
static void _gcry_twofish_xts_crypt (void *context, unsigned char *tweak,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks, int encrypt);
+static void _gcry_twofish_ctr32le_enc (void *context, unsigned char *ctr,
+ void *outbuf_arg, const void *inbuf_arg,
+ size_t nblocks);
static void _gcry_twofish_ecb_crypt (void *context, void *outbuf_arg,
const void *inbuf_arg, size_t nblocks,
int encrypt);
@@ -778,6 +781,7 @@ twofish_setkey (void *context, const byte *key, unsigned int keylen,
bulk_ops->ocb_crypt = _gcry_twofish_ocb_crypt;
bulk_ops->ocb_auth = _gcry_twofish_ocb_auth;
bulk_ops->xts_crypt = _gcry_twofish_xts_crypt;
+ bulk_ops->ctr32le_enc = _gcry_twofish_ctr32le_enc;
bulk_ops->ecb_crypt = _gcry_twofish_ecb_crypt;
(void)hwfeatures;
@@ -1631,6 +1635,42 @@ _gcry_twofish_xts_crypt (void *context, unsigned char *tweak, void *outbuf_arg,
_gcry_burn_stack(burn_stack_depth);
}
+/* Bulk encryption of complete blocks in CTR32LE mode (for GCM-SIV). */
+static void
+_gcry_twofish_ctr32le_enc(void *context, unsigned char *ctr,
+ void *outbuf_arg, const void *inbuf_arg,
+ size_t nblocks)
+{
+ TWOFISH_context *ctx = context;
+ unsigned char *outbuf = outbuf_arg;
+ const unsigned char *inbuf = inbuf_arg;
+ int burn_stack_depth = 0;
+
+ /* Process remaining blocks. */
+ if (nblocks)
+ {
+ unsigned char tmpbuf[16 * 16];
+ unsigned int tmp_used = 16;
+ size_t tmpbufsize = 15 * 16;
+ size_t nburn;
+
+#ifdef USE_AVX2
+ if (ctx->use_avx2)
+ tmpbufsize = 16 * 16;
+#endif
+
+ nburn = bulk_ctr32le_enc_128 (ctx, twofish_encrypt_blk1_16, outbuf, inbuf,
+ nblocks, ctr, tmpbuf, tmpbufsize / 16,
+ &tmp_used);
+ burn_stack_depth = nburn > burn_stack_depth ? nburn : burn_stack_depth;
+
+ wipememory (tmpbuf, tmp_used);
+ }
+
+ if (burn_stack_depth)
+ _gcry_burn_stack (burn_stack_depth);
+}
+
/* Bulk encryption/decryption in ECB mode. */
static void
--
2.53.0
More information about the Gcrypt-devel
mailing list