Latest round of changes to the CCM modes, this moves the processing of L(a) into ccm_set_nonce() and updates the all-at-once API to concatenate the ciphertext and digest together.
Cheers, Owen
2014-03-20 Owen Kirby osk@exegin.com * ccm.c (ccm_digest, ccm_set_nonce): Moved L(a) generation into ccm_set_nonce() * ccm.c (ccm_encrypt_message): Modified API to append the tag to the ciphertext. * ccm.c (ccm_decrypt_message): Modified API to parse the tag from the ciphertext. * ccm.h (struct ccm_ctx): Removed alen parameter, and made blength unsigned. * testsuite/ccm-test.c: Updated the test vectors for the all-at-once API.
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 7643b88984cc71deb16ae2f3e91a6e7a0e2b8023 Mon Sep 17 00:00:00 2001
From: Owen Kirby osk@exegin.com Date: Wed, 20 Mar 2014 14:28:56 -0800 Subject: [PATCH] Support for CCM mode ciphers.
--- Makefile.in | 1 + ccm-aes128.c | 100 +++++++ ccm-aes192.c | 101 +++++++ ccm-aes256.c | 102 +++++++ ccm.c | 255 ++++++++++++++++ ccm.h | 273 +++++++++++++++++ testsuite/.gitignore | 1 + testsuite/.test-rules.make | 3 + testsuite/Makefile.in | 2 +- testsuite/ccm-test.c | 713 ++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 1550 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..94554e5 --- /dev/null +++ b/ccm-aes128.c @@ -0,0 +1,100 @@ +/* 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_crypt_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_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, + size_t clength, uint8_t *dst, const uint8_t *src) +{ + ccm_encrypt_message(&ctx->cipher, (nettle_crypt_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_crypt_func *)aes128_encrypt, + nlength, nonce, alength, adata, tlength, clength, dst, src); +} \ No newline at end of file diff --git a/ccm-aes192.c b/ccm-aes192.c new file mode 100644 index 0000000..a2618a5 --- /dev/null +++ b/ccm-aes192.c @@ -0,0 +1,101 @@ +/* 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_crypt_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_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, + size_t clength, uint8_t *dst, const uint8_t *src) +{ + ccm_encrypt_message(&ctx->cipher, (nettle_crypt_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_crypt_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 0000000..0779a2d --- /dev/null +++ b/ccm-aes256.c @@ -0,0 +1,102 @@ +/* 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_crypt_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_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, + size_t clength, uint8_t *dst, const uint8_t *src) +{ + ccm_encrypt_message(&ctx->cipher, (nettle_crypt_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_crypt_func *)aes256_encrypt, + nlength, nonce, alength, adata, tlength, clength, dst, src); +} + diff --git a/ccm.c b/ccm.c new file mode 100644 index 0000000..82c2612 --- /dev/null +++ b/ccm.c @@ -0,0 +1,255 @@ +/* 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) + +/* + * 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, void *cipher, nettle_crypt_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, void *cipher, nettle_crypt_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, void *cipher, nettle_crypt_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, 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, + 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(void *cipher, nettle_crypt_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 0000000..da10cf9 --- /dev/null +++ b/ccm.h @@ -0,0 +1,273 @@ +/* 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. */ + /* 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, void *cipher, nettle_crypt_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, 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: + * 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(void *cipher, nettle_crypt_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(void *cipher, nettle_crypt_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 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..845d27f --- /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")); +}
Owen Kirby osk@exegin.com writes:
Latest round of changes to the CCM modes, this moves the processing of L(a) into ccm_set_nonce() and updates the all-at-once API to concatenate the ciphertext and digest together.
Pushed now, with some smaller changes. All uses of nettle_crypt_func are replaced by nettle_cipher_func (introduced last week), and the cipher context arguments accordingly changed to const. And some tweaks of indentation and line breaks.
Documentation remains to do.
Thanks, /Niels
Awesome, thank you. I will take a look at assembling documentation regarding the CCM modes when I get some spare time this week.
Cheers, Owen
On 14-03-23 11:06 AM, Niels Möller wrote:
Owen Kirby osk@exegin.com writes:
Latest round of changes to the CCM modes, this moves the processing of L(a) into ccm_set_nonce() and updates the all-at-once API to concatenate the ciphertext and digest together.
Pushed now, with some smaller changes. All uses of nettle_crypt_func are replaced by nettle_cipher_func (introduced last week), and the cipher context arguments accordingly changed to const. And some tweaks of indentation and line breaks.
Documentation remains to do.
Thanks, /Niels
nisse@lysator.liu.se (Niels Möller) writes:
Pushed now, with some smaller changes.
I get a couple of warnings, when compiling for 32-bit platforms, e.g., ARM.
/home/nisse/hack/nettle/ccm.c: In function `nettle_ccm_set_nonce': /home/nisse/hack/nettle/ccm.c:134:3: warning: comparison is always false due to limited range of data type [-Wtype-limits] /home/nisse/hack/nettle/ccm.c:138:5: warning: right shift count >= width of type [enabled by default] /home/nisse/hack/nettle/ccm.c:139:5: warning: right shift count >= width of type [enabled by default] /home/nisse/hack/nettle/ccm.c:140:5: warning: right shift count >= width of type [enabled by default] /home/nisse/hack/nettle/ccm.c:141:5: warning: right shift count >= width of type [enabled by default]
As long as it's "always false", the code should be correct, but it would be nice to get rid of these warnings.
Regards, /Niels
Actually, that's not entirely correct. I have seen some architectures that will turn a shift into a nop when the shift width is greater than the word size. I have some ARM boards that I can cross compile for, so I'll take a look at cleaning up the warnings when I get some time this weekend.
Thanks, Owen
On 14-04-11 06:39 AM, Niels Möller wrote:
nisse@lysator.liu.se (Niels Möller) writes:
Pushed now, with some smaller changes.
I get a couple of warnings, when compiling for 32-bit platforms, e.g., ARM.
/home/nisse/hack/nettle/ccm.c: In function `nettle_ccm_set_nonce': /home/nisse/hack/nettle/ccm.c:134:3: warning: comparison is always false due to limited range of data type [-Wtype-limits] /home/nisse/hack/nettle/ccm.c:138:5: warning: right shift count >= width of type [enabled by default] /home/nisse/hack/nettle/ccm.c:139:5: warning: right shift count >= width of type [enabled by default] /home/nisse/hack/nettle/ccm.c:140:5: warning: right shift count >= width of type [enabled by default] /home/nisse/hack/nettle/ccm.c:141:5: warning: right shift count >= width of type [enabled by default]
As long as it's "always false", the code should be correct, but it would be nice to get rid of these warnings.
Regards, /Niels
Owen Kirby osk@exegin.com writes:
Actually, that's not entirely correct. I have seen some architectures that will turn a shift into a nop when the shift width is greater than the word size.
Shifts greater than the word size can give different types of undefined behaviour. Ignoring higher bits of the shift count is also common, I think, depending on compiler and instruction set.
But in this case, I think it can't cause any real harm, because these shifts are inside an
if (authlen >= (0x01ULL << 32)) {
which should be always false if authlen (of type size_t) is 32-bits.
I have some ARM boards that I can cross compile for, so I'll take a look at cleaning up the warnings when I get some time this weekend.
I think you get the same warnings if you configure with CC='gcc -m32' CXX='g++ -m32' on a plain x86_64 gnu/linux box or similar.
Regards, /Niels
nisse@lysator.liu.se (Niels Möller) writes:
I get a couple of warnings, when compiling for 32-bit platforms, e.g., ARM.
/home/nisse/hack/nettle/ccm.c: In function `nettle_ccm_set_nonce': /home/nisse/hack/nettle/ccm.c:134:3: warning: comparison is always false due to limited range of data type [-Wtype-limits] /home/nisse/hack/nettle/ccm.c:138:5: warning: right shift count >= width of type [enabled by default] /home/nisse/hack/nettle/ccm.c:139:5: warning: right shift count >= width of type [enabled by default] /home/nisse/hack/nettle/ccm.c:140:5: warning: right shift count >= width of type [enabled by default] /home/nisse/hack/nettle/ccm.c:141:5: warning: right shift count >= width of type [enabled by default]
Fixed now. Added a configure test for sizeof(size_t).
Regards, /Niels
nettle-bugs@lists.lysator.liu.se