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

Reply via email to