diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-01-10 09:29:17 +0100 |
---|---|---|
committer | Niels Möller <nisse@lysator.liu.se> | 2018-02-19 21:31:51 +0100 |
commit | a254a7761fd1165f2a1ffd3bb2f4c38ee5723715 (patch) | |
tree | dc27d093f71333780b69f91d4c07a50989ba1f38 | |
parent | 36168d2942b82c351daf00cd3e2744ebb10add13 (diff) | |
download | nettle-a254a7761fd1165f2a1ffd3bb2f4c38ee5723715.tar.gz |
Added support for CMAC
That adds support for CMAC as a generic framework for
128-bit block and key ciphers, as well as API for AES-128-CMAC,
and AES-256-CMAC.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | cmac-aes128.c | 60 | ||||
-rw-r--r-- | cmac-aes256.c | 60 | ||||
-rw-r--r-- | cmac.c | 158 | ||||
-rw-r--r-- | cmac.h | 133 | ||||
-rw-r--r-- | examples/nettle-benchmark.c | 24 | ||||
-rw-r--r-- | nettle.texinfo | 60 | ||||
-rw-r--r-- | testsuite/.test-rules.make | 3 | ||||
-rw-r--r-- | testsuite/Makefile.in | 1 | ||||
-rw-r--r-- | testsuite/cmac-test.c | 146 |
10 files changed, 645 insertions, 2 deletions
diff --git a/Makefile.in b/Makefile.in index 4444e8bd..de12bb3f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -100,6 +100,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ gcm-aes256.c gcm-aes256-meta.c \ gcm-camellia128.c gcm-camellia128-meta.c \ gcm-camellia256.c gcm-camellia256-meta.c \ + cmac.c cmac-aes128.c cmac-aes256.c \ gosthash94.c gosthash94-meta.c \ hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \ hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c \ @@ -192,6 +193,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \ gcm.h gosthash94.h hmac.h \ knuth-lfib.h hkdf.h \ macros.h \ + cmac.h \ md2.h md4.h \ md5.h md5-compat.h \ memops.h memxor.h \ diff --git a/cmac-aes128.c b/cmac-aes128.c new file mode 100644 index 00000000..e53e114e --- /dev/null +++ b/cmac-aes128.c @@ -0,0 +1,60 @@ +/* cmac-aes128.c + + CMAC using AES128 as the underlying cipher. + + Copyright (C) 2017 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> + +#include "cmac.h" + +void +cmac_aes128_set_key(struct cmac_aes128_ctx *ctx, const uint8_t *key) +{ + CMAC128_SET_KEY(ctx, aes128_set_encrypt_key, aes128_encrypt, key); +} + +void +cmac_aes128_update (struct cmac_aes128_ctx *ctx, + size_t length, const uint8_t *data) +{ + CMAC128_UPDATE (ctx, aes128_encrypt, length, data); +} + +void +cmac_aes128_digest(struct cmac_aes128_ctx *ctx, + size_t length, uint8_t *digest) +{ + CMAC128_DIGEST(ctx, aes128_encrypt, length, digest); +} diff --git a/cmac-aes256.c b/cmac-aes256.c new file mode 100644 index 00000000..ec3b50db --- /dev/null +++ b/cmac-aes256.c @@ -0,0 +1,60 @@ +/* cmac-aes256.c + + CMAC using AES256 as the underlying cipher. + + Copyright (C) 2017 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> + +#include "cmac.h" + +void +cmac_aes256_set_key(struct cmac_aes256_ctx *ctx, const uint8_t *key) +{ + CMAC128_SET_KEY(ctx, aes256_set_encrypt_key, aes256_encrypt, key); +} + +void +cmac_aes256_update (struct cmac_aes256_ctx *ctx, + size_t length, const uint8_t *data) +{ + CMAC128_UPDATE (ctx, aes256_encrypt, length, data); +} + +void +cmac_aes256_digest(struct cmac_aes256_ctx *ctx, + size_t length, uint8_t *digest) +{ + CMAC128_DIGEST(ctx, aes256_encrypt, length, digest); +} @@ -0,0 +1,158 @@ +/* + AES-CMAC-128 (rfc 4493) + Copyright (C) Stefan Metzmacher 2012 + Copyright (C) Jeremy Allison 2012 + Copyright (C) Michael Adam 2012 + Copyright (C) 2017, Red Hat Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include "cmac.h" + +#include "memxor.h" +#include "nettle-internal.h" +#include "macros.h" + +static const uint8_t const_zero[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* shift one and XOR with 0x87. */ +static inline void block_mulx(union nettle_block16 *dst, + const union nettle_block16 *src) +{ + uint64_t b1 = READ_UINT64(src->b); + uint64_t b2 = READ_UINT64(src->b+8); + + b1 = (b1 << 1) | (b2 >> 63); + b2 <<= 1; + + if (src->b[0] & 0x80) + b2 ^= 0x87; + + WRITE_UINT64(dst->b, b1); + WRITE_UINT64(dst->b+8, b2); +} + +void cmac128_set_key(struct cmac128 *ctx, void *cipher, + nettle_cipher_func *encrypt) +{ + union nettle_block16 *L = &ctx->block; + memset(ctx, 0, sizeof(*ctx)); + + /* step 1 - generate subkeys k1 and k2 */ + encrypt(cipher, 16, L->b, const_zero); + + block_mulx(&ctx->K1, L); + block_mulx(&ctx->K2, &ctx->K1); +} + +#define MIN(x,y) ((x)<(y)?(x):(y)) + +void cmac128_update(struct cmac128 *ctx, void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg) +{ + union nettle_block16 Y; + /* + * check if we expand the block + */ + if (ctx->index < 16) { + size_t len = MIN(16 - ctx->index, msg_len); + memcpy(&ctx->block.b[ctx->index], msg, len); + msg += len; + msg_len -= len; + ctx->index += len; + } + + if (msg_len == 0) { + /* if it is still the last block, we are done */ + return; + } + + /* + * now checksum everything but the last block + */ + memxor3(Y.b, ctx->X.b, ctx->block.b, 16); + encrypt(cipher, 16, ctx->X.b, Y.b); + + while (msg_len > 16) { + memxor3(Y.b, ctx->X.b, msg, 16); + encrypt(cipher, 16, ctx->X.b, Y.b); + msg += 16; + msg_len -= 16; + } + + /* + * copy the last block, it will be processed in + * cmac128_digest(). + */ + memcpy(ctx->block.b, msg, msg_len); + ctx->index = msg_len; +} + +void cmac128_digest(struct cmac128 *ctx, void *cipher, + nettle_cipher_func *encrypt, + unsigned length, + uint8_t *dst) +{ + union nettle_block16 Y; + + memset(ctx->block.b+ctx->index, 0, sizeof(ctx->block.b)-ctx->index); + + /* re-use ctx->block for memxor output */ + if (ctx->index < 16) { + ctx->block.b[ctx->index] = 0x80; + memxor(ctx->block.b, ctx->K2.b, 16); + } else { + memxor(ctx->block.b, ctx->K1.b, 16); + } + + memxor3(Y.b, ctx->block.b, ctx->X.b, 16); + + assert(length <= 16); + if (length == 16) { + encrypt(cipher, 16, dst, Y.b); + } else { + encrypt(cipher, 16, ctx->block.b, Y.b); + memcpy(dst, ctx->block.b, length); + } + + /* reset state for re-use */ + memset(&ctx->X, 0, sizeof(ctx->X)); + ctx->index = 0; +} @@ -0,0 +1,133 @@ +/* cmac.h + + CMAC mode, as specified in RFC4493 + + Copyright (C) 2017 Red Hat, Inc. + + Contributed by Nikos Mavrogiannopoulos + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#ifndef NETTLE_CMAC_H_INCLUDED +#define NETTLE_CMAC_H_INCLUDED + +#include "aes.h" +#include "nettle-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CMAC128_DIGEST_SIZE 16 + +#define cmac128_set_key nettle_cmac128_set_key +#define cmac128_update nettle_cmac128_update +#define cmac128_digest nettle_cmac128_digest +#define cmac_aes128_set_key nettle_cmac_aes128_set_key +#define cmac_aes128_update nettle_cmac_aes128_update +#define cmac_aes128_digest nettle_cmac_aes128_digest +#define cmac_aes256_set_key nettle_cmac_aes256_set_key +#define cmac_aes256_update nettle_cmac_aes256_update +#define cmac_aes256_digest nettle_cmac_aes256_digest + +struct cmac128 { + union nettle_block16 K1; + union nettle_block16 K2; + + union nettle_block16 X; + + union nettle_block16 block; + size_t index; +}; + +void cmac128_set_key(struct cmac128 *ctx, void *cipher, + nettle_cipher_func *encrypt); +void cmac128_update(struct cmac128 *ctx, void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg); +void cmac128_digest(struct cmac128 *ctx, void *cipher, + nettle_cipher_func *encrypt, + unsigned length, + uint8_t *out); + + +#define CMAC128_CTX(type) \ + { struct cmac128 data; type cipher; } + +/* NOTE: Avoid using NULL, as we don't include anything defining it. */ +#define CMAC128_SET_KEY(ctx, set_key, encrypt, cmac_key) \ + do { \ + (set_key)(&(ctx)->cipher, (cmac_key)); \ + if (0) (encrypt)(&(ctx)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0); \ + cmac128_set_key(&(ctx)->data, &(ctx)->cipher, \ + (nettle_cipher_func *) (encrypt)); \ + } while (0) + +#define CMAC128_UPDATE(ctx, encrypt, length, src) \ + cmac128_update(&(ctx)->data, &(ctx)->cipher, \ + (nettle_cipher_func *)encrypt, (length), (src)) + +#define CMAC128_DIGEST(ctx, encrypt, length, digest) \ + (0 ? (encrypt)(&(ctx)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0) \ + : cmac128_digest(&(ctx)->data, &(ctx)->cipher, \ + (nettle_cipher_func *) (encrypt), \ + (length), (digest))) + +struct cmac_aes128_ctx CMAC128_CTX(struct aes128_ctx); + +void +cmac_aes128_set_key(struct cmac_aes128_ctx *ctx, const uint8_t *key); + +void +cmac_aes128_update(struct cmac_aes128_ctx *ctx, + size_t length, const uint8_t *data); + +void +cmac_aes128_digest(struct cmac_aes128_ctx *ctx, + size_t length, uint8_t *digest); + +struct cmac_aes256_ctx CMAC128_CTX(struct aes256_ctx); + +void +cmac_aes256_set_key(struct cmac_aes256_ctx *ctx, const uint8_t *key); + +void +cmac_aes256_update(struct cmac_aes256_ctx *ctx, + size_t length, const uint8_t *data); + +void +cmac_aes256_digest(struct cmac_aes256_ctx *ctx, + size_t length, uint8_t *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* CMAC_H_INCLUDED */ diff --git a/examples/nettle-benchmark.c b/examples/nettle-benchmark.c index 655ce09e..b6863cb5 100644 --- a/examples/nettle-benchmark.c +++ b/examples/nettle-benchmark.c @@ -64,6 +64,7 @@ #include "sha3.h" #include "twofish.h" #include "umac.h" +#include "cmac.h" #include "poly1305.h" #include "nettle-meta.h" @@ -403,7 +404,7 @@ time_umac(void) struct umac64_ctx ctx64; struct umac96_ctx ctx96; struct umac128_ctx ctx128; - + uint8_t key[16]; umac32_set_key (&ctx32, key); @@ -440,6 +441,24 @@ time_umac(void) } static void +time_cmac(void) +{ + static uint8_t data[BENCH_BLOCK]; + struct bench_hash_info info; + struct cmac_aes128_ctx ctx; + + uint8_t key[16]; + + cmac_aes128_set_key (&ctx, key); + info.ctx = &ctx; + info.update = (nettle_hash_update_func *) cmac_aes128_update; + info.data = data; + + display("cmac-aes128", "update", AES_BLOCK_SIZE, + time_function(bench_hash, &info)); +} + +static void time_poly1305_aes(void) { static uint8_t data[BENCH_BLOCK]; @@ -849,6 +868,9 @@ main(int argc, char **argv) if (!alg || strstr ("umac", alg)) time_umac(); + if (!alg || strstr ("cmac", alg)) + time_cmac(); + if (!alg || strstr ("poly1305-aes", alg)) time_poly1305_aes(); diff --git a/nettle.texinfo b/nettle.texinfo index efa5670e..ecebbe64 100644 --- a/nettle.texinfo +++ b/nettle.texinfo @@ -101,6 +101,7 @@ Keyed Hash Functions * HMAC:: * UMAC:: +* CMAC:: Public-key algorithms @@ -271,6 +272,9 @@ The implementation of the TWOFISH cipher is written by Ruud de Rooij. @item UMAC Written by @value{AUTHOR}. +@item CMAC +Written by Nikos Mavrogiannopoulos, @value{AUTHOR}, Jeremy Allison, Michael Adam and Stefan Metzmacher. + @item RSA Written by @value{AUTHOR}. Uses the GMP library for bignum operations. @@ -3159,6 +3163,7 @@ as well. @menu * HMAC:: * UMAC:: +* CMAC:: * Poly1305:: @end menu @@ -3501,7 +3506,60 @@ as described above, the new value is used unless you call the @code{_set_nonce} function explicitly for each message. @end deftypefun -@node Poly1305,, UMAC, Keyed hash functions +@node CMAC,, UMAC, Keyed hash functions +@subsection @acronym{CMAC} +@cindex CMAC + +@acronym{CMAC} is a message authentication code based on CBC encryption +mode. It is suitable for systems where block ciphers are preferrable +and perform better than hash functions. @acronym{CMAC} is specified in +@cite{RFC4493}. The block size is always 128 bits (16 octets). + +Nettle provides helper functions for @acronym{CMAC } with +the @acronym{AES} block cipher. + +Nettle defines @acronym{CMAC} in @file{<nettle/cmac.h>}. + +@deftp {Context struct} {struct cmac128_ctx} +@end deftp + +@defvr Constant CMAC128_DIGEST_SIZE +The size of an CMAC digest, 16. +@end defvr + +@deftypefun void cmac_aes128_set_key (struct cmac_aes128_ctx *@var{ctx}, const uint8_t *@var{key}) +This function initializes the @acronym{CMAC} context struct for AES-128. +@end deftypefun + +@deftypefun void cmac_aes128_update (struct cmac_aes128_ctx *@var{ctx}, size_t @var{length}, const uint8_t *@var{data}) +This function is called zero or more times to process the message. +@end deftypefun + +@deftypefun void cmac_aes128_digest (struct cmac_aes128_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{digest}) +Extracts the @acronym{MAC} of the message, writing it to @var{digest}. +@var{length} is usually equal to the specified output size, but if you +provide a smaller value, only the first @var{length} octets of the +@acronym{MAC} are written. This function resets the context for +processing of a new message with the same key. +@end deftypefun + +@deftypefun void cmac_aes256_set_key (struct cmac_aes256_ctx *@var{ctx}, const uint8_t *@var{key}) +This function initializes the @acronym{CMAC} context struct for AES-256. +@end deftypefun + +@deftypefun void cmac_aes256_update (struct cmac_aes256_ctx *@var{ctx}, size_t @var{length}, const uint8_t *@var{data}) +This function is called zero or more times to process the message. +@end deftypefun + +@deftypefun void cmac_aes256_digest (struct cmac_aes256_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{digest}) +Extracts the @acronym{MAC} of the message, writing it to @var{digest}. +@var{length} is usually equal to the specified output size, but if you +provide a smaller value, only the first @var{length} octets of the +@acronym{MAC} are written. This function resets the context for +processing of a new message with the same key. +@end deftypefun + +@node Poly1305,, CMAC, Keyed hash functions @comment node-name, next, previous, up @subsection Poly1305 diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make index 12c39f30..033d8e0b 100644 --- a/testsuite/.test-rules.make +++ b/testsuite/.test-rules.make @@ -130,6 +130,9 @@ eax-test$(EXEEXT): eax-test.$(OBJEXT) ccm-test$(EXEEXT): ccm-test.$(OBJEXT) $(LINK) ccm-test.$(OBJEXT) $(TEST_OBJS) -o ccm-test$(EXEEXT) +cmac-test$(EXEEXT): cmac-test.$(OBJEXT) + $(LINK) cmac-test.$(OBJEXT) $(TEST_OBJS) -o cmac-test$(EXEEXT) + poly1305-test$(EXEEXT): poly1305-test.$(OBJEXT) $(LINK) poly1305-test.$(OBJEXT) $(TEST_OBJS) -o poly1305-test$(EXEEXT) diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index df1c8150..3ab1d3f0 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -26,6 +26,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \ serpent-test.c twofish-test.c version-test.c \ knuth-lfib-test.c \ cbc-test.c cfb-test.c ctr-test.c gcm-test.c eax-test.c ccm-test.c \ + cmac-test.c \ poly1305-test.c chacha-poly1305-test.c \ hmac-test.c umac-test.c \ meta-hash-test.c meta-cipher-test.c\ diff --git a/testsuite/cmac-test.c b/testsuite/cmac-test.c new file mode 100644 index 00000000..58544f2a --- /dev/null +++ b/testsuite/cmac-test.c @@ -0,0 +1,146 @@ +#include "testutils.h" +#include "nettle-internal.h" +#include "cmac.h" + +typedef void set_key_func(void *ctx, const uint8_t *key); +typedef void update_func(void *ctx, size_t length, const uint8_t *data); +typedef void digest_func(void *ctx, size_t length, uint8_t *digest); + +#define test_cmac_aes128(key, msg, ref) \ + test_cmac_hash ((set_key_func*)cmac_aes128_set_key, (update_func*)cmac_aes128_update, \ + (digest_func*)cmac_aes128_digest, sizeof(struct cmac_aes128_ctx), \ + key, msg, ref) + +#define test_cmac_aes256(key, msg, ref) \ + test_cmac_hash ((set_key_func*)cmac_aes256_set_key, (update_func*)cmac_aes256_update, \ + (digest_func*)cmac_aes256_digest, sizeof(struct cmac_aes256_ctx), \ + key, msg, ref) + +static void +test_cmac_hash (set_key_func *set_key, update_func *update, + digest_func *digest, size_t ctx_size, + const struct tstring *key, const struct tstring *msg, + const struct tstring *ref) +{ + void *ctx; + uint8_t hash[16]; + unsigned i; + + ctx = xalloc(ctx_size); + + ASSERT (ref->length == sizeof(hash)); + ASSERT (key->length == 16 || key->length == 32); + set_key (ctx, key->data); + update (ctx, msg->length, msg->data); + digest (ctx, sizeof(hash), hash); + if (!MEMEQ (ref->length, ref->data, hash)) + { + fprintf (stderr, "cmac_hash failed, msg: "); + print_hex (msg->length, msg->data); + fprintf(stderr, "Output:"); + print_hex (16, hash); + fprintf(stderr, "Expected:"); + tstring_print_hex(ref); + fprintf(stderr, "\n"); + FAIL(); + } + + /* attempt to re-use the structure */ + update (ctx, msg->length, msg->data); + digest (ctx, sizeof(hash), hash); + if (!MEMEQ (ref->length, ref->data, hash)) + { + fprintf (stderr, "cmac_hash failed on re-use, msg: "); + print_hex (msg->length, msg->data); + fprintf(stderr, "Output:"); + print_hex (16, hash); + fprintf(stderr, "Expected:"); + tstring_print_hex(ref); + fprintf(stderr, "\n"); + FAIL(); + } + + /* attempt byte-by-byte hashing */ + set_key (ctx, key->data); + for (i=0;i<msg->length;i++) + update (ctx, 1, msg->data+i); + digest (ctx, sizeof(hash), hash); + if (!MEMEQ (ref->length, ref->data, hash)) + { + fprintf (stderr, "cmac_hash failed on byte-by-byte, msg: "); + print_hex (msg->length, msg->data); + fprintf(stderr, "Output:"); + print_hex (16, hash); + fprintf(stderr, "Expected:"); + tstring_print_hex(ref); + fprintf(stderr, "\n"); + FAIL(); + } +} + +void +test_main(void) +{ + /* + * CMAC-AES Test Vectors from RFC4493. + */ + test_cmac_aes128 (SHEX("2b7e151628aed2a6abf7158809cf4f3c"), + SDATA(""), + SHEX("bb1d6929e95937287fa37d129b756746")); + + test_cmac_aes128 (SHEX("2b7e151628aed2a6abf7158809cf4f3c"), + SHEX("6bc1bee22e409f96e93d7e117393172a"), + SHEX("070a16b46b4d4144f79bdd9dd04a287c")); + + test_cmac_aes128 (SHEX("2b7e151628aed2a6abf7158809cf4f3c"), + SHEX("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411"), + SHEX("dfa66747de9ae63030ca32611497c827")); + + test_cmac_aes128 (SHEX("2b7e151628aed2a6abf7158809cf4f3c"), + SHEX("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710"), + SHEX("51f0bebf7e3b9d92fc49741779363cfe")); + + /* Additional tests with different keys (same plaintext) + * to check all variants of set_key() */ + test_cmac_aes128 (SHEX("2b7e151628aed2a8abf7158809cf4f3c"), + SHEX("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411"), + SHEX("87dd33c2945a4e228028690ae8954945")); + + test_cmac_aes128 (SHEX("2b7e1ab628aed2a8abf7158809cf4f3c"), + SHEX("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411"), + SHEX("f0dc613a88886c7ed76eeb51f1c5e8d3")); + + test_cmac_aes128 (SHEX("2b7e1ab628aed2a8abf7158809cf4f3d"), + SHEX("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411"), + SHEX("b9d092dc387a9e42cdfeb9f9930cf567")); + + /* CMAC-AES256 vectors taken from phplib */ + test_cmac_aes256 (SHEX("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + SDATA(""), + SHEX("028962f61b7bf89efc6b551f4667d983")); + + test_cmac_aes256 (SHEX("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + SHEX("6bc1bee22e409f96e93d7e117393172a"), + SHEX("28a7023f452e8f82bd4bf28d8c37c35c")); + + test_cmac_aes256 (SHEX("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + SHEX("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411"), + SHEX("aaf3d8f1de5640c232f5b169b9c911e6")); + + test_cmac_aes256 (SHEX("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + SHEX("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"), + SHEX("e1992190549f6ed5696a2c056c315410")); + +} + |