summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2018-10-26 13:38:13 -0400
committerSimo Sorce <simo@redhat.com>2018-10-28 19:40:26 -0400
commitc8d9b6261e88062ca58bf40f0ceaab4a559b9b00 (patch)
tree1c278ab438c8f7cfe45a3d1288a2a0030cd1b6c2
parente369b069428ca5e0393598acfbd00e950e905963 (diff)
downloadgnutls-c8d9b6261e88062ca58bf40f0ceaab4a559b9b00.tar.gz
Vendor in CMAC functionality from Nettle
If nettle's CMAC is not available, use a vendored in version from master. This is necessary as long as we need to link against 3.4 for ABI compatibility reasons. Signed-off-by: Simo Sorce <simo@redhat.com>
-rw-r--r--configure.ac6
-rw-r--r--lib/nettle/Makefile.am1
-rw-r--r--lib/nettle/backport/cmac.c213
-rw-r--r--lib/nettle/backport/cmac.h140
-rw-r--r--lib/nettle/mac.c5
5 files changed, 365 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 7b50f548d2..3f87907516 100644
--- a/configure.ac
+++ b/configure.ac
@@ -565,6 +565,12 @@ LIBS="$LIBS $NETTLE_LIBS"
AC_CHECK_FUNCS(nettle_cfb8_encrypt)
LIBS=$save_LIBS
+# Check if nettle has CMAC support
+save_LIBS=$LIBS
+LIBS="$LIBS $NETTLE_LIBS"
+AC_CHECK_FUNCS(nettle_cmac128_update)
+LIBS=$save_LIBS
+
AC_MSG_CHECKING([whether to build libdane])
AC_ARG_ENABLE(libdane,
AS_HELP_STRING([--disable-libdane],
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
index 7bb88b8c8f..b3d9ec5dac 100644
--- a/lib/nettle/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -41,6 +41,7 @@ noinst_LTLIBRARIES = libcrypto.la
libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c init.c \
gnettle.h rnd-common.h prf.c \
backport/cfb8.c backport/cfb8.h \
+ backport/cmac.c backport/cmac.h \
rnd.c int/rsa-fips.h int/rsa-keygen-fips186.c int/provable-prime.c \
int/dsa-fips.h int/dsa-keygen-fips186.c int/dsa-validate.c \
int/tls1-prf.c int/tls1-prf.h
diff --git a/lib/nettle/backport/cmac.c b/lib/nettle/backport/cmac.c
new file mode 100644
index 0000000000..481e5c080d
--- /dev/null
+++ b/lib/nettle/backport/cmac.c
@@ -0,0 +1,213 @@
+/* backport of cmac*.c for CMAC
+
+ 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/.
+*/
+
+/* #############################################
+ * THIS IS A BACKPORT FROM NETTLE, DO NOT MODIFY
+ * #############################################
+ */
+
+#ifndef HAVE_NETTLE_CMAC128_UPDATE
+
+#include <nettle/aes.h>
+#include "cmac.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <nettle/memxor.h>
+#include <nettle/macros.h>
+
+/* shift one and XOR with 0x87. */
+static 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 *ctx, const void *cipher,
+ nettle_cipher_func *encrypt)
+{
+ static const uint8_t const_zero[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ 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 *ctx, const 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 *ctx, const 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;
+}
+
+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);
+}
+
+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);
+}
+#endif /* HAVE_NETTLE_CMAC128_UPDATE */
diff --git a/lib/nettle/backport/cmac.h b/lib/nettle/backport/cmac.h
new file mode 100644
index 0000000000..94a2b06295
--- /dev/null
+++ b/lib/nettle/backport/cmac.h
@@ -0,0 +1,140 @@
+/* backport of 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 <nettle/nettle-types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CMAC128_DIGEST_SIZE 16
+
+#define cmac128_set_key _gnutls_backport_nettle_cmac128_set_key
+#define cmac128_update _gnutls_backport_nettle_cmac128_update
+#define cmac128_digest _gnutls_backport_nettle_cmac128_digest
+#define cmac_aes128_set_key _gnutls_backport_nettle_cmac_aes128_set_key
+#define cmac_aes128_update _gnutls_backport_nettle_cmac_aes128_update
+#define cmac_aes128_digest _gnutls_backport_nettle_cmac_aes128_digest
+#define cmac_aes256_set_key _gnutls_backport_nettle_cmac_aes256_set_key
+#define cmac_aes256_update _gnutls_backport_nettle_cmac_aes256_update
+#define cmac_aes256_digest _gnutls_backport_nettle_cmac_aes256_digest
+
+struct cmac128_ctx
+{
+ /* Key */
+ union nettle_block16 K1;
+ union nettle_block16 K2;
+
+ /* MAC state */
+ union nettle_block16 X;
+
+ /* Block buffer */
+ union nettle_block16 block;
+ size_t index;
+};
+
+void
+cmac128_set_key(struct cmac128_ctx *ctx, const void *cipher,
+ nettle_cipher_func *encrypt);
+void
+cmac128_update(struct cmac128_ctx *ctx, const void *cipher,
+ nettle_cipher_func *encrypt,
+ size_t msg_len, const uint8_t *msg);
+void
+cmac128_digest(struct cmac128_ctx *ctx, const void *cipher,
+ nettle_cipher_func *encrypt,
+ unsigned length,
+ uint8_t *digest);
+
+
+#define CMAC128_CTX(type) \
+ { struct cmac128_ctx ctx; type cipher; }
+
+/* NOTE: Avoid using NULL, as we don't include anything defining it. */
+#define CMAC128_SET_KEY(self, set_key, encrypt, cmac_key) \
+ do { \
+ (set_key)(&(self)->cipher, (cmac_key)); \
+ if (0) (encrypt)(&(self)->cipher, ~(size_t) 0, \
+ (uint8_t *) 0, (const uint8_t *) 0); \
+ cmac128_set_key(&(self)->ctx, &(self)->cipher, \
+ (nettle_cipher_func *) (encrypt)); \
+ } while (0)
+
+#define CMAC128_UPDATE(self, encrypt, length, src) \
+ cmac128_update(&(self)->ctx, &(self)->cipher, \
+ (nettle_cipher_func *)encrypt, (length), (src))
+
+#define CMAC128_DIGEST(self, encrypt, length, digest) \
+ (0 ? (encrypt)(&(self)->cipher, ~(size_t) 0, \
+ (uint8_t *) 0, (const uint8_t *) 0) \
+ : cmac128_digest(&(self)->ctx, &(self)->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/lib/nettle/mac.c b/lib/nettle/mac.c
index 3d26c44e12..202bdc4951 100644
--- a/lib/nettle/mac.c
+++ b/lib/nettle/mac.c
@@ -37,6 +37,11 @@
#include "gost/gosthash94.h"
#include "gost/streebog.h"
#endif
+#ifdef HAVE_NETTLE_CMAC128_UPDATE
+#include <nettle/cmac.h>
+#else
+#include "cmac.h"
+#endif /* HAVE_NETTLE_CMAC128_UPDATE */
typedef void (*update_func) (void *, size_t, const uint8_t *);
typedef void (*digest_func) (void *, size_t, uint8_t *);