51ad59
From 440a178c5aad19050a3d5b5d76881931138af680 Mon Sep 17 00:00:00 2001
51ad59
From: Colin Walters <walters@verbum.org>
51ad59
Date: Fri, 7 Jun 2019 18:44:43 +0000
51ad59
Subject: [PATCH 1/2] ghmac: Split off wrapper functions into ghmac-utils.c
51ad59
51ad59
Prep for adding a GnuTLS HMAC implementation; these are just
51ad59
utility functions that call the "core" API.
51ad59
---
51ad59
 glib/Makefile.am   |   1 +
51ad59
 glib/ghmac-utils.c | 145 +++++++++++++++++++++++++++++++++++++++++++++
51ad59
 glib/ghmac.c       | 112 ----------------------------------
51ad59
 glib/meson.build   |   1 +
51ad59
 4 files changed, 147 insertions(+), 112 deletions(-)
51ad59
 create mode 100644 glib/ghmac-utils.c
51ad59
51ad59
diff --git a/glib/Makefile.am b/glib/Makefile.am
51ad59
index 8da549c7f..c367b09ad 100644
51ad59
--- a/glib/Makefile.am
51ad59
+++ b/glib/Makefile.am
51ad59
@@ -126,6 +126,7 @@ libglib_2_0_la_SOURCES = 	\
51ad59
 	ggettext.c		\
51ad59
 	ghash.c			\
51ad59
 	ghmac.c			\
51ad59
+	ghmac-utils.c		\
51ad59
 	ghook.c			\
51ad59
 	ghostutils.c		\
51ad59
 	giochannel.c    	\
51ad59
diff --git a/glib/ghmac-utils.c b/glib/ghmac-utils.c
51ad59
new file mode 100644
51ad59
index 000000000..a17359ff1
51ad59
--- /dev/null
51ad59
+++ b/glib/ghmac-utils.c
51ad59
@@ -0,0 +1,145 @@
51ad59
+/* ghmac.h - data hashing functions
51ad59
+ *
51ad59
+ * Copyright (C) 2011  Collabora Ltd.
51ad59
+ * Copyright (C) 2019  Red Hat, Inc.
51ad59
+ *
51ad59
+ * This library is free software; you can redistribute it and/or
51ad59
+ * modify it under the terms of the GNU Lesser General Public
51ad59
+ * License as published by the Free Software Foundation; either
51ad59
+ * version 2.1 of the License, or (at your option) any later version.
51ad59
+ *
51ad59
+ * This library is distributed in the hope that it will be useful,
51ad59
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51ad59
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
51ad59
+ * Lesser General Public License for more details.
51ad59
+ *
51ad59
+ * You should have received a copy of the GNU Lesser General Public License
51ad59
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
51ad59
+ */
51ad59
+
51ad59
+#include "config.h"
51ad59
+
51ad59
+#include <string.h>
51ad59
+
51ad59
+#include "ghmac.h"
51ad59
+
51ad59
+#include "glib/galloca.h"
51ad59
+#include "gatomic.h"
51ad59
+#include "gslice.h"
51ad59
+#include "gmem.h"
51ad59
+#include "gstrfuncs.h"
51ad59
+#include "gtestutils.h"
51ad59
+#include "gtypes.h"
51ad59
+#include "glibintl.h"
51ad59
+
51ad59
+/**
51ad59
+ * g_compute_hmac_for_data:
51ad59
+ * @digest_type: a #GChecksumType to use for the HMAC
51ad59
+ * @key: (array length=key_len): the key to use in the HMAC
51ad59
+ * @key_len: the length of the key
51ad59
+ * @data: (array length=length): binary blob to compute the HMAC of
51ad59
+ * @length: length of @data
51ad59
+ *
51ad59
+ * Computes the HMAC for a binary @data of @length. This is a
51ad59
+ * convenience wrapper for g_hmac_new(), g_hmac_get_string()
51ad59
+ * and g_hmac_unref().
51ad59
+ *
51ad59
+ * The hexadecimal string returned will be in lower case.
51ad59
+ *
51ad59
+ * Returns: the HMAC of the binary data as a string in hexadecimal.
51ad59
+ *   The returned string should be freed with g_free() when done using it.
51ad59
+ *
51ad59
+ * Since: 2.30
51ad59
+ */
51ad59
+gchar *
51ad59
+g_compute_hmac_for_data (GChecksumType  digest_type,
51ad59
+                         const guchar  *key,
51ad59
+                         gsize          key_len,
51ad59
+                         const guchar  *data,
51ad59
+                         gsize          length)
51ad59
+{
51ad59
+  GHmac *hmac;
51ad59
+  gchar *retval;
51ad59
+
51ad59
+  g_return_val_if_fail (length == 0 || data != NULL, NULL);
51ad59
+
51ad59
+  hmac = g_hmac_new (digest_type, key, key_len);
51ad59
+  if (!hmac)
51ad59
+    return NULL;
51ad59
+
51ad59
+  g_hmac_update (hmac, data, length);
51ad59
+  retval = g_strdup (g_hmac_get_string (hmac));
51ad59
+  g_hmac_unref (hmac);
51ad59
+
51ad59
+  return retval;
51ad59
+}
51ad59
+
51ad59
+/**
51ad59
+ * g_compute_hmac_for_bytes:
51ad59
+ * @digest_type: a #GChecksumType to use for the HMAC
51ad59
+ * @key: the key to use in the HMAC
51ad59
+ * @data: binary blob to compute the HMAC of
51ad59
+ *
51ad59
+ * Computes the HMAC for a binary @data. This is a
51ad59
+ * convenience wrapper for g_hmac_new(), g_hmac_get_string()
51ad59
+ * and g_hmac_unref().
51ad59
+ *
51ad59
+ * The hexadecimal string returned will be in lower case.
51ad59
+ *
51ad59
+ * Returns: the HMAC of the binary data as a string in hexadecimal.
51ad59
+ *   The returned string should be freed with g_free() when done using it.
51ad59
+ *
51ad59
+ * Since: 2.50
51ad59
+ */
51ad59
+gchar *
51ad59
+g_compute_hmac_for_bytes (GChecksumType  digest_type,
51ad59
+                          GBytes        *key,
51ad59
+                          GBytes        *data)
51ad59
+{
51ad59
+  gconstpointer byte_data;
51ad59
+  gsize length;
51ad59
+  gconstpointer key_data;
51ad59
+  gsize key_len;
51ad59
+
51ad59
+  g_return_val_if_fail (data != NULL, NULL);
51ad59
+  g_return_val_if_fail (key != NULL, NULL);
51ad59
+
51ad59
+  byte_data = g_bytes_get_data (data, &length);
51ad59
+  key_data = g_bytes_get_data (key, &key_len);
51ad59
+  return g_compute_hmac_for_data (digest_type, key_data, key_len, byte_data, length);
51ad59
+}
51ad59
+
51ad59
+
51ad59
+/**
51ad59
+ * g_compute_hmac_for_string:
51ad59
+ * @digest_type: a #GChecksumType to use for the HMAC
51ad59
+ * @key: (array length=key_len): the key to use in the HMAC
51ad59
+ * @key_len: the length of the key
51ad59
+ * @str: the string to compute the HMAC for
51ad59
+ * @length: the length of the string, or -1 if the string is nul-terminated
51ad59
+ *
51ad59
+ * Computes the HMAC for a string.
51ad59
+ *
51ad59
+ * The hexadecimal string returned will be in lower case.
51ad59
+ *
51ad59
+ * Returns: the HMAC as a hexadecimal string.
51ad59
+ *     The returned string should be freed with g_free()
51ad59
+ *     when done using it.
51ad59
+ *
51ad59
+ * Since: 2.30
51ad59
+ */
51ad59
+gchar *
51ad59
+g_compute_hmac_for_string (GChecksumType  digest_type,
51ad59
+                           const guchar  *key,
51ad59
+                           gsize          key_len,
51ad59
+                           const gchar   *str,
51ad59
+                           gssize         length)
51ad59
+{
51ad59
+  g_return_val_if_fail (length == 0 || str != NULL, NULL);
51ad59
+
51ad59
+  if (length < 0)
51ad59
+    length = strlen (str);
51ad59
+
51ad59
+  return g_compute_hmac_for_data (digest_type, key, key_len,
51ad59
+                                  (const guchar *) str, length);
51ad59
+}
51ad59
diff --git a/glib/ghmac.c b/glib/ghmac.c
51ad59
index 9b58fd81c..7db38e34a 100644
51ad59
--- a/glib/ghmac.c
51ad59
+++ b/glib/ghmac.c
51ad59
@@ -329,115 +329,3 @@ g_hmac_get_digest (GHmac  *hmac,
51ad59
   g_checksum_update (hmac->digesto, buffer, len);
51ad59
   g_checksum_get_digest (hmac->digesto, buffer, digest_len);
51ad59
 }
51ad59
-
51ad59
-/**
51ad59
- * g_compute_hmac_for_data:
51ad59
- * @digest_type: a #GChecksumType to use for the HMAC
51ad59
- * @key: (array length=key_len): the key to use in the HMAC
51ad59
- * @key_len: the length of the key
51ad59
- * @data: (array length=length): binary blob to compute the HMAC of
51ad59
- * @length: length of @data
51ad59
- *
51ad59
- * Computes the HMAC for a binary @data of @length. This is a
51ad59
- * convenience wrapper for g_hmac_new(), g_hmac_get_string()
51ad59
- * and g_hmac_unref().
51ad59
- *
51ad59
- * The hexadecimal string returned will be in lower case.
51ad59
- *
51ad59
- * Returns: the HMAC of the binary data as a string in hexadecimal.
51ad59
- *   The returned string should be freed with g_free() when done using it.
51ad59
- *
51ad59
- * Since: 2.30
51ad59
- */
51ad59
-gchar *
51ad59
-g_compute_hmac_for_data (GChecksumType  digest_type,
51ad59
-                         const guchar  *key,
51ad59
-                         gsize          key_len,
51ad59
-                         const guchar  *data,
51ad59
-                         gsize          length)
51ad59
-{
51ad59
-  GHmac *hmac;
51ad59
-  gchar *retval;
51ad59
-
51ad59
-  g_return_val_if_fail (length == 0 || data != NULL, NULL);
51ad59
-
51ad59
-  hmac = g_hmac_new (digest_type, key, key_len);
51ad59
-  if (!hmac)
51ad59
-    return NULL;
51ad59
-
51ad59
-  g_hmac_update (hmac, data, length);
51ad59
-  retval = g_strdup (g_hmac_get_string (hmac));
51ad59
-  g_hmac_unref (hmac);
51ad59
-
51ad59
-  return retval;
51ad59
-}
51ad59
-
51ad59
-/**
51ad59
- * g_compute_hmac_for_bytes:
51ad59
- * @digest_type: a #GChecksumType to use for the HMAC
51ad59
- * @key: the key to use in the HMAC
51ad59
- * @data: binary blob to compute the HMAC of
51ad59
- *
51ad59
- * Computes the HMAC for a binary @data. This is a
51ad59
- * convenience wrapper for g_hmac_new(), g_hmac_get_string()
51ad59
- * and g_hmac_unref().
51ad59
- *
51ad59
- * The hexadecimal string returned will be in lower case.
51ad59
- *
51ad59
- * Returns: the HMAC of the binary data as a string in hexadecimal.
51ad59
- *   The returned string should be freed with g_free() when done using it.
51ad59
- *
51ad59
- * Since: 2.50
51ad59
- */
51ad59
-gchar *
51ad59
-g_compute_hmac_for_bytes (GChecksumType  digest_type,
51ad59
-                          GBytes        *key,
51ad59
-                          GBytes        *data)
51ad59
-{
51ad59
-  gconstpointer byte_data;
51ad59
-  gsize length;
51ad59
-  gconstpointer key_data;
51ad59
-  gsize key_len;
51ad59
-
51ad59
-  g_return_val_if_fail (data != NULL, NULL);
51ad59
-  g_return_val_if_fail (key != NULL, NULL);
51ad59
-
51ad59
-  byte_data = g_bytes_get_data (data, &length);
51ad59
-  key_data = g_bytes_get_data (key, &key_len);
51ad59
-  return g_compute_hmac_for_data (digest_type, key_data, key_len, byte_data, length);
51ad59
-}
51ad59
-
51ad59
-
51ad59
-/**
51ad59
- * g_compute_hmac_for_string:
51ad59
- * @digest_type: a #GChecksumType to use for the HMAC
51ad59
- * @key: (array length=key_len): the key to use in the HMAC
51ad59
- * @key_len: the length of the key
51ad59
- * @str: the string to compute the HMAC for
51ad59
- * @length: the length of the string, or -1 if the string is nul-terminated
51ad59
- *
51ad59
- * Computes the HMAC for a string.
51ad59
- *
51ad59
- * The hexadecimal string returned will be in lower case.
51ad59
- *
51ad59
- * Returns: the HMAC as a hexadecimal string.
51ad59
- *     The returned string should be freed with g_free()
51ad59
- *     when done using it.
51ad59
- *
51ad59
- * Since: 2.30
51ad59
- */
51ad59
-gchar *
51ad59
-g_compute_hmac_for_string (GChecksumType  digest_type,
51ad59
-                           const guchar  *key,
51ad59
-                           gsize          key_len,
51ad59
-                           const gchar   *str,
51ad59
-                           gssize         length)
51ad59
-{
51ad59
-  g_return_val_if_fail (length == 0 || str != NULL, NULL);
51ad59
-
51ad59
-  if (length < 0)
51ad59
-    length = strlen (str);
51ad59
-
51ad59
-  return g_compute_hmac_for_data (digest_type, key, key_len,
51ad59
-                                  (const guchar *) str, length);
51ad59
-}
51ad59
diff --git a/glib/meson.build b/glib/meson.build
51ad59
index 9df77b6f9..c7f28b5b6 100644
51ad59
--- a/glib/meson.build
51ad59
+++ b/glib/meson.build
51ad59
@@ -138,6 +138,7 @@ glib_sources = files(
51ad59
   'ggettext.c',
51ad59
   'ghash.c',
51ad59
   'ghmac.c',
51ad59
+  'ghmac-utils.c',
51ad59
   'ghook.c',
51ad59
   'ghostutils.c',
51ad59
   'giochannel.c',
51ad59
-- 
51ad59
2.21.0
51ad59
51ad59
51ad59
From 423355787ba9133b310c0b72708024b1428d7d14 Mon Sep 17 00:00:00 2001
51ad59
From: Colin Walters <walters@verbum.org>
51ad59
Date: Fri, 7 Jun 2019 19:36:54 +0000
51ad59
Subject: [PATCH 2/2] Add a gnutls backend for GHmac
51ad59
51ad59
For RHEL we want apps to use FIPS-certified crypto libraries,
51ad59
and HMAC apparently counts as "keyed" and hence needs to
51ad59
be validated.
51ad59
51ad59
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1630260
51ad59
Replaces: https://gitlab.gnome.org/GNOME/glib/merge_requests/897
51ad59
51ad59
This is a build-time option that backs the GHmac API with GnuTLS.
51ad59
Most distributors ship glib-networking built with GnuTLS, and
51ad59
most apps use glib-networking, so this isn't a net-new library
51ad59
in most cases.
51ad59
51ad59
However, a fun wrinkle is that the GnuTLS HMAC API doesn't expose
51ad59
the necessary bits to implement `g_hmac_copy()`; OpenSSL does.
51ad59
I chose to just make that abort for now since I didn't find
51ad59
apps using it.
51ad59
---
51ad59
 glib/Makefile.am        |   9 ++-
51ad59
 glib/gchecksum.c        |   9 +--
51ad59
 glib/gchecksumprivate.h |  32 +++++++++
51ad59
 glib/ghmac-gnutls.c     | 151 ++++++++++++++++++++++++++++++++++++++++
51ad59
 glib/ghmac.c            |   1 +
51ad59
 glib/meson.build        |  10 ++-
51ad59
 glib/tests/hmac.c       |   6 ++
51ad59
 meson.build             |   7 ++
51ad59
 meson_options.txt       |   5 ++
51ad59
 9 files changed, 221 insertions(+), 9 deletions(-)
51ad59
 create mode 100644 glib/gchecksumprivate.h
51ad59
 create mode 100644 glib/ghmac-gnutls.c
51ad59
51ad59
diff --git a/glib/Makefile.am b/glib/Makefile.am
51ad59
index c367b09ad..b0a721ad0 100644
51ad59
--- a/glib/Makefile.am
51ad59
+++ b/glib/Makefile.am
51ad59
@@ -125,7 +125,7 @@ libglib_2_0_la_SOURCES = 	\
51ad59
 	gfileutils.c		\
51ad59
 	ggettext.c		\
51ad59
 	ghash.c			\
51ad59
-	ghmac.c			\
51ad59
+	ghmac-gnutls.c		\
51ad59
 	ghmac-utils.c		\
51ad59
 	ghook.c			\
51ad59
 	ghostutils.c		\
51ad59
@@ -352,11 +352,14 @@ pcre_lib = pcre/libpcre.la
51ad59
 pcre_inc =
51ad59
 endif
51ad59
 
51ad59
-libglib_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS) $(LIBSYSTEMD_CFLAGS)
51ad59
+gnutls_libs = $(shell pkg-config --libs gnutls)
51ad59
+gnutls_cflags = $(shell pkg-config --cflags gnutls)
51ad59
+
51ad59
+libglib_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS) $(LIBSYSTEMD_CFLAGS) $(gnutls_cflags)
51ad59
 libglib_2_0_la_LIBADD = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ @ICONV_LIBS@ @G_LIBS_EXTRA@ $(pcre_lib) $(G_THREAD_LIBS_EXTRA) $(G_THREAD_LIBS_FOR_GTHREAD) $(LIBSYSTEMD_LIBS)
51ad59
 libglib_2_0_la_DEPENDENCIES = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ $(glib_win32_res) $(glib_def)
51ad59
 
51ad59
-libglib_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \
51ad59
+libglib_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) $(gnutls_libs) \
51ad59
 	 $(glib_win32_res_ldflag) \
51ad59
 	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
51ad59
 	-export-dynamic $(no_undefined)
51ad59
diff --git a/glib/gchecksum.c b/glib/gchecksum.c
51ad59
index 40b1d50e2..2f59d4a66 100644
51ad59
--- a/glib/gchecksum.c
51ad59
+++ b/glib/gchecksum.c
51ad59
@@ -20,7 +20,7 @@
51ad59
 
51ad59
 #include <string.h>
51ad59
 
51ad59
-#include "gchecksum.h"
51ad59
+#include "gchecksumprivate.h"
51ad59
 
51ad59
 #include "gslice.h"
51ad59
 #include "gmem.h"
51ad59
@@ -173,9 +173,9 @@ sha_byte_reverse (guint32 *buffer,
51ad59
 }
51ad59
 #endif /* G_BYTE_ORDER == G_BIG_ENDIAN */
51ad59
 
51ad59
-static gchar *
51ad59
-digest_to_string (guint8 *digest,
51ad59
-                  gsize   digest_len)
51ad59
+gchar *
51ad59
+gchecksum_digest_to_string (guint8 *digest,
51ad59
+                            gsize   digest_len)
51ad59
 {
51ad59
   gint len = digest_len * 2;
51ad59
   gint i;
51ad59
@@ -195,6 +195,7 @@ digest_to_string (guint8 *digest,
51ad59
 
51ad59
   return retval;
51ad59
 }
51ad59
+#define digest_to_string gchecksum_digest_to_string
51ad59
 
51ad59
 /*
51ad59
  * MD5 Checksum
51ad59
diff --git a/glib/gchecksumprivate.h b/glib/gchecksumprivate.h
51ad59
new file mode 100644
51ad59
index 000000000..86c7a3b61
51ad59
--- /dev/null
51ad59
+++ b/glib/gchecksumprivate.h
51ad59
@@ -0,0 +1,32 @@
51ad59
+/* gstdioprivate.h - Private GLib stdio functions
51ad59
+ *
51ad59
+ * Copyright 2017 Руслан Ижбулатов
51ad59
+ *
51ad59
+ * This library is free software; you can redistribute it and/or
51ad59
+ * modify it under the terms of the GNU Lesser General Public
51ad59
+ * License as published by the Free Software Foundation; either
51ad59
+ * version 2.1 of the License, or (at your option) any later version.
51ad59
+ *
51ad59
+ * This library is distributed in the hope that it will be useful,
51ad59
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51ad59
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
51ad59
+ * Lesser General Public License for more details.
51ad59
+ *
51ad59
+ * You should have received a copy of the GNU Lesser General Public License
51ad59
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
51ad59
+ */
51ad59
+
51ad59
+#ifndef __G_CHECKSUMPRIVATE_H__
51ad59
+#define __G_CHECKSUMPRIVATE_H__
51ad59
+
51ad59
+#include "gchecksum.h"
51ad59
+
51ad59
+G_BEGIN_DECLS
51ad59
+
51ad59
+gchar *
51ad59
+gchecksum_digest_to_string (guint8 *digest,
51ad59
+                            gsize   digest_len);
51ad59
+
51ad59
+G_END_DECLS
51ad59
+
51ad59
+#endif
51ad59
\ No newline at end of file
51ad59
diff --git a/glib/ghmac-gnutls.c b/glib/ghmac-gnutls.c
51ad59
new file mode 100644
51ad59
index 000000000..3b4dfb872
51ad59
--- /dev/null
51ad59
+++ b/glib/ghmac-gnutls.c
51ad59
@@ -0,0 +1,151 @@
51ad59
+/* ghmac.h - data hashing functions
51ad59
+ *
51ad59
+ * Copyright (C) 2011  Collabora Ltd.
51ad59
+ * Copyright (C) 2019  Red Hat, Inc.
51ad59
+ *
51ad59
+ * This library is free software; you can redistribute it and/or
51ad59
+ * modify it under the terms of the GNU Lesser General Public
51ad59
+ * License as published by the Free Software Foundation; either
51ad59
+ * version 2.1 of the License, or (at your option) any later version.
51ad59
+ *
51ad59
+ * This library is distributed in the hope that it will be useful,
51ad59
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51ad59
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
51ad59
+ * Lesser General Public License for more details.
51ad59
+ *
51ad59
+ * You should have received a copy of the GNU Lesser General Public License
51ad59
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
51ad59
+ */
51ad59
+
51ad59
+#include "config.h"
51ad59
+
51ad59
+#include <string.h>
51ad59
+#include <gnutls/crypto.h>
51ad59
+
51ad59
+#include "ghmac.h"
51ad59
+
51ad59
+#include "glib/galloca.h"
51ad59
+#include "gatomic.h"
51ad59
+#include "gslice.h"
51ad59
+#include "gmem.h"
51ad59
+#include "gstrfuncs.h"
51ad59
+#include "gchecksumprivate.h"
51ad59
+#include "gtestutils.h"
51ad59
+#include "gtypes.h"
51ad59
+#include "glibintl.h"
51ad59
+
51ad59
+struct _GHmac
51ad59
+{
51ad59
+  int ref_count;
51ad59
+  GChecksumType digest_type;
51ad59
+  gnutls_hmac_hd_t hmac;
51ad59
+  gchar *digest_str;
51ad59
+};
51ad59
+
51ad59
+GHmac *
51ad59
+g_hmac_new (GChecksumType  digest_type,
51ad59
+            const guchar  *key,
51ad59
+            gsize          key_len)
51ad59
+{
51ad59
+  gnutls_mac_algorithm_t algo;
51ad59
+  GHmac *hmac = g_slice_new0 (GHmac);
51ad59
+  hmac->ref_count = 1;
51ad59
+  hmac->digest_type = digest_type;  
51ad59
+
51ad59
+  switch (digest_type)
51ad59
+    {
51ad59
+    case G_CHECKSUM_MD5:
51ad59
+      algo = GNUTLS_MAC_MD5;
51ad59
+      break;
51ad59
+    case G_CHECKSUM_SHA1:
51ad59
+      algo = GNUTLS_MAC_SHA1;
51ad59
+      break;
51ad59
+    case G_CHECKSUM_SHA256:
51ad59
+      algo = GNUTLS_MAC_SHA256;
51ad59
+      break;
51ad59
+    case G_CHECKSUM_SHA384:
51ad59
+      algo = GNUTLS_MAC_SHA384;
51ad59
+      break;
51ad59
+    case G_CHECKSUM_SHA512:
51ad59
+      algo = GNUTLS_MAC_SHA512;
51ad59
+      break;
51ad59
+    default:
51ad59
+      g_return_val_if_reached (NULL);
51ad59
+    }
51ad59
+
51ad59
+  gnutls_hmac_init (&hmac->hmac, algo, key, key_len);
51ad59
+
51ad59
+  return hmac;
51ad59
+}
51ad59
+
51ad59
+GHmac *
51ad59
+g_hmac_copy (const GHmac *hmac)
51ad59
+{
51ad59
+  g_error ("g_hmac_copy is not available with GnuTLS-backend GHmac");
51ad59
+}
51ad59
+
51ad59
+GHmac *
51ad59
+g_hmac_ref (GHmac *hmac)
51ad59
+{
51ad59
+  g_return_val_if_fail (hmac != NULL, NULL);
51ad59
+
51ad59
+  g_atomic_int_inc (&hmac->ref_count);
51ad59
+
51ad59
+  return hmac;
51ad59
+}
51ad59
+
51ad59
+void
51ad59
+g_hmac_unref (GHmac *hmac)
51ad59
+{
51ad59
+  g_return_if_fail (hmac != NULL);
51ad59
+
51ad59
+  if (g_atomic_int_dec_and_test (&hmac->ref_count))
51ad59
+    {
51ad59
+      gnutls_hmac_deinit (hmac->hmac, NULL);
51ad59
+      g_free (hmac->digest_str);
51ad59
+      g_slice_free (GHmac, hmac);
51ad59
+    }
51ad59
+}
51ad59
+
51ad59
+
51ad59
+void
51ad59
+g_hmac_update (GHmac        *hmac,
51ad59
+               const guchar *data,
51ad59
+               gssize        length)
51ad59
+{
51ad59
+  g_return_if_fail (hmac != NULL);
51ad59
+  g_return_if_fail (length == 0 || data != NULL);
51ad59
+
51ad59
+  gnutls_hmac (hmac->hmac, data, length);
51ad59
+}
51ad59
+
51ad59
+const gchar *
51ad59
+g_hmac_get_string (GHmac *hmac)
51ad59
+{
51ad59
+  guint8 *buffer;
51ad59
+  gsize digest_len;
51ad59
+
51ad59
+  g_return_val_if_fail (hmac != NULL, NULL);
51ad59
+
51ad59
+  if (hmac->digest_str)
51ad59
+    return hmac->digest_str;
51ad59
+
51ad59
+  digest_len = g_checksum_type_get_length (hmac->digest_type);
51ad59
+  buffer = g_alloca (digest_len);
51ad59
+
51ad59
+  gnutls_hmac_output (hmac->hmac, buffer);
51ad59
+  hmac->digest_str = gchecksum_digest_to_string (buffer, digest_len);
51ad59
+  return hmac->digest_str;
51ad59
+}
51ad59
+
51ad59
+
51ad59
+void
51ad59
+g_hmac_get_digest (GHmac  *hmac,
51ad59
+                   guint8 *buffer,
51ad59
+                   gsize  *digest_len)
51ad59
+{
51ad59
+  g_return_if_fail (hmac != NULL);
51ad59
+
51ad59
+  gnutls_hmac_output (hmac->hmac, buffer);
51ad59
+  *digest_len = g_checksum_type_get_length (hmac->digest_type);
51ad59
+}
51ad59
diff --git a/glib/ghmac.c b/glib/ghmac.c
51ad59
index 7db38e34a..b12eb07c4 100644
51ad59
--- a/glib/ghmac.c
51ad59
+++ b/glib/ghmac.c
51ad59
@@ -33,6 +33,7 @@
51ad59
 #include "gtypes.h"
51ad59
 #include "glibintl.h"
51ad59
 
51ad59
+#error "build configuration error"
51ad59
 
51ad59
 /**
51ad59
  * SECTION:hmac
51ad59
diff --git a/glib/meson.build b/glib/meson.build
51ad59
index c7f28b5b6..a2f9da81c 100644
51ad59
--- a/glib/meson.build
51ad59
+++ b/glib/meson.build
51ad59
@@ -137,7 +137,6 @@ glib_sources = files(
51ad59
   'gfileutils.c',
51ad59
   'ggettext.c',
51ad59
   'ghash.c',
51ad59
-  'ghmac.c',
51ad59
   'ghmac-utils.c',
51ad59
   'ghook.c',
51ad59
   'ghostutils.c',
51ad59
@@ -185,6 +184,7 @@ glib_sources = files(
51ad59
   'gunidecomp.c',
51ad59
   'gurifuncs.c',
51ad59
   'gutils.c',
51ad59
+  'gchecksumprivate.h',
51ad59
   'guuid.c',
51ad59
   'gvariant.c',
51ad59
   'gvariant-core.c',
51ad59
@@ -222,6 +222,12 @@ else
51ad59
   glib_dtrace_hdr = []
51ad59
 endif
51ad59
 
51ad59
+if get_option('gnutls')
51ad59
+  glib_sources += files('ghmac-gnutls.c')
51ad59
+else
51ad59
+  glib_sources += files('ghmac.c')
51ad59
+endif
51ad59
+
51ad59
 pcre_static_args = []
51ad59
 
51ad59
 if use_pcre_static_flag
51ad59
@@ -238,7 +244,7 @@ libglib = library('glib-2.0',
51ad59
   link_args : platform_ldflags + noseh_link_args,
51ad59
   include_directories : configinc,
51ad59
   link_with : [charset_lib, gnulib_lib],
51ad59
-  dependencies : [pcre, thread_dep, libintl, librt] + libiconv + platform_deps,
51ad59
+  dependencies : [pcre, thread_dep, libintl, librt] + libiconv + platform_deps + libgnutls_dep,
51ad59
   c_args : ['-DG_LOG_DOMAIN="GLib"', '-DGLIB_COMPILATION'] + pcre_static_args + glib_hidden_visibility_args
51ad59
 )
51ad59
 
51ad59
diff --git a/glib/tests/hmac.c b/glib/tests/hmac.c
51ad59
index 3ac3206df..5212c2523 100644
51ad59
--- a/glib/tests/hmac.c
51ad59
+++ b/glib/tests/hmac.c
51ad59
@@ -1,3 +1,5 @@
51ad59
+#include "config.h"
51ad59
+
51ad59
 #include <glib.h>
51ad59
 #include <string.h>
51ad59
 #include <stdlib.h>
51ad59
@@ -427,6 +429,9 @@ test_hmac_ref_unref (void)
51ad59
 static void
51ad59
 test_hmac_copy (void)
51ad59
 {
51ad59
+#ifdef HAVE_GNUTLS
51ad59
+  g_test_skip ("No g_hmac_copy with gnutls");
51ad59
+#else
51ad59
   GHmac *hmac, *check;
51ad59
 
51ad59
   hmac = g_hmac_new (G_CHECKSUM_SHA256, (guchar*)"aaa", 3);
51ad59
@@ -435,6 +440,7 @@ test_hmac_copy (void)
51ad59
   g_assert_cmpstr (g_hmac_get_string (hmac), ==, g_hmac_get_string (check));
51ad59
   g_hmac_unref (check);
51ad59
   g_hmac_unref (hmac);
51ad59
+#endif
51ad59
 }
51ad59
 
51ad59
 static void
51ad59
diff --git a/meson.build b/meson.build
51ad59
index 0cefee51d..81b16b004 100644
51ad59
--- a/meson.build
51ad59
+++ b/meson.build
51ad59
@@ -1596,6 +1596,13 @@ if host_system == 'linux' and get_option('libmount')
51ad59
   libmount_dep = [dependency('mount', version : '>=2.23', required : true)]
51ad59
 endif
51ad59
 
51ad59
+# gnutls is used optionally by ghmac
51ad59
+libgnutls_dep = []
51ad59
+if get_option('gnutls')
51ad59
+  libgnutls_dep = [dependency('gnutls', version : '>=3.6.7', required : true)]
51ad59
+  glib_conf.set('HAVE_GNUTLS', 1)
51ad59
+endif
51ad59
+
51ad59
 if host_system == 'windows'
51ad59
   winsock2 = cc.find_library('ws2_32')
51ad59
 endif
51ad59
diff --git a/meson_options.txt b/meson_options.txt
51ad59
index 4504c6858..d18c42a36 100644
51ad59
--- a/meson_options.txt
51ad59
+++ b/meson_options.txt
51ad59
@@ -34,6 +34,11 @@ option('libmount',
51ad59
        value : true,
51ad59
        description : 'build with libmount support')
51ad59
 
51ad59
+option('gnutls',
51ad59
+       type : 'boolean',
51ad59
+       value : false,
51ad59
+       description : 'build with gnutls support')
51ad59
+
51ad59
 option('internal_pcre',
51ad59
        type : 'boolean',
51ad59
        value : false,
51ad59
-- 
51ad59
2.21.0
51ad59