summaryrefslogtreecommitdiff
path: root/cipher/camellia-glue.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2013-01-23 11:55:03 +0200
committerWerner Koch <wk@gnupg.org>2013-02-19 11:02:24 +0100
commit537f12ce072d568f9fa344c447d32b2e0efffbe8 (patch)
treebec3f13d3e200e70ac8594cc34927d95898c6a54 /cipher/camellia-glue.c
parent09ac5d87d11aa0b1fa0e0a4184ab03b3671a73e2 (diff)
downloadlibgcrypt-537f12ce072d568f9fa344c447d32b2e0efffbe8.tar.gz
Camellia, prepare glue code for AES-NI/AVX implementation
* cipher/camellia-glue.c (ATTR_ALIGNED_16): Add macro. (CAMELLIA_encrypt_stack_burn_size): Add macro. (camellia_encrypt): Use macro above for stack burn size. (CAMELLIA_decrypt_stack_burn_size): Add macro. (camellia_decrypt): Use macro above for stack burn size. (_gcry_camellia_ctr_enc): New function. (_gcry_camellia_cbc_dec): New function. (selftest_ctr_128): New function. (selftest): Call function above. * cipher/cipher.c (gcry_cipher_open) [USE_CAMELLIA]: Register bulk functions for CBC-decryption and CTR-mode. * src/cipher.h (_gcry_camellia_ctr_enc): New prototype. (_gcry_camellia_cbc_dec): New prototype. -- AES-NI/AVX implementation needs multi-block input, so prepare glue code for that by adding bulk-functions for CBC-decryption and CTR-mode. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Diffstat (limited to 'cipher/camellia-glue.c')
-rw-r--r--cipher/camellia-glue.c202
1 files changed, 190 insertions, 12 deletions
diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c
index c5019d02..686262aa 100644
--- a/cipher/camellia-glue.c
+++ b/cipher/camellia-glue.c
@@ -62,6 +62,14 @@
#include "g10lib.h"
#include "cipher.h"
#include "camellia.h"
+#include "bufhelp.h"
+
+/* Helper macro to force alignment to 16 bytes. */
+#ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
+# define ATTR_ALIGNED_16 __attribute__ ((aligned (16)))
+#else
+# define ATTR_ALIGNED_16
+#endif
typedef struct
{
@@ -110,12 +118,15 @@ camellia_encrypt(void *c, byte *outbuf, const byte *inbuf)
CAMELLIA_context *ctx=c;
Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
- _gcry_burn_stack
- (sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/)
- +4*sizeof(u32)
- +2*sizeof(u32*)+4*sizeof(u32)
- +2*2*sizeof(void*) /* Function calls. */
- );
+
+#define CAMELLIA_encrypt_stack_burn_size \
+ (sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/) \
+ +4*sizeof(u32) \
+ +2*sizeof(u32*)+4*sizeof(u32) \
+ +2*2*sizeof(void*) /* Function calls. */ \
+ )
+
+ _gcry_burn_stack(CAMELLIA_encrypt_stack_burn_size);
}
static void
@@ -124,12 +135,175 @@ camellia_decrypt(void *c, byte *outbuf, const byte *inbuf)
CAMELLIA_context *ctx=c;
Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
- _gcry_burn_stack
- (sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/)
- +4*sizeof(u32)
- +2*sizeof(u32*)+4*sizeof(u32)
- +2*2*sizeof(void*) /* Function calls. */
- );
+
+#define CAMELLIA_decrypt_stack_burn_size \
+ (sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/) \
+ +4*sizeof(u32) \
+ +2*sizeof(u32*)+4*sizeof(u32) \
+ +2*2*sizeof(void*) /* Function calls. */ \
+ )
+
+ _gcry_burn_stack(CAMELLIA_decrypt_stack_burn_size);
+}
+
+/* Bulk encryption of complete blocks in CTR mode. This function is only
+ intended for the bulk encryption feature of cipher.c. CTR is expected to be
+ of size CAMELLIA_BLOCK_SIZE. */
+void
+_gcry_camellia_ctr_enc(void *context, unsigned char *ctr,
+ 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;
+ unsigned char tmpbuf[CAMELLIA_BLOCK_SIZE];
+ int i;
+
+ for ( ;nblocks; nblocks-- )
+ {
+ /* Encrypt the counter. */
+ Camellia_EncryptBlock(ctx->keybitlength, ctr, ctx->keytable, tmpbuf);
+ /* XOR the input with the encrypted counter and store in output. */
+ buf_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE);
+ outbuf += CAMELLIA_BLOCK_SIZE;
+ inbuf += CAMELLIA_BLOCK_SIZE;
+ /* Increment the counter. */
+ for (i = CAMELLIA_BLOCK_SIZE; i > 0; i--)
+ {
+ ctr[i-1]++;
+ if (ctr[i-1])
+ break;
+ }
+ }
+
+ wipememory(tmpbuf, sizeof(tmpbuf));
+ _gcry_burn_stack(CAMELLIA_encrypt_stack_burn_size);
+}
+
+/* Bulk decryption of complete blocks in CBC mode. This function is only
+ intended for the bulk encryption feature of cipher.c. */
+void
+_gcry_camellia_cbc_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;
+ unsigned char savebuf[CAMELLIA_BLOCK_SIZE];
+
+ for ( ;nblocks; nblocks-- )
+ {
+ /* We need to save INBUF away because it may be identical to
+ OUTBUF. */
+ memcpy(savebuf, inbuf, CAMELLIA_BLOCK_SIZE);
+
+ Camellia_DecryptBlock(ctx->keybitlength, inbuf, ctx->keytable, outbuf);
+
+ buf_xor(outbuf, outbuf, iv, CAMELLIA_BLOCK_SIZE);
+ memcpy(iv, savebuf, CAMELLIA_BLOCK_SIZE);
+ inbuf += CAMELLIA_BLOCK_SIZE;
+ outbuf += CAMELLIA_BLOCK_SIZE;
+ }
+
+ wipememory(savebuf, sizeof(savebuf));
+ _gcry_burn_stack(CAMELLIA_decrypt_stack_burn_size);
+}
+
+/* Run the self-tests for CAMELLIA-CTR-128, tests IV increment of bulk CTR
+ encryption. Returns NULL on success. */
+static const char*
+selftest_ctr_128 (void)
+{
+ const int nblocks = 16+1;
+ CAMELLIA_context ctx ATTR_ALIGNED_16;
+ unsigned char plaintext[nblocks*16] ATTR_ALIGNED_16;
+ unsigned char ciphertext[nblocks*16] ATTR_ALIGNED_16;
+ unsigned char plaintext2[nblocks*16] ATTR_ALIGNED_16;
+ unsigned char iv[16] ATTR_ALIGNED_16;
+ unsigned char iv2[16] ATTR_ALIGNED_16;
+ int i, j, diff;
+
+ static const unsigned char key[16] ATTR_ALIGNED_16 = {
+ 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
+ 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21
+ };
+ static char error_str[128];
+
+ camellia_setkey (&ctx, key, sizeof (key));
+
+ /* Test single block code path */
+ memset(iv, 0xff, sizeof(iv));
+ for (i = 0; i < 16; i++)
+ plaintext[i] = i;
+
+ /* CTR manually. */
+ camellia_encrypt (&ctx, ciphertext, iv);
+ for (i = 0; i < 16; i++)
+ ciphertext[i] ^= plaintext[i];
+ for (i = 16; i > 0; i--)
+ {
+ iv[i-1]++;
+ if (iv[i-1])
+ break;
+ }
+
+ memset(iv2, 0xff, sizeof(iv2));
+ _gcry_camellia_ctr_enc (&ctx, iv2, plaintext2, ciphertext, 1);
+
+ if (memcmp(plaintext2, plaintext, 16))
+ return "CAMELLIA-128-CTR test failed (plaintext mismatch)";
+
+ if (memcmp(iv2, iv, 16))
+ return "CAMELLIA-128-CTR test failed (IV mismatch)";
+
+ /* Test parallelized code paths */
+ for (diff = 0; diff < nblocks; diff++) {
+ memset(iv, 0xff, sizeof(iv));
+ iv[15] -= diff;
+
+ for (i = 0; i < sizeof(plaintext); i++)
+ plaintext[i] = i;
+
+ /* Create CTR ciphertext manually. */
+ for (i = 0; i < sizeof(plaintext); i+=16)
+ {
+ camellia_encrypt (&ctx, &ciphertext[i], iv);
+ for (j = 0; j < 16; j++)
+ ciphertext[i+j] ^= plaintext[i+j];
+ for (j = 16; j > 0; j--)
+ {
+ iv[j-1]++;
+ if (iv[j-1])
+ break;
+ }
+ }
+
+ /* Decrypt using bulk CTR and compare result. */
+ memset(iv2, 0xff, sizeof(iv2));
+ iv2[15] -= diff;
+
+ _gcry_camellia_ctr_enc (&ctx, iv2, plaintext2, ciphertext,
+ sizeof(ciphertext) / CAMELLIA_BLOCK_SIZE);
+
+ if (memcmp(plaintext2, plaintext, sizeof(plaintext)))
+ {
+ snprintf(error_str, sizeof(error_str),
+ "CAMELLIA-128-CTR test failed (plaintext mismatch, diff: %d)",
+ diff);
+ return error_str;
+ }
+ if (memcmp(iv2, iv, sizeof(iv)))
+ {
+ snprintf(error_str, sizeof(error_str),
+ "CAMELLIA-128-CTR test failed (IV mismatch, diff: %d)",
+ diff);
+ return error_str;
+ }
+ }
+
+ return NULL;
}
static const char *
@@ -137,6 +311,7 @@ selftest(void)
{
CAMELLIA_context ctx;
byte scratch[16];
+ const char *r;
/* These test vectors are from RFC-3713 */
const byte plaintext[]=
@@ -200,6 +375,9 @@ selftest(void)
if(memcmp(scratch,plaintext,sizeof(plaintext))!=0)
return "CAMELLIA-256 test decryption failed.";
+ if ( (r = selftest_ctr_128 ()) )
+ return r;
+
return NULL;
}