summaryrefslogtreecommitdiff
path: root/cipher/cipher-gcm.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2019-01-02 21:25:44 +0200
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2019-01-02 21:25:44 +0200
commit3ee6588de8311b461ef8707c70ff86d2b252966d (patch)
tree8d7c30e8145e9035d4c2fd5a3992187ff40a018f /cipher/cipher-gcm.c
parent4871f11745f33c5c5051bfe6f325ac1c10764b04 (diff)
downloadlibgcrypt-3ee6588de8311b461ef8707c70ff86d2b252966d.tar.gz
Process CCM/EAX/GCM/Poly1305 AEAD cipher modes input in 24 KiB chucks
* cipher/cipher-ccm.c (_gcry_cipher_ccm_encrypt) (_gcry_cipher_ccm_decrypt): Process data in 24 KiB chunks. * cipher/cipher-eax.c (_gcry_cipher_eax_encrypt) (_gcry_cipher_eax_decrypt): Ditto. * cipher/cipher-gcm.c (_gcry_cipher_gcm_encrypt) (_gcry_cipher_gcm_decrypt): Ditto. * cipher/cipher-poly1305.c (_gcry_cipher_poly1305_encrypt) (_gcry_cipher_poly1305_decrypt): Ditto. -- Patch changes AEAD modes to process input in 24 KiB chuncks to improve cache locality when processing large buffers. Huge buffer test in tests/benchmark show 0.7% improvement for AES-CCM and AES-EAX, 6% for AES-GCM and 4% for Chacha20-Poly1305 on Intel Core i7-4790K. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/cipher-gcm.c')
-rw-r--r--cipher/cipher-gcm.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c
index 32ec9fa0..f9ddbc56 100644
--- a/cipher/cipher-gcm.c
+++ b/cipher/cipher-gcm.c
@@ -666,11 +666,26 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c,
return GPG_ERR_INV_LENGTH;
}
- err = gcm_ctr_encrypt(c, outbuf, outbuflen, inbuf, inbuflen);
- if (err != 0)
- return err;
+ while (inbuflen)
+ {
+ size_t currlen = inbuflen;
- do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, outbuf, inbuflen, 0);
+ /* Since checksumming is done after encryption, process input in 24KiB
+ * chunks to keep data loaded in L1 cache for checksumming. */
+ if (currlen > 24 * 1024)
+ currlen = 24 * 1024;
+
+ err = gcm_ctr_encrypt(c, outbuf, outbuflen, inbuf, currlen);
+ if (err != 0)
+ return err;
+
+ do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, outbuf, currlen, 0);
+
+ outbuf += currlen;
+ inbuf += currlen;
+ outbuflen -= currlen;
+ inbuflen -= currlen;
+ }
return 0;
}
@@ -682,6 +697,7 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c,
const byte *inbuf, size_t inbuflen)
{
static const unsigned char zerobuf[MAX_BLOCKSIZE];
+ gcry_err_code_t err;
if (c->spec->blocksize != GCRY_GCM_BLOCK_LEN)
return GPG_ERR_CIPHER_ALGO;
@@ -711,9 +727,28 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c,
return GPG_ERR_INV_LENGTH;
}
- do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, inbuf, inbuflen, 0);
+ while (inbuflen)
+ {
+ size_t currlen = inbuflen;
+
+ /* Since checksumming is done before decryption, process input in
+ * 24KiB chunks to keep data loaded in L1 cache for decryption. */
+ if (currlen > 24 * 1024)
+ currlen = 24 * 1024;
- return gcm_ctr_encrypt(c, outbuf, outbuflen, inbuf, inbuflen);
+ do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, inbuf, currlen, 0);
+
+ err = gcm_ctr_encrypt(c, outbuf, outbuflen, inbuf, currlen);
+ if (err)
+ return err;
+
+ outbuf += currlen;
+ inbuf += currlen;
+ outbuflen -= currlen;
+ inbuflen -= currlen;
+ }
+
+ return 0;
}