From 6551e67f07eb5cf0ed08ab5324492c5d56edfde7 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@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 <nmav@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

