diff options
author | Simo Sorce <simo@redhat.com> | 2018-10-26 13:38:13 -0400 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2018-10-28 19:40:26 -0400 |
commit | c8d9b6261e88062ca58bf40f0ceaab4a559b9b00 (patch) | |
tree | 1c278ab438c8f7cfe45a3d1288a2a0030cd1b6c2 | |
parent | e369b069428ca5e0393598acfbd00e950e905963 (diff) | |
download | gnutls-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.ac | 6 | ||||
-rw-r--r-- | lib/nettle/Makefile.am | 1 | ||||
-rw-r--r-- | lib/nettle/backport/cmac.c | 213 | ||||
-rw-r--r-- | lib/nettle/backport/cmac.h | 140 | ||||
-rw-r--r-- | lib/nettle/mac.c | 5 |
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 *); |