summaryrefslogtreecommitdiff
path: root/cipher/serpent.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2013-05-23 14:15:51 +0300
committerWerner Koch <wk@gnupg.org>2013-05-23 17:35:05 +0200
commit6deb0ccdf718a0670f80e6762a3842caf76437d6 (patch)
tree5bf7f4bb2de2049de8eb0a9d6ce6d2ce43f93a40 /cipher/serpent.c
parentb60f06f70227c1e69e1010da8b47ea51ade48145 (diff)
downloadlibgcrypt-6deb0ccdf718a0670f80e6762a3842caf76437d6.tar.gz
serpent: add parallel processing for CFB decryption
* cipher/cipher.c (gcry_cipher_open): Add bulf CFB decryption function for Serpent. * cipher/serpent-sse2-amd64.S (_gcry_serpent_sse2_cfb_dec): New function. * cipher/serpent.c (_gcry_serpent_sse2_cfb_dec): New prototype. (_gcry_serpent_cfb_dec) New function. (selftest_cfb_128) New function. (selftest) Call selftest_cfb_128. * src/cipher.h (_gcry_serpent_cfb_dec): New prototype. -- Patch makes Serpent-CFB decryption 4.0 times faster on Intel Sandy-Bridge and 2.7 times faster on AMD K10. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/serpent.c')
-rw-r--r--cipher/serpent.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/cipher/serpent.c b/cipher/serpent.c
index 7b82b48c..95ac7c15 100644
--- a/cipher/serpent.c
+++ b/cipher/serpent.c
@@ -74,6 +74,11 @@ extern void _gcry_serpent_sse2_cbc_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv);
+
+extern void _gcry_serpent_sse2_cfb_dec(serpent_context_t *ctx,
+ unsigned char *out,
+ const unsigned char *in,
+ unsigned char *iv);
#endif
/* A prototype. */
@@ -916,6 +921,71 @@ _gcry_serpent_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_serpent_cfb_dec(void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks)
+{
+ serpent_context_t *ctx = context;
+ unsigned char *outbuf = outbuf_arg;
+ const unsigned char *inbuf = inbuf_arg;
+ int burn_stack_depth = 2 * sizeof (serpent_block_t);
+
+#ifdef USE_SSE2
+ {
+ int did_use_sse2 = 0;
+
+ /* Process data in 8 block chunks. */
+ while (nblocks >= 8)
+ {
+ _gcry_serpent_sse2_cfb_dec(ctx, outbuf, inbuf, iv);
+
+ nblocks -= 8;
+ outbuf += 8 * sizeof(serpent_block_t);
+ inbuf += 8 * sizeof(serpent_block_t);
+ did_use_sse2 = 1;
+ }
+
+ if (did_use_sse2)
+ {
+ /* clear SSE2 registers used by serpent-sse2 */
+ asm volatile (
+ "pxor %%xmm0, %%xmm0;\n"
+ "pxor %%xmm1, %%xmm1;\n"
+ "pxor %%xmm2, %%xmm2;\n"
+ "pxor %%xmm3, %%xmm3;\n"
+ "pxor %%xmm4, %%xmm4;\n"
+ "pxor %%xmm5, %%xmm5;\n"
+ "pxor %%xmm6, %%xmm6;\n"
+ "pxor %%xmm7, %%xmm7;\n"
+ "pxor %%xmm10, %%xmm10;\n"
+ "pxor %%xmm11, %%xmm11;\n"
+ "pxor %%xmm12, %%xmm12;\n"
+ "pxor %%xmm13, %%xmm13;\n"
+ :::);
+
+ /* serpent-sse2 assembly code does not use stack */
+ if (nblocks == 0)
+ burn_stack_depth = 0;
+ }
+
+ /* Use generic code to handle smaller chunks... */
+ }
+#endif
+
+ for ( ;nblocks; nblocks-- )
+ {
+ serpent_encrypt_internal(ctx, iv, iv);
+ buf_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t));
+ outbuf += sizeof(serpent_block_t);
+ inbuf += sizeof(serpent_block_t);
+ }
+
+ _gcry_burn_stack(burn_stack_depth);
+}
+
/* Run the self-tests for SERPENT-CTR-128, tests IV increment of bulk CTR
@@ -948,6 +1018,21 @@ selftest_cbc_128 (void)
}
+/* Run the self-tests for SERPENT-CBC-128, tests bulk CBC decryption.
+ Returns NULL on success. */
+static const char*
+selftest_cfb_128 (void)
+{
+ const int nblocks = 8+2;
+ const int blocksize = sizeof(serpent_block_t);
+ const int context_size = sizeof(serpent_context_t);
+
+ return _gcry_selftest_helper_cfb_128("SERPENT", &serpent_setkey,
+ &serpent_encrypt, &_gcry_serpent_cfb_dec, nblocks, blocksize,
+ context_size);
+}
+
+
/* Serpent test. */
static const char *
@@ -1034,6 +1119,9 @@ serpent_test (void)
if ( (r = selftest_cbc_128 ()) )
return r;
+ if ( (r = selftest_cfb_128 ()) )
+ return r;
+
return NULL;
}