summaryrefslogtreecommitdiff
path: root/cipher/camellia-glue.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2013-05-23 14:15:46 +0300
committerWerner Koch <wk@gnupg.org>2013-05-23 17:34:23 +0200
commitb60f06f70227c1e69e1010da8b47ea51ade48145 (patch)
treec59a9a6977c260a658bd9eb53a512eb07084027a /cipher/camellia-glue.c
parent319ee14f2aab8db56a830fd7ac8926f91b4f738a (diff)
downloadlibgcrypt-b60f06f70227c1e69e1010da8b47ea51ade48145.tar.gz
camellia: add parallel processing for CFB decryption
* cipher/camellia-aesni-avx-amd64.S (_gcry_camellia_aesni_avx_cfb_dec): New function. * cipher/camellia-glue.c (_gcry_camellia_aesni_avx_cfb_dec): New prototype. (_gcry_camellia_cfb_dec): New function. (selftest_cfb_128): New function. (selftest): Call selftest_cfb_128. * cipher/cipher.c (gry_cipher_open): Add bulk CFB decryption function for Camellia. * src/cipher.h (_gcry_camellia_cfb_dec): New prototype. -- Patch makes Camellia-CFB decryption 4.7 times faster on Intel Sandy-Bridge. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/camellia-glue.c')
-rw-r--r--cipher/camellia-glue.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c
index 4c724a9b..f9bbb334 100644
--- a/cipher/camellia-glue.c
+++ b/cipher/camellia-glue.c
@@ -102,6 +102,11 @@ extern void _gcry_camellia_aesni_avx_cbc_dec(CAMELLIA_context *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv);
+
+extern void _gcry_camellia_aesni_avx_cfb_dec(CAMELLIA_context *ctx,
+ unsigned char *out,
+ const unsigned char *in,
+ unsigned char *iv);
#endif
static const char *selftest(void);
@@ -308,6 +313,58 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv,
_gcry_burn_stack(burn_stack_depth);
}
+/* Bulk decryption of complete blocks in CFB mode. This function is only
+ intended for the bulk encryption feature of cipher.c. */
+void
+_gcry_camellia_cfb_dec(void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks)
+{
+ CAMELLIA_context *ctx = context;
+ unsigned char *outbuf = outbuf_arg;
+ const unsigned char *inbuf = inbuf_arg;
+ int burn_stack_depth = CAMELLIA_decrypt_stack_burn_size;
+
+#ifdef USE_AESNI_AVX
+ if (ctx->use_aesni_avx)
+ {
+ int did_use_aesni_avx = 0;
+
+ /* Process data in 16 block chunks. */
+ while (nblocks >= 16)
+ {
+ _gcry_camellia_aesni_avx_cfb_dec(ctx, outbuf, inbuf, iv);
+
+ nblocks -= 16;
+ outbuf += 16 * CAMELLIA_BLOCK_SIZE;
+ inbuf += 16 * CAMELLIA_BLOCK_SIZE;
+ did_use_aesni_avx = 1;
+ }
+
+ if (did_use_aesni_avx)
+ {
+ /* clear AVX registers */
+ asm volatile ("vzeroall;\n":::);
+
+ if (burn_stack_depth < 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *))
+ burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *);
+ }
+
+ /* Use generic code to handle smaller chunks... */
+ }
+#endif
+
+ for ( ;nblocks; nblocks-- )
+ {
+ Camellia_EncryptBlock(ctx->keybitlength, iv, ctx->keytable, iv);
+ buf_xor_n_copy(outbuf, iv, inbuf, CAMELLIA_BLOCK_SIZE);
+ outbuf += CAMELLIA_BLOCK_SIZE;
+ inbuf += CAMELLIA_BLOCK_SIZE;
+ }
+
+ _gcry_burn_stack(burn_stack_depth);
+}
+
/* Run the self-tests for CAMELLIA-CTR-128, tests IV increment of bulk CTR
encryption. Returns NULL on success. */
static const char*
@@ -336,6 +393,20 @@ selftest_cbc_128 (void)
context_size);
}
+/* Run the self-tests for CAMELLIA-CFB-128, tests bulk CFB decryption.
+ Returns NULL on success. */
+static const char*
+selftest_cfb_128 (void)
+{
+ const int nblocks = 16+2;
+ const int blocksize = CAMELLIA_BLOCK_SIZE;
+ const int context_size = sizeof(CAMELLIA_context);
+
+ return _gcry_selftest_helper_cfb_128("CAMELLIA", &camellia_setkey,
+ &camellia_encrypt, &_gcry_camellia_cfb_dec, nblocks, blocksize,
+ context_size);
+}
+
static const char *
selftest(void)
{
@@ -411,6 +482,9 @@ selftest(void)
if ( (r = selftest_cbc_128 ()) )
return r;
+ if ( (r = selftest_cfb_128 ()) )
+ return r;
+
return NULL;
}