On Wed, 2018-01-17 at 10:59 +0100, Nikos Mavrogiannopoulos wrote:

> Thank you for the catch. Hopefully the x86 run on our CI would have
> caught it but I never run it there. I've now sent a build with the
> 0001
> patch at:
> https://gitlab.com/nmav/nettle/pipelines/16256301

Following up on my patchset, this (hopefully final) version introduces
CMAC with AES-256 as well. It also removes the CMAC128_KEY_SIZE
definition as the key size only depends on the block algorithm used.

regards,
Nikos
From cc60df9f2e083633fe1d258f3d0ddc17da251508 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <n...@redhat.com>
Date: Wed, 10 Jan 2018 09:29:17 +0100
Subject: [PATCH 1/3] 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.

Signed-off-by: Nikos Mavrogiannopoulos <n...@redhat.com>
---
 Makefile.in                 |   2 +
 cmac-aes128.c               |  60 ++++++++++++++++
 cmac.c                      | 162 ++++++++++++++++++++++++++++++++++++++++++++
 cmac.h                      | 118 ++++++++++++++++++++++++++++++++
 examples/nettle-benchmark.c |  24 ++++++-
 nettle.texinfo              |  47 ++++++++++++-
 testsuite/.test-rules.make  |   3 +
 testsuite/Makefile.in       |   1 +
 testsuite/cmac-test.c       | 111 ++++++++++++++++++++++++++++++
 9 files changed, 526 insertions(+), 2 deletions(-)
 create mode 100644 cmac-aes128.c
 create mode 100644 cmac.c
 create mode 100644 cmac.h
 create mode 100644 testsuite/cmac-test.c

diff --git a/Makefile.in b/Makefile.in
index 6a0c13ec..a25c0f99 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -103,6 +103,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 \
 		 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 \
@@ -195,6 +196,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.c b/cmac.c
new file mode 100644
index 00000000..a4d2468a
--- /dev/null
+++ b/cmac.c
@@ -0,0 +1,162 @@
+/*
+   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 *out,
+			      const union nettle_block16 *in)
+{
+	uint64_t b1 = READ_UINT64(in->b);
+	uint64_t b2 = READ_UINT64(in->b+8);
+	unsigned overflow = (b2 & UINT64_C(0x8000000000000000))?1:0;
+
+	b1 <<= 1;
+	b2 <<= 1;
+
+	if (overflow)
+		b1 |= 0x01;
+
+	if (in->b[0] & 0x80)
+		b2 ^= 0x87;
+
+	WRITE_UINT64(out->b, b1);
+	WRITE_UINT64(out->b+8, b2);
+}
+
+void cmac128_set_key(struct cmac128 *ctx, void *key,
+		     nettle_cipher_func *encrypt)
+{
+	union nettle_block16 *L = &ctx->block;
+	memset(ctx, 0, sizeof(*ctx));
+
+	/* step 1 - generate subkeys k1 and k2 */
+	encrypt(key, 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 *key,
+		    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(key, 16, ctx->X.b, Y.b);
+
+	while (msg_len > 16) {
+		memxor3(Y.b, ctx->X.b, msg, 16);
+		encrypt(key, 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 *key,
+		    nettle_cipher_func *encrypt,
+		    unsigned length,
+		    uint8_t *out)
+{
+	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(key, 16, out, Y.b);
+	} else {
+		encrypt(key, 16, ctx->block.b, Y.b);
+		memcpy(out, ctx->block.b, length);
+	}
+
+	/* reset state for re-use */
+	memset(&ctx->X, 0, sizeof(ctx->X));
+	ctx->index = 0;
+}
diff --git a/cmac.h b/cmac.h
new file mode 100644
index 00000000..168ca95a
--- /dev/null
+++ b/cmac.h
@@ -0,0 +1,118 @@
+/* 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_KEY_SIZE 16
+#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
+
+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 *key,
+		     nettle_cipher_func *encrypt);
+void cmac128_update(struct cmac128 *ctx, void *key,
+		 nettle_cipher_func *encrypt,
+		 size_t msg_len, const uint8_t *msg);
+void cmac128_digest(struct cmac128 *ctx, void *key,
+		    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, data)			\
+  cmac128_update(&(ctx)->data, &(ctx)->cipher, \
+	      (nettle_cipher_func *)encrypt, (length), (data))
+
+#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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CMAC_H_INCLUDED */
diff --git a/examples/nettle-benchmark.c b/examples/nettle-benchmark.c
index 4efcca5c..b8062c5b 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);
@@ -439,6 +440,24 @@ time_umac(void)
 	  time_function(bench_hash, &info));
 }
 
+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)
 {
@@ -846,6 +865,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 f501cfbe..4c7b5312 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.
 
@@ -3134,6 +3138,7 @@ as well.
 @menu
 * HMAC::
 * UMAC::
+* CMAC::
 * Poly1305::
 @end menu
 
@@ -3476,7 +3481,47 @@ 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 secret key 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_KEY_SIZE
+The CMAC key size, 16.
+@end defvr
+@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.
+@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
+
+@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 1f780310..c7e04cb4 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 3117d66d..dd1ecf41 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..983c5127
--- /dev/null
+++ b/testsuite/cmac-test.c
@@ -0,0 +1,111 @@
+#include "testutils.h"
+#include "nettle-internal.h"
+#include "cmac.h"
+
+static void
+test_cmac_hash (const struct tstring *key, const struct tstring *msg, const struct tstring *ref)
+{
+  struct cmac_aes128_ctx ctx;
+  uint8_t digest[16];
+  unsigned i;
+
+  ASSERT (ref->length == sizeof(digest));
+  ASSERT (key->length == 16);
+  cmac_aes128_set_key (&ctx, key->data);
+  cmac_aes128_update (&ctx, msg->length, msg->data);
+  cmac_aes128_digest (&ctx, sizeof(digest), digest);
+  if (!MEMEQ (ref->length, ref->data, digest))
+    {
+      fprintf (stderr, "cmac_hash failed, msg: ");
+      print_hex (msg->length, msg->data);
+      fprintf(stderr, "Output:");
+      print_hex (16, digest);
+      fprintf(stderr, "Expected:");
+      tstring_print_hex(ref);
+      fprintf(stderr, "\n");
+      FAIL();
+    }
+
+  /* attempt to re-use the structure */
+  cmac_aes128_update (&ctx, msg->length, msg->data);
+  cmac_aes128_digest (&ctx, sizeof(digest), digest);
+  if (!MEMEQ (ref->length, ref->data, digest))
+    {
+      fprintf (stderr, "cmac_hash failed on re-use, msg: ");
+      print_hex (msg->length, msg->data);
+      fprintf(stderr, "Output:");
+      print_hex (16, digest);
+      fprintf(stderr, "Expected:");
+      tstring_print_hex(ref);
+      fprintf(stderr, "\n");
+      FAIL();
+    }
+
+  /* attempt byte-by-byte hashing */
+  cmac_aes128_set_key (&ctx, key->data);
+  for (i=0;i<msg->length;i++)
+    cmac_aes128_update (&ctx, 1, msg->data+i);
+  cmac_aes128_digest (&ctx, sizeof(digest), digest);
+  if (!MEMEQ (ref->length, ref->data, digest))
+    {
+      fprintf (stderr, "cmac_hash failed on byte-by-byte, msg: ");
+      print_hex (msg->length, msg->data);
+      fprintf(stderr, "Output:");
+      print_hex (16, digest);
+      fprintf(stderr, "Expected:");
+      tstring_print_hex(ref);
+      fprintf(stderr, "\n");
+      FAIL();
+    }
+}
+
+void
+test_main(void)
+{
+  /*
+   * CMAC-AES Test Vectors from RFC4493.
+   */
+
+  test_cmac_hash (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+		  SDATA(""),
+		  SHEX("bb1d6929e95937287fa37d129b756746"));
+
+  test_cmac_hash (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+		  SHEX("6bc1bee22e409f96e93d7e117393172a"),
+		  SHEX("070a16b46b4d4144f79bdd9dd04a287c"));
+
+  test_cmac_hash (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+		  SHEX("6bc1bee22e409f96e93d7e117393172a"
+		       "ae2d8a571e03ac9c9eb76fac45af8e51"
+		       "30c81c46a35ce411"),
+		  SHEX("dfa66747de9ae63030ca32611497c827"));
+
+  test_cmac_hash (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_hash (SHEX("2b7e151628aed2a8abf7158809cf4f3c"),
+		  SHEX("6bc1bee22e409f96e93d7e117393172a"
+		       "ae2d8a571e03ac9c9eb76fac45af8e51"
+		       "30c81c46a35ce411"),
+		  SHEX("87dd33c2945a4e228028690ae8954945"));
+
+  test_cmac_hash (SHEX("2b7e1ab628aed2a8abf7158809cf4f3c"),
+		  SHEX("6bc1bee22e409f96e93d7e117393172a"
+		       "ae2d8a571e03ac9c9eb76fac45af8e51"
+		       "30c81c46a35ce411"),
+		  SHEX("f0dc613a88886c7ed76eeb51f1c5e8d3"));
+
+  test_cmac_hash (SHEX("2b7e1ab628aed2a8abf7158809cf4f3d"),
+		  SHEX("6bc1bee22e409f96e93d7e117393172a"
+		       "ae2d8a571e03ac9c9eb76fac45af8e51"
+		       "30c81c46a35ce411"),
+		  SHEX("b9d092dc387a9e42cdfeb9f9930cf567"));
+
+}
+
-- 
2.14.3

From 627ddf9b745f4fa8da61e0cedb11d024c5b0ddeb Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <n...@redhat.com>
Date: Wed, 17 Jan 2018 10:47:23 +0100
Subject: [PATCH 2/3] cmac: block_mulx: simplify shifts

Signed-off-by: Nikos Mavrogiannopoulos <n...@redhat.com>
---
 cmac.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/cmac.c b/cmac.c
index a4d2468a..27df917e 100644
--- a/cmac.c
+++ b/cmac.c
@@ -57,14 +57,10 @@ static inline void block_mulx(union nettle_block16 *out,
 {
 	uint64_t b1 = READ_UINT64(in->b);
 	uint64_t b2 = READ_UINT64(in->b+8);
-	unsigned overflow = (b2 & UINT64_C(0x8000000000000000))?1:0;
 
-	b1 <<= 1;
+	b1 = (b1 << 1) | (b2 >> 63);
 	b2 <<= 1;
 
-	if (overflow)
-		b1 |= 0x01;
-
 	if (in->b[0] & 0x80)
 		b2 ^= 0x87;
 
-- 
2.14.3

From 6551e67f07eb5cf0ed08ab5324492c5d56edfde7 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <n...@redhat.com>
Date: Tue, 23 Jan 2018 11:33:56 +0100
Subject: [PATCH 3/3] Added support for cmac with aes-256

Signed-off-by: Nikos Mavrogiannopoulos <n...@redhat.com>
---
 Makefile.in           |  2 +-
 cmac-aes256.c         | 60 ++++++++++++++++++++++++++++++++++
 cmac.h                | 17 +++++++++-
 nettle.texinfo        | 21 +++++++++---
 testsuite/cmac-test.c | 89 +++++++++++++++++++++++++++++++++++----------------
 5 files changed, 156 insertions(+), 33 deletions(-)
 create mode 100644 cmac-aes256.c

diff --git a/Makefile.in b/Makefile.in
index a25c0f99..f6d92755 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -103,7 +103,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.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 \
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);
+}
diff --git a/cmac.h b/cmac.h
index 168ca95a..1632f54e 100644
--- a/cmac.h
+++ b/cmac.h
@@ -43,7 +43,6 @@
 extern "C" {
 #endif
 
-#define CMAC128_KEY_SIZE 16
 #define CMAC128_DIGEST_SIZE 16
 
 #define cmac128_set_key nettle_cmac128_set_key
@@ -52,6 +51,9 @@ extern "C" {
 #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;
@@ -111,6 +113,19 @@ 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
diff --git a/nettle.texinfo b/nettle.texinfo
index 4c7b5312..657c4d4c 100644
--- a/nettle.texinfo
+++ b/nettle.texinfo
@@ -3498,15 +3498,12 @@ Nettle defines @acronym{CMAC} in @file{<nettle/cmac.h>}.
 @deftp {Context struct} {struct cmac128_ctx}
 @end deftp
 
-@defvr Constant CMAC128_KEY_SIZE
-The CMAC key size, 16.
-@end defvr
 @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.
+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})
@@ -3521,6 +3518,22 @@ provide a smaller value, only the first @var{length} octets of the
 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/cmac-test.c b/testsuite/cmac-test.c
index 983c5127..58544f2a 100644
--- a/testsuite/cmac-test.c
+++ b/testsuite/cmac-test.c
@@ -2,24 +2,43 @@
 #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 (const struct tstring *key, const struct tstring *msg, const struct tstring *ref)
+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)
 {
-  struct cmac_aes128_ctx ctx;
-  uint8_t digest[16];
+  void *ctx;
+  uint8_t hash[16];
   unsigned i;
 
-  ASSERT (ref->length == sizeof(digest));
-  ASSERT (key->length == 16);
-  cmac_aes128_set_key (&ctx, key->data);
-  cmac_aes128_update (&ctx, msg->length, msg->data);
-  cmac_aes128_digest (&ctx, sizeof(digest), digest);
-  if (!MEMEQ (ref->length, ref->data, digest))
+  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, digest);
+      print_hex (16, hash);
       fprintf(stderr, "Expected:");
       tstring_print_hex(ref);
       fprintf(stderr, "\n");
@@ -27,14 +46,14 @@ test_cmac_hash (const struct tstring *key, const struct tstring *msg, const stru
     }
 
   /* attempt to re-use the structure */
-  cmac_aes128_update (&ctx, msg->length, msg->data);
-  cmac_aes128_digest (&ctx, sizeof(digest), digest);
-  if (!MEMEQ (ref->length, ref->data, digest))
+  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, digest);
+      print_hex (16, hash);
       fprintf(stderr, "Expected:");
       tstring_print_hex(ref);
       fprintf(stderr, "\n");
@@ -42,16 +61,16 @@ test_cmac_hash (const struct tstring *key, const struct tstring *msg, const stru
     }
 
   /* attempt byte-by-byte hashing */
-  cmac_aes128_set_key (&ctx, key->data);
+  set_key (ctx, key->data);
   for (i=0;i<msg->length;i++)
-    cmac_aes128_update (&ctx, 1, msg->data+i);
-  cmac_aes128_digest (&ctx, sizeof(digest), digest);
-  if (!MEMEQ (ref->length, ref->data, digest))
+    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, digest);
+      print_hex (16, hash);
       fprintf(stderr, "Expected:");
       tstring_print_hex(ref);
       fprintf(stderr, "\n");
@@ -65,22 +84,21 @@ test_main(void)
   /*
    * CMAC-AES Test Vectors from RFC4493.
    */
-
-  test_cmac_hash (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+  test_cmac_aes128 (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
 		  SDATA(""),
 		  SHEX("bb1d6929e95937287fa37d129b756746"));
 
-  test_cmac_hash (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+  test_cmac_aes128 (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
 		  SHEX("6bc1bee22e409f96e93d7e117393172a"),
 		  SHEX("070a16b46b4d4144f79bdd9dd04a287c"));
 
-  test_cmac_hash (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+  test_cmac_aes128 (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
 		  SHEX("6bc1bee22e409f96e93d7e117393172a"
 		       "ae2d8a571e03ac9c9eb76fac45af8e51"
 		       "30c81c46a35ce411"),
 		  SHEX("dfa66747de9ae63030ca32611497c827"));
 
-  test_cmac_hash (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+  test_cmac_aes128 (SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
 		  SHEX("6bc1bee22e409f96e93d7e117393172a"
 		       "ae2d8a571e03ac9c9eb76fac45af8e51"
 		       "30c81c46a35ce411e5fbc1191a0a52ef"
@@ -89,23 +107,40 @@ test_main(void)
 
   /* Additional tests with different keys (same plaintext)
    * to check all variants of set_key() */
-  test_cmac_hash (SHEX("2b7e151628aed2a8abf7158809cf4f3c"),
+  test_cmac_aes128 (SHEX("2b7e151628aed2a8abf7158809cf4f3c"),
 		  SHEX("6bc1bee22e409f96e93d7e117393172a"
 		       "ae2d8a571e03ac9c9eb76fac45af8e51"
 		       "30c81c46a35ce411"),
 		  SHEX("87dd33c2945a4e228028690ae8954945"));
 
-  test_cmac_hash (SHEX("2b7e1ab628aed2a8abf7158809cf4f3c"),
+  test_cmac_aes128 (SHEX("2b7e1ab628aed2a8abf7158809cf4f3c"),
 		  SHEX("6bc1bee22e409f96e93d7e117393172a"
 		       "ae2d8a571e03ac9c9eb76fac45af8e51"
 		       "30c81c46a35ce411"),
 		  SHEX("f0dc613a88886c7ed76eeb51f1c5e8d3"));
 
-  test_cmac_hash (SHEX("2b7e1ab628aed2a8abf7158809cf4f3d"),
+  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"));
+
 }
 
-- 
2.14.3

_______________________________________________
nettle-bugs mailing list
nettle-bugs@lists.lysator.liu.se
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to