Two Message Authentication Code (MAC) libraries will be added: nettle and gnutls. This patch introduces the gnutls mac library along with all functions required including initialization/deinitialization of mac handle using key data and generating the digest/mac/icv
Signed-off-by: Clay Kaiser <clay.kai...@ibm.com> --- incdefs.sh | 14 ++++ makefile | 3 + sad_gnutls.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++ sad_private.h | 2 +- 4 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 sad_gnutls.c diff --git a/incdefs.sh b/incdefs.sh index 5bbc7bc..ca21780 100755 --- a/incdefs.sh +++ b/incdefs.sh @@ -77,6 +77,20 @@ user_flags() fi done done + + # Look for gnutls support. + for d in $dirs; do + sdirs=$(find $d -type d -name "gnutls") + for s in $sdirs; do + files=$(find $s -type f -name crypto.h) + for f in $files; do + if grep -q gnutls_hmac_init $f; then + printf " -DHAVE_GNUTLS" + break 3 + fi + done + done + done } # diff --git a/makefile b/makefile index fc14ee1..8c51bed 100644 --- a/makefile +++ b/makefile @@ -47,6 +47,9 @@ VPATH = $(srcdir) ifneq (,$(findstring -DHAVE_NETTLE, $(incdefs))) LDLIBS += -lnettle SECURITY += sad_nettle.o +else ifneq (,$(findstring -DHAVE_GNUTLS, $(incdefs))) +LDLIBS += -lgnutls +SECURITY += sad_gnutls.o endif prefix = /usr/local diff --git a/sad_gnutls.c b/sad_gnutls.c new file mode 100644 index 0000000..069cf8b --- /dev/null +++ b/sad_gnutls.c @@ -0,0 +1,185 @@ +/** + * @file sad.c + * @brief Security Association Database gnutls functions + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include <gnutls/crypto.h> +#include <stdlib.h> +#include <string.h> +#include <sys/queue.h> + +#include "print.h" +#include "sad.h" +#include "sad_private.h" + +static int mac_count = -1; + +struct mac_data { + gnutls_mac_algorithm_t algorithm; + gnutls_hmac_hd_t handle; +}; + +static void sad_init_gnutls(void) +{ + int err = 0; + + if (mac_count >= 0) { + return; + } + + err = gnutls_global_init(); + if (err < 0) { + pr_err("gnutls_global_init() failed: %s", + gnutls_strerror(err)); + return; + } + + mac_count = 0; +} + +static void sad_deinit_gnutls(void) +{ + if (mac_count < 0) { + return; + } + + gnutls_global_deinit(); + + mac_count = -1; +} + +struct mac_data *sad_init_mac(integrity_alg_type algorithm, + const unsigned char *key, int key_len) +{ + int err, length; + + gnutls_hmac_hd_t handle; + gnutls_mac_algorithm_t mac_algorithm; + struct mac_data *mac_data; + + /* initialize gnutls if not already */ + if (mac_count < 0) { + sad_init_gnutls(); + } + + /* verify key length */ + if (key_len <= 0) { + sad_deinit_gnutls(); + return NULL; + } + + /* retrieve mac algorithm */ + switch (algorithm) { + case HMAC_SHA256_128: + case HMAC_SHA256: + mac_algorithm = GNUTLS_MAC_SHA256; + break; + case CMAC_AES128: + mac_algorithm = GNUTLS_MAC_AES_CMAC_128; + break; + case CMAC_AES256: + mac_algorithm = GNUTLS_MAC_AES_CMAC_256; + break; + default: + sad_deinit_gnutls(); + return NULL; + } + + /* retrieve mac key length */ + length = gnutls_hmac_get_key_size(mac_algorithm); + if (length < 0) { + sad_deinit_gnutls(); + return NULL; + } + /* verify key length matches for cmac only */ + switch (algorithm) { + case CMAC_AES128: + case CMAC_AES256: + if (key_len != length) { + sad_deinit_gnutls(); + return NULL; + } + break; + default: + break; + } + + /* initialize handle and set key */ + err = gnutls_hmac_init(&handle, mac_algorithm, key, key_len); + if (err < 0) { + pr_err("gnutls_hmac_init() failed: %s", + gnutls_strerror(err)); + sad_deinit_gnutls(); + return NULL; + } + /* initialize mac_data */ + mac_data = calloc(1, sizeof(*mac_data)); + if (!mac_data) { + return NULL; + } + mac_data->algorithm = mac_algorithm; + mac_data->handle = handle; + + mac_count++; + + return mac_data; +} + +void sad_deinit_mac(struct mac_data *data) +{ + gnutls_hmac_deinit(data->handle, NULL); + free(data); + + mac_count--; + if (mac_count == 0) { + sad_deinit_gnutls(); + } +} + +int sad_hash(struct mac_data *mac_data, + const void *data, int data_len, + unsigned char *mac, int mac_len) +{ + int digest_len; + unsigned char digest_buffer[MAX_DIGEST_LENGTH]; + + /* verify data and mac lengths */ + if (data_len < 0 || mac_len < 0) { + return 0; + } + + /* confirm mac length is within library support */ + digest_len = gnutls_hmac_get_len(mac_data->algorithm); + if (mac_len > digest_len) { + mac_len = digest_len; + } + + if (mac_len > MAX_DIGEST_LENGTH) { + return 0; + } + + /* update data and retrieve mac */ + if (gnutls_hmac(mac_data->handle, data, data_len) < 0) { + gnutls_hmac_output(mac_data->handle, digest_buffer); + return 0; + } + gnutls_hmac_output(mac_data->handle, digest_buffer); + + /* move mac to desired location */ + memcpy(mac, digest_buffer, mac_len); + + return mac_len; +} diff --git a/sad_private.h b/sad_private.h index 8e39bc2..9e4fce4 100644 --- a/sad_private.h +++ b/sad_private.h @@ -47,7 +47,7 @@ struct security_association_key { UInteger32 key_id; /* symmetric key ID */ }; -#if defined (HAVE_NETTLE) +#if defined (HAVE_NETTLE) || defined (HAVE_GNUTLS) int sad_hash(struct mac_data *parms, const void *data, int data_len, unsigned char *mac, int mac_len); -- 2.42.1 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel