summaryrefslogtreecommitdiff
path: root/tests/benchmark.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2013-10-22 17:07:53 +0300
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2013-10-22 19:48:19 +0300
commit335d9bf7b035815750b63a3a8334d6ce44dc4449 (patch)
tree75a9ff903f9b7d2bd3f92dc459962ac7741e68c8 /tests/benchmark.c
parent95654041f2aa62f71aac4d8614dafe8433d10f95 (diff)
downloadlibgcrypt-335d9bf7b035815750b63a3a8334d6ce44dc4449.tar.gz
Add Counter with CBC-MAC mode (CCM)
* cipher/Makefile.am: Add 'cipher-ccm.c'. * cipher/cipher-ccm.c: New. * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode'. (_gcry_cipher_ccm_encrypt, _gcry_cipher_ccm_decrypt) (_gcry_cipher_ccm_set_nonce, _gcry_cipher_ccm_authenticate) (_gcry_cipher_ccm_get_tag, _gcry_cipher_ccm_check_tag) (_gcry_cipher_ccm_set_lengths): New prototypes. * cipher/cipher.c (gcry_cipher_open, cipher_encrypt, cipher_decrypt) (_gcry_cipher_setiv, _gcry_cipher_authenticate, _gcry_cipher_gettag) (_gcry_cipher_checktag, gry_cipher_ctl): Add handling for CCM mode. * doc/gcrypt.texi: Add documentation for GCRY_CIPHER_MODE_CCM. * src/gcrypt.h.in (gcry_cipher_modes): Add 'GCRY_CIPHER_MODE_CCM'. (gcry_ctl_cmds): Add 'GCRYCTL_SET_CCM_LENGTHS'. (GCRY_CCM_BLOCK_LEN): New. * tests/basic.c (check_ccm_cipher): New. (check_cipher_modes): Call 'check_ccm_cipher'. * tests/benchmark.c (ccm_aead_init): New. (cipher_bench): Add handling for AEAD modes and add CCM benchmarking. -- Patch adds CCM (Counter with CBC-MAC) mode as defined in RFC 3610 and NIST Special Publication 800-38C. Example for encrypting message (split in two buffers; buf1, buf2) and authenticating additional non-encrypted data (split in two buffers; aadbuf1, aadbuf2) with authentication tag length of eigth bytes: size_t params[3]; taglen = 8; gcry_cipher_setkey(h, key, len(key)); gcry_cipher_setiv(h, nonce, len(nonce)); params[0] = len(buf1) + len(buf2); /* 0: enclen */ params[1] = len(aadbuf1) + len(aadbuf2); /* 1: aadlen */ params[2] = taglen; /* 2: authtaglen */ gcry_cipher_ctl(h, GCRYCTL_SET_CCM_LENGTHS, params, sizeof(size_t) * 3); gcry_cipher_authenticate(h, aadbuf1, len(aadbuf1)); gcry_cipher_authenticate(h, aadbuf2, len(aadbuf2)); gcry_cipher_encrypt(h, buf1, len(buf1), buf1, len(buf1)); gcry_cipher_encrypt(h, buf2, len(buf2), buf2, len(buf2)); gcry_cipher_gettag(h, tag, taglen); Example for decrypting above message and checking authentication tag: size_t params[3]; taglen = 8; gcry_cipher_setkey(h, key, len(key)); gcry_cipher_setiv(h, nonce, len(nonce)); params[0] = len(buf1) + len(buf2); /* 0: enclen */ params[1] = len(aadbuf1) + len(aadbuf2); /* 1: aadlen */ params[2] = taglen; /* 2: authtaglen */ gcry_cipher_ctl(h, GCRYCTL_SET_CCM_LENGTHS, params, sizeof(size_t) * 3); gcry_cipher_authenticate(h, aadbuf1, len(aadbuf1)); gcry_cipher_authenticate(h, aadbuf2, len(aadbuf2)); gcry_cipher_decrypt(h, buf1, len(buf1), buf1, len(buf1)); gcry_cipher_decrypt(h, buf2, len(buf2), buf2, len(buf2)); err = gcry_cipher_checktag(h, tag, taglen); if (gpg_err_code (err) == GPG_ERR_CHECKSUM) { /* Authentication failed. */ } else if (err == 0) { /* Authentication ok. */ } Example for encrypting message without additional authenticated data: size_t params[3]; taglen = 10; gcry_cipher_setkey(h, key, len(key)); gcry_cipher_setiv(h, nonce, len(nonce)); params[0] = len(buf1); /* 0: enclen */ params[1] = 0; /* 1: aadlen */ params[2] = taglen; /* 2: authtaglen */ gcry_cipher_ctl(h, GCRYCTL_SET_CCM_LENGTHS, params, sizeof(size_t) * 3); gcry_cipher_encrypt(h, buf1, len(buf1), buf1, len(buf1)); gcry_cipher_gettag(h, tag, taglen); To reset CCM state for cipher handle, one can either set new nonce or use 'gcry_cipher_reset'. This implementation reuses existing CTR mode code for encryption/decryption and is there for able to process multiple buffers that are not multiple of blocksize. AAD data maybe also be passed into gcry_cipher_authenticate in non-blocksize chunks. [v4]: GCRYCTL_SET_CCM_PARAMS => GCRY_SET_CCM_LENGTHS Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'tests/benchmark.c')
-rw-r--r--tests/benchmark.c80
1 files changed, 76 insertions, 4 deletions
diff --git a/tests/benchmark.c b/tests/benchmark.c
index ecda0d3c..d3ef1a23 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -435,6 +435,40 @@ md_bench ( const char *algoname )
fflush (stdout);
}
+
+static void ccm_aead_init(gcry_cipher_hd_t hd, size_t buflen, int authlen)
+{
+ const int _L = 4;
+ const int noncelen = 15 - _L;
+ char nonce[noncelen];
+ size_t params[3];
+ gcry_error_t err = GPG_ERR_NO_ERROR;
+
+ memset (nonce, 0x33, noncelen);
+
+ err = gcry_cipher_setiv (hd, nonce, noncelen);
+ if (err)
+ {
+ fprintf (stderr, "gcry_cipher_setiv failed: %s\n",
+ gpg_strerror (err));
+ gcry_cipher_close (hd);
+ exit (1);
+ }
+
+ params[0] = buflen; /* encryptedlen */
+ params[1] = 0; /* aadlen */
+ params[2] = authlen; /* authtaglen */
+ err = gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof(params));
+ if (err)
+ {
+ fprintf (stderr, "gcry_cipher_setiv failed: %s\n",
+ gpg_strerror (err));
+ gcry_cipher_close (hd);
+ exit (1);
+ }
+}
+
+
static void
cipher_bench ( const char *algoname )
{
@@ -448,12 +482,21 @@ cipher_bench ( const char *algoname )
char *raw_outbuf, *raw_buf;
size_t allocated_buflen, buflen;
int repetitions;
- static struct { int mode; const char *name; int blocked; } modes[] = {
+ static const struct {
+ int mode;
+ const char *name;
+ int blocked;
+ void (* const aead_init)(gcry_cipher_hd_t hd, size_t buflen, int authlen);
+ int req_blocksize;
+ int authlen;
+ } modes[] = {
{ GCRY_CIPHER_MODE_ECB, " ECB/Stream", 1 },
{ GCRY_CIPHER_MODE_CBC, " CBC", 1 },
{ GCRY_CIPHER_MODE_CFB, " CFB", 0 },
{ GCRY_CIPHER_MODE_OFB, " OFB", 0 },
{ GCRY_CIPHER_MODE_CTR, " CTR", 0 },
+ { GCRY_CIPHER_MODE_CCM, " CCM", 0,
+ ccm_aead_init, GCRY_CCM_BLOCK_LEN, 8 },
{ GCRY_CIPHER_MODE_STREAM, "", 0 },
{0}
};
@@ -542,9 +585,16 @@ cipher_bench ( const char *algoname )
for (modeidx=0; modes[modeidx].mode; modeidx++)
{
if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM)
- | (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM))
+ || (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM))
continue;
+ if (modes[modeidx].req_blocksize > 0
+ && blklen != modes[modeidx].req_blocksize)
+ {
+ printf (" %7s %7s", "-", "-" );
+ continue;
+ }
+
for (i=0; i < sizeof buf; i++)
buf[i] = i;
@@ -585,7 +635,18 @@ cipher_bench ( const char *algoname )
exit (1);
}
}
- err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen);
+ if (modes[modeidx].aead_init)
+ {
+ (*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen);
+ err = gcry_cipher_encrypt (hd, outbuf, buflen, buf, buflen);
+ if (err)
+ break;
+ err = gcry_cipher_gettag (hd, outbuf, modes[modeidx].authlen);
+ }
+ else
+ {
+ err = gcry_cipher_encrypt (hd, outbuf, buflen, buf, buflen);
+ }
}
stop_timer ();
@@ -632,7 +693,18 @@ cipher_bench ( const char *algoname )
exit (1);
}
}
- err = gcry_cipher_decrypt ( hd, outbuf, buflen, buf, buflen);
+ if (modes[modeidx].aead_init)
+ {
+ (*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen);
+ err = gcry_cipher_decrypt (hd, outbuf, buflen, buf, buflen);
+ if (err)
+ break;
+ err = gcry_cipher_checktag (hd, outbuf, modes[modeidx].authlen);
+ if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
+ err = gpg_error (GPG_ERR_NO_ERROR);
+ }
+ else
+ err = gcry_cipher_decrypt (hd, outbuf, buflen, buf, buflen);
}
stop_timer ();
printf (" %s", elapsed_time ());