summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--Makefile.in3
-rw-r--r--ccm-aes128.c106
-rw-r--r--ccm-aes192.c106
-rw-r--r--ccm-aes256.c106
-rw-r--r--ccm.c256
-rw-r--r--ccm.h281
-rw-r--r--testsuite/.gitignore1
-rw-r--r--testsuite/.test-rules.make3
-rw-r--r--testsuite/Makefile.in2
-rw-r--r--testsuite/ccm-test.c713
11 files changed, 1588 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 128f8983..49e5e66a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2014-03-23 Niels Möller <nisse@lysator.liu.se>
+
+ From Owen Kirby:
+ * ccm.c: New file.
+ * ccm.h: New file.
+ * ccm-aes128.c: New file.
+ * ccm-aes192.c: New file.
+ * ccm-aes256.c: New file.
+ * Makefile.in (nettle_SOURCES): Added ccm source files.
+ (HEADERS): Added ccm.h.
+ * testsuite/ccm-test.c: New file.
+ * testsuite/Makefile.in (TS_NETTLE_SOURCES): Added ccm-test.c.
+
2014-03-20 Niels Möller <nisse@lysator.liu.se>
From Joachim Strömbergson:
diff --git a/Makefile.in b/Makefile.in
index d88e331f..e61cbd03 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -87,6 +87,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
camellia256-set-decrypt-key.c \
camellia256-meta.c \
cast128.c cast128-meta.c cbc.c \
+ ccm.c ccm-aes128.c ccm-aes192.c ccm-aes256.c \
chacha-crypt.c chacha-core-internal.c \
chacha-poly1305.c chacha-poly1305-meta.c \
chacha-set-key.c chacha-set-nonce.c \
@@ -167,7 +168,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
base16.h base64.h buffer.h camellia.h cast128.h \
- cbc.h chacha.h chacha-poly1305.h ctr.h \
+ cbc.h ccm.h chacha.h chacha-poly1305.h ctr.h \
des.h des-compat.h dsa.h eax.h ecc-curve.h ecc.h ecdsa.h \
gcm.h gosthash94.h hmac.h \
knuth-lfib.h \
diff --git a/ccm-aes128.c b/ccm-aes128.c
new file mode 100644
index 00000000..903ff41d
--- /dev/null
+++ b/ccm-aes128.c
@@ -0,0 +1,106 @@
+/* ccm-aes128.c
+ *
+ * Counter with CBC-MAC mode using AES128 as the underlying cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 Exegin Technologies Limited
+ * Copyright (C) 2014 Owen Kirby
+ *
+ * The nettle library 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.
+ *
+ * The nettle library 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 the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "aes.h"
+#include "ccm.h"
+
+void
+ccm_aes128_set_key(struct ccm_aes128_ctx *ctx, const uint8_t *key)
+{
+ aes128_set_encrypt_key(&ctx->cipher, key);
+}
+
+void
+ccm_aes128_set_nonce(struct ccm_aes128_ctx *ctx,
+ size_t length, const uint8_t *nonce,
+ size_t authlen, size_t msglen, size_t taglen)
+{
+ ccm_set_nonce(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes128_encrypt,
+ length, nonce, authlen, msglen, taglen);
+}
+
+void
+ccm_aes128_update(struct ccm_aes128_ctx *ctx,
+ size_t length, const uint8_t *data)
+{
+ ccm_update(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes128_encrypt,
+ length, data);
+}
+
+void
+ccm_aes128_encrypt(struct ccm_aes128_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src)
+{
+ ccm_encrypt(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes128_encrypt,
+ length, dst, src);
+}
+
+void
+ccm_aes128_decrypt(struct ccm_aes128_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src)
+{
+ ccm_decrypt(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes128_encrypt,
+ length, dst, src);
+}
+
+void
+ccm_aes128_digest(struct ccm_aes128_ctx *ctx,
+ size_t length, uint8_t *digest)
+{
+ ccm_digest(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes128_encrypt,
+ length, digest);
+}
+
+void
+ccm_aes128_encrypt_message(struct ccm_aes128_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ ccm_encrypt_message(&ctx->cipher, (nettle_cipher_func *) aes128_encrypt,
+ nlength, nonce, alength, adata,
+ tlength, clength, dst, src);
+}
+
+int
+ccm_aes128_decrypt_message(struct ccm_aes128_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ return ccm_decrypt_message(&ctx->cipher,
+ (nettle_cipher_func *) aes128_encrypt,
+ nlength, nonce, alength, adata,
+ tlength, clength, dst, src);
+}
diff --git a/ccm-aes192.c b/ccm-aes192.c
new file mode 100644
index 00000000..cd02da72
--- /dev/null
+++ b/ccm-aes192.c
@@ -0,0 +1,106 @@
+/* ccm-aes192.c
+ *
+ * Counter with CBC-MAC mode using AES192 as the underlying cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 Exegin Technologies Limited
+ * Copyright (C) 2014 Owen Kirby
+ *
+ * The nettle library 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.
+ *
+ * The nettle library 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 the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "aes.h"
+#include "ccm.h"
+
+
+void
+ccm_aes192_set_key(struct ccm_aes192_ctx *ctx, const uint8_t *key)
+{
+ aes192_set_encrypt_key(&ctx->cipher, key);
+}
+
+void
+ccm_aes192_set_nonce(struct ccm_aes192_ctx *ctx, size_t length, const uint8_t *nonce,
+ size_t authlen, size_t msglen, size_t taglen)
+{
+ ccm_set_nonce(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes192_encrypt,
+ length, nonce, authlen, msglen, taglen);
+}
+
+void
+ccm_aes192_update(struct ccm_aes192_ctx *ctx,
+ size_t length, const uint8_t *data)
+{
+ ccm_update(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes192_encrypt,
+ length, data);
+}
+
+void
+ccm_aes192_encrypt(struct ccm_aes192_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src)
+{
+ ccm_encrypt(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes192_encrypt,
+ length, dst, src);
+}
+
+void
+ccm_aes192_decrypt(struct ccm_aes192_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src)
+{
+ ccm_decrypt(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes192_encrypt,
+ length, dst, src);
+}
+
+void
+ccm_aes192_digest(struct ccm_aes192_ctx *ctx,
+ size_t length, uint8_t *digest)
+{
+ ccm_digest(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes192_encrypt,
+ length, digest);
+}
+
+void
+ccm_aes192_encrypt_message(struct ccm_aes192_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ ccm_encrypt_message(&ctx->cipher, (nettle_cipher_func *) aes192_encrypt,
+ nlength, nonce, alength, adata,
+ tlength, clength, dst, src);
+}
+
+int
+ccm_aes192_decrypt_message(struct ccm_aes192_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ return ccm_decrypt_message(&ctx->cipher,
+ (nettle_cipher_func *) aes192_encrypt,
+ nlength, nonce, alength, adata,
+ tlength, clength, dst, src);
+}
diff --git a/ccm-aes256.c b/ccm-aes256.c
new file mode 100644
index 00000000..b93ec586
--- /dev/null
+++ b/ccm-aes256.c
@@ -0,0 +1,106 @@
+/* ccm-aes256.c
+ *
+ * Counter with CBC-MAC mode using AES256 as the underlying cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 Exegin Technologies Limited
+ * Copyright (C) 2014 Owen Kirby
+ *
+ * The nettle library 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.
+ *
+ * The nettle library 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 the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "aes.h"
+#include "ccm.h"
+
+
+void
+ccm_aes256_set_key(struct ccm_aes256_ctx *ctx, const uint8_t *key)
+{
+ aes256_set_encrypt_key(&ctx->cipher, key);
+}
+
+void
+ccm_aes256_set_nonce(struct ccm_aes256_ctx *ctx,
+ size_t length, const uint8_t *nonce,
+ size_t authlen, size_t msglen, size_t taglen)
+{
+ ccm_set_nonce(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes256_encrypt,
+ length, nonce, authlen, msglen, taglen);
+}
+
+void
+ccm_aes256_update(struct ccm_aes256_ctx *ctx,
+ size_t length, const uint8_t *data)
+{
+ ccm_update(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes256_encrypt,
+ length, data);
+}
+
+void
+ccm_aes256_encrypt(struct ccm_aes256_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src)
+{
+ ccm_encrypt(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes256_encrypt,
+ length, dst, src);
+}
+
+void
+ccm_aes256_decrypt(struct ccm_aes256_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src)
+{
+ ccm_decrypt(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes256_encrypt,
+ length, dst, src);
+}
+
+void
+ccm_aes256_digest(struct ccm_aes256_ctx *ctx,
+ size_t length, uint8_t *digest)
+{
+ ccm_digest(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes256_encrypt,
+ length, digest);
+}
+
+void
+ccm_aes256_encrypt_message(struct ccm_aes256_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ ccm_encrypt_message(&ctx->cipher, (nettle_cipher_func *) aes256_encrypt,
+ nlength, nonce, alength, adata,
+ tlength, clength, dst, src);
+}
+
+int
+ccm_aes256_decrypt_message(struct ccm_aes256_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ return ccm_decrypt_message(&ctx->cipher, (nettle_cipher_func *) aes256_encrypt,
+ nlength, nonce, alength, adata,
+ tlength, clength, dst, src);
+}
diff --git a/ccm.c b/ccm.c
new file mode 100644
index 00000000..35b5cde7
--- /dev/null
+++ b/ccm.c
@@ -0,0 +1,256 @@
+/* ccm.c
+ *
+ * Counter with CBC-MAC mode, specified by NIST,
+ * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+ *
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 Exegin Technologies Limited
+ * Copyright (C) 2014 Owen Kirby
+ *
+ * The nettle library 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.
+ *
+ * The nettle library 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 the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ccm.h"
+#include "ctr.h"
+
+#include "memxor.h"
+#include "nettle-internal.h"
+#include "macros.h"
+
+/*
+ * The format of the CCM IV (for both CTR and CBC-MAC) is: flags | nonce | count
+ * flags = 1 octet
+ * nonce = N octets
+ * count >= 1 octet
+ *
+ * such that:
+ * sizeof(flags) + sizeof(nonce) + sizeof(count) == 1 block
+ */
+#define CCM_FLAG_L 0x07
+#define CCM_FLAG_M 0x38
+#define CCM_FLAG_ADATA 0x40
+#define CCM_FLAG_RESERVED 0x80
+#define CCM_FLAG_GET_L(_x_) (((_x_) & CCM_FLAG_L) + 1)
+#define CCM_FLAG_SET_L(_x_) (((_x_) - 1) & CCM_FLAG_L)
+#define CCM_FLAG_SET_M(_x_) ((((_x_) - 2) << 2) & CCM_FLAG_M)
+
+#define CCM_OFFSET_FLAGS 0
+#define CCM_OFFSET_NONCE 1
+#define CCM_L_SIZE(_nlen_) (CCM_BLOCK_SIZE - CCM_OFFSET_NONCE - (_nlen_))
+#define CCM_L_MAX_SIZE (CCM_FLAG_L+1)
+#define CCM_IV_MAX_SIZE (CCM_BLOCK_SIZE - CCM_OFFSET_NONCE - 1)
+#define CCM_IV_MIN_SIZE (CCM_BLOCK_SIZE - CCM_OFFSET_NONCE - CCM_L_MAX_SIZE)
+
+/*
+ * The data input to the CBC-MAC: L(a) | adata | padding | plaintext | padding
+ *
+ * blength is the length of data that has been added to the CBC-MAC modulus the
+ * cipher block size. If the value of blength is non-zero then some data has
+ * been XOR'ed into the CBC-MAC, and we will need to pad the block (XOR with 0),
+ * and iterate the cipher one more time.
+ *
+ * The end of adata is detected implicitly by the first call to the encrypt()
+ * and decrypt() functions, and will call ccm_pad() to insert the padding if
+ * necessary. Because of the underlying CTR encryption, the encrypt() and
+ * decrypt() functions must be called with a multiple of the block size and
+ * therefore blength should be zero on all but the first call.
+ *
+ * Likewise, the end of the plaintext is implicitly determined by the first call
+ * to the digest() function, which will pad if the final CTR encryption was not
+ * a multiple of the block size.
+ */
+static void
+ccm_pad(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f)
+{
+ if (ctx->blength) f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);
+ ctx->blength = 0;
+}
+
+static void
+ccm_build_iv(uint8_t *iv, size_t noncelen, const uint8_t *nonce,
+ uint8_t flags, size_t count)
+{
+ unsigned int i;
+
+ /* Sanity check the nonce length. */
+ assert(noncelen >= CCM_IV_MIN_SIZE);
+ assert(noncelen <= CCM_IV_MAX_SIZE);
+
+ /* Generate the IV */
+ iv[CCM_OFFSET_FLAGS] = flags | CCM_FLAG_SET_L(CCM_L_SIZE(noncelen));
+ memcpy(&iv[CCM_OFFSET_NONCE], nonce, noncelen);
+ for (i=(CCM_BLOCK_SIZE - 1); i >= (CCM_OFFSET_NONCE + noncelen); i--) {
+ iv[i] = count & 0xff;
+ count >>= 8;
+ }
+
+ /* Ensure the count was not truncated. */
+ assert(!count);
+}
+
+void
+ccm_set_nonce(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t length, const uint8_t *nonce,
+ size_t authlen, size_t msglen, size_t taglen)
+{
+ /* Generate the IV for the CTR and CBC-MAC */
+ ctx->blength = 0;
+ ccm_build_iv(ctx->tag.b, length, nonce, CCM_FLAG_SET_M(taglen), msglen);
+ ccm_build_iv(ctx->ctr.b, length, nonce, 0, 1);
+
+ /* If no auth data, encrypt B0 and skip L(a) */
+ if (!authlen) {
+ f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);
+ return;
+ }
+
+ /* Encrypt B0 (with the adata flag), and input L(a) to the CBC-MAC. */
+ ctx->tag.b[CCM_OFFSET_FLAGS] |= CCM_FLAG_ADATA;
+ f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);
+ if (authlen >= (0x01ULL << 32)) {
+ /* Encode L(a) as 0xff || 0xff || <64-bit integer> */
+ ctx->tag.b[ctx->blength++] ^= 0xff;
+ ctx->tag.b[ctx->blength++] ^= 0xff;
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 56) & 0xff;
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 48) & 0xff;
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 40) & 0xff;
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 32) & 0xff;
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 24) & 0xff;
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 16) & 0xff;
+ }
+ else if (authlen >= ((0x1ULL << 16) - (0x1ULL << 8))) {
+ /* Encode L(a) as 0xff || 0xfe || <32-bit integer> */
+ ctx->tag.b[ctx->blength++] ^= 0xff;
+ ctx->tag.b[ctx->blength++] ^= 0xfe;
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 24) & 0xff;
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 16) & 0xff;
+ }
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 8) & 0xff;
+ ctx->tag.b[ctx->blength++] ^= (authlen >> 0) & 0xff;
+}
+
+void
+ccm_update(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t length, const uint8_t *data)
+{
+ const uint8_t *end = data + length;
+
+ /* If we don't have enough to fill a block, save the data for later. */
+ if ((ctx->blength + length) < CCM_BLOCK_SIZE) {
+ memxor(&ctx->tag.b[ctx->blength], data, length);
+ ctx->blength += length;
+ return;
+ }
+
+ /* Process a partially filled block. */
+ if (ctx->blength) {
+ memxor(&ctx->tag.b[ctx->blength], data, CCM_BLOCK_SIZE - ctx->blength);
+ data += (CCM_BLOCK_SIZE - ctx->blength);
+ f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);
+ }
+
+ /* Process full blocks. */
+ while ((data + CCM_BLOCK_SIZE) < end) {
+ memxor(ctx->tag.b, data, CCM_BLOCK_SIZE);
+ f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);
+ data += CCM_BLOCK_SIZE;
+ } /* while */
+
+ /* Save leftovers for later. */
+ ctx->blength = (end - data);
+ if (ctx->blength) memxor(&ctx->tag.b, data, ctx->blength);
+}
+
+/*
+ * Because of the underlying CTR mode encryption, when called multiple times
+ * the data in intermediate calls must be provided in multiples of the block
+ * size.
+ */
+void
+ccm_encrypt(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t length, uint8_t *dst, const uint8_t *src)
+{
+ ccm_pad(ctx, cipher, f);
+ ccm_update(ctx, cipher, f, length, src);
+ ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, dst, src);
+}
+
+/*
+ * Because of the underlying CTR mode decryption, when called multiple times
+ * the data in intermediate calls must be provided in multiples of the block
+ * size.
+ */
+void
+ccm_decrypt(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t length, uint8_t *dst, const uint8_t *src)
+{
+ ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, dst, src);
+ ccm_pad(ctx, cipher, f);
+ ccm_update(ctx, cipher, f, length, dst);
+}
+
+void
+ccm_digest(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t length, uint8_t *digest)
+{
+ int i = CCM_BLOCK_SIZE - CCM_FLAG_GET_L(ctx->ctr.b[CCM_OFFSET_FLAGS]);
+ assert(length <= CCM_BLOCK_SIZE);
+ while (i < CCM_BLOCK_SIZE) ctx->ctr.b[i++] = 0;
+ ccm_pad(ctx, cipher, f);
+ ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, digest, ctx->tag.b);
+}
+
+void
+ccm_encrypt_message(const void *cipher, nettle_cipher_func *f,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata, size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ struct ccm_ctx ctx;
+ uint8_t *tag = dst + (clength-tlength);
+ assert(clength >= tlength);
+ ccm_set_nonce(&ctx, cipher, f, nlength, nonce, alength, clength-tlength, tlength);
+ ccm_update(&ctx, cipher, f, alength, adata);
+ ccm_encrypt(&ctx, cipher, f, clength-tlength, dst, src);
+ ccm_digest(&ctx, cipher, f, tlength, tag);
+}
+
+int
+ccm_decrypt_message(const void *cipher, nettle_cipher_func *f,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata, size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ struct ccm_ctx ctx;
+ uint8_t tag[CCM_BLOCK_SIZE];
+ assert(clength >= tlength);
+ ccm_set_nonce(&ctx, cipher, f, nlength, nonce, alength, clength-tlength, tlength);
+ ccm_update(&ctx, cipher, f, alength, adata);
+ ccm_decrypt(&ctx, cipher, f, clength-tlength, dst, src);
+ ccm_digest(&ctx, cipher, f, tlength, tag);
+ return (memcmp(tag, src + (clength-tlength), tlength) == 0);
+}
diff --git a/ccm.h b/ccm.h
new file mode 100644
index 00000000..40e9823b
--- /dev/null
+++ b/ccm.h
@@ -0,0 +1,281 @@
+/* ccm.h
+ *
+ * Counter with CBC-MAC mode, specified by NIST,
+ * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+ *
+ * NIST SP800-38C doesn't specify the particular formatting and counter generation
+ * algorithm for CCM, but it does include an example algorithm. This example
+ * has become the de-factor standard, and has been adopted by both the IETF and
+ * IEEE across a wide variety of protocols.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 Exegin Technologies Limited
+ * Copyright (C) 2014 Owen Kirby
+ *
+ * Contributed by Owen Kirby
+ *
+ * The nettle library 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.
+ *
+ * The nettle library 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 the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#ifndef NETTLE_CCM_H_INCLUDED
+#define NETTLE_CCM_H_INCLUDED
+
+#include "aes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Name mangling */
+#define ccm_set_nonce nettle_ccm_set_nonce
+#define ccm_update nettle_ccm_update
+#define ccm_encrypt nettle_ccm_encrypt
+#define ccm_decrypt nettle_ccm_decrypt
+#define ccm_digest nettle_ccm_digest
+#define ccm_encrypt_message nettle_ccm_encrypt_message
+#define ccm_decrypt_message nettle_ccm_decrypt_message
+
+#define ccm_aes128_set_key nettle_ccm_aes128_set_key
+#define ccm_aes128_set_nonce nettle_ccm_aes128_set_nonce
+#define ccm_aes128_update nettle_ccm_aes128_update
+#define ccm_aes128_encrypt nettle_ccm_aes128_encrypt
+#define ccm_aes128_decrypt nettle_ccm_aes128_decrypt
+#define ccm_aes128_digest nettle_ccm_aes128_digest
+#define ccm_aes128_encrypt_message nettle_ccm_aes128_encrypt_message
+#define ccm_aes128_decrypt_message nettle_ccm_aes128_decrypt_message
+
+#define ccm_aes192_set_key nettle_ccm_aes192_set_key
+#define ccm_aes192_set_nonce nettle_ccm_aes192_set_nonce
+#define ccm_aes192_update nettle_ccm_aes192_update
+#define ccm_aes192_encrypt nettle_ccm_aes192_encrypt
+#define ccm_aes192_decrypt nettle_ccm_aes192_decrypt
+#define ccm_aes192_digest nettle_ccm_aes192_digest
+#define ccm_aes192_encrypt_message nettle_ccm_aes192_encrypt_message
+#define ccm_aes192_decrypt_message nettle_ccm_aes192_decrypt_message
+
+#define ccm_aes256_set_key nettle_ccm_aes256_set_key
+#define ccm_aes256_set_nonce nettle_ccm_aes256_set_nonce
+#define ccm_aes256_update nettle_ccm_aes256_update
+#define ccm_aes256_encrypt nettle_ccm_aes256_encrypt
+#define ccm_aes256_decrypt nettle_ccm_aes256_decrypt
+#define ccm_aes256_digest nettle_ccm_aes256_digest
+#define ccm_aes256_encrypt_message nettle_ccm_aes256_encrypt_message
+#define ccm_aes256_decrypt_message nettle_ccm_aes256_decrypt_message
+
+/* For CCM, the block size of the block cipher shall be 128 bits. */
+#define CCM_BLOCK_SIZE 16
+
+/* Per-message state */
+struct ccm_ctx {
+ union nettle_block16 ctr; /* Counter for CTR encryption. */
+ union nettle_block16 tag; /* CBC-MAC message tag. */
+ /* Length of data processed by the CBC-MAC modulus the block size */
+ unsigned int blength;
+};
+
+/*
+ * CCM mode requires the adata and message lengths when building the IV, which
+ * prevents streaming processing and it incompatible with the AEAD API.
+ */
+void
+ccm_set_nonce(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t noncelen, const uint8_t *nonce,
+ size_t authlen, size_t msglen, size_t taglen);
+
+void
+ccm_update(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t length, const uint8_t *data);
+
+void
+ccm_encrypt(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+ccm_decrypt(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+ccm_digest(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
+ size_t length, uint8_t *digest);
+
+/*
+ * All-in-one encryption and decryption API:
+ * tlength = sizeof(digest)
+ * mlength = sizeof(cleartext)
+ * clength = sizeof(ciphertext) = mlength + tlength
+ *
+ * The ciphertext will contain the encrypted payload with the message digest
+ * appended to the end.
+ */
+void
+ccm_encrypt_message(const void *cipher, nettle_cipher_func *f,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+/*
+ * The decryption function will write the plaintext to dst and parse the digest
+ * from the final tlength bytes of the ciphertext. If the digest matched the
+ * value computed during decryption then this will return 1, or it will return
+ * 0 if the digest was invalid.
+ */
+int
+ccm_decrypt_message(const void *cipher, nettle_cipher_func *f,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+/* CCM Mode with AES-128 */
+struct ccm_aes128_ctx {
+ struct ccm_ctx ccm;
+ struct aes128_ctx cipher;
+};
+
+void
+ccm_aes128_set_key(struct ccm_aes128_ctx *ctx, const uint8_t *key);
+
+void
+ccm_aes128_set_nonce(struct ccm_aes128_ctx *ctx,
+ size_t length, const uint8_t *nonce,
+ size_t authlen, size_t msglen, size_t taglen);
+
+void
+ccm_aes128_update (struct ccm_aes128_ctx *ctx,
+ size_t length, const uint8_t *data);
+
+void
+ccm_aes128_encrypt(struct ccm_aes128_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+ccm_aes128_decrypt(struct ccm_aes128_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+ccm_aes128_digest(struct ccm_aes128_ctx *ctx,
+ size_t length, uint8_t *digest);
+
+void
+ccm_aes128_encrypt_message(struct ccm_aes128_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+int
+ccm_aes128_decrypt_message(struct ccm_aes128_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+struct ccm_aes192_ctx {
+ struct ccm_ctx ccm;
+ struct aes192_ctx cipher;
+};
+
+/* CCM Mode with AES-192 */
+void
+ccm_aes192_set_key(struct ccm_aes192_ctx *ctx, const uint8_t *key);
+
+void
+ccm_aes192_set_nonce(struct ccm_aes192_ctx *ctx,
+ size_t length, const uint8_t *nonce,
+ size_t authlen, size_t msglen, size_t taglen);
+
+void
+ccm_aes192_update(struct ccm_aes192_ctx *ctx,
+ size_t length, const uint8_t *data);
+
+void
+ccm_aes192_encrypt(struct ccm_aes192_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+ccm_aes192_decrypt(struct ccm_aes192_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+ccm_aes192_digest(struct ccm_aes192_ctx *ctx,
+ size_t length, uint8_t *digest);
+
+void
+ccm_aes192_encrypt_message(struct ccm_aes192_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+int
+ccm_aes192_decrypt_message(struct ccm_aes192_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+/* CCM Mode with AES-256 */
+struct ccm_aes256_ctx {
+ struct ccm_ctx ccm;
+ struct aes256_ctx cipher;
+};
+
+void
+ccm_aes256_set_key(struct ccm_aes256_ctx *ctx, const uint8_t *key);
+
+void
+ccm_aes256_set_nonce(struct ccm_aes256_ctx *ctx,
+ size_t length, const uint8_t *nonce,
+ size_t authlen, size_t msglen, size_t taglen);
+
+void
+ccm_aes256_update(struct ccm_aes256_ctx *ctx,
+ size_t length, const uint8_t *data);
+
+void
+ccm_aes256_encrypt(struct ccm_aes256_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+ccm_aes256_decrypt(struct ccm_aes256_ctx *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+ccm_aes256_digest(struct ccm_aes256_ctx *ctx,
+ size_t length, uint8_t *digest);
+
+void
+ccm_aes256_encrypt_message(struct ccm_aes256_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+int
+ccm_aes256_decrypt_message(struct ccm_aes256_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t tlength,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_CCM_H_INCLUDED */
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
index 3b836af5..8e5521b4 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -11,6 +11,7 @@
/camellia-test
/cast128-test
/cbc-test
+/ccm-test
/ctr-test
/cxx-test
/des-compat-test
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index 43079ecb..16d107ca 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -100,6 +100,9 @@ knuth-lfib-test$(EXEEXT): knuth-lfib-test.$(OBJEXT)
cbc-test$(EXEEXT): cbc-test.$(OBJEXT)
$(LINK) cbc-test.$(OBJEXT) $(TEST_OBJS) -o cbc-test$(EXEEXT)
+ccm-test$(EXEEXT): ccm-test.$(OBJEXT)
+ $(LINK) ccm-test.$(OBJEXT) $(TEST_OBJS) -o ccm-test$(EXEEXT)
+
ctr-test$(EXEEXT): ctr-test.$(OBJEXT)
$(LINK) ctr-test.$(OBJEXT) $(TEST_OBJS) -o ctr-test$(EXEEXT)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index d59a2cba..30611c76 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -25,7 +25,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
sha3-384-test.c sha3-512-test.c \
serpent-test.c twofish-test.c \
knuth-lfib-test.c \
- cbc-test.c ctr-test.c gcm-test.c eax-test.c \
+ cbc-test.c ctr-test.c gcm-test.c eax-test.c ccm-test.c \
poly1305-test.c chacha-poly1305-test.c \
hmac-test.c umac-test.c \
meta-hash-test.c meta-cipher-test.c meta-armor-test.c \
diff --git a/testsuite/ccm-test.c b/testsuite/ccm-test.c
new file mode 100644
index 00000000..a3efb3d1
--- /dev/null
+++ b/testsuite/ccm-test.c
@@ -0,0 +1,713 @@
+/* ccm-test.c
+ *
+ * Self-test and vectors for CCM mode ciphers using AES-128 and AES-256. The
+ * test vectors have been collected from the following standards:
+ * NIST SP800-38C
+ * RFC 3610
+ * IEEE 802.15.4-2011
+ * IEEE P1619.1/D22 July 2007 (draft version)
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 Exegin Technologies Limited
+ * Copyright (C) 2014 Owen Kirby
+ *
+ * The nettle library 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.
+ *
+ * The nettle library 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 the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+#include "testutils.h"
+#include "aes.h"
+#include "ccm.h"
+#include "knuth-lfib.h"
+
+static void
+test_compare_results(const char *name,
+ const struct tstring *adata,
+ /* Expected results. */
+ const struct tstring *e_clear,
+ const struct tstring *e_cipher,
+ /* Actual results. */
+ const void *clear,
+ const void *cipher,
+ const void *digest) /* digest optional. */
+{
+ int tlength = (e_cipher->length - e_clear->length);
+ if (digest && tlength && !MEMEQ(tlength, e_cipher->data + e_clear->length, digest))
+ {
+ fprintf(stderr, "%s digest failed:\nAdata:", name);
+ tstring_print_hex(adata);
+ fprintf(stderr, "\nInput: ");
+ tstring_print_hex(e_clear);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(tlength, digest);
+ fprintf(stderr, "\nExpected:");
+ print_hex(tlength, e_cipher->data + e_clear->length);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ if (!MEMEQ(e_cipher->length, e_cipher->data, cipher))
+ {
+ fprintf(stderr, "%s: encryption failed\nAdata: ", name);
+ tstring_print_hex(adata);
+ fprintf(stderr, "\nInput: ");
+ tstring_print_hex(e_clear);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(e_cipher->length, cipher);
+ fprintf(stderr, "\nExpected:");
+ tstring_print_hex(e_cipher);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ if (!MEMEQ(e_clear->length, e_clear->data, clear))
+ {
+ fprintf(stderr, "%s decrypt failed:\nAdata:", name);
+ tstring_print_hex(adata);
+ fprintf(stderr, "\nInput: ");
+ tstring_print_hex(e_cipher);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(e_clear->length, clear);
+ fprintf(stderr, "\nExpected:");
+ tstring_print_hex(e_clear);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+} /* test_compare_results */
+
+static void
+test_cipher_ccm(const struct nettle_cipher *cipher,
+ const struct tstring *key,
+ const struct tstring *nonce,
+ const struct tstring *authdata,
+ int repeat,
+ const struct tstring *cleartext,
+ const struct tstring *ciphertext)
+{
+ void *ctx = xalloc(cipher->context_size);
+ uint8_t *en_data;
+ uint8_t *de_data;
+ uint8_t *en_digest;
+ uint8_t de_digest[CCM_BLOCK_SIZE];
+ size_t tlength;
+ struct ccm_ctx ccm;
+ int i;
+
+ ASSERT (key->length == cipher->key_size);
+ ASSERT (cleartext->length <= ciphertext->length);
+ ASSERT ((cleartext->length + CCM_BLOCK_SIZE) >= ciphertext->length);
+ tlength = ciphertext->length - cleartext->length;
+ if (!authdata) repeat = 0;
+
+ de_data = xalloc(cleartext->length);
+ en_data = xalloc(ciphertext->length);
+ en_digest = en_data + cleartext->length;
+ cipher->set_encrypt_key(ctx, key->data);
+
+ /* Encrypt using the incremental API. */
+ ccm_set_nonce(&ccm, ctx, cipher->encrypt, nonce->length, nonce->data,
+ authdata->length * repeat, cleartext->length, tlength);
+ for (i = 0; i < repeat; i++) {
+ ccm_update(&ccm, ctx, cipher->encrypt, authdata->length, authdata->data);
+ }
+ ccm_encrypt(&ccm, ctx, cipher->encrypt, cleartext->length, en_data, cleartext->data);
+ ccm_digest(&ccm, ctx, cipher->encrypt, tlength, en_digest);
+
+ /* Decrypt using the incremental API. */
+ ccm_set_nonce(&ccm, ctx, cipher->encrypt, nonce->length, nonce->data,
+ authdata->length * repeat, cleartext->length, tlength);
+ for (i = 0; i < repeat; i++) {
+ ccm_update(&ccm, ctx, cipher->encrypt, authdata->length, authdata->data);
+ }
+ ccm_decrypt(&ccm, ctx, cipher->encrypt, cleartext->length, de_data, ciphertext->data);
+ ccm_digest(&ccm, ctx, cipher->encrypt, tlength, de_digest);
+
+ /* Compare results using the generic API. */
+ test_compare_results("CCM", authdata,
+ cleartext, ciphertext, de_data, en_data, de_digest);
+
+ /* Ensure we get the same answers using the all-in-one API. */
+ if (repeat <= 1) {
+ int ret;
+ memset(de_data, 0, cleartext->length);
+ memset(en_data, 0, ciphertext->length);
+ memset(de_digest, 0, sizeof(de_digest));
+
+ ccm_encrypt_message(ctx, cipher->encrypt, nonce->length, nonce->data,
+ authdata->length, authdata->data, tlength, ciphertext->length, en_data, cleartext->data);
+
+ ret = ccm_decrypt_message(ctx, cipher->encrypt, nonce->length, nonce->data,
+ authdata->length, authdata->data, tlength, ciphertext->length, de_data, ciphertext->data);
+
+ if (ret != 1) fprintf(stderr, "ccm_decrypt_message failed to validate message\n");
+ test_compare_results("CCM_MSG", authdata,
+ cleartext, ciphertext, de_data, en_data, NULL);
+
+ /* Ensure that we can detect corrupted message or tag data. */
+ if (tlength) {
+ en_data[0] ^= 1;
+ ret = ccm_decrypt_message(ctx, cipher->encrypt, nonce->length, nonce->data,
+ authdata->length, authdata->data, tlength, ciphertext->length, de_data, en_data);
+ if (ret != 0) fprintf(stderr, "ccm_decrypt_message failed to detect corrupted message\n");
+ }
+ /* Ensure we can detect corrupted adata. */
+ if (tlength && authdata->length) {
+ ret = ccm_decrypt_message(ctx, cipher->encrypt, nonce->length, nonce->data,
+ authdata->length-1, authdata->data, tlength, ciphertext->length, de_data, ciphertext->data);
+ if (ret != 0) fprintf(stderr, "ccm_decrypt_message failed to detect corrupted message\n");
+ }
+ }
+
+ /* Ensure we get the same answers using the per-cipher API. */
+ if (cipher == &nettle_aes128) {
+ struct ccm_aes128_ctx aes;
+ memset(de_data, 0, cleartext->length);
+ memset(en_data, 0, ciphertext->length);
+ memset(de_digest, 0, sizeof(de_digest));
+
+ /* AES-128 encrypt. */
+ ccm_aes128_set_key(&aes, key->data);
+ ccm_aes128_set_nonce(&aes, nonce->length, nonce->data,
+ authdata->length * repeat, cleartext->length, tlength);
+ for (i = 0; i < repeat; i++) {
+ ccm_aes128_update(&aes, authdata->length, authdata->data);
+ }
+ ccm_aes128_encrypt(&aes, cleartext->length, en_data, cleartext->data);
+ ccm_aes128_digest(&aes, tlength, en_digest);
+
+ /* AES-128 decrypt. */
+ ccm_aes128_set_nonce(&aes, nonce->length, nonce->data,
+ authdata->length * repeat, cleartext->length, tlength);
+ for (i = 0; i < repeat; i++) {
+ ccm_aes128_update(&aes, authdata->length, authdata->data);
+ }
+ ccm_aes128_decrypt(&aes, cleartext->length, de_data, ciphertext->data);
+ ccm_aes128_digest(&aes, tlength, de_digest);
+
+ test_compare_results("CCM_AES_128", authdata,
+ cleartext, ciphertext, de_data, en_data, de_digest);
+ }
+ /* TODO: I couldn't find any test cases for CCM-AES-192 */
+ if (cipher == &nettle_aes256) {
+ struct ccm_aes256_ctx aes;
+ memset(de_data, 0, cleartext->length);
+ memset(en_data, 0, ciphertext->length);
+ memset(de_digest, 0, sizeof(de_digest));
+
+ /* AES-256 encrypt. */
+ ccm_aes256_set_key(&aes, key->data);
+ ccm_aes256_set_nonce(&aes, nonce->length, nonce->data,
+ authdata->length * repeat, cleartext->length, tlength);
+ for (i = 0; i < repeat; i++) {
+ ccm_aes256_update(&aes, authdata->length, authdata->data);
+ }
+ ccm_aes256_encrypt(&aes, cleartext->length, en_data, cleartext->data);
+ ccm_aes256_digest(&aes, tlength, en_digest);
+
+ /* AES-256 decrypt. */
+ ccm_aes256_set_nonce(&aes, nonce->length, nonce->data,
+ authdata->length * repeat, cleartext->length, tlength);
+ for (i = 0; i < repeat; i++) {
+ ccm_aes256_update(&aes, authdata->length, authdata->data);
+ }
+ ccm_aes256_decrypt(&aes, cleartext->length, de_data, ciphertext->data);
+ ccm_aes256_digest(&aes, tlength, de_digest);
+
+ test_compare_results("CCM_AES_256", authdata,
+ cleartext, ciphertext, de_data, en_data, de_digest);
+ }
+
+ free(ctx);
+ free(en_data);
+ free(de_data);
+}
+
+void
+test_main(void)
+{
+ /* Create a pattern of 00010203 04050607 08090a00b 0c0d0e0f ... */
+ struct tstring *adata;
+ unsigned int i;
+ adata = tstring_alloc(256);
+ for (i=0; i<adata->length; i++) adata->data[i] = (i & 0xff);
+
+ /* From NIST spec 800-38C on AES modes.
+ *
+ * Appendix C: Example Vectors
+ */
+ /*
+ * C.1 Example 1
+ * Klen = 128, Tlen = 32, Nlen = 56, Alen = 64, Plen = 32
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("404142434445464748494a4b4c4d4e4f"),
+ SHEX("10111213141516"),
+ SHEX("0001020304050607"), 1,
+ SHEX("20212223"),
+ SHEX("7162015b"
+ "4dac255d"));
+
+ /*
+ * C.2 Example 2
+ * Klen = 128, Tlen = 48, Nlen = 64, Alen = 128, Plen = 128
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("404142434445464748494a4b4c4d4e4f"),
+ SHEX("1011121314151617"),
+ SHEX("000102030405060708090a0b0c0d0e0f"), 1,
+ SHEX("202122232425262728292a2b2c2d2e2f"),
+ SHEX("d2a1f0e051ea5f62081a7792073d593d"
+ "1fc64fbfaccd"));
+
+ /*
+ * C.3 Example 3
+ * Klen = 128, Tlen = 64, Nlen = 96, Alen = 160, Plen = 192
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("404142434445464748494a4b4c4d4e4f"),
+ SHEX("101112131415161718191a1b"),
+ SHEX("000102030405060708090a0b0c0d0e0f"
+ "10111213"), 1,
+ SHEX("202122232425262728292a2b2c2d2e2f"
+ "3031323334353637"),
+ SHEX("e3b201a9f5b71a7a9b1ceaeccd97e70b"
+ "6176aad9a4428aa5 484392fbc1b09951"));
+
+ /*
+ * C.4 Example 4
+ * Klen = 128, Tlen = 112, Nlen = 104, Alen = 524288, Plen = 256
+ * A = 00010203 04050607 08090a0b 0c0d0e0f
+ * 10111213 ...
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("404142434445464748494a4b4c4d4e4f"),
+ SHEX("101112131415161718191a1b1c"),
+ adata, 256,
+ SHEX("202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"),
+ SHEX("69915dad1e84c6376a68c2967e4dab61"
+ "5ae0fd1faec44cc484828529463ccf72"
+ "b4ac6bec93e8598e7f0dadbcea5b"));
+
+ /* From RFC 3610
+ *
+ * Section 8: Test Vectors
+ * Packet Vector #1
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 03 02 01 00 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07"), 1,
+ SHEX("08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E"),
+ SHEX("58 8C 97 9A 61 C6 63 D2 F0 66 D0 C2 C0 F9 89 80 6D 5F 6B 61 DA C3 84"
+ "17 E8 D1 2C FD F9 26 E0"));
+
+ /*
+ * Packet Vector #2
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 04 03 02 01 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07"), 1,
+ SHEX("08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"),
+ SHEX("72 C9 1A 36 E1 35 F8 CF 29 1C A8 94 08 5C 87 E3 CC 15 C4 39 C9 E4 3A 3B"
+ "A0 91 D5 6E 10 40 09 16"));
+
+ /*
+ * Packet Vector #3
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 05 04 03 02 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07"), 1,
+ SHEX("08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20"),
+ SHEX("51 B1 E5 F4 4A 19 7D 1D A4 6B 0F 8E 2D 28 2A E8 71 E8 38 BB 64 DA 85 96 57"
+ "4A DA A7 6F BD 9F B0 C5"));
+
+ /*
+ * Packet Vector #4
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 06 05 04 03 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07 08 09 0A 0B"), 1,
+ SHEX("0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E"),
+ SHEX("A2 8C 68 65 93 9A 9A 79 FA AA 5C 4C 2A 9D 4A 91 CD AC 8C"
+ "96 C8 61 B9 C9 E6 1E F1"));
+
+ /*
+ * Packet Vector #5
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 07 06 05 04 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07 08 09 0A 0B"), 1,
+ SHEX("0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"),
+ SHEX("DC F1 FB 7B 5D 9E 23 FB 9D 4E 13 12 53 65 8A D8 6E BD CA 3E"
+ "51 E8 3F 07 7D 9C 2D 93"));
+
+ /*
+ * Packet Vector #6
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 08 07 06 05 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07 08 09 0A 0B"), 1,
+ SHEX("0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20"),
+ SHEX("6F C1 B0 11 F0 06 56 8B 51 71 A4 2D 95 3D 46 9B 25 70 A4 BD 87"
+ "40 5A 04 43 AC 91 CB 94"));
+
+ /*
+ * Packet Vector #7
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 09 08 07 06 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07"), 1,
+ SHEX("08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E"),
+ SHEX("01 35 D1 B2 C9 5F 41 D5 D1 D4 FE C1 85 D1 66 B8 09 4E 99 9D FE D9 6C"
+ "04 8C 56 60 2C 97 AC BB 74 90"));
+
+ /*
+ * Packet Vector #8
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 0A 09 08 07 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07"), 1,
+ SHEX("08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"),
+ SHEX("7B 75 39 9A C0 83 1D D2 F0 BB D7 58 79 A2 FD 8F 6C AE 6B 6C D9 B7 DB 24"
+ "C1 7B 44 33 F4 34 96 3F 34 B4"));
+
+ /*
+ * Packet Vector #9
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 0B 0A 09 08 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07"), 1,
+ SHEX("08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20"),
+ SHEX("82 53 1A 60 CC 24 94 5A 4B 82 79 18 1A B5 C8 4D F2 1C E7 F9 B7 3F 42 E1 97"
+ "EA 9C 07 E5 6B 5E B1 7E 5F 4E"));
+
+ /*
+ * Packet Vector #10
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 0C 0B 0A 09 A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07 08 09 0A 0B"), 1,
+ SHEX("0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E"),
+ SHEX("07 34 25 94 15 77 85 15 2B 07 40 98 33 0A BB 14 1B 94 7B"
+ "56 6A A9 40 6B 4D 99 99 88 DD"));
+
+ /*
+ * Packet Vector #11
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 0D 0C 0B 0A A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07 08 09 0A 0B"), 1,
+ SHEX("0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"),
+ SHEX("67 6B B2 03 80 B0 E3 01 E8 AB 79 59 0A 39 6D A7 8B 83 49 34"
+ "F5 3A A2 E9 10 7A 8B 6C 02 2C"));
+
+ /*
+ * Packet Vector #12
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("00 00 00 0E 0D 0C 0B A0 A1 A2 A3 A4 A5"),
+ SHEX("00 01 02 03 04 05 06 07 08 09 0A 0B"), 1,
+ SHEX("0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20"),
+ SHEX("C0 FF A0 D6 F0 5B DB 67 F2 4D 43 A4 33 8D 2A A4 BE D7 B2 0E 43"
+ "CD 1A A3 16 62 E7 AD 65 D6 DB"));
+
+ /*
+ * Packet Vector #13
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 41 2B 4E A9 CD BE 3C 96 96 76 6C FA"),
+ SHEX("0B E1 A8 8B AC E0 18 B1"), 1,
+ SHEX("08 E8 CF 97 D8 20 EA 25 84 60 E9 6A D9 CF 52 89 05 4D 89 5C EA C4 7C"),
+ SHEX("4C B9 7F 86 A2 A4 68 9A 87 79 47 AB 80 91 EF 53 86 A6 FF BD D0 80 F8"
+ "E7 8C F7 CB 0C DD D7 B3"));
+
+ /*
+ * Packet Vector #14
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 33 56 8E F7 B2 63 3C 96 96 76 6C FA"),
+ SHEX("63 01 8F 76 DC 8A 1B CB"), 1,
+ SHEX("90 20 EA 6F 91 BD D8 5A FA 00 39 BA 4B AF F9 BF B7 9C 70 28 94 9C D0 EC"),
+ SHEX("4C CB 1E 7C A9 81 BE FA A0 72 6C 55 D3 78 06 12 98 C8 5C 92 81 4A BC 33"
+ "C5 2E E8 1D 7D 77 C0 8A"));
+
+ /*
+ * Packet Vector #15
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 10 3F E4 13 36 71 3C 96 96 76 6C FA"),
+ SHEX("AA 6C FA 36 CA E8 6B 40"), 1,
+ SHEX("B9 16 E0 EA CC 1C 00 D7 DC EC 68 EC 0B 3B BB 1A 02 DE 8A 2D 1A A3 46 13 2E"),
+ SHEX("B1 D2 3A 22 20 DD C0 AC 90 0D 9A A0 3C 61 FC F4 A5 59 A4 41 77 67 08 97 08"
+ "A7 76 79 6E DB 72 35 06"));
+
+ /*
+ * Packet Vector #16
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 76 4C 63 B8 05 8E 3C 96 96 76 6C FA"),
+ SHEX("D0 D0 73 5C 53 1E 1B EC F0 49 C2 44"), 1,
+ SHEX("12 DA AC 56 30 EF A5 39 6F 77 0C E1 A6 6B 21 F7 B2 10 1C"),
+ SHEX("14 D2 53 C3 96 7B 70 60 9B 7C BB 7C 49 91 60 28 32 45 26"
+ "9A 6F 49 97 5B CA DE AF"));
+
+ /*
+ * Packet Vector #17
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 F8 B6 78 09 4E 3B 3C 96 96 76 6C FA"),
+ SHEX("77 B6 0F 01 1C 03 E1 52 58 99 BC AE"), 1,
+ SHEX("E8 8B 6A 46 C7 8D 63 E5 2E B8 C5 46 EF B5 DE 6F 75 E9 CC 0D"),
+ SHEX("55 45 FF 1A 08 5E E2 EF BF 52 B2 E0 4B EE 1E 23 36 C7 3E 3F"
+ "76 2C 0C 77 44 FE 7E 3C"));
+
+ /*
+ * Packet Vector #18
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 D5 60 91 2D 3F 70 3C 96 96 76 6C FA"),
+ SHEX("CD 90 44 D2 B7 1F DB 81 20 EA 60 C0"), 1,
+ SHEX("64 35 AC BA FB 11 A8 2E 2F 07 1D 7C A4 A5 EB D9 3A 80 3B A8 7F"),
+ SHEX("00 97 69 EC AB DF 48 62 55 94 C5 92 51 E6 03 57 22 67 5E 04 C8"
+ "47 09 9E 5A E0 70 45 51"));
+
+ /*
+ * Packet Vector #19
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 42 FF F8 F1 95 1C 3C 96 96 76 6C FA"),
+ SHEX("D8 5B C7 E6 9F 94 4F B8"), 1,
+ SHEX("8A 19 B9 50 BC F7 1A 01 8E 5E 67 01 C9 17 87 65 98 09 D6 7D BE DD 18"),
+ SHEX("BC 21 8D AA 94 74 27 B6 DB 38 6A 99 AC 1A EF 23 AD E0 B5 29 39 CB 6A"
+ "63 7C F9 BE C2 40 88 97 C6 BA"));
+
+ /*
+ * Packet Vector #20
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 92 0F 40 E5 6C DC 3C 96 96 76 6C FA"),
+ SHEX("74 A0 EB C9 06 9F 5B 37"), 1,
+ SHEX("17 61 43 3C 37 C5 A3 5F C1 F3 9F 40 63 02 EB 90 7C 61 63 BE 38 C9 84 37"),
+ SHEX("58 10 E6 FD 25 87 40 22 E8 03 61 A4 78 E3 E9 CF 48 4A B0 4F 44 7E FF F6"
+ "F0 A4 77 CC 2F C9 BF 54 89 44"));
+
+ /*
+ * Packet Vector #21
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 27 CA 0C 71 20 BC 3C 96 96 76 6C FA"),
+ SHEX("44 A3 AA 3A AE 64 75 CA"), 1,
+ SHEX("A4 34 A8 E5 85 00 C6 E4 15 30 53 88 62 D6 86 EA 9E 81 30 1B 5A E4 22 6B FA"),
+ SHEX("F2 BE ED 7B C5 09 8E 83 FE B5 B3 16 08 F8 E2 9C 38 81 9A 89 C8 E7 76 F1 54"
+ "4D 41 51 A4 ED 3A 8B 87 B9 CE"));
+
+ /*
+ * Packet Vector #22
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 5B 8C CB CD 9A F8 3C 96 96 76 6C FA"),
+ SHEX("EC 46 BB 63 B0 25 20 C3 3C 49 FD 70"), 1,
+ SHEX("B9 6B 49 E2 1D 62 17 41 63 28 75 DB 7F 6C 92 43 D2 D7 C2"),
+ SHEX("31 D7 50 A0 9D A3 ED 7F DD D4 9A 20 32 AA BF 17 EC 8E BF"
+ "7D 22 C8 08 8C 66 6B E5 C1 97"));
+
+ /*
+ * Packet Vector #23
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 3E BE 94 04 4B 9A 3C 96 96 76 6C FA"),
+ SHEX("47 A6 5A C7 8B 3D 59 42 27 E8 5E 71"), 1,
+ SHEX("E2 FC FB B8 80 44 2C 73 1B F9 51 67 C8 FF D7 89 5E 33 70 76"),
+ SHEX("E8 82 F1 DB D3 8C E3 ED A7 C2 3F 04 DD 65 07 1E B4 13 42 AC"
+ "DF 7E 00 DC CE C7 AE 52 98 7D"));
+
+ /*
+ * Packet Vector #24
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("D7 82 8D 13 B2 B0 BD C3 25 A7 62 36 DF 93 CC 6B"),
+ SHEX("00 8D 49 3B 30 AE 8B 3C 96 96 76 6C FA"),
+ SHEX("6E 37 A6 EF 54 6D 95 5D 34 AB 60 59"), 1,
+ SHEX("AB F2 1C 0B 02 FE B8 8F 85 6D F4 A3 73 81 BC E3 CC 12 85 17 D4"),
+ SHEX("F3 29 05 B8 8A 64 1B 04 B9 C9 FF B5 8C C3 90 90 0F 3D A1 2A B1"
+ "6D CE 9E 82 EF A1 6D A6 20 59"));
+
+ /* From IEEE 802.15.4-2011
+ *
+ * Annex C: Test vectors for cryptographic building blocks
+ * C.2.1 MAC beacon frame
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("AC DE 48 00 00 00 00 01 00 00 00 05 02"),
+ SHEX("08 D0 84 21 43 01 00 00 00 00 48 DE AC 02 05 00 00 00 55 CF 00 00 51 52 53 54"), 1,
+ SHEX(""),
+ SHEX("22 3B C1 EC 84 1A B5 53"));
+
+ /*
+ * C.2.2 MAC data frame
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("AC DE 48 00 00 00 00 01 00 00 00 05 04"),
+ SHEX("69 DC 84 21 43 02 00 00 00 00 48 DE AC 01 00 00 00 00 48 DE AC 04 05 00 00 00"), 1,
+ SHEX("61 62 63 64"),
+ SHEX("D4 3E 02 2B"));
+
+ /*
+ * C.2.3 MAC command frame
+ */
+ test_cipher_ccm(&nettle_aes128,
+ SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
+ SHEX("AC DE 48 00 00 00 00 01 00 00 00 05 06"),
+ SHEX("2B DC 84 21 43 02 00 0000 00 48 DE AC FF FF 01 00 00 00 00 48 DE AC 06 05 00 00 00 01"), 1,
+ SHEX("CE"),
+ SHEX("D8 4F DE 52 90 61 F9 C6 F1"));
+
+ /* From IEEE P1619.1/D22 July 2007 (draft version)
+ *
+ * Annex D: Test Vectors
+ * D.2.1 CCM-128-AES-256 test vector 1
+ */
+ test_cipher_ccm(&nettle_aes256,
+ SHEX("0000000000000000000000000000000000000000000000000000000000000000"),
+ SHEX("000000000000000000000000"),
+ SHEX(""), 0,
+ SHEX("00000000000000000000000000000000"),
+ SHEX("c1944044c8e7aa95d2de9513c7f3dd8c"
+ "4b0a3e5e51f151eb0ffae7c43d010fdb"));
+
+ /*
+ * D.2.2 CCM-128-AES-256 test vector 2
+ */
+ test_cipher_ccm(&nettle_aes256,
+ SHEX("0000000000000000000000000000000000000000000000000000000000000000"),
+ SHEX("000000000000000000000000"),
+ SHEX("00000000000000000000000000000000"), 1,
+ SHEX(""),
+ SHEX("904704e89fb216443cb9d584911fc3c2"));
+
+ /*
+ * D.2.3 CCM-128-AES-256 test vector 3
+ */
+ test_cipher_ccm(&nettle_aes256,
+ SHEX("0000000000000000000000000000000000000000000000000000000000000000"),
+ SHEX("000000000000000000000000"),
+ SHEX("00000000000000000000000000000000"), 1,
+ SHEX("00000000000000000000000000000000"),
+ SHEX("c1944044c8e7aa95d2de9513c7f3dd8c"
+ "87314e9c1fa01abe6a6415943dc38521"));
+
+ /*
+ * D.2.4 CCM-128-AES-256 test vector 4
+ */
+ test_cipher_ccm(&nettle_aes256,
+ SHEX("fb7615b23d80891dd470980bc79584c8b2fb64ce60978f4d17fce45a49e830b7"),
+ SHEX("dbd1a3636024b7b402da7d6f"),
+ SHEX(""), 0,
+ SHEX("a845348ec8c5b5f126f50e76fefd1b1e"),
+ SHEX("cc881261c6a7fa72b96a1739176b277f"
+ "3472e1145f2c0cbe146349062cf0e423"));
+
+ /*
+ * D.2.5 CCM-128-AES-256 test vector 5
+ */
+ test_cipher_ccm(&nettle_aes256,
+ SHEX("404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"),
+ SHEX("101112131415161718191a1b"),
+ SHEX("000102030405060708090a0b0c0d0e0f10111213"), 1,
+ SHEX("202122232425262728292a2b2c2d2e2f3031323334353637"),
+ SHEX("04f883aeb3bd0730eaf50bb6de4fa2212034e4e41b0e75e5"
+ "9bba3f3a107f3239bd63902923f80371"));
+
+ /*
+ * D.2.6 CCM-128-AES-256 test vector 6
+ */
+ test_cipher_ccm(&nettle_aes256,
+ SHEX("404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"),
+ SHEX("101112131415161718191a1b"),
+ adata, 256,
+ SHEX("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"),
+ SHEX("04f883aeb3bd0730eaf50bb6de4fa2212034e4e41b0e75e577f6bf2422c0f6d2"
+ "3376d2cf256ef613c56454cbb5265834"));
+
+ /*
+ * D.2.7 CCM-128-AES-256 test vector 7
+ */
+ test_cipher_ccm(&nettle_aes256,
+ SHEX("404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"),
+ SHEX("101112131415161718191a1b"),
+ SHEX("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), 1,
+ SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+ SHEX("24d8a38e939d2710cad52b96fe6f82010014c4c43b2e55c557d69f0402e0d6f2"
+ "06c53d6cbd3f1c3c6de5dcdcad9fb74f25741dea741149fe4278a0cc24741e86"
+ "58cc0523b8d7838c60fb1de4b7c3941f5b26dea9322aa29656ec37ac18a9b108"
+ "a6f38b7917f5a9c398838b22afbd17252e96694a9e6237964a0eae21c0a6e152"
+ "15a0e82022926be97268249599e456e05029c3ebc07d78fc5b4a0862e04e68c2"
+ "9514c7bdafc4b52e04833bf30622e4eb42504a44a9dcbc774752de7bb82891ad"
+ "1eba9dc3281422a8aba8654268d3d9c81705f4c5a531ef856df5609a159af738"
+ "eb753423ed2001b8f20c23725f2bef18c409f7e52132341f27cb8f0e79894dd9"
+ "ebb1fa9d28ccfe21bdfea7e6d91e0bab"));
+
+ /*
+ * D.2.8 CCM-128-AES-256 test vector 8
+ */
+ test_cipher_ccm(&nettle_aes256,
+ SHEX("fb7615b23d80891dd470980bc79584c8b2fb64ce6097878d17fce45a49e830b7"),
+ SHEX("dbd1a3636024b7b402da7d6f"),
+ SHEX("36"), 1,
+ SHEX("a9"),
+ SHEX("9d3261b1cf931431e99a32806738ecbd2a"));
+
+ /*
+ * D.2.9 CCM-128-AES-256 test vector 9
+ */
+ test_cipher_ccm(&nettle_aes256,
+ SHEX("f8d476cfd646ea6c2384cb1c27d6195dfef1a9f37b9c8d21a79c21f8cb90d289"),
+ SHEX("dbd1a3636024b7b402da7d6f"),
+ SHEX("7bd859a247961a21823b380e9fe8b65082ba61d3"), 1,
+ SHEX("90ae61cf7baebd4cade494c54a29ae70269aec71"),
+ SHEX("6c05313e45dc8ec10bea6c670bd94f31569386a6"
+ "8f3829e8e76ee23c04f566189e63c686"));
+}