From e68adc5e81ff8814707cddba47118f99778deabc Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Wed, 10 Jan 2018 09:29:17 +0100
Subject: [PATCH] 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 <nmav@redhat.com>
---
 Makefile.in                 |   3 +
 cmac-aes128.c               |  60 +++++
 cmac-internal.h             | 588 ++++++++++++++++++++++++++++++++++++++++++++
 cmac.c                      | 139 +++++++++++
 cmac.h                      | 117 +++++++++
 examples/nettle-benchmark.c |  24 +-
 testsuite/.test-rules.make  |   3 +
 testsuite/Makefile.in       |   1 +
 testsuite/cmac-test.c       |  57 +++++
 9 files changed, 991 insertions(+), 1 deletion(-)
 create mode 100644 cmac-aes128.c
 create mode 100644 cmac-internal.h
 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..8d6219b6 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 \
@@ -226,6 +228,7 @@ DISTFILES = $(SOURCES) $(HEADERS) getopt.h getopt_int.h \
 	nettle.pc.in hogweed.pc.in \
 	$(des_headers) descore.README \
 	aes-internal.h camellia-internal.h serpent-internal.h \
+	cmac-internal.h \
 	cast128_sboxes.h desinfo.h desCode.h \
 	memxor-internal.h nettle-internal.h nettle-write.h \
 	gmp-glue.h ecc-internal.h fat-setup.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-internal.h b/cmac-internal.h
new file mode 100644
index 00000000..51b4b014
--- /dev/null
+++ b/cmac-internal.h
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2003-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef LIB_CRYPTO_AES_H
+#define LIB_CRYPTO_AES_H 1
+
+#include "aes.h"
+
+static inline void block_lshift(const uint8_t in[AES_BLOCK_SIZE],
+				uint8_t out[AES_BLOCK_SIZE])
+{
+	static const struct block_lshift_entry {
+		uint8_t lshift;
+		uint8_t overflow;
+	} block_lshift_table[UINT8_MAX+1] = {
+		[0x00] = { .lshift = 0x00, .overflow = 0x00 },
+		[0x01] = { .lshift = 0x02, .overflow = 0x00 },
+		[0x02] = { .lshift = 0x04, .overflow = 0x00 },
+		[0x03] = { .lshift = 0x06, .overflow = 0x00 },
+		[0x04] = { .lshift = 0x08, .overflow = 0x00 },
+		[0x05] = { .lshift = 0x0a, .overflow = 0x00 },
+		[0x06] = { .lshift = 0x0c, .overflow = 0x00 },
+		[0x07] = { .lshift = 0x0e, .overflow = 0x00 },
+		[0x08] = { .lshift = 0x10, .overflow = 0x00 },
+		[0x09] = { .lshift = 0x12, .overflow = 0x00 },
+		[0x0a] = { .lshift = 0x14, .overflow = 0x00 },
+		[0x0b] = { .lshift = 0x16, .overflow = 0x00 },
+		[0x0c] = { .lshift = 0x18, .overflow = 0x00 },
+		[0x0d] = { .lshift = 0x1a, .overflow = 0x00 },
+		[0x0e] = { .lshift = 0x1c, .overflow = 0x00 },
+		[0x0f] = { .lshift = 0x1e, .overflow = 0x00 },
+		[0x10] = { .lshift = 0x20, .overflow = 0x00 },
+		[0x11] = { .lshift = 0x22, .overflow = 0x00 },
+		[0x12] = { .lshift = 0x24, .overflow = 0x00 },
+		[0x13] = { .lshift = 0x26, .overflow = 0x00 },
+		[0x14] = { .lshift = 0x28, .overflow = 0x00 },
+		[0x15] = { .lshift = 0x2a, .overflow = 0x00 },
+		[0x16] = { .lshift = 0x2c, .overflow = 0x00 },
+		[0x17] = { .lshift = 0x2e, .overflow = 0x00 },
+		[0x18] = { .lshift = 0x30, .overflow = 0x00 },
+		[0x19] = { .lshift = 0x32, .overflow = 0x00 },
+		[0x1a] = { .lshift = 0x34, .overflow = 0x00 },
+		[0x1b] = { .lshift = 0x36, .overflow = 0x00 },
+		[0x1c] = { .lshift = 0x38, .overflow = 0x00 },
+		[0x1d] = { .lshift = 0x3a, .overflow = 0x00 },
+		[0x1e] = { .lshift = 0x3c, .overflow = 0x00 },
+		[0x1f] = { .lshift = 0x3e, .overflow = 0x00 },
+		[0x20] = { .lshift = 0x40, .overflow = 0x00 },
+		[0x21] = { .lshift = 0x42, .overflow = 0x00 },
+		[0x22] = { .lshift = 0x44, .overflow = 0x00 },
+		[0x23] = { .lshift = 0x46, .overflow = 0x00 },
+		[0x24] = { .lshift = 0x48, .overflow = 0x00 },
+		[0x25] = { .lshift = 0x4a, .overflow = 0x00 },
+		[0x26] = { .lshift = 0x4c, .overflow = 0x00 },
+		[0x27] = { .lshift = 0x4e, .overflow = 0x00 },
+		[0x28] = { .lshift = 0x50, .overflow = 0x00 },
+		[0x29] = { .lshift = 0x52, .overflow = 0x00 },
+		[0x2a] = { .lshift = 0x54, .overflow = 0x00 },
+		[0x2b] = { .lshift = 0x56, .overflow = 0x00 },
+		[0x2c] = { .lshift = 0x58, .overflow = 0x00 },
+		[0x2d] = { .lshift = 0x5a, .overflow = 0x00 },
+		[0x2e] = { .lshift = 0x5c, .overflow = 0x00 },
+		[0x2f] = { .lshift = 0x5e, .overflow = 0x00 },
+		[0x30] = { .lshift = 0x60, .overflow = 0x00 },
+		[0x31] = { .lshift = 0x62, .overflow = 0x00 },
+		[0x32] = { .lshift = 0x64, .overflow = 0x00 },
+		[0x33] = { .lshift = 0x66, .overflow = 0x00 },
+		[0x34] = { .lshift = 0x68, .overflow = 0x00 },
+		[0x35] = { .lshift = 0x6a, .overflow = 0x00 },
+		[0x36] = { .lshift = 0x6c, .overflow = 0x00 },
+		[0x37] = { .lshift = 0x6e, .overflow = 0x00 },
+		[0x38] = { .lshift = 0x70, .overflow = 0x00 },
+		[0x39] = { .lshift = 0x72, .overflow = 0x00 },
+		[0x3a] = { .lshift = 0x74, .overflow = 0x00 },
+		[0x3b] = { .lshift = 0x76, .overflow = 0x00 },
+		[0x3c] = { .lshift = 0x78, .overflow = 0x00 },
+		[0x3d] = { .lshift = 0x7a, .overflow = 0x00 },
+		[0x3e] = { .lshift = 0x7c, .overflow = 0x00 },
+		[0x3f] = { .lshift = 0x7e, .overflow = 0x00 },
+		[0x40] = { .lshift = 0x80, .overflow = 0x00 },
+		[0x41] = { .lshift = 0x82, .overflow = 0x00 },
+		[0x42] = { .lshift = 0x84, .overflow = 0x00 },
+		[0x43] = { .lshift = 0x86, .overflow = 0x00 },
+		[0x44] = { .lshift = 0x88, .overflow = 0x00 },
+		[0x45] = { .lshift = 0x8a, .overflow = 0x00 },
+		[0x46] = { .lshift = 0x8c, .overflow = 0x00 },
+		[0x47] = { .lshift = 0x8e, .overflow = 0x00 },
+		[0x48] = { .lshift = 0x90, .overflow = 0x00 },
+		[0x49] = { .lshift = 0x92, .overflow = 0x00 },
+		[0x4a] = { .lshift = 0x94, .overflow = 0x00 },
+		[0x4b] = { .lshift = 0x96, .overflow = 0x00 },
+		[0x4c] = { .lshift = 0x98, .overflow = 0x00 },
+		[0x4d] = { .lshift = 0x9a, .overflow = 0x00 },
+		[0x4e] = { .lshift = 0x9c, .overflow = 0x00 },
+		[0x4f] = { .lshift = 0x9e, .overflow = 0x00 },
+		[0x50] = { .lshift = 0xa0, .overflow = 0x00 },
+		[0x51] = { .lshift = 0xa2, .overflow = 0x00 },
+		[0x52] = { .lshift = 0xa4, .overflow = 0x00 },
+		[0x53] = { .lshift = 0xa6, .overflow = 0x00 },
+		[0x54] = { .lshift = 0xa8, .overflow = 0x00 },
+		[0x55] = { .lshift = 0xaa, .overflow = 0x00 },
+		[0x56] = { .lshift = 0xac, .overflow = 0x00 },
+		[0x57] = { .lshift = 0xae, .overflow = 0x00 },
+		[0x58] = { .lshift = 0xb0, .overflow = 0x00 },
+		[0x59] = { .lshift = 0xb2, .overflow = 0x00 },
+		[0x5a] = { .lshift = 0xb4, .overflow = 0x00 },
+		[0x5b] = { .lshift = 0xb6, .overflow = 0x00 },
+		[0x5c] = { .lshift = 0xb8, .overflow = 0x00 },
+		[0x5d] = { .lshift = 0xba, .overflow = 0x00 },
+		[0x5e] = { .lshift = 0xbc, .overflow = 0x00 },
+		[0x5f] = { .lshift = 0xbe, .overflow = 0x00 },
+		[0x60] = { .lshift = 0xc0, .overflow = 0x00 },
+		[0x61] = { .lshift = 0xc2, .overflow = 0x00 },
+		[0x62] = { .lshift = 0xc4, .overflow = 0x00 },
+		[0x63] = { .lshift = 0xc6, .overflow = 0x00 },
+		[0x64] = { .lshift = 0xc8, .overflow = 0x00 },
+		[0x65] = { .lshift = 0xca, .overflow = 0x00 },
+		[0x66] = { .lshift = 0xcc, .overflow = 0x00 },
+		[0x67] = { .lshift = 0xce, .overflow = 0x00 },
+		[0x68] = { .lshift = 0xd0, .overflow = 0x00 },
+		[0x69] = { .lshift = 0xd2, .overflow = 0x00 },
+		[0x6a] = { .lshift = 0xd4, .overflow = 0x00 },
+		[0x6b] = { .lshift = 0xd6, .overflow = 0x00 },
+		[0x6c] = { .lshift = 0xd8, .overflow = 0x00 },
+		[0x6d] = { .lshift = 0xda, .overflow = 0x00 },
+		[0x6e] = { .lshift = 0xdc, .overflow = 0x00 },
+		[0x6f] = { .lshift = 0xde, .overflow = 0x00 },
+		[0x70] = { .lshift = 0xe0, .overflow = 0x00 },
+		[0x71] = { .lshift = 0xe2, .overflow = 0x00 },
+		[0x72] = { .lshift = 0xe4, .overflow = 0x00 },
+		[0x73] = { .lshift = 0xe6, .overflow = 0x00 },
+		[0x74] = { .lshift = 0xe8, .overflow = 0x00 },
+		[0x75] = { .lshift = 0xea, .overflow = 0x00 },
+		[0x76] = { .lshift = 0xec, .overflow = 0x00 },
+		[0x77] = { .lshift = 0xee, .overflow = 0x00 },
+		[0x78] = { .lshift = 0xf0, .overflow = 0x00 },
+		[0x79] = { .lshift = 0xf2, .overflow = 0x00 },
+		[0x7a] = { .lshift = 0xf4, .overflow = 0x00 },
+		[0x7b] = { .lshift = 0xf6, .overflow = 0x00 },
+		[0x7c] = { .lshift = 0xf8, .overflow = 0x00 },
+		[0x7d] = { .lshift = 0xfa, .overflow = 0x00 },
+		[0x7e] = { .lshift = 0xfc, .overflow = 0x00 },
+		[0x7f] = { .lshift = 0xfe, .overflow = 0x00 },
+		[0x80] = { .lshift = 0x00, .overflow = 0x01 },
+		[0x81] = { .lshift = 0x02, .overflow = 0x01 },
+		[0x82] = { .lshift = 0x04, .overflow = 0x01 },
+		[0x83] = { .lshift = 0x06, .overflow = 0x01 },
+		[0x84] = { .lshift = 0x08, .overflow = 0x01 },
+		[0x85] = { .lshift = 0x0a, .overflow = 0x01 },
+		[0x86] = { .lshift = 0x0c, .overflow = 0x01 },
+		[0x87] = { .lshift = 0x0e, .overflow = 0x01 },
+		[0x88] = { .lshift = 0x10, .overflow = 0x01 },
+		[0x89] = { .lshift = 0x12, .overflow = 0x01 },
+		[0x8a] = { .lshift = 0x14, .overflow = 0x01 },
+		[0x8b] = { .lshift = 0x16, .overflow = 0x01 },
+		[0x8c] = { .lshift = 0x18, .overflow = 0x01 },
+		[0x8d] = { .lshift = 0x1a, .overflow = 0x01 },
+		[0x8e] = { .lshift = 0x1c, .overflow = 0x01 },
+		[0x8f] = { .lshift = 0x1e, .overflow = 0x01 },
+		[0x90] = { .lshift = 0x20, .overflow = 0x01 },
+		[0x91] = { .lshift = 0x22, .overflow = 0x01 },
+		[0x92] = { .lshift = 0x24, .overflow = 0x01 },
+		[0x93] = { .lshift = 0x26, .overflow = 0x01 },
+		[0x94] = { .lshift = 0x28, .overflow = 0x01 },
+		[0x95] = { .lshift = 0x2a, .overflow = 0x01 },
+		[0x96] = { .lshift = 0x2c, .overflow = 0x01 },
+		[0x97] = { .lshift = 0x2e, .overflow = 0x01 },
+		[0x98] = { .lshift = 0x30, .overflow = 0x01 },
+		[0x99] = { .lshift = 0x32, .overflow = 0x01 },
+		[0x9a] = { .lshift = 0x34, .overflow = 0x01 },
+		[0x9b] = { .lshift = 0x36, .overflow = 0x01 },
+		[0x9c] = { .lshift = 0x38, .overflow = 0x01 },
+		[0x9d] = { .lshift = 0x3a, .overflow = 0x01 },
+		[0x9e] = { .lshift = 0x3c, .overflow = 0x01 },
+		[0x9f] = { .lshift = 0x3e, .overflow = 0x01 },
+		[0xa0] = { .lshift = 0x40, .overflow = 0x01 },
+		[0xa1] = { .lshift = 0x42, .overflow = 0x01 },
+		[0xa2] = { .lshift = 0x44, .overflow = 0x01 },
+		[0xa3] = { .lshift = 0x46, .overflow = 0x01 },
+		[0xa4] = { .lshift = 0x48, .overflow = 0x01 },
+		[0xa5] = { .lshift = 0x4a, .overflow = 0x01 },
+		[0xa6] = { .lshift = 0x4c, .overflow = 0x01 },
+		[0xa7] = { .lshift = 0x4e, .overflow = 0x01 },
+		[0xa8] = { .lshift = 0x50, .overflow = 0x01 },
+		[0xa9] = { .lshift = 0x52, .overflow = 0x01 },
+		[0xaa] = { .lshift = 0x54, .overflow = 0x01 },
+		[0xab] = { .lshift = 0x56, .overflow = 0x01 },
+		[0xac] = { .lshift = 0x58, .overflow = 0x01 },
+		[0xad] = { .lshift = 0x5a, .overflow = 0x01 },
+		[0xae] = { .lshift = 0x5c, .overflow = 0x01 },
+		[0xaf] = { .lshift = 0x5e, .overflow = 0x01 },
+		[0xb0] = { .lshift = 0x60, .overflow = 0x01 },
+		[0xb1] = { .lshift = 0x62, .overflow = 0x01 },
+		[0xb2] = { .lshift = 0x64, .overflow = 0x01 },
+		[0xb3] = { .lshift = 0x66, .overflow = 0x01 },
+		[0xb4] = { .lshift = 0x68, .overflow = 0x01 },
+		[0xb5] = { .lshift = 0x6a, .overflow = 0x01 },
+		[0xb6] = { .lshift = 0x6c, .overflow = 0x01 },
+		[0xb7] = { .lshift = 0x6e, .overflow = 0x01 },
+		[0xb8] = { .lshift = 0x70, .overflow = 0x01 },
+		[0xb9] = { .lshift = 0x72, .overflow = 0x01 },
+		[0xba] = { .lshift = 0x74, .overflow = 0x01 },
+		[0xbb] = { .lshift = 0x76, .overflow = 0x01 },
+		[0xbc] = { .lshift = 0x78, .overflow = 0x01 },
+		[0xbd] = { .lshift = 0x7a, .overflow = 0x01 },
+		[0xbe] = { .lshift = 0x7c, .overflow = 0x01 },
+		[0xbf] = { .lshift = 0x7e, .overflow = 0x01 },
+		[0xc0] = { .lshift = 0x80, .overflow = 0x01 },
+		[0xc1] = { .lshift = 0x82, .overflow = 0x01 },
+		[0xc2] = { .lshift = 0x84, .overflow = 0x01 },
+		[0xc3] = { .lshift = 0x86, .overflow = 0x01 },
+		[0xc4] = { .lshift = 0x88, .overflow = 0x01 },
+		[0xc5] = { .lshift = 0x8a, .overflow = 0x01 },
+		[0xc6] = { .lshift = 0x8c, .overflow = 0x01 },
+		[0xc7] = { .lshift = 0x8e, .overflow = 0x01 },
+		[0xc8] = { .lshift = 0x90, .overflow = 0x01 },
+		[0xc9] = { .lshift = 0x92, .overflow = 0x01 },
+		[0xca] = { .lshift = 0x94, .overflow = 0x01 },
+		[0xcb] = { .lshift = 0x96, .overflow = 0x01 },
+		[0xcc] = { .lshift = 0x98, .overflow = 0x01 },
+		[0xcd] = { .lshift = 0x9a, .overflow = 0x01 },
+		[0xce] = { .lshift = 0x9c, .overflow = 0x01 },
+		[0xcf] = { .lshift = 0x9e, .overflow = 0x01 },
+		[0xd0] = { .lshift = 0xa0, .overflow = 0x01 },
+		[0xd1] = { .lshift = 0xa2, .overflow = 0x01 },
+		[0xd2] = { .lshift = 0xa4, .overflow = 0x01 },
+		[0xd3] = { .lshift = 0xa6, .overflow = 0x01 },
+		[0xd4] = { .lshift = 0xa8, .overflow = 0x01 },
+		[0xd5] = { .lshift = 0xaa, .overflow = 0x01 },
+		[0xd6] = { .lshift = 0xac, .overflow = 0x01 },
+		[0xd7] = { .lshift = 0xae, .overflow = 0x01 },
+		[0xd8] = { .lshift = 0xb0, .overflow = 0x01 },
+		[0xd9] = { .lshift = 0xb2, .overflow = 0x01 },
+		[0xda] = { .lshift = 0xb4, .overflow = 0x01 },
+		[0xdb] = { .lshift = 0xb6, .overflow = 0x01 },
+		[0xdc] = { .lshift = 0xb8, .overflow = 0x01 },
+		[0xdd] = { .lshift = 0xba, .overflow = 0x01 },
+		[0xde] = { .lshift = 0xbc, .overflow = 0x01 },
+		[0xdf] = { .lshift = 0xbe, .overflow = 0x01 },
+		[0xe0] = { .lshift = 0xc0, .overflow = 0x01 },
+		[0xe1] = { .lshift = 0xc2, .overflow = 0x01 },
+		[0xe2] = { .lshift = 0xc4, .overflow = 0x01 },
+		[0xe3] = { .lshift = 0xc6, .overflow = 0x01 },
+		[0xe4] = { .lshift = 0xc8, .overflow = 0x01 },
+		[0xe5] = { .lshift = 0xca, .overflow = 0x01 },
+		[0xe6] = { .lshift = 0xcc, .overflow = 0x01 },
+		[0xe7] = { .lshift = 0xce, .overflow = 0x01 },
+		[0xe8] = { .lshift = 0xd0, .overflow = 0x01 },
+		[0xe9] = { .lshift = 0xd2, .overflow = 0x01 },
+		[0xea] = { .lshift = 0xd4, .overflow = 0x01 },
+		[0xeb] = { .lshift = 0xd6, .overflow = 0x01 },
+		[0xec] = { .lshift = 0xd8, .overflow = 0x01 },
+		[0xed] = { .lshift = 0xda, .overflow = 0x01 },
+		[0xee] = { .lshift = 0xdc, .overflow = 0x01 },
+		[0xef] = { .lshift = 0xde, .overflow = 0x01 },
+		[0xf0] = { .lshift = 0xe0, .overflow = 0x01 },
+		[0xf1] = { .lshift = 0xe2, .overflow = 0x01 },
+		[0xf2] = { .lshift = 0xe4, .overflow = 0x01 },
+		[0xf3] = { .lshift = 0xe6, .overflow = 0x01 },
+		[0xf4] = { .lshift = 0xe8, .overflow = 0x01 },
+		[0xf5] = { .lshift = 0xea, .overflow = 0x01 },
+		[0xf6] = { .lshift = 0xec, .overflow = 0x01 },
+		[0xf7] = { .lshift = 0xee, .overflow = 0x01 },
+		[0xf8] = { .lshift = 0xf0, .overflow = 0x01 },
+		[0xf9] = { .lshift = 0xf2, .overflow = 0x01 },
+		[0xfa] = { .lshift = 0xf4, .overflow = 0x01 },
+		[0xfb] = { .lshift = 0xf6, .overflow = 0x01 },
+		[0xfc] = { .lshift = 0xf8, .overflow = 0x01 },
+		[0xfd] = { .lshift = 0xfa, .overflow = 0x01 },
+		[0xfe] = { .lshift = 0xfc, .overflow = 0x01 },
+		[0xff] = { .lshift = 0xfe, .overflow = 0x01 },
+	};
+	int8_t i;
+	uint8_t overflow = 0;
+
+	for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
+		const struct block_lshift_entry *e = &block_lshift_table[in[i]];
+		out[i] = e->lshift | overflow;
+		overflow = e->overflow;
+	}
+}
+
+static inline void block_rshift(const uint8_t in[AES_BLOCK_SIZE],
+				    uint8_t out[AES_BLOCK_SIZE])
+{
+	static const struct block_rshift_entry {
+		uint8_t rshift;
+		uint8_t overflow;
+	} block_rshift_table[UINT8_MAX+1] = {
+		[0x00] = { .rshift = 0x00, .overflow = 0x00 },
+		[0x01] = { .rshift = 0x00, .overflow = 0x80 },
+		[0x02] = { .rshift = 0x01, .overflow = 0x00 },
+		[0x03] = { .rshift = 0x01, .overflow = 0x80 },
+		[0x04] = { .rshift = 0x02, .overflow = 0x00 },
+		[0x05] = { .rshift = 0x02, .overflow = 0x80 },
+		[0x06] = { .rshift = 0x03, .overflow = 0x00 },
+		[0x07] = { .rshift = 0x03, .overflow = 0x80 },
+		[0x08] = { .rshift = 0x04, .overflow = 0x00 },
+		[0x09] = { .rshift = 0x04, .overflow = 0x80 },
+		[0x0a] = { .rshift = 0x05, .overflow = 0x00 },
+		[0x0b] = { .rshift = 0x05, .overflow = 0x80 },
+		[0x0c] = { .rshift = 0x06, .overflow = 0x00 },
+		[0x0d] = { .rshift = 0x06, .overflow = 0x80 },
+		[0x0e] = { .rshift = 0x07, .overflow = 0x00 },
+		[0x0f] = { .rshift = 0x07, .overflow = 0x80 },
+		[0x10] = { .rshift = 0x08, .overflow = 0x00 },
+		[0x11] = { .rshift = 0x08, .overflow = 0x80 },
+		[0x12] = { .rshift = 0x09, .overflow = 0x00 },
+		[0x13] = { .rshift = 0x09, .overflow = 0x80 },
+		[0x14] = { .rshift = 0x0a, .overflow = 0x00 },
+		[0x15] = { .rshift = 0x0a, .overflow = 0x80 },
+		[0x16] = { .rshift = 0x0b, .overflow = 0x00 },
+		[0x17] = { .rshift = 0x0b, .overflow = 0x80 },
+		[0x18] = { .rshift = 0x0c, .overflow = 0x00 },
+		[0x19] = { .rshift = 0x0c, .overflow = 0x80 },
+		[0x1a] = { .rshift = 0x0d, .overflow = 0x00 },
+		[0x1b] = { .rshift = 0x0d, .overflow = 0x80 },
+		[0x1c] = { .rshift = 0x0e, .overflow = 0x00 },
+		[0x1d] = { .rshift = 0x0e, .overflow = 0x80 },
+		[0x1e] = { .rshift = 0x0f, .overflow = 0x00 },
+		[0x1f] = { .rshift = 0x0f, .overflow = 0x80 },
+		[0x20] = { .rshift = 0x10, .overflow = 0x00 },
+		[0x21] = { .rshift = 0x10, .overflow = 0x80 },
+		[0x22] = { .rshift = 0x11, .overflow = 0x00 },
+		[0x23] = { .rshift = 0x11, .overflow = 0x80 },
+		[0x24] = { .rshift = 0x12, .overflow = 0x00 },
+		[0x25] = { .rshift = 0x12, .overflow = 0x80 },
+		[0x26] = { .rshift = 0x13, .overflow = 0x00 },
+		[0x27] = { .rshift = 0x13, .overflow = 0x80 },
+		[0x28] = { .rshift = 0x14, .overflow = 0x00 },
+		[0x29] = { .rshift = 0x14, .overflow = 0x80 },
+		[0x2a] = { .rshift = 0x15, .overflow = 0x00 },
+		[0x2b] = { .rshift = 0x15, .overflow = 0x80 },
+		[0x2c] = { .rshift = 0x16, .overflow = 0x00 },
+		[0x2d] = { .rshift = 0x16, .overflow = 0x80 },
+		[0x2e] = { .rshift = 0x17, .overflow = 0x00 },
+		[0x2f] = { .rshift = 0x17, .overflow = 0x80 },
+		[0x30] = { .rshift = 0x18, .overflow = 0x00 },
+		[0x31] = { .rshift = 0x18, .overflow = 0x80 },
+		[0x32] = { .rshift = 0x19, .overflow = 0x00 },
+		[0x33] = { .rshift = 0x19, .overflow = 0x80 },
+		[0x34] = { .rshift = 0x1a, .overflow = 0x00 },
+		[0x35] = { .rshift = 0x1a, .overflow = 0x80 },
+		[0x36] = { .rshift = 0x1b, .overflow = 0x00 },
+		[0x37] = { .rshift = 0x1b, .overflow = 0x80 },
+		[0x38] = { .rshift = 0x1c, .overflow = 0x00 },
+		[0x39] = { .rshift = 0x1c, .overflow = 0x80 },
+		[0x3a] = { .rshift = 0x1d, .overflow = 0x00 },
+		[0x3b] = { .rshift = 0x1d, .overflow = 0x80 },
+		[0x3c] = { .rshift = 0x1e, .overflow = 0x00 },
+		[0x3d] = { .rshift = 0x1e, .overflow = 0x80 },
+		[0x3e] = { .rshift = 0x1f, .overflow = 0x00 },
+		[0x3f] = { .rshift = 0x1f, .overflow = 0x80 },
+		[0x40] = { .rshift = 0x20, .overflow = 0x00 },
+		[0x41] = { .rshift = 0x20, .overflow = 0x80 },
+		[0x42] = { .rshift = 0x21, .overflow = 0x00 },
+		[0x43] = { .rshift = 0x21, .overflow = 0x80 },
+		[0x44] = { .rshift = 0x22, .overflow = 0x00 },
+		[0x45] = { .rshift = 0x22, .overflow = 0x80 },
+		[0x46] = { .rshift = 0x23, .overflow = 0x00 },
+		[0x47] = { .rshift = 0x23, .overflow = 0x80 },
+		[0x48] = { .rshift = 0x24, .overflow = 0x00 },
+		[0x49] = { .rshift = 0x24, .overflow = 0x80 },
+		[0x4a] = { .rshift = 0x25, .overflow = 0x00 },
+		[0x4b] = { .rshift = 0x25, .overflow = 0x80 },
+		[0x4c] = { .rshift = 0x26, .overflow = 0x00 },
+		[0x4d] = { .rshift = 0x26, .overflow = 0x80 },
+		[0x4e] = { .rshift = 0x27, .overflow = 0x00 },
+		[0x4f] = { .rshift = 0x27, .overflow = 0x80 },
+		[0x50] = { .rshift = 0x28, .overflow = 0x00 },
+		[0x51] = { .rshift = 0x28, .overflow = 0x80 },
+		[0x52] = { .rshift = 0x29, .overflow = 0x00 },
+		[0x53] = { .rshift = 0x29, .overflow = 0x80 },
+		[0x54] = { .rshift = 0x2a, .overflow = 0x00 },
+		[0x55] = { .rshift = 0x2a, .overflow = 0x80 },
+		[0x56] = { .rshift = 0x2b, .overflow = 0x00 },
+		[0x57] = { .rshift = 0x2b, .overflow = 0x80 },
+		[0x58] = { .rshift = 0x2c, .overflow = 0x00 },
+		[0x59] = { .rshift = 0x2c, .overflow = 0x80 },
+		[0x5a] = { .rshift = 0x2d, .overflow = 0x00 },
+		[0x5b] = { .rshift = 0x2d, .overflow = 0x80 },
+		[0x5c] = { .rshift = 0x2e, .overflow = 0x00 },
+		[0x5d] = { .rshift = 0x2e, .overflow = 0x80 },
+		[0x5e] = { .rshift = 0x2f, .overflow = 0x00 },
+		[0x5f] = { .rshift = 0x2f, .overflow = 0x80 },
+		[0x60] = { .rshift = 0x30, .overflow = 0x00 },
+		[0x61] = { .rshift = 0x30, .overflow = 0x80 },
+		[0x62] = { .rshift = 0x31, .overflow = 0x00 },
+		[0x63] = { .rshift = 0x31, .overflow = 0x80 },
+		[0x64] = { .rshift = 0x32, .overflow = 0x00 },
+		[0x65] = { .rshift = 0x32, .overflow = 0x80 },
+		[0x66] = { .rshift = 0x33, .overflow = 0x00 },
+		[0x67] = { .rshift = 0x33, .overflow = 0x80 },
+		[0x68] = { .rshift = 0x34, .overflow = 0x00 },
+		[0x69] = { .rshift = 0x34, .overflow = 0x80 },
+		[0x6a] = { .rshift = 0x35, .overflow = 0x00 },
+		[0x6b] = { .rshift = 0x35, .overflow = 0x80 },
+		[0x6c] = { .rshift = 0x36, .overflow = 0x00 },
+		[0x6d] = { .rshift = 0x36, .overflow = 0x80 },
+		[0x6e] = { .rshift = 0x37, .overflow = 0x00 },
+		[0x6f] = { .rshift = 0x37, .overflow = 0x80 },
+		[0x70] = { .rshift = 0x38, .overflow = 0x00 },
+		[0x71] = { .rshift = 0x38, .overflow = 0x80 },
+		[0x72] = { .rshift = 0x39, .overflow = 0x00 },
+		[0x73] = { .rshift = 0x39, .overflow = 0x80 },
+		[0x74] = { .rshift = 0x3a, .overflow = 0x00 },
+		[0x75] = { .rshift = 0x3a, .overflow = 0x80 },
+		[0x76] = { .rshift = 0x3b, .overflow = 0x00 },
+		[0x77] = { .rshift = 0x3b, .overflow = 0x80 },
+		[0x78] = { .rshift = 0x3c, .overflow = 0x00 },
+		[0x79] = { .rshift = 0x3c, .overflow = 0x80 },
+		[0x7a] = { .rshift = 0x3d, .overflow = 0x00 },
+		[0x7b] = { .rshift = 0x3d, .overflow = 0x80 },
+		[0x7c] = { .rshift = 0x3e, .overflow = 0x00 },
+		[0x7d] = { .rshift = 0x3e, .overflow = 0x80 },
+		[0x7e] = { .rshift = 0x3f, .overflow = 0x00 },
+		[0x7f] = { .rshift = 0x3f, .overflow = 0x80 },
+		[0x80] = { .rshift = 0x40, .overflow = 0x00 },
+		[0x81] = { .rshift = 0x40, .overflow = 0x80 },
+		[0x82] = { .rshift = 0x41, .overflow = 0x00 },
+		[0x83] = { .rshift = 0x41, .overflow = 0x80 },
+		[0x84] = { .rshift = 0x42, .overflow = 0x00 },
+		[0x85] = { .rshift = 0x42, .overflow = 0x80 },
+		[0x86] = { .rshift = 0x43, .overflow = 0x00 },
+		[0x87] = { .rshift = 0x43, .overflow = 0x80 },
+		[0x88] = { .rshift = 0x44, .overflow = 0x00 },
+		[0x89] = { .rshift = 0x44, .overflow = 0x80 },
+		[0x8a] = { .rshift = 0x45, .overflow = 0x00 },
+		[0x8b] = { .rshift = 0x45, .overflow = 0x80 },
+		[0x8c] = { .rshift = 0x46, .overflow = 0x00 },
+		[0x8d] = { .rshift = 0x46, .overflow = 0x80 },
+		[0x8e] = { .rshift = 0x47, .overflow = 0x00 },
+		[0x8f] = { .rshift = 0x47, .overflow = 0x80 },
+		[0x90] = { .rshift = 0x48, .overflow = 0x00 },
+		[0x91] = { .rshift = 0x48, .overflow = 0x80 },
+		[0x92] = { .rshift = 0x49, .overflow = 0x00 },
+		[0x93] = { .rshift = 0x49, .overflow = 0x80 },
+		[0x94] = { .rshift = 0x4a, .overflow = 0x00 },
+		[0x95] = { .rshift = 0x4a, .overflow = 0x80 },
+		[0x96] = { .rshift = 0x4b, .overflow = 0x00 },
+		[0x97] = { .rshift = 0x4b, .overflow = 0x80 },
+		[0x98] = { .rshift = 0x4c, .overflow = 0x00 },
+		[0x99] = { .rshift = 0x4c, .overflow = 0x80 },
+		[0x9a] = { .rshift = 0x4d, .overflow = 0x00 },
+		[0x9b] = { .rshift = 0x4d, .overflow = 0x80 },
+		[0x9c] = { .rshift = 0x4e, .overflow = 0x00 },
+		[0x9d] = { .rshift = 0x4e, .overflow = 0x80 },
+		[0x9e] = { .rshift = 0x4f, .overflow = 0x00 },
+		[0x9f] = { .rshift = 0x4f, .overflow = 0x80 },
+		[0xa0] = { .rshift = 0x50, .overflow = 0x00 },
+		[0xa1] = { .rshift = 0x50, .overflow = 0x80 },
+		[0xa2] = { .rshift = 0x51, .overflow = 0x00 },
+		[0xa3] = { .rshift = 0x51, .overflow = 0x80 },
+		[0xa4] = { .rshift = 0x52, .overflow = 0x00 },
+		[0xa5] = { .rshift = 0x52, .overflow = 0x80 },
+		[0xa6] = { .rshift = 0x53, .overflow = 0x00 },
+		[0xa7] = { .rshift = 0x53, .overflow = 0x80 },
+		[0xa8] = { .rshift = 0x54, .overflow = 0x00 },
+		[0xa9] = { .rshift = 0x54, .overflow = 0x80 },
+		[0xaa] = { .rshift = 0x55, .overflow = 0x00 },
+		[0xab] = { .rshift = 0x55, .overflow = 0x80 },
+		[0xac] = { .rshift = 0x56, .overflow = 0x00 },
+		[0xad] = { .rshift = 0x56, .overflow = 0x80 },
+		[0xae] = { .rshift = 0x57, .overflow = 0x00 },
+		[0xaf] = { .rshift = 0x57, .overflow = 0x80 },
+		[0xb0] = { .rshift = 0x58, .overflow = 0x00 },
+		[0xb1] = { .rshift = 0x58, .overflow = 0x80 },
+		[0xb2] = { .rshift = 0x59, .overflow = 0x00 },
+		[0xb3] = { .rshift = 0x59, .overflow = 0x80 },
+		[0xb4] = { .rshift = 0x5a, .overflow = 0x00 },
+		[0xb5] = { .rshift = 0x5a, .overflow = 0x80 },
+		[0xb6] = { .rshift = 0x5b, .overflow = 0x00 },
+		[0xb7] = { .rshift = 0x5b, .overflow = 0x80 },
+		[0xb8] = { .rshift = 0x5c, .overflow = 0x00 },
+		[0xb9] = { .rshift = 0x5c, .overflow = 0x80 },
+		[0xba] = { .rshift = 0x5d, .overflow = 0x00 },
+		[0xbb] = { .rshift = 0x5d, .overflow = 0x80 },
+		[0xbc] = { .rshift = 0x5e, .overflow = 0x00 },
+		[0xbd] = { .rshift = 0x5e, .overflow = 0x80 },
+		[0xbe] = { .rshift = 0x5f, .overflow = 0x00 },
+		[0xbf] = { .rshift = 0x5f, .overflow = 0x80 },
+		[0xc0] = { .rshift = 0x60, .overflow = 0x00 },
+		[0xc1] = { .rshift = 0x60, .overflow = 0x80 },
+		[0xc2] = { .rshift = 0x61, .overflow = 0x00 },
+		[0xc3] = { .rshift = 0x61, .overflow = 0x80 },
+		[0xc4] = { .rshift = 0x62, .overflow = 0x00 },
+		[0xc5] = { .rshift = 0x62, .overflow = 0x80 },
+		[0xc6] = { .rshift = 0x63, .overflow = 0x00 },
+		[0xc7] = { .rshift = 0x63, .overflow = 0x80 },
+		[0xc8] = { .rshift = 0x64, .overflow = 0x00 },
+		[0xc9] = { .rshift = 0x64, .overflow = 0x80 },
+		[0xca] = { .rshift = 0x65, .overflow = 0x00 },
+		[0xcb] = { .rshift = 0x65, .overflow = 0x80 },
+		[0xcc] = { .rshift = 0x66, .overflow = 0x00 },
+		[0xcd] = { .rshift = 0x66, .overflow = 0x80 },
+		[0xce] = { .rshift = 0x67, .overflow = 0x00 },
+		[0xcf] = { .rshift = 0x67, .overflow = 0x80 },
+		[0xd0] = { .rshift = 0x68, .overflow = 0x00 },
+		[0xd1] = { .rshift = 0x68, .overflow = 0x80 },
+		[0xd2] = { .rshift = 0x69, .overflow = 0x00 },
+		[0xd3] = { .rshift = 0x69, .overflow = 0x80 },
+		[0xd4] = { .rshift = 0x6a, .overflow = 0x00 },
+		[0xd5] = { .rshift = 0x6a, .overflow = 0x80 },
+		[0xd6] = { .rshift = 0x6b, .overflow = 0x00 },
+		[0xd7] = { .rshift = 0x6b, .overflow = 0x80 },
+		[0xd8] = { .rshift = 0x6c, .overflow = 0x00 },
+		[0xd9] = { .rshift = 0x6c, .overflow = 0x80 },
+		[0xda] = { .rshift = 0x6d, .overflow = 0x00 },
+		[0xdb] = { .rshift = 0x6d, .overflow = 0x80 },
+		[0xdc] = { .rshift = 0x6e, .overflow = 0x00 },
+		[0xdd] = { .rshift = 0x6e, .overflow = 0x80 },
+		[0xde] = { .rshift = 0x6f, .overflow = 0x00 },
+		[0xdf] = { .rshift = 0x6f, .overflow = 0x80 },
+		[0xe0] = { .rshift = 0x70, .overflow = 0x00 },
+		[0xe1] = { .rshift = 0x70, .overflow = 0x80 },
+		[0xe2] = { .rshift = 0x71, .overflow = 0x00 },
+		[0xe3] = { .rshift = 0x71, .overflow = 0x80 },
+		[0xe4] = { .rshift = 0x72, .overflow = 0x00 },
+		[0xe5] = { .rshift = 0x72, .overflow = 0x80 },
+		[0xe6] = { .rshift = 0x73, .overflow = 0x00 },
+		[0xe7] = { .rshift = 0x73, .overflow = 0x80 },
+		[0xe8] = { .rshift = 0x74, .overflow = 0x00 },
+		[0xe9] = { .rshift = 0x74, .overflow = 0x80 },
+		[0xea] = { .rshift = 0x75, .overflow = 0x00 },
+		[0xeb] = { .rshift = 0x75, .overflow = 0x80 },
+		[0xec] = { .rshift = 0x76, .overflow = 0x00 },
+		[0xed] = { .rshift = 0x76, .overflow = 0x80 },
+		[0xee] = { .rshift = 0x77, .overflow = 0x00 },
+		[0xef] = { .rshift = 0x77, .overflow = 0x80 },
+		[0xf0] = { .rshift = 0x78, .overflow = 0x00 },
+		[0xf1] = { .rshift = 0x78, .overflow = 0x80 },
+		[0xf2] = { .rshift = 0x79, .overflow = 0x00 },
+		[0xf3] = { .rshift = 0x79, .overflow = 0x80 },
+		[0xf4] = { .rshift = 0x7a, .overflow = 0x00 },
+		[0xf5] = { .rshift = 0x7a, .overflow = 0x80 },
+		[0xf6] = { .rshift = 0x7b, .overflow = 0x00 },
+		[0xf7] = { .rshift = 0x7b, .overflow = 0x80 },
+		[0xf8] = { .rshift = 0x7c, .overflow = 0x00 },
+		[0xf9] = { .rshift = 0x7c, .overflow = 0x80 },
+		[0xfa] = { .rshift = 0x7d, .overflow = 0x00 },
+		[0xfb] = { .rshift = 0x7d, .overflow = 0x80 },
+		[0xfc] = { .rshift = 0x7e, .overflow = 0x00 },
+		[0xfd] = { .rshift = 0x7e, .overflow = 0x80 },
+		[0xfe] = { .rshift = 0x7f, .overflow = 0x00 },
+		[0xff] = { .rshift = 0x7f, .overflow = 0x80 },
+	};
+	uint8_t i;
+	uint8_t overflow = 0;
+
+	for (i = 0; i < AES_BLOCK_SIZE; i++) {
+		const struct block_rshift_entry *e = &block_rshift_table[in[i]];
+		out[i] = e->rshift | overflow;
+		overflow = e->overflow;
+	}
+}
+#endif /* LIB_CRYPTO_AES_H */
diff --git a/cmac.c b/cmac.c
new file mode 100644
index 00000000..afea79fd
--- /dev/null
+++ b/cmac.c
@@ -0,0 +1,139 @@
+/*
+   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 program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 a copy of the GNU 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 "cmac-internal.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
+};
+
+static const uint8_t const_Rb[] = {
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x87
+};
+
+#define _MSB(x) (((x)[0] & 0x80)?1:0)
+
+void cmac128_set_key(struct cmac128 *ctx, void *key,
+		     nettle_cipher_func *encrypt)
+{
+	memset(ctx, 0, sizeof(*ctx));
+
+	/* step 1 - generate subkeys k1 and k2 */
+	encrypt(key, 16, ctx->L, const_Zero);
+
+	if (_MSB(ctx->L) == 0) {
+		block_lshift(ctx->L, ctx->K1);
+	} else {
+		block_lshift(ctx->L, ctx->K1);
+		memxor(ctx->K1, const_Rb, 16);
+	}
+
+	if (_MSB(ctx->K1) == 0) {
+		block_lshift(ctx->K1, ctx->K2);
+	} else {
+		block_lshift(ctx->K1, ctx->K2);
+		memxor(ctx->K2, const_Rb, 16);
+	}
+}
+
+#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)
+{
+	/*
+	 * check if we expand the block
+	 */
+	if (ctx->last_len < 16) {
+		size_t len = MIN(16 - ctx->last_len, msg_len);
+		memcpy(&ctx->last[ctx->last_len], msg, len);
+		msg += len;
+		msg_len -= len;
+		ctx->last_len += len;
+	}
+
+	if (msg_len == 0) {
+		/* if it is still the last block, we are done */
+		return;
+	}
+
+	/*
+	 * now checksum everything but the last block
+	 */
+	memxor3(ctx->Y, ctx->X, ctx->last, 16);
+	encrypt(key, 16, ctx->X, ctx->Y);
+
+	while (msg_len > 16) {
+		memxor3(ctx->Y, ctx->X, msg, 16);
+		encrypt(key, 16, ctx->X, ctx->Y);
+		msg += 16;
+		msg_len -= 16;
+	}
+
+	/*
+	 * copy the last block, it will be processed in
+	 * cmac128_digest().
+	 */
+	memset(ctx->last, 0, sizeof(ctx->last));
+	memcpy(ctx->last, msg, msg_len);
+	ctx->last_len = msg_len;
+}
+
+void cmac128_digest(struct cmac128 *ctx, void *key,
+		    nettle_cipher_func *encrypt,
+		    unsigned length,
+		    uint8_t *out)
+{
+	uint8_t tmp[16];
+
+	if (ctx->last_len < 16) {
+		ctx->last[ctx->last_len] = 0x80;
+		memxor3(tmp, ctx->last, ctx->K2, 16);
+	} else {
+		memxor3(tmp, ctx->last, ctx->K1, 16);
+	}
+
+	memxor3(ctx->Y, tmp, ctx->X, 16);
+
+	assert(length <= 16);
+	if (length == 16) {
+		encrypt(key, length, out, ctx->Y);
+	} else {
+		encrypt(key, length, tmp, ctx->Y);
+		memcpy(out, tmp, length);
+	}
+}
diff --git a/cmac.h b/cmac.h
new file mode 100644
index 00000000..832cf38d
--- /dev/null
+++ b/cmac.h
@@ -0,0 +1,117 @@
+/* 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_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 {
+	uint8_t K1[16];
+	uint8_t K2[16];
+
+	uint8_t L[16];
+	uint8_t X[16];
+	uint8_t Y[16];
+
+	uint8_t last[16];
+	size_t last_len;
+};
+
+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 b73196b0..b9cef924 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)
 {
@@ -843,6 +862,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/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..45cad3c2
--- /dev/null
+++ b/testsuite/cmac-test.c
@@ -0,0 +1,57 @@
+#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];
+
+  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();
+    }
+}
+
+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"));
+}
+
-- 
2.14.3

