I've incorporated a few of your suggestions and updated my patch for the CCM cipher modes. This improves the API coverage in the CCM test suite, adds the all-at-once API for message processing, and fixes the copyright of the CCM mode source code.
Thanks, Owen
ChangeLog from V1 of the patch:
2014-03-14 Owen Kirby osk@exegin.com * ccm-aes.c: Removed legacy AES API. * ccm.c (ccm_encrypt_message): Added all-at-once API for CCM mode ciphers. * ccm.c (ccm_digest): Added assert to ensure CCM digest length <= block size. * ccm.h: Updated copyright for CCM modes to Owen Kirby and Exegin Technologies. * ccm.c: Minor changes to CCM IV and nonce building functions. * ccm-aesXXX.c: Added all-at-once API, and removed the CCM helper macros. * testsuite/ccm-test.c: Added tests for the cipher-specific CCM functions. * testsuite/.test-rules.make: Fixed the building of the CCM self-test.
From 0e40ade7f0f3e41783973e53c50b10ba497e52e7 Mon Sep 17 00:00:00 2001
From: Owen Kirby osk@exegin.com Date: Wed, 5 Mar 2014 19:40:56 -0800 Subject: [PATCH] Support for CCM mode ciphers.
--- Makefile.in | 1 + ccm-aes128.c | 101 +++++++ ccm-aes192.c | 102 +++++++ ccm-aes256.c | 103 +++++++ ccm.c | 253 ++++++++++++++++ ccm.h | 267 +++++++++++++++++ testsuite/.gitignore | 1 + testsuite/.test-rules.make | 3 + testsuite/Makefile.in | 2 +- testsuite/ccm-test.c | 709 ++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 1541 insertions(+), 1 deletion(-) create mode 100644 ccm-aes128.c create mode 100644 ccm-aes192.c create mode 100644 ccm-aes256.c create mode 100644 ccm.c create mode 100644 ccm.h create mode 100644 testsuite/ccm-test.c
diff --git a/Makefile.in b/Makefile.in index 24349c3..c05d891 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-aes.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 \ diff --git a/ccm-aes128.c b/ccm-aes128.c new file mode 100644 index 0000000..cb87897 --- /dev/null +++ b/ccm-aes128.c @@ -0,0 +1,101 @@ +/* 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, 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_crypt_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_crypt_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_crypt_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_crypt_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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src) +{ + ccm_encrypt_message(&ctx->cipher, (nettle_crypt_func *)aes128_encrypt, + nlength, nonce, alength, adata, tlength, tag, mlength, dst, src); +} + +void +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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src) +{ + ccm_decrypt_message(&ctx->cipher, (nettle_crypt_func *)aes128_encrypt, + nlength, nonce, alength, adata, tlength, tag, mlength, dst, src); +} \ No newline at end of file diff --git a/ccm-aes192.c b/ccm-aes192.c new file mode 100644 index 0000000..6073f4a --- /dev/null +++ b/ccm-aes192.c @@ -0,0 +1,102 @@ +/* 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, 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_crypt_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_crypt_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_crypt_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_crypt_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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src) +{ + ccm_encrypt_message(&ctx->cipher, (nettle_crypt_func *)aes192_encrypt, + nlength, nonce, alength, adata, tlength, tag, mlength, dst, src); +} + +void +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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src) +{ + ccm_decrypt_message(&ctx->cipher, (nettle_crypt_func *)aes192_encrypt, + nlength, nonce, alength, adata, tlength, tag, mlength, dst, src); +} diff --git a/ccm-aes256.c b/ccm-aes256.c new file mode 100644 index 0000000..78906f4 --- /dev/null +++ b/ccm-aes256.c @@ -0,0 +1,103 @@ +/* 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, 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_crypt_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_crypt_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_crypt_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_crypt_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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src) +{ + ccm_encrypt_message(&ctx->cipher, (nettle_crypt_func *)aes256_encrypt, + nlength, nonce, alength, adata, tlength, tag, mlength, dst, src); +} + +void +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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src) +{ + ccm_decrypt_message(&ctx->cipher, (nettle_crypt_func *)aes256_encrypt, + nlength, nonce, alength, adata, tlength, tag, mlength, dst, src); +} + diff --git a/ccm.c b/ccm.c new file mode 100644 index 0000000..44771f0 --- /dev/null +++ b/ccm.c @@ -0,0 +1,253 @@ +/* ccm.c + * + * Counter with CBC-MAC mode, specified by NIST, + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_... + * + */ + +/* 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) + +/* Pad an unaligned CBC-MAC digest with zero, or initialize B0 if no adata. */ +static void +ccm_pad(struct ccm_ctx *ctx, void *cipher, nettle_crypt_func *f) +{ + if (ctx->blen) f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b); + ctx->blen = 0; +} + +/* + * Future work: We might be able to support the nettle_aead API by making the + * caller generate the entire IV rather than providing only the nonce. For now, + * this function is only used internally by the CCM mode. + */ +static void +ccm_build_iv(size_t noncelen, const uint8_t *nonce, size_t msglen, + size_t taglen, uint8_t *iv) +{ + 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] = CCM_FLAG_SET_M(taglen) | 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] = msglen & 0xff; + msglen >>= 8; + } + + /* Ensure the message length was not truncated. */ + assert(!msglen); +} + +/* Sets the IVs used by CCM, for now this is only used internally. */ +static void +ccm_set_iv(struct ccm_ctx *ctx, const uint8_t *iv) +{ + int i = CCM_BLOCK_SIZE - CCM_FLAG_GET_L(iv[CCM_OFFSET_FLAGS]); + memcpy(ctx->tag.b, iv, CCM_BLOCK_SIZE); + memcpy(ctx->ctr.b, iv, CCM_BLOCK_SIZE); + ctx->ctr.b[CCM_OFFSET_FLAGS] &= ~(CCM_FLAG_ADATA | CCM_FLAG_M); + ctx->ctr.b[CCM_BLOCK_SIZE-1] = 1; + while (i < (CCM_BLOCK_SIZE-1)) ctx->ctr.b[i++] = 0; + ctx->alen = 0; /* Adata length unknown, streaming not possible. */ + ctx->blen = -1; /* IV is set, but unencrypted. */ +} + +void +ccm_set_nonce(struct ccm_ctx *ctx, size_t length, const uint8_t *nonce, + size_t authlen, size_t msglen, size_t taglen) +{ + uint8_t iv[CCM_BLOCK_SIZE]; + ccm_build_iv(length, nonce, msglen, taglen, iv); + ccm_set_iv(ctx, iv); + ctx->alen = authlen; +} + +void +ccm_update(struct ccm_ctx *ctx, void *cipher, nettle_crypt_func *f, + size_t length, const uint8_t *data) +{ + const uint8_t *end = data + length; + + /* nop */ + if (!length) return; + + /* On the first call, encrypt B0 and encode L(a) */ + if (ctx->blen < 0) { + if (!ctx->alen) ctx->alen = length; /* If alen unknown, set it now. */ + ctx->tag.b[CCM_OFFSET_FLAGS] |= CCM_FLAG_ADATA; + f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b); + ctx->blen = 0; + if (ctx->alen >= (0x01ULL << 32)) { + /* Encode L(a) as 0xff || 0xff || <64-bit integer> */ + ctx->tag.b[ctx->blen++] ^= 0xff; + ctx->tag.b[ctx->blen++] ^= 0xff; + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 56) & 0xff; + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 48) & 0xff; + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 40) & 0xff; + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 32) & 0xff; + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 24) & 0xff; + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 16) & 0xff; + } + else if (ctx->alen >= ((0x1ULL << 16) - (0x1ULL << 8))) { + /* Encode L(a) as 0xff || 0xfe || <32-bit integer> */ + ctx->tag.b[ctx->blen++] ^= 0xff; + ctx->tag.b[ctx->blen++] ^= 0xfe; + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 24) & 0xff; + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 16) & 0xff; + } + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 8) & 0xff; + ctx->tag.b[ctx->blen++] ^= (ctx->alen >> 0) & 0xff; + } + + /* Process unaligned blocks. */ + if (ctx->blen) { + if ((ctx->blen + length) < CCM_BLOCK_SIZE) { + memxor(&ctx->tag.b[ctx->blen], data, length); + ctx->blen += length; + return; + } + memxor(&ctx->tag.b[ctx->blen], data, CCM_BLOCK_SIZE - ctx->blen); + data += (CCM_BLOCK_SIZE - ctx->blen); + f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b); + } + + /* Process aligned 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->blen = (end - data); + if (ctx->blen) memxor(&ctx->tag.b, data, ctx->blen); +} + +/* + * 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, void *cipher, nettle_crypt_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, void *cipher, nettle_crypt_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, void *cipher, nettle_crypt_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(void *cipher, nettle_crypt_func *f, + size_t nlength, const uint8_t *nonce, + size_t alength, const uint8_t *adata, + size_t tlength, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src) +{ + struct ccm_ctx ctx; + ccm_set_nonce(&ctx, nlength, nonce, alength, mlength, tlength); + ccm_update(&ctx, cipher, f, alength, adata); + ccm_encrypt(&ctx, cipher, f, mlength, dst, src); + ccm_digest(&ctx, cipher, f, tlength, tag); +} + +void +ccm_decrypt_message(void *cipher, nettle_crypt_func *f, + size_t nlength, const uint8_t *nonce, + size_t alength, const uint8_t *adata, + size_t tlength, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src) +{ + struct ccm_ctx ctx; + ccm_set_nonce(&ctx, nlength, nonce, alength, mlength, tlength); + ccm_update(&ctx, cipher, f, alength, adata); + ccm_decrypt(&ctx, cipher, f, mlength, dst, src); + ccm_digest(&ctx, cipher, f, tlength, tag); +} diff --git a/ccm.h b/ccm.h new file mode 100644 index 0000000..76b4cc4 --- /dev/null +++ b/ccm.h @@ -0,0 +1,267 @@ +/* ccm.h + * + * Counter with CBC-MAC mode, specified by NIST, + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_... + * + * 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. */ + uint64_t alen; /* Length of adata set during the nonce generation. */ + int blen; /* <0 on init or # of bytes since the last aligned block */ +}; + +/* + * Obnoxiously, CCM mode requires the adata and message lengths when building + * the IV, which prevents any streaming API to the cipher. As such, this makes + * the set_nonce() function incompatible with the nettle AEAD API. + */ +void +ccm_set_nonce(struct ccm_ctx *ctx, size_t noncelen, const uint8_t *nonce, + size_t authlen, size_t msglen, size_t taglen); + +void +ccm_update(struct ccm_ctx *ctx, void *cipher, nettle_crypt_func *f, + size_t length, const uint8_t *data); + +void +ccm_encrypt(struct ccm_ctx *ctx, void *cipher, nettle_crypt_func *f, + size_t length, uint8_t *dst, const uint8_t *src); + +void +ccm_decrypt(struct ccm_ctx *ctx, void *cipher, nettle_crypt_func *f, + size_t length, uint8_t *dst, const uint8_t *src); + +void +ccm_digest(struct ccm_ctx *ctx, void *cipher, nettle_crypt_func *f, + size_t length, uint8_t *digest); + +/* All-in-one encryption and decryption API. */ +void +ccm_encrypt_message(void *cipher, nettle_crypt_func *f, + size_t nlength, const uint8_t *nonce, + size_t alength, const uint8_t *adata, + size_t tlength, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src); + +void +ccm_decrypt_message(void *cipher, nettle_crypt_func *f, + size_t nlength, const uint8_t *nonce, + size_t alength, const uint8_t *adata, + size_t tlength, uint8_t *tag, + size_t mlength, 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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src); + +void +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, uint8_t *tag, + size_t mlength, 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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src); + +void +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, uint8_t *tag, + size_t mlength, 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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src); + +void +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, uint8_t *tag, + size_t mlength, uint8_t *dst, const uint8_t *src); + +#ifdef __cplusplus +} +#endif + +#endif /* NETTLE_CCM_H_INCLUDED */ diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 3b836af..8e5521b 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 43079ec..16d107c 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 d59a2cb..30611c7 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 0000000..cd74db7 --- /dev/null +++ b/testsuite/ccm-test.c @@ -0,0 +1,709 @@ +/* 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, + const struct tstring *e_tag, + /* Actual results. */ + const void *clear, + const void *cipher, + const void *de_tag, + const void *en_tag) +{ + if (!MEMEQ(e_cipher->length, e_cipher->data, cipher)) + { + fprintf(stderr, "%s: encrypt failed\nInput:", name); + 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:\nInput:", name); + 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(); + } + if (!MEMEQ(e_tag->length, e_tag->data, en_tag)) + { + fprintf(stderr, "%s digest failed during encryption:\nAdata:", name); + tstring_print_hex(adata); + fprintf(stderr, "\nInput: "); + tstring_print_hex(e_clear); + fprintf(stderr, "\nOutput: "); + print_hex(e_tag->length, en_tag); + fprintf(stderr, "\nExpected:"); + tstring_print_hex(e_tag); + fprintf(stderr, "\n"); + FAIL(); + } + if (!MEMEQ(e_tag->length, e_tag->data, de_tag)) + { + fprintf(stderr, "%s digest failed during decryption:\nAdata:", name); + tstring_print_hex(adata); + fprintf(stderr, "\nInput: "); + tstring_print_hex(e_clear); + fprintf(stderr, "\nOutput: "); + print_hex(e_tag->length, de_tag); + fprintf(stderr, "\nExpected:"); + tstring_print_hex(e_tag); + 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, + const struct tstring *tag) +{ + void *ctx = xalloc(cipher->context_size); + uint8_t *en_data; + uint8_t *de_data; + uint8_t en_digest[CCM_BLOCK_SIZE]; + uint8_t de_digest[CCM_BLOCK_SIZE]; + size_t len; + size_t tlen; + struct ccm_ctx ccm; + int i; + + ASSERT (key->length == cipher->key_size); + ASSERT (cleartext->length == ciphertext->length); + len = cleartext->length; + tlen = tag->length; + if (!authdata) repeat = 0; + + en_data = xalloc(len); + de_data = xalloc(len); + cipher->set_encrypt_key(ctx, key->data); + + /* Encrypt using the incremental API. */ + ccm_set_nonce(&ccm, nonce->length, nonce->data, authdata->length * repeat, len, tlen); + for (i = 0; i < repeat; i++) { + ccm_update(&ccm, ctx, cipher->encrypt, authdata->length, authdata->data); + } + ccm_encrypt(&ccm, ctx, cipher->encrypt, len, en_data, cleartext->data); + ccm_digest(&ccm, ctx, cipher->encrypt, tag->length, en_digest); + + /* Decrypt using the incremental API. */ + ccm_set_nonce(&ccm, nonce->length, nonce->data, authdata->length * repeat, len, tlen); + for (i = 0; i < repeat; i++) { + ccm_update(&ccm, ctx, cipher->encrypt, authdata->length, authdata->data); + } + ccm_decrypt(&ccm, ctx, cipher->encrypt, len, de_data, ciphertext->data); + ccm_digest(&ccm, ctx, cipher->encrypt, tag->length, de_digest); + + /* Compare results using the generic API. */ + test_compare_results("CCM", authdata, + cleartext, ciphertext, tag, + de_data, en_data, de_digest, en_digest); + + /* Ensure we get the same answers using the all-in-one API. */ + if (repeat <= 1) { + memset(en_data, 0, len); memset(de_data, 0, len); + memset(en_digest, 0, tlen); memset(de_digest, 0, tlen); + + ccm_encrypt_message(ctx, cipher->encrypt, nonce->length, nonce->data, + authdata->length, authdata->data, tlen, en_digest, len, en_data, cleartext->data); + + ccm_decrypt_message(ctx, cipher->encrypt, nonce->length, nonce->data, + authdata->length, authdata->data, tlen, de_digest, len, de_data, ciphertext->data); + + test_compare_results("CCM_MSG", authdata, + cleartext, ciphertext, tag, + de_data, en_data, de_digest, en_digest); + } + + /* Ensure we get the same answers using the per-cipher API. */ + if (cipher == &nettle_aes128) { + struct ccm_aes128_ctx aes; + memset(en_data, 0, len); memset(de_data, 0, len); + memset(en_digest, 0, tlen); memset(de_digest, 0, tlen); + + /* AES-128 encrypt. */ + ccm_aes128_set_key(&aes, key->data); + ccm_aes128_set_nonce(&aes, nonce->length, nonce->data, authdata->length * repeat, len, tlen); + for (i = 0; i < repeat; i++) { + ccm_aes128_update(&aes, authdata->length, authdata->data); + } + ccm_aes128_encrypt(&aes,len, en_data, cleartext->data); + ccm_aes128_digest(&aes, tag->length, en_digest); + + /* AES-128 decrypt. */ + ccm_aes128_set_nonce(&aes, nonce->length, nonce->data, authdata->length * repeat, len, tlen); + for (i = 0; i < repeat; i++) { + ccm_aes128_update(&aes, authdata->length, authdata->data); + } + ccm_aes128_decrypt(&aes, len, de_data, ciphertext->data); + ccm_aes128_digest(&aes, tag->length, de_digest); + + test_compare_results("CCM_AES_128", authdata, + cleartext, ciphertext, tag, + de_data, en_data, de_digest, en_digest); + } + /* TODO: I couldn't find any test cases for CCM-AES-192 */ + if (cipher == &nettle_aes256) { + struct ccm_aes256_ctx aes; + memset(en_data, 0, len); memset(de_data, 0, len); + memset(en_digest, 0, tlen); memset(de_digest, 0, tlen); + + /* AES-256 encrypt. */ + ccm_aes256_set_key(&aes, key->data); + ccm_aes256_set_nonce(&aes, nonce->length, nonce->data, authdata->length * repeat, len, tlen); + for (i = 0; i < repeat; i++) { + ccm_aes256_update(&aes, authdata->length, authdata->data); + } + ccm_aes256_encrypt(&aes,len, en_data, cleartext->data); + ccm_aes256_digest(&aes, tag->length, en_digest); + + /* AES-256 decrypt. */ + ccm_aes256_set_nonce(&aes, nonce->length, nonce->data, authdata->length * repeat, len, tlen); + for (i = 0; i < repeat; i++) { + ccm_aes256_update(&aes, authdata->length, authdata->data); + } + ccm_aes256_decrypt(&aes,len, de_data, ciphertext->data); + ccm_aes256_digest(&aes, tag->length, de_digest); + + test_compare_results("CCM_AES_256", authdata, + cleartext, ciphertext, tag, + de_data, en_data, de_digest, en_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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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(""), + 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"), + SHEX("")); + + /* + * 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"), + SHEX("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"), + SHEX("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(""), + 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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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"), + SHEX("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("9d"), + SHEX("3261b1cf931431e99a32806738ecbd2a")); + + /* + * 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"), + SHEX("8f3829e8e76ee23c04f566189e63c686")); +}