[RFC PATCH 3/3] Add Counter with CBC-MAC mode (CCM)
Jussi Kivilinna
jussi.kivilinna at iki.fi
Sun Oct 13 12:02:38 CEST 2013
--
Patch adds CCM (Counter with CBC-MAC) mode as defined in RFC 3610 and NIST
Special Publication 800-38C.
---
cipher/Makefile.am | 1
cipher/cipher-ccm.c | 349 ++++++++++++++++++++++++++++++
cipher/cipher-internal.h | 41 +++-
cipher/cipher.c | 88 ++++++--
src/gcrypt.h.in | 5
tests/basic.c | 532 ++++++++++++++++++++++++++++++++++++++++++++++
tests/benchmark.c | 67 +++++-
7 files changed, 1063 insertions(+), 20 deletions(-)
create mode 100644 cipher/cipher-ccm.c
diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index a2b2c8a..b0efd89 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
@@ -40,6 +40,7 @@ libcipher_la_LIBADD = $(GCRYPT_MODULES)
libcipher_la_SOURCES = \
cipher.c cipher-internal.h \
cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \
+cipher-ccm.c \
cipher-selftest.c cipher-selftest.h \
pubkey.c pubkey-internal.h pubkey-util.c \
md.c \
diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c
new file mode 100644
index 0000000..94ffbea
--- /dev/null
+++ b/cipher/cipher-ccm.c
@@ -0,0 +1,349 @@
+/* cipher-ccm.c - CTR mode with CBC-MAC mode implementation
+ * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna at iki.fi>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "cipher.h"
+#include "ath.h"
+#include "bufhelp.h"
+#include "./cipher-internal.h"
+
+
+#define set_burn(burn, nburn) do { \
+ unsigned int __nburn = (nburn); \
+ (burn) = (burn) > __nburn ? (burn) : __nburn; } while (0)
+
+
+static unsigned int
+do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, unsigned int inlen,
+ int do_padding)
+{
+ unsigned int burn = 0;
+ unsigned int unused = c->u_mode.ccm.mac_unused;
+ unsigned int blocksize = 16;
+
+ if (inlen == 0 && unused == 0)
+ return 0;
+
+ do
+ {
+ if (inlen + unused < blocksize || unused > 0)
+ {
+ for (; inlen && unused < blocksize; inlen--)
+ c->u_mode.ccm.macbuf[unused++] = *inbuf++;
+ }
+ if (!inlen)
+ {
+ if (!do_padding)
+ break;
+
+ while (unused < blocksize)
+ c->u_mode.ccm.macbuf[unused++] = 0;
+ }
+
+ if (unused > 0)
+ {
+ /* Process one block from macbuf. */
+ buf_xor(c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.macbuf, blocksize);
+ set_burn (burn, c->spec->encrypt ( &c->context.c, c->u_iv.iv,
+ c->u_iv.iv ));
+
+ unused = 0;
+ }
+
+ while (inlen >= blocksize)
+ {
+ buf_xor(c->u_iv.iv, c->u_iv.iv, inbuf, blocksize);
+
+ set_burn (burn, c->spec->encrypt ( &c->context.c, c->u_iv.iv,
+ c->u_iv.iv ));
+
+ inlen -= blocksize;
+ inbuf += blocksize;
+ }
+ }
+ while (inlen > 0);
+
+ c->u_mode.ccm.mac_unused = unused;
+
+ if (burn)
+ burn += 4 * sizeof(void *);
+
+ return burn;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_ccm_aead_init (gcry_cipher_hd_t c, const unsigned char *nonce,
+ unsigned int noncelen, unsigned int authlen,
+ size_t encryptlen)
+{
+ unsigned int L = 15 - noncelen;
+ unsigned int M = authlen;
+ unsigned int L_, M_;
+ int i;
+
+ M_ = (M - 2) / 2;
+ L_ = L - 1;
+
+ if (!nonce)
+ return GPG_ERR_INV_ARG;
+ /* Authentication field must be 4, 6, 8, 10, 12, 14 or 16. */
+ if ((M_ * 2 + 2) != M || M < 4 || M > 16)
+ return GPG_ERR_INV_LENGTH;
+ /* Length field must be 2, 3, ..., or 8. */
+ if (L < 2 || L > 8)
+ return GPG_ERR_INV_LENGTH;
+
+ /* Reset state */
+ memset (&c->u_mode, 0, sizeof(c->u_mode));
+ memset (&c->marks, 0, sizeof(c->marks));
+ memset (&c->u_iv, 0, sizeof(c->u_iv));
+ memset (&c->u_ctr, 0, sizeof(c->u_ctr));
+ memset (c->lastiv, 0, sizeof(c->lastiv));
+ c->unused = 0;
+
+ c->u_mode.ccm.authlen = authlen;
+ c->u_mode.ccm.encryptlen = encryptlen;
+
+ /* Setup IV & CTR */
+ c->u_iv.iv[0] = M_ * 8 + L_; /* Do not yet know if addlen > 0. */
+ memcpy (&c->u_iv.iv[1], nonce, noncelen);
+ for (i = 16 - 1; i >= 1 + noncelen; i--)
+ {
+ c->u_iv.iv[i] = encryptlen & 0xff;
+ encryptlen >>= 8;
+ }
+ c->u_ctr.ctr[0] = L_;
+ memcpy (&c->u_ctr.ctr[1], nonce, noncelen);
+ memset (&c->u_ctr.ctr[1 + noncelen], 0, L);
+
+ c->u_mode.ccm.aead = 1;
+
+ return GPG_ERR_NO_ERROR;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_ccm_authenticate (gcry_cipher_hd_t c, const unsigned char *aadbuf,
+ unsigned int aadbuflen)
+{
+ unsigned int burn = 0;
+ unsigned char b0[16];
+
+ if (aadbuflen > 0 && !aadbuf)
+ return GPG_ERR_INV_ARG;
+ if (!c->u_mode.ccm.aead || c->u_mode.ccm.tag)
+ return GPG_ERR_INV_STATE;
+ if (c->u_mode.ccm.aad)
+ return GPG_ERR_INV_STATE;
+
+ memcpy (b0, c->u_iv.iv, 16);
+ memset (c->u_iv.iv, 0, 16);
+
+ b0[0] |= (aadbuflen > 0) * 64;
+
+ set_burn (burn, do_cbc_mac (c, b0, 16, 0));
+
+ if (aadbuflen > 0 && aadbuflen <= (unsigned int)0xfeff)
+ {
+ b0[0] = (aadbuflen >> 8) & 0xff;
+ b0[1] = aadbuflen & 0xff;
+ set_burn (burn, do_cbc_mac (c, b0, 2, 0));
+ }
+ else if (aadbuflen > 0xfeff && aadbuflen <= (unsigned int)0xffffffff)
+ {
+ b0[0] = 0xff;
+ b0[1] = 0xfe;
+ buf_put_be32(&b0[2], aadbuflen);
+ set_burn (burn, do_cbc_mac (c, b0, 6, 0));
+ }
+#ifdef HAVE_U64_TYPEDEF
+ else if (aadbuflen > (unsigned int)0xffffffff)
+ {
+ b0[0] = 0xff;
+ b0[1] = 0xff;
+ buf_put_be64(&b0[2], aadbuflen);
+ set_burn (burn, do_cbc_mac (c, b0, 10, 0));
+ }
+#endif
+
+ if (aadbuflen > 0)
+ set_burn (burn, do_cbc_mac (c, aadbuf, aadbuflen, 1));
+
+
+ /* Generate S_0 and increase counter. */
+ set_burn (burn, c->spec->encrypt ( &c->context.c, c->u_mode.ccm.s0,
+ c->u_ctr.ctr ));
+ c->u_ctr.ctr[15]++;
+
+ if (burn)
+ _gcry_burn_stack (burn + sizeof(void *) * 5);
+
+ c->u_mode.ccm.aad = 1;
+
+ return GPG_ERR_NO_ERROR;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf,
+ unsigned int outbuflen, int check)
+{
+ gcry_err_code_t err;
+ unsigned int burn;
+
+ if (!outbuf || outbuflen == 0)
+ return GPG_ERR_INV_ARG;
+ /* Tag length must be same as initial authlen. */
+ if (c->u_mode.ccm.authlen != outbuflen)
+ return GPG_ERR_INV_LENGTH;
+ if (!c->u_mode.ccm.aead)
+ return GPG_ERR_INV_STATE;
+ /* Initial encrypt length must match with length of actual data processed. */
+ if (c->u_mode.ccm.encryptlen > 0)
+ return GPG_ERR_UNFINISHED;
+
+ if (!c->u_mode.ccm.aad)
+ {
+ err = _gcry_cipher_ccm_authenticate (c, NULL, 0);
+ if (err)
+ return err;
+ }
+
+ if (!c->u_mode.ccm.tag)
+ {
+ burn = do_cbc_mac (c, NULL, 0, 1); /* Perform final padding. */
+
+ /* Add S_0 */
+ buf_xor (c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.s0, 16);
+
+ wipememory (c->u_ctr.ctr, 16);
+ wipememory (c->u_mode.ccm.s0, 16);
+ wipememory (c->u_mode.ccm.macbuf, 16);
+
+ if (burn)
+ _gcry_burn_stack (burn + sizeof(void *) * 5);
+ }
+
+ if (!check)
+ {
+ memcpy (outbuf, c->u_iv.iv, outbuflen);
+ return GPG_ERR_NO_ERROR;
+ }
+ else
+ {
+ int diff, i;
+
+ /* Constant-time compare. */
+ for (i = 0, diff = 0; i < outbuflen; i++)
+ diff -= !!(outbuf[i] - c->u_iv.iv[i]);
+
+ return !diff ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM;
+ }
+}
+
+
+gcry_err_code_t
+_gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
+ unsigned int outbuflen, const unsigned char *inbuf,
+ unsigned int inbuflen)
+{
+ gcry_err_code_t err;
+ unsigned int burn;
+
+ if (outbuflen < inbuflen + c->u_mode.ccm.authlen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+ if (!c->u_mode.ccm.aead || c->u_mode.ccm.tag)
+ return GPG_ERR_INV_STATE;
+ if (inbuflen != c->u_mode.ccm.encryptlen)
+ return GPG_ERR_INV_LENGTH;
+
+ if (!c->u_mode.ccm.aad)
+ {
+ err = _gcry_cipher_ccm_authenticate (c, NULL, 0);
+ if (err)
+ return err;
+ }
+
+ c->u_mode.ccm.encryptlen -= inbuflen;
+ burn = do_cbc_mac (c, inbuf, inbuflen, 0);
+ if (burn)
+ _gcry_burn_stack (burn + sizeof(void *) * 5);
+
+ err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ if (err)
+ return err;
+
+ /* Generate and append MAC. */
+ return _gcry_cipher_ccm_tag (c, &outbuf[inbuflen], c->u_mode.ccm.authlen, 0);
+}
+
+
+gcry_err_code_t
+_gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
+ unsigned int outbuflen, const unsigned char *inbuf,
+ unsigned int inbuflen)
+{
+ gcry_err_code_t err;
+ unsigned int burn;
+ unsigned int datalen;
+
+ if (inbuflen < c->u_mode.ccm.authlen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+ if (outbuflen < inbuflen - c->u_mode.ccm.authlen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+ if (!c->u_mode.ccm.aead || c->u_mode.ccm.tag)
+ return GPG_ERR_INV_STATE;
+ datalen = inbuflen - c->u_mode.ccm.authlen;
+ if (datalen != c->u_mode.ccm.encryptlen)
+ return GPG_ERR_INV_LENGTH;
+
+ if (!c->u_mode.ccm.aad)
+ {
+ err = _gcry_cipher_ccm_authenticate (c, NULL, 0);
+ if (err)
+ return err;
+ }
+
+ err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, datalen);
+ if (err)
+ return err;
+
+ c->u_mode.ccm.encryptlen -= datalen;
+ burn = do_cbc_mac (c, outbuf, datalen, 0);
+ if (burn)
+ _gcry_burn_stack (burn + sizeof(void *) * 5);
+
+ err = _gcry_cipher_ccm_tag (c, (unsigned char *)&inbuf[datalen],
+ c->u_mode.ccm.authlen, 1);
+ if (err)
+ {
+ /* MAC check failed! */
+ wipememory (outbuf, outbuflen);
+ wipememory (c->u_iv.iv, 16);
+ }
+ return err;
+}
+
diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h
index b60ef38..abd70f4 100644
--- a/cipher/cipher-internal.h
+++ b/cipher/cipher-internal.h
@@ -100,7 +100,8 @@ struct gcry_cipher_handle
/* The initialization vector. For best performance we make sure
that it is properly aligned. In particular some implementations
- of bulk operations expect an 16 byte aligned IV. */
+ of bulk operations expect an 16 byte aligned IV. IV is also used
+ to store CBC-MAC in CCM mode; counter IV is stored in U_CTR. */
union {
cipher_context_alignment_t iv_align;
unsigned char iv[MAX_BLOCKSIZE];
@@ -117,6 +118,24 @@ struct gcry_cipher_handle
unsigned char lastiv[MAX_BLOCKSIZE];
int unused; /* Number of unused bytes in LASTIV. */
+ union {
+ /* Mode specific storage for CCM mode. */
+ struct {
+ /* Space to save partial input lengths for MAC. */
+ unsigned char macbuf[GCRY_CCM_BLOCK_LEN];
+ int mac_unused; /* Number of unprocessed bytes in MACBUF. */
+
+ unsigned char s0[GCRY_CCM_BLOCK_LEN];
+
+ unsigned int authlen;
+ unsigned int encryptlen;
+
+ unsigned int aead:1;/* Set to 1 if AEAD mode has been initialized. */
+ unsigned int aad:1; /* Set to 1 if AAD has been processed. */
+ unsigned int tag:1; /* Set to 1 if tag has been finalized. */
+ } ccm;
+ } u_mode;
+
/* What follows are two contexts of the cipher in use. The first
one needs to be aligned well enough for the cipher operation
whereas the second one is a copy created by cipher_setkey and
@@ -175,5 +194,25 @@ gcry_err_code_t _gcry_cipher_aeswrap_decrypt
const byte *inbuf, unsigned int inbuflen);
+/*-- cipher-ccm.c --*/
+gcry_err_code_t _gcry_cipher_ccm_encrypt
+/* */ (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen);
+gcry_err_code_t _gcry_cipher_ccm_decrypt
+/* */ (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen);
+gcry_err_code_t _gcry_cipher_ccm_aead_init
+/* */ (gcry_cipher_hd_t c,
+ const unsigned char *nonce, unsigned int noncelen,
+ unsigned int authlen, size_t encryptlen);
+gcry_err_code_t _gcry_cipher_ccm_authenticate
+/* */ (gcry_cipher_hd_t c,
+ const unsigned char *aadbuf, unsigned int aadbuflen);
+gcry_err_code_t _gcry_cipher_ccm_tag
+/* */ (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen, int check);
+
#endif /*G10_CIPHER_INTERNAL_H*/
diff --git a/cipher/cipher.c b/cipher/cipher.c
index 8ebab7c..42fecce 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -375,6 +375,13 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
if (! err)
switch (mode)
{
+ case GCRY_CIPHER_MODE_CCM:
+ if (spec->blocksize != GCRY_CCM_BLOCK_LEN)
+ err = GPG_ERR_INV_CIPHER_MODE;
+ if (!spec->encrypt || !spec->decrypt)
+ err = GPG_ERR_INV_CIPHER_MODE;
+ break;
+
case GCRY_CIPHER_MODE_ECB:
case GCRY_CIPHER_MODE_CBC:
case GCRY_CIPHER_MODE_CFB:
@@ -718,6 +725,10 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
inbuf, inbuflen);
break;
+ case GCRY_CIPHER_MODE_CCM:
+ rc = _gcry_cipher_ccm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
case GCRY_CIPHER_MODE_STREAM:
c->spec->stencrypt (&c->context.c,
outbuf, (byte*)/*arggg*/inbuf, inbuflen);
@@ -811,6 +822,10 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
inbuf, inbuflen);
break;
+ case GCRY_CIPHER_MODE_CCM:
+ rc = _gcry_cipher_ccm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
case GCRY_CIPHER_MODE_STREAM:
c->spec->stdecrypt (&c->context.c,
outbuf, (byte*)/*arggg*/inbuf, inbuflen);
@@ -885,8 +900,20 @@ _gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen)
gcry_error_t
_gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen)
{
- cipher_setiv (hd, iv, ivlen);
- return 0;
+ gcry_err_code_t rc = GPG_ERR_NO_ERROR;
+
+ switch (hd->mode)
+ {
+ case GCRY_CIPHER_MODE_CCM:
+ log_fatal ("cipher_setiv: invalid mode %d\n", hd->mode );
+ rc = GPG_ERR_INV_CIPHER_MODE;
+ break;
+
+ default:
+ cipher_setiv (hd, iv, ivlen);
+ break;
+ }
+ return gpg_error (rc);
}
/* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of
@@ -915,35 +942,70 @@ gcry_error_t
_gcry_cipher_authenticate (gcry_cipher_hd_t hd,
const void *aad, size_t aadsize)
{
- log_fatal ("gcry_cipher_tag: invalid mode %d\n", hd->mode );
+ gcry_err_code_t rc = GPG_ERR_NO_ERROR;
+
+ switch (hd->mode)
+ {
+ case GCRY_CIPHER_MODE_CCM:
+ rc = _gcry_cipher_ccm_authenticate (hd, aad, aadsize);
+ break;
- (void)aad;
- (void)aadsize;
+ default:
+ log_fatal ("gcry_cipher_tag: invalid mode %d\n", hd->mode );
+ rc = GPG_ERR_INV_CIPHER_MODE;
+ break;
+ }
- return gpg_error (GPG_ERR_INV_CIPHER_MODE);
+ return gpg_error (rc);
}
gcry_error_t
_gcry_cipher_tag (gcry_cipher_hd_t hd, void *out, size_t outsize)
{
- log_fatal ("gcry_cipher_tag: invalid mode %d\n", hd->mode );
+ gcry_err_code_t rc = GPG_ERR_NO_ERROR;
- (void)out;
- (void)outsize;
+ switch (hd->mode)
+ {
+ case GCRY_CIPHER_MODE_CCM:
+ rc = _gcry_cipher_ccm_tag (hd, out, outsize, 0);
+ break;
+
+ default:
+ log_fatal ("gcry_cipher_tag: invalid mode %d\n", hd->mode );
+ rc = GPG_ERR_INV_CIPHER_MODE;
+ break;
+ }
- return gpg_error (GPG_ERR_INV_CIPHER_MODE);
+ return gpg_error (rc);
}
gcry_error_t
_gcry_cipher_aead_vinit (gcry_cipher_hd_t hd, va_list arg_ptr)
{
- log_fatal ("gcry_cipher_aead_init: invalid mode %d\n", hd->mode );
+ gcry_err_code_t rc;
- (void)arg_ptr;
+ switch (hd->mode)
+ {
+ case GCRY_CIPHER_MODE_CCM:
+ {
+ const void *nonce = va_arg(arg_ptr, const void *);
+ unsigned int nonce_len = va_arg(arg_ptr, unsigned int);
+ unsigned int auth_len = va_arg(arg_ptr, unsigned int);
+ size_t encrypt_len = va_arg(arg_ptr, size_t);
+
+ rc = _gcry_cipher_ccm_aead_init (hd, nonce, nonce_len, auth_len,
+ encrypt_len);
+ break;
+ }
+ default:
+ log_fatal ("gcry_cipher_aead_init: invalid mode %d\n", hd->mode );
+ rc = GPG_ERR_INV_CIPHER_MODE;
+ break;
+ }
- return gpg_error (GPG_ERR_INV_CIPHER_MODE);
+ return gpg_error (rc);
}
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 2fffd69..88e9c36 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -871,7 +871,8 @@ enum gcry_cipher_modes
GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */
GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */
GCRY_CIPHER_MODE_CTR = 6, /* Counter. */
- GCRY_CIPHER_MODE_AESWRAP= 7 /* AES-WRAP algorithm. */
+ GCRY_CIPHER_MODE_AESWRAP= 7, /* AES-WRAP algorithm. */
+ GCRY_CIPHER_MODE_CCM = 8 /* Counter with CBC-MAC. */
};
/* Flags used with the open function. */
@@ -883,6 +884,8 @@ enum gcry_cipher_flags
GCRY_CIPHER_CBC_MAC = 8 /* Enable CBC message auth. code (MAC). */
};
+/* CCM works only with blocks of 128 bits. */
+#define GCRY_CCM_BLOCK_LEN (128 / 8)
/* Create a handle for algorithm ALGO to be used in MODE. FLAGS may
be given as an bitwise OR of the gcry_cipher_flags values. */
diff --git a/tests/basic.c b/tests/basic.c
index ee04900..78f6a48 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -1139,6 +1139,537 @@ check_ofb_cipher (void)
static void
+check_ccm_cipher (void)
+{
+ static const struct tv
+ {
+ int algo;
+ int keylen;
+ const char *key;
+ int noncelen;
+ const char *nonce;
+ int aadlen;
+ const char *aad;
+ int plainlen;
+ const char *plaintext;
+ int cipherlen;
+ const char *ciphertext;
+ } tv[] =
+ {
+ /* RFC 3610 */
+ { GCRY_CIPHER_AES, /* Packet Vector #1 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x03\x02\x01\x00\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 23,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
+ 31,
+ "\x58\x8C\x97\x9A\x61\xC6\x63\xD2\xF0\x66\xD0\xC2\xC0\xF9\x89\x80\x6D\x5F\x6B\x61\xDA\xC3\x84\x17\xE8\xD1\x2C\xFD\xF9\x26\xE0"},
+ { GCRY_CIPHER_AES, /* Packet Vector #2 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x04\x03\x02\x01\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 24,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
+ 32,
+ "\x72\xC9\x1A\x36\xE1\x35\xF8\xCF\x29\x1C\xA8\x94\x08\x5C\x87\xE3\xCC\x15\xC4\x39\xC9\xE4\x3A\x3B\xA0\x91\xD5\x6E\x10\x40\x09\x16"},
+ { GCRY_CIPHER_AES, /* Packet Vector #3 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x05\x04\x03\x02\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 25,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
+ 33,
+ "\x51\xB1\xE5\xF4\x4A\x19\x7D\x1D\xA4\x6B\x0F\x8E\x2D\x28\x2A\xE8\x71\xE8\x38\xBB\x64\xDA\x85\x96\x57\x4A\xDA\xA7\x6F\xBD\x9F\xB0\xC5"},
+ { GCRY_CIPHER_AES, /* Packet Vector #4 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x06\x05\x04\x03\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 19,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
+ 27,
+ "\xA2\x8C\x68\x65\x93\x9A\x9A\x79\xFA\xAA\x5C\x4C\x2A\x9D\x4A\x91\xCD\xAC\x8C\x96\xC8\x61\xB9\xC9\xE6\x1E\xF1"},
+ { GCRY_CIPHER_AES, /* Packet Vector #5 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x07\x06\x05\x04\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 20,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
+ 28,
+ "\xDC\xF1\xFB\x7B\x5D\x9E\x23\xFB\x9D\x4E\x13\x12\x53\x65\x8A\xD8\x6E\xBD\xCA\x3E\x51\xE8\x3F\x07\x7D\x9C\x2D\x93"},
+ { GCRY_CIPHER_AES, /* Packet Vector #6 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x08\x07\x06\x05\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 21,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
+ 29,
+ "\x6F\xC1\xB0\x11\xF0\x06\x56\x8B\x51\x71\xA4\x2D\x95\x3D\x46\x9B\x25\x70\xA4\xBD\x87\x40\x5A\x04\x43\xAC\x91\xCB\x94"},
+ { GCRY_CIPHER_AES, /* Packet Vector #7 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x09\x08\x07\x06\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 23,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
+ 33,
+ "\x01\x35\xD1\xB2\xC9\x5F\x41\xD5\xD1\xD4\xFE\xC1\x85\xD1\x66\xB8\x09\x4E\x99\x9D\xFE\xD9\x6C\x04\x8C\x56\x60\x2C\x97\xAC\xBB\x74\x90"},
+ { GCRY_CIPHER_AES, /* Packet Vector #8 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0A\x09\x08\x07\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 24,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
+ 34,
+ "\x7B\x75\x39\x9A\xC0\x83\x1D\xD2\xF0\xBB\xD7\x58\x79\xA2\xFD\x8F\x6C\xAE\x6B\x6C\xD9\xB7\xDB\x24\xC1\x7B\x44\x33\xF4\x34\x96\x3F\x34\xB4"},
+ { GCRY_CIPHER_AES, /* Packet Vector #9 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0B\x0A\x09\x08\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 25,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
+ 35,
+ "\x82\x53\x1A\x60\xCC\x24\x94\x5A\x4B\x82\x79\x18\x1A\xB5\xC8\x4D\xF2\x1C\xE7\xF9\xB7\x3F\x42\xE1\x97\xEA\x9C\x07\xE5\x6B\x5E\xB1\x7E\x5F\x4E"},
+ { GCRY_CIPHER_AES, /* Packet Vector #10 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0C\x0B\x0A\x09\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 19,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
+ 29,
+ "\x07\x34\x25\x94\x15\x77\x85\x15\x2B\x07\x40\x98\x33\x0A\xBB\x14\x1B\x94\x7B\x56\x6A\xA9\x40\x6B\x4D\x99\x99\x88\xDD"},
+ { GCRY_CIPHER_AES, /* Packet Vector #11 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0D\x0C\x0B\x0A\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 20,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
+ 30,
+ "\x67\x6B\xB2\x03\x80\xB0\xE3\x01\xE8\xAB\x79\x59\x0A\x39\x6D\xA7\x8B\x83\x49\x34\xF5\x3A\xA2\xE9\x10\x7A\x8B\x6C\x02\x2C"},
+ { GCRY_CIPHER_AES, /* Packet Vector #12 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0E\x0D\x0C\x0B\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 21,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
+ 31,
+ "\xC0\xFF\xA0\xD6\xF0\x5B\xDB\x67\xF2\x4D\x43\xA4\x33\x8D\x2A\xA4\xBE\xD7\xB2\x0E\x43\xCD\x1A\xA3\x16\x62\xE7\xAD\x65\xD6\xDB"},
+ { GCRY_CIPHER_AES, /* Packet Vector #13 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x41\x2B\x4E\xA9\xCD\xBE\x3C\x96\x96\x76\x6C\xFA",
+ 8, "\x0B\xE1\xA8\x8B\xAC\xE0\x18\xB1",
+ 23,
+ "\x08\xE8\xCF\x97\xD8\x20\xEA\x25\x84\x60\xE9\x6A\xD9\xCF\x52\x89\x05\x4D\x89\x5C\xEA\xC4\x7C",
+ 31,
+ "\x4C\xB9\x7F\x86\xA2\xA4\x68\x9A\x87\x79\x47\xAB\x80\x91\xEF\x53\x86\xA6\xFF\xBD\xD0\x80\xF8\xE7\x8C\xF7\xCB\x0C\xDD\xD7\xB3"},
+ { GCRY_CIPHER_AES, /* Packet Vector #14 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x33\x56\x8E\xF7\xB2\x63\x3C\x96\x96\x76\x6C\xFA",
+ 8, "\x63\x01\x8F\x76\xDC\x8A\x1B\xCB",
+ 24,
+ "\x90\x20\xEA\x6F\x91\xBD\xD8\x5A\xFA\x00\x39\xBA\x4B\xAF\xF9\xBF\xB7\x9C\x70\x28\x94\x9C\xD0\xEC",
+ 32,
+ "\x4C\xCB\x1E\x7C\xA9\x81\xBE\xFA\xA0\x72\x6C\x55\xD3\x78\x06\x12\x98\xC8\x5C\x92\x81\x4A\xBC\x33\xC5\x2E\xE8\x1D\x7D\x77\xC0\x8A"},
+ { GCRY_CIPHER_AES, /* Packet Vector #15 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x10\x3F\xE4\x13\x36\x71\x3C\x96\x96\x76\x6C\xFA",
+ 8, "\xAA\x6C\xFA\x36\xCA\xE8\x6B\x40",
+ 25,
+ "\xB9\x16\xE0\xEA\xCC\x1C\x00\xD7\xDC\xEC\x68\xEC\x0B\x3B\xBB\x1A\x02\xDE\x8A\x2D\x1A\xA3\x46\x13\x2E",
+ 33,
+ "\xB1\xD2\x3A\x22\x20\xDD\xC0\xAC\x90\x0D\x9A\xA0\x3C\x61\xFC\xF4\xA5\x59\xA4\x41\x77\x67\x08\x97\x08\xA7\x76\x79\x6E\xDB\x72\x35\x06"},
+ { GCRY_CIPHER_AES, /* Packet Vector #16 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x76\x4C\x63\xB8\x05\x8E\x3C\x96\x96\x76\x6C\xFA",
+ 12, "\xD0\xD0\x73\x5C\x53\x1E\x1B\xEC\xF0\x49\xC2\x44",
+ 19,
+ "\x12\xDA\xAC\x56\x30\xEF\xA5\x39\x6F\x77\x0C\xE1\xA6\x6B\x21\xF7\xB2\x10\x1C",
+ 27,
+ "\x14\xD2\x53\xC3\x96\x7B\x70\x60\x9B\x7C\xBB\x7C\x49\x91\x60\x28\x32\x45\x26\x9A\x6F\x49\x97\x5B\xCA\xDE\xAF"},
+ { GCRY_CIPHER_AES, /* Packet Vector #17 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\xF8\xB6\x78\x09\x4E\x3B\x3C\x96\x96\x76\x6C\xFA",
+ 12, "\x77\xB6\x0F\x01\x1C\x03\xE1\x52\x58\x99\xBC\xAE",
+ 20,
+ "\xE8\x8B\x6A\x46\xC7\x8D\x63\xE5\x2E\xB8\xC5\x46\xEF\xB5\xDE\x6F\x75\xE9\xCC\x0D",
+ 28,
+ "\x55\x45\xFF\x1A\x08\x5E\xE2\xEF\xBF\x52\xB2\xE0\x4B\xEE\x1E\x23\x36\xC7\x3E\x3F\x76\x2C\x0C\x77\x44\xFE\x7E\x3C"},
+ { GCRY_CIPHER_AES, /* Packet Vector #18 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\xD5\x60\x91\x2D\x3F\x70\x3C\x96\x96\x76\x6C\xFA",
+ 12, "\xCD\x90\x44\xD2\xB7\x1F\xDB\x81\x20\xEA\x60\xC0",
+ 21,
+ "\x64\x35\xAC\xBA\xFB\x11\xA8\x2E\x2F\x07\x1D\x7C\xA4\xA5\xEB\xD9\x3A\x80\x3B\xA8\x7F",
+ 29,
+ "\x00\x97\x69\xEC\xAB\xDF\x48\x62\x55\x94\xC5\x92\x51\xE6\x03\x57\x22\x67\x5E\x04\xC8\x47\x09\x9E\x5A\xE0\x70\x45\x51"},
+ { GCRY_CIPHER_AES, /* Packet Vector #19 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x42\xFF\xF8\xF1\x95\x1C\x3C\x96\x96\x76\x6C\xFA",
+ 8, "\xD8\x5B\xC7\xE6\x9F\x94\x4F\xB8",
+ 23,
+ "\x8A\x19\xB9\x50\xBC\xF7\x1A\x01\x8E\x5E\x67\x01\xC9\x17\x87\x65\x98\x09\xD6\x7D\xBE\xDD\x18",
+ 33,
+ "\xBC\x21\x8D\xAA\x94\x74\x27\xB6\xDB\x38\x6A\x99\xAC\x1A\xEF\x23\xAD\xE0\xB5\x29\x39\xCB\x6A\x63\x7C\xF9\xBE\xC2\x40\x88\x97\xC6\xBA"},
+ { GCRY_CIPHER_AES, /* Packet Vector #20 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x92\x0F\x40\xE5\x6C\xDC\x3C\x96\x96\x76\x6C\xFA",
+ 8, "\x74\xA0\xEB\xC9\x06\x9F\x5B\x37",
+ 24,
+ "\x17\x61\x43\x3C\x37\xC5\xA3\x5F\xC1\xF3\x9F\x40\x63\x02\xEB\x90\x7C\x61\x63\xBE\x38\xC9\x84\x37",
+ 34,
+ "\x58\x10\xE6\xFD\x25\x87\x40\x22\xE8\x03\x61\xA4\x78\xE3\xE9\xCF\x48\x4A\xB0\x4F\x44\x7E\xFF\xF6\xF0\xA4\x77\xCC\x2F\xC9\xBF\x54\x89\x44"},
+ { GCRY_CIPHER_AES, /* Packet Vector #21 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x27\xCA\x0C\x71\x20\xBC\x3C\x96\x96\x76\x6C\xFA",
+ 8, "\x44\xA3\xAA\x3A\xAE\x64\x75\xCA",
+ 25,
+ "\xA4\x34\xA8\xE5\x85\x00\xC6\xE4\x15\x30\x53\x88\x62\xD6\x86\xEA\x9E\x81\x30\x1B\x5A\xE4\x22\x6B\xFA",
+ 35,
+ "\xF2\xBE\xED\x7B\xC5\x09\x8E\x83\xFE\xB5\xB3\x16\x08\xF8\xE2\x9C\x38\x81\x9A\x89\xC8\xE7\x76\xF1\x54\x4D\x41\x51\xA4\xED\x3A\x8B\x87\xB9\xCE"},
+ { GCRY_CIPHER_AES, /* Packet Vector #22 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x5B\x8C\xCB\xCD\x9A\xF8\x3C\x96\x96\x76\x6C\xFA",
+ 12, "\xEC\x46\xBB\x63\xB0\x25\x20\xC3\x3C\x49\xFD\x70",
+ 19,
+ "\xB9\x6B\x49\xE2\x1D\x62\x17\x41\x63\x28\x75\xDB\x7F\x6C\x92\x43\xD2\xD7\xC2",
+ 29,
+ "\x31\xD7\x50\xA0\x9D\xA3\xED\x7F\xDD\xD4\x9A\x20\x32\xAA\xBF\x17\xEC\x8E\xBF\x7D\x22\xC8\x08\x8C\x66\x6B\xE5\xC1\x97"},
+ { GCRY_CIPHER_AES, /* Packet Vector #23 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x3E\xBE\x94\x04\x4B\x9A\x3C\x96\x96\x76\x6C\xFA",
+ 12, "\x47\xA6\x5A\xC7\x8B\x3D\x59\x42\x27\xE8\x5E\x71",
+ 20,
+ "\xE2\xFC\xFB\xB8\x80\x44\x2C\x73\x1B\xF9\x51\x67\xC8\xFF\xD7\x89\x5E\x33\x70\x76",
+ 30,
+ "\xE8\x82\xF1\xDB\xD3\x8C\xE3\xED\xA7\xC2\x3F\x04\xDD\x65\x07\x1E\xB4\x13\x42\xAC\xDF\x7E\x00\xDC\xCE\xC7\xAE\x52\x98\x7D"},
+ { GCRY_CIPHER_AES, /* Packet Vector #24 */
+ 16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
+ 13, "\x00\x8D\x49\x3B\x30\xAE\x8B\x3C\x96\x96\x76\x6C\xFA",
+ 12, "\x6E\x37\xA6\xEF\x54\x6D\x95\x5D\x34\xAB\x60\x59",
+ 21,
+ "\xAB\xF2\x1C\x0B\x02\xFE\xB8\x8F\x85\x6D\xF4\xA3\x73\x81\xBC\xE3\xCC\x12\x85\x17\xD4",
+ 31,
+ "\xF3\x29\x05\xB8\x8A\x64\x1B\x04\xB9\xC9\xFF\xB5\x8C\xC3\x90\x90\x0F\x3D\xA1\x2A\xB1\x6D\xCE\x9E\x82\xEF\xA1\x6D\xA6\x20\x59"},
+ /* RFC 5528 */
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #1 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x03\x02\x01\x00\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 23,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
+ 31,
+ "\xBA\x73\x71\x85\xE7\x19\x31\x04\x92\xF3\x8A\x5F\x12\x51\xDA\x55\xFA\xFB\xC9\x49\x84\x8A\x0D\xFC\xAE\xCE\x74\x6B\x3D\xB9\xAD"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #2 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x04\x03\x02\x01\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 24,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
+ 32,
+ "\x5D\x25\x64\xBF\x8E\xAF\xE1\xD9\x95\x26\xEC\x01\x6D\x1B\xF0\x42\x4C\xFB\xD2\xCD\x62\x84\x8F\x33\x60\xB2\x29\x5D\xF2\x42\x83\xE8"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #3 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x05\x04\x03\x02\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 25,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
+ 33,
+ "\x81\xF6\x63\xD6\xC7\x78\x78\x17\xF9\x20\x36\x08\xB9\x82\xAD\x15\xDC\x2B\xBD\x87\xD7\x56\xF7\x92\x04\xF5\x51\xD6\x68\x2F\x23\xAA\x46"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #4 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x06\x05\x04\x03\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 19,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
+ 27,
+ "\xCA\xEF\x1E\x82\x72\x11\xB0\x8F\x7B\xD9\x0F\x08\xC7\x72\x88\xC0\x70\xA4\xA0\x8B\x3A\x93\x3A\x63\xE4\x97\xA0"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #5 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x07\x06\x05\x04\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 20,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
+ 28,
+ "\x2A\xD3\xBA\xD9\x4F\xC5\x2E\x92\xBE\x43\x8E\x82\x7C\x10\x23\xB9\x6A\x8A\x77\x25\x8F\xA1\x7B\xA7\xF3\x31\xDB\x09"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #6 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x08\x07\x06\x05\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 21,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
+ 29,
+ "\xFE\xA5\x48\x0B\xA5\x3F\xA8\xD3\xC3\x44\x22\xAA\xCE\x4D\xE6\x7F\xFA\x3B\xB7\x3B\xAB\xAB\x36\xA1\xEE\x4F\xE0\xFE\x28"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #7 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x09\x08\x07\x06\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 23,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
+ 33,
+ "\x54\x53\x20\x26\xE5\x4C\x11\x9A\x8D\x36\xD9\xEC\x6E\x1E\xD9\x74\x16\xC8\x70\x8C\x4B\x5C\x2C\xAC\xAF\xA3\xBC\xCF\x7A\x4E\xBF\x95\x73"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #8 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0A\x09\x08\x07\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 24,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
+ 34,
+ "\x8A\xD1\x9B\x00\x1A\x87\xD1\x48\xF4\xD9\x2B\xEF\x34\x52\x5C\xCC\xE3\xA6\x3C\x65\x12\xA6\xF5\x75\x73\x88\xE4\x91\x3E\xF1\x47\x01\xF4\x41"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #9 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0B\x0A\x09\x08\xA0\xA1\xA2\xA3\xA4\xA5",
+ 8, "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 25,
+ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
+ 35,
+ "\x5D\xB0\x8D\x62\x40\x7E\x6E\x31\xD6\x0F\x9C\xA2\xC6\x04\x74\x21\x9A\xC0\xBE\x50\xC0\xD4\xA5\x77\x87\x94\xD6\xE2\x30\xCD\x25\xC9\xFE\xBF\x87"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #10 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0C\x0B\x0A\x09\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 19,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
+ 29,
+ "\xDB\x11\x8C\xCE\xC1\xB8\x76\x1C\x87\x7C\xD8\x96\x3A\x67\xD6\xF3\xBB\xBC\x5C\xD0\x92\x99\xEB\x11\xF3\x12\xF2\x32\x37"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #11 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0D\x0C\x0B\x0A\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 20,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
+ 30,
+ "\x7C\xC8\x3D\x8D\xC4\x91\x03\x52\x5B\x48\x3D\xC5\xCA\x7E\xA9\xAB\x81\x2B\x70\x56\x07\x9D\xAF\xFA\xDA\x16\xCC\xCF\x2C\x4E"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #12 */
+ 16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
+ 13, "\x00\x00\x00\x0E\x0D\x0C\x0B\xA0\xA1\xA2\xA3\xA4\xA5",
+ 12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
+ 21,
+ "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
+ 31,
+ "\x2C\xD3\x5B\x88\x20\xD2\x3E\x7A\xA3\x51\xB0\xE9\x2F\xC7\x93\x67\x23\x8B\x2C\xC7\x48\xCB\xB9\x4C\x29\x47\x79\x3D\x64\xAF\x75"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #13 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\xA9\x70\x11\x0E\x19\x27\xB1\x60\xB6\xA3\x1C\x1C",
+ 8, "\x6B\x7F\x46\x45\x07\xFA\xE4\x96",
+ 23,
+ "\xC6\xB5\xF3\xE6\xCA\x23\x11\xAE\xF7\x47\x2B\x20\x3E\x73\x5E\xA5\x61\xAD\xB1\x7D\x56\xC5\xA3",
+ 31,
+ "\xA4\x35\xD7\x27\x34\x8D\xDD\x22\x90\x7F\x7E\xB8\xF5\xFD\xBB\x4D\x93\x9D\xA6\x52\x4D\xB4\xF6\x45\x58\xC0\x2D\x25\xB1\x27\xEE"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #14 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\x83\xCD\x8C\xE0\xCB\x42\xB1\x60\xB6\xA3\x1C\x1C",
+ 8, "\x98\x66\x05\xB4\x3D\xF1\x5D\xE7",
+ 24,
+ "\x01\xF6\xCE\x67\x64\xC5\x74\x48\x3B\xB0\x2E\x6B\xBF\x1E\x0A\xBD\x26\xA2\x25\x72\xB4\xD8\x0E\xE7",
+ 32,
+ "\x8A\xE0\x52\x50\x8F\xBE\xCA\x93\x2E\x34\x6F\x05\xE0\xDC\x0D\xFB\xCF\x93\x9E\xAF\xFA\x3E\x58\x7C\x86\x7D\x6E\x1C\x48\x70\x38\x06"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #15 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\x5F\x54\x95\x0B\x18\xF2\xB1\x60\xB6\xA3\x1C\x1C",
+ 8, "\x48\xF2\xE7\xE1\xA7\x67\x1A\x51",
+ 25,
+ "\xCD\xF1\xD8\x40\x6F\xC2\xE9\x01\x49\x53\x89\x70\x05\xFB\xFB\x8B\xA5\x72\x76\xF9\x24\x04\x60\x8E\x08",
+ 33,
+ "\x08\xB6\x7E\xE2\x1C\x8B\xF2\x6E\x47\x3E\x40\x85\x99\xE9\xC0\x83\x6D\x6A\xF0\xBB\x18\xDF\x55\x46\x6C\xA8\x08\x78\xA7\x90\x47\x6D\xE5"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #16 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\xEC\x60\x08\x63\x31\x9A\xB1\x60\xB6\xA3\x1C\x1C",
+ 12, "\xDE\x97\xDF\x3B\x8C\xBD\x6D\x8E\x50\x30\xDA\x4C",
+ 19,
+ "\xB0\x05\xDC\xFA\x0B\x59\x18\x14\x26\xA9\x61\x68\x5A\x99\x3D\x8C\x43\x18\x5B",
+ 27,
+ "\x63\xB7\x8B\x49\x67\xB1\x9E\xDB\xB7\x33\xCD\x11\x14\xF6\x4E\xB2\x26\x08\x93\x68\xC3\x54\x82\x8D\x95\x0C\xC5"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #17 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\x60\xCF\xF1\xA3\x1E\xA1\xB1\x60\xB6\xA3\x1C\x1C",
+ 12, "\xA5\xEE\x93\xE4\x57\xDF\x05\x46\x6E\x78\x2D\xCF",
+ 20,
+ "\x2E\x20\x21\x12\x98\x10\x5F\x12\x9D\x5E\xD9\x5B\x93\xF7\x2D\x30\xB2\xFA\xCC\xD7",
+ 28,
+ "\x0B\xC6\xBB\xE2\xA8\xB9\x09\xF4\x62\x9E\xE6\xDC\x14\x8D\xA4\x44\x10\xE1\x8A\xF4\x31\x47\x38\x32\x76\xF6\x6A\x9F"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #18 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\x0F\x85\xCD\x99\x5C\x97\xB1\x60\xB6\xA3\x1C\x1C",
+ 12, "\x24\xAA\x1B\xF9\xA5\xCD\x87\x61\x82\xA2\x50\x74",
+ 21,
+ "\x26\x45\x94\x1E\x75\x63\x2D\x34\x91\xAF\x0F\xC0\xC9\x87\x6C\x3B\xE4\xAA\x74\x68\xC9",
+ 29,
+ "\x22\x2A\xD6\x32\xFA\x31\xD6\xAF\x97\x0C\x34\x5F\x7E\x77\xCA\x3B\xD0\xDC\x25\xB3\x40\xA1\xA3\xD3\x1F\x8D\x4B\x44\xB7"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #19 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\xC2\x9B\x2C\xAA\xC4\xCD\xB1\x60\xB6\xA3\x1C\x1C",
+ 8, "\x69\x19\x46\xB9\xCA\x07\xBE\x87",
+ 23,
+ "\x07\x01\x35\xA6\x43\x7C\x9D\xB1\x20\xCD\x61\xD8\xF6\xC3\x9C\x3E\xA1\x25\xFD\x95\xA0\xD2\x3D",
+ 33,
+ "\x05\xB8\xE1\xB9\xC4\x9C\xFD\x56\xCF\x13\x0A\xA6\x25\x1D\xC2\xEC\xC0\x6C\xCC\x50\x8F\xE6\x97\xA0\x06\x6D\x57\xC8\x4B\xEC\x18\x27\x68"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #20 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\x2C\x6B\x75\x95\xEE\x62\xB1\x60\xB6\xA3\x1C\x1C",
+ 8, "\xD0\xC5\x4E\xCB\x84\x62\x7D\xC4",
+ 24,
+ "\xC8\xC0\x88\x0E\x6C\x63\x6E\x20\x09\x3D\xD6\x59\x42\x17\xD2\xE1\x88\x77\xDB\x26\x4E\x71\xA5\xCC",
+ 34,
+ "\x54\xCE\xB9\x68\xDE\xE2\x36\x11\x57\x5E\xC0\x03\xDF\xAA\x1C\xD4\x88\x49\xBD\xF5\xAE\x2E\xDB\x6B\x7F\xA7\x75\xB1\x50\xED\x43\x83\xC5\xA9"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #21 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\xC5\x3C\xD4\xC2\xAA\x24\xB1\x60\xB6\xA3\x1C\x1C",
+ 8, "\xE2\x85\xE0\xE4\x80\x8C\xDA\x3D",
+ 25,
+ "\xF7\x5D\xAA\x07\x10\xC4\xE6\x42\x97\x79\x4D\xC2\xB7\xD2\xA2\x07\x57\xB1\xAA\x4E\x44\x80\x02\xFF\xAB",
+ 35,
+ "\xB1\x40\x45\x46\xBF\x66\x72\x10\xCA\x28\xE3\x09\xB3\x9B\xD6\xCA\x7E\x9F\xC8\x28\x5F\xE6\x98\xD4\x3C\xD2\x0A\x02\xE0\xBD\xCA\xED\x20\x10\xD3"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #22 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\xBE\xE9\x26\x7F\xBA\xDC\xB1\x60\xB6\xA3\x1C\x1C",
+ 12, "\x6C\xAE\xF9\x94\x11\x41\x57\x0D\x7C\x81\x34\x05",
+ 19,
+ "\xC2\x38\x82\x2F\xAC\x5F\x98\xFF\x92\x94\x05\xB0\xAD\x12\x7A\x4E\x41\x85\x4E",
+ 29,
+ "\x94\xC8\x95\x9C\x11\x56\x9A\x29\x78\x31\xA7\x21\x00\x58\x57\xAB\x61\xB8\x7A\x2D\xEA\x09\x36\xB6\xEB\x5F\x62\x5F\x5D"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #23 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\xDF\xA8\xB1\x24\x50\x07\xB1\x60\xB6\xA3\x1C\x1C",
+ 12, "\x36\xA5\x2C\xF1\x6B\x19\xA2\x03\x7A\xB7\x01\x1E",
+ 20,
+ "\x4D\xBF\x3E\x77\x4A\xD2\x45\xE5\xD5\x89\x1F\x9D\x1C\x32\xA0\xAE\x02\x2C\x85\xD7",
+ 30,
+ "\x58\x69\xE3\xAA\xD2\x44\x7C\x74\xE0\xFC\x05\xF9\xA4\xEA\x74\x57\x7F\x4D\xE8\xCA\x89\x24\x76\x42\x96\xAD\x04\x11\x9C\xE7"},
+ { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #24 */
+ 16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
+ 13, "\x00\x3B\x8F\xD8\xD3\xA9\x37\xB1\x60\xB6\xA3\x1C\x1C",
+ 12, "\xA4\xD4\x99\xF7\x84\x19\x72\x8C\x19\x17\x8B\x0C",
+ 21,
+ "\x9D\xC9\xED\xAE\x2F\xF5\xDF\x86\x36\xE8\xC6\xDE\x0E\xED\x55\xF7\x86\x7E\x33\x33\x7D",
+ 31,
+ "\x4B\x19\x81\x56\x39\x3B\x0F\x77\x96\x08\x6A\xAF\xB4\x54\xF8\xC3\xF0\x34\xCC\xA9\x66\x94\x5F\x1F\xCE\xA7\xE1\x1B\xEE\x6A\x2F"}
+ };
+ gcry_cipher_hd_t hde, hdd;
+ unsigned char out[MAX_DATA_LEN];
+ int i, keylen, blklen, authlen;
+ gcry_error_t err = 0;
+
+ if (verbose)
+ fprintf (stderr, " Starting CCM checks.\n");
+
+ for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+ {
+ if (verbose)
+ fprintf (stderr, " checking CCM mode for %s [%i]\n",
+ gcry_cipher_algo_name (tv[i].algo),
+ tv[i].algo);
+ err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CCM, 0);
+ if (!err)
+ err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CCM, 0);
+ if (err)
+ {
+ fail ("cipher-ccm, gcry_cipher_open failed: %s\n",
+ gpg_strerror (err));
+ return;
+ }
+
+ keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
+ if (!keylen)
+ {
+ fail ("cipher-ccm, gcry_cipher_get_algo_keylen failed\n");
+ return;
+ }
+
+ err = gcry_cipher_setkey (hde, tv[i].key, keylen);
+ if (!err)
+ err = gcry_cipher_setkey (hdd, tv[i].key, keylen);
+ if (err)
+ {
+ fail ("cipher-ccm, gcry_cipher_setkey failed: %s\n",
+ gpg_strerror (err));
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ return;
+ }
+
+ blklen = gcry_cipher_get_algo_blklen(tv[i].algo);
+ if (!blklen)
+ {
+ fail ("cipher-ccm, gcry_cipher_get_algo_blklen failed\n");
+ return;
+ }
+
+ authlen = tv[i].cipherlen - tv[i].plainlen;
+ err = gcry_cipher_aead_init (hde, tv[i].nonce, tv[i].noncelen,
+ authlen, tv[i].plainlen);
+ if (!err)
+ err = gcry_cipher_aead_init (hdd, tv[i].nonce, tv[i].noncelen,
+ authlen, tv[i].plainlen);
+ if (err)
+ {
+ fail ("cipher-ccm, gcry_cipher_aead_init failed: %s\n",
+ gpg_strerror (err));
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ return;
+ }
+
+ err = gcry_cipher_authenticate (hde, tv[i].aad, tv[i].aadlen);
+ if (!err)
+ err = gcry_cipher_authenticate (hdd, tv[i].aad, tv[i].aadlen);
+ if (err)
+ {
+ fail ("cipher-ccm, gcry_cipher_authenticate failed: %s\n",
+ gpg_strerror (err));
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ return;
+ }
+
+ err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN, tv[i].plaintext,
+ tv[i].plainlen);
+ if (err)
+ {
+ fail ("cipher-ccm, gcry_cipher_encrypt (%d) failed: %s\n",
+ i, gpg_strerror (err));
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ return;
+ }
+
+ if (memcmp (tv[i].ciphertext, out, tv[i].cipherlen))
+ fail ("cipher-ccm, encrypt mismatch entry %d\n", i);
+
+ err = gcry_cipher_decrypt (hdd, out, tv[i].cipherlen, NULL, 0);
+ if (err)
+ {
+ fail ("cipher-ccm, gcry_cipher_decrypt (%d) failed: %s\n",
+ i, gpg_strerror (err));
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ return;
+ }
+
+ if (memcmp (tv[i].plaintext, out, tv[i].plainlen))
+ fail ("cipher-ccm, decrypt mismatch entry %d:%d\n", i);
+
+ memset (out, 0, sizeof(out));
+ err = gcry_cipher_tag (hdd, out, authlen);
+ if (err)
+ {
+ fail ("cipher-ccm, gcry_cipher_tag (%d) failed: %s\n",
+ i, gpg_strerror (err));
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ return;
+ }
+
+ if (memcmp (&tv[i].ciphertext[tv[i].plainlen], out, authlen))
+ fail ("cipher-ccm, decrypt auth-tag mismatch entry %d\n", i);
+
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ }
+ if (verbose)
+ fprintf (stderr, " Completed CCM checks.\n");
+}
+
+
+static void
check_stream_cipher (void)
{
struct tv
@@ -2455,6 +2986,7 @@ check_cipher_modes(void)
check_ctr_cipher ();
check_cfb_cipher ();
check_ofb_cipher ();
+ check_ccm_cipher ();
check_stream_cipher ();
check_stream_cipher_large_block ();
diff --git a/tests/benchmark.c b/tests/benchmark.c
index 5d1434a..21ae176 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -435,6 +435,36 @@ 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];
+ gcry_error_t err = GPG_ERR_NO_ERROR;
+
+ memset (nonce, 0x33, noncelen);
+
+ err = gcry_cipher_aead_init (hd, nonce, noncelen, authlen, buflen - authlen);
+ if (err)
+ {
+ fprintf (stderr, "gcry_cipher_aead_init failed: %s\n",
+ gpg_strerror (err));
+ gcry_cipher_close (hd);
+ exit (1);
+ }
+
+ err = gcry_cipher_authenticate (hd, NULL, 0);
+ if (err)
+ {
+ fprintf (stderr, "gcry_cipher_authenticate failed: %s\n",
+ gpg_strerror (err));
+ gcry_cipher_close (hd);
+ exit (1);
+ }
+}
+
+
static void
cipher_bench ( const char *algoname )
{
@@ -446,14 +476,23 @@ cipher_bench ( const char *algoname )
char key[128];
char *outbuf, *buf;
char *raw_outbuf, *raw_buf;
- size_t allocated_buflen, buflen;
+ size_t allocated_buflen, buflen, plainlen;
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 +581,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;
@@ -570,6 +616,7 @@ cipher_bench ( const char *algoname )
buflen = allocated_buflen;
if (modes[modeidx].blocked)
buflen = (buflen / blklen) * blklen;
+ plainlen = buflen - modes[modeidx].authlen;
start_timer ();
for (i=err=0; !err && i < repetitions; i++)
@@ -585,7 +632,9 @@ 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, plainlen);
}
stop_timer ();
@@ -632,7 +681,15 @@ 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, plainlen, buf, buflen);
+ if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
+ err = gpg_error (GPG_ERR_NO_ERROR);
+ }
+ else
+ err = gcry_cipher_decrypt (hd, outbuf, plainlen, buf, buflen);
}
stop_timer ();
printf (" %s", elapsed_time ());
More information about the Gcrypt-devel
mailing list