3d08d3
From 7ab93b8205093b4d176e63947039981515af1932 Mon Sep 17 00:00:00 2001
2d3b65
From: Colin Walters <walters@verbum.org>
2d3b65
Date: Fri, 7 Jun 2019 18:44:43 +0000
3d08d3
Subject: [PATCH 1/3] ghmac: Split off wrapper functions into ghmac-utils.c
2d3b65
2d3b65
Prep for adding a GnuTLS HMAC implementation; these are just
2d3b65
utility functions that call the "core" API.
2d3b65
---
2d3b65
 glib/Makefile.am   |   1 +
2d3b65
 glib/ghmac-utils.c | 145 +++++++++++++++++++++++++++++++++++++++++++++
2d3b65
 glib/ghmac.c       | 112 ----------------------------------
2d3b65
 glib/meson.build   |   1 +
2d3b65
 4 files changed, 147 insertions(+), 112 deletions(-)
2d3b65
 create mode 100644 glib/ghmac-utils.c
2d3b65
2d3b65
diff --git a/glib/Makefile.am b/glib/Makefile.am
3d08d3
index c0c3b92f0..43fa17051 100644
2d3b65
--- a/glib/Makefile.am
2d3b65
+++ b/glib/Makefile.am
2d3b65
@@ -126,6 +126,7 @@ libglib_2_0_la_SOURCES = 	\
2d3b65
 	ggettext.c		\
2d3b65
 	ghash.c			\
2d3b65
 	ghmac.c			\
2d3b65
+	ghmac-utils.c		\
2d3b65
 	ghook.c			\
2d3b65
 	ghostutils.c		\
2d3b65
 	giochannel.c    	\
2d3b65
diff --git a/glib/ghmac-utils.c b/glib/ghmac-utils.c
2d3b65
new file mode 100644
2d3b65
index 000000000..a17359ff1
2d3b65
--- /dev/null
2d3b65
+++ b/glib/ghmac-utils.c
2d3b65
@@ -0,0 +1,145 @@
2d3b65
+/* ghmac.h - data hashing functions
2d3b65
+ *
2d3b65
+ * Copyright (C) 2011  Collabora Ltd.
2d3b65
+ * Copyright (C) 2019  Red Hat, Inc.
2d3b65
+ *
2d3b65
+ * This library is free software; you can redistribute it and/or
2d3b65
+ * modify it under the terms of the GNU Lesser General Public
2d3b65
+ * License as published by the Free Software Foundation; either
2d3b65
+ * version 2.1 of the License, or (at your option) any later version.
2d3b65
+ *
2d3b65
+ * This library is distributed in the hope that it will be useful,
2d3b65
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2d3b65
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2d3b65
+ * Lesser General Public License for more details.
2d3b65
+ *
2d3b65
+ * You should have received a copy of the GNU Lesser General Public License
2d3b65
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
2d3b65
+ */
2d3b65
+
2d3b65
+#include "config.h"
2d3b65
+
2d3b65
+#include <string.h>
2d3b65
+
2d3b65
+#include "ghmac.h"
2d3b65
+
2d3b65
+#include "glib/galloca.h"
2d3b65
+#include "gatomic.h"
2d3b65
+#include "gslice.h"
2d3b65
+#include "gmem.h"
2d3b65
+#include "gstrfuncs.h"
2d3b65
+#include "gtestutils.h"
2d3b65
+#include "gtypes.h"
2d3b65
+#include "glibintl.h"
2d3b65
+
2d3b65
+/**
2d3b65
+ * g_compute_hmac_for_data:
2d3b65
+ * @digest_type: a #GChecksumType to use for the HMAC
2d3b65
+ * @key: (array length=key_len): the key to use in the HMAC
2d3b65
+ * @key_len: the length of the key
2d3b65
+ * @data: (array length=length): binary blob to compute the HMAC of
2d3b65
+ * @length: length of @data
2d3b65
+ *
2d3b65
+ * Computes the HMAC for a binary @data of @length. This is a
2d3b65
+ * convenience wrapper for g_hmac_new(), g_hmac_get_string()
2d3b65
+ * and g_hmac_unref().
2d3b65
+ *
2d3b65
+ * The hexadecimal string returned will be in lower case.
2d3b65
+ *
2d3b65
+ * Returns: the HMAC of the binary data as a string in hexadecimal.
2d3b65
+ *   The returned string should be freed with g_free() when done using it.
2d3b65
+ *
2d3b65
+ * Since: 2.30
2d3b65
+ */
2d3b65
+gchar *
2d3b65
+g_compute_hmac_for_data (GChecksumType  digest_type,
2d3b65
+                         const guchar  *key,
2d3b65
+                         gsize          key_len,
2d3b65
+                         const guchar  *data,
2d3b65
+                         gsize          length)
2d3b65
+{
2d3b65
+  GHmac *hmac;
2d3b65
+  gchar *retval;
2d3b65
+
2d3b65
+  g_return_val_if_fail (length == 0 || data != NULL, NULL);
2d3b65
+
2d3b65
+  hmac = g_hmac_new (digest_type, key, key_len);
2d3b65
+  if (!hmac)
2d3b65
+    return NULL;
2d3b65
+
2d3b65
+  g_hmac_update (hmac, data, length);
2d3b65
+  retval = g_strdup (g_hmac_get_string (hmac));
2d3b65
+  g_hmac_unref (hmac);
2d3b65
+
2d3b65
+  return retval;
2d3b65
+}
2d3b65
+
2d3b65
+/**
2d3b65
+ * g_compute_hmac_for_bytes:
2d3b65
+ * @digest_type: a #GChecksumType to use for the HMAC
2d3b65
+ * @key: the key to use in the HMAC
2d3b65
+ * @data: binary blob to compute the HMAC of
2d3b65
+ *
2d3b65
+ * Computes the HMAC for a binary @data. This is a
2d3b65
+ * convenience wrapper for g_hmac_new(), g_hmac_get_string()
2d3b65
+ * and g_hmac_unref().
2d3b65
+ *
2d3b65
+ * The hexadecimal string returned will be in lower case.
2d3b65
+ *
2d3b65
+ * Returns: the HMAC of the binary data as a string in hexadecimal.
2d3b65
+ *   The returned string should be freed with g_free() when done using it.
2d3b65
+ *
2d3b65
+ * Since: 2.50
2d3b65
+ */
2d3b65
+gchar *
2d3b65
+g_compute_hmac_for_bytes (GChecksumType  digest_type,
2d3b65
+                          GBytes        *key,
2d3b65
+                          GBytes        *data)
2d3b65
+{
2d3b65
+  gconstpointer byte_data;
2d3b65
+  gsize length;
2d3b65
+  gconstpointer key_data;
2d3b65
+  gsize key_len;
2d3b65
+
2d3b65
+  g_return_val_if_fail (data != NULL, NULL);
2d3b65
+  g_return_val_if_fail (key != NULL, NULL);
2d3b65
+
2d3b65
+  byte_data = g_bytes_get_data (data, &length);
2d3b65
+  key_data = g_bytes_get_data (key, &key_len);
2d3b65
+  return g_compute_hmac_for_data (digest_type, key_data, key_len, byte_data, length);
2d3b65
+}
2d3b65
+
2d3b65
+
2d3b65
+/**
2d3b65
+ * g_compute_hmac_for_string:
2d3b65
+ * @digest_type: a #GChecksumType to use for the HMAC
2d3b65
+ * @key: (array length=key_len): the key to use in the HMAC
2d3b65
+ * @key_len: the length of the key
2d3b65
+ * @str: the string to compute the HMAC for
2d3b65
+ * @length: the length of the string, or -1 if the string is nul-terminated
2d3b65
+ *
2d3b65
+ * Computes the HMAC for a string.
2d3b65
+ *
2d3b65
+ * The hexadecimal string returned will be in lower case.
2d3b65
+ *
2d3b65
+ * Returns: the HMAC as a hexadecimal string.
2d3b65
+ *     The returned string should be freed with g_free()
2d3b65
+ *     when done using it.
2d3b65
+ *
2d3b65
+ * Since: 2.30
2d3b65
+ */
2d3b65
+gchar *
2d3b65
+g_compute_hmac_for_string (GChecksumType  digest_type,
2d3b65
+                           const guchar  *key,
2d3b65
+                           gsize          key_len,
2d3b65
+                           const gchar   *str,
2d3b65
+                           gssize         length)
2d3b65
+{
2d3b65
+  g_return_val_if_fail (length == 0 || str != NULL, NULL);
2d3b65
+
2d3b65
+  if (length < 0)
2d3b65
+    length = strlen (str);
2d3b65
+
2d3b65
+  return g_compute_hmac_for_data (digest_type, key, key_len,
2d3b65
+                                  (const guchar *) str, length);
2d3b65
+}
2d3b65
diff --git a/glib/ghmac.c b/glib/ghmac.c
2d3b65
index 9b58fd81c..7db38e34a 100644
2d3b65
--- a/glib/ghmac.c
2d3b65
+++ b/glib/ghmac.c
2d3b65
@@ -329,115 +329,3 @@ g_hmac_get_digest (GHmac  *hmac,
2d3b65
   g_checksum_update (hmac->digesto, buffer, len);
2d3b65
   g_checksum_get_digest (hmac->digesto, buffer, digest_len);
2d3b65
 }
2d3b65
-
2d3b65
-/**
2d3b65
- * g_compute_hmac_for_data:
2d3b65
- * @digest_type: a #GChecksumType to use for the HMAC
2d3b65
- * @key: (array length=key_len): the key to use in the HMAC
2d3b65
- * @key_len: the length of the key
2d3b65
- * @data: (array length=length): binary blob to compute the HMAC of
2d3b65
- * @length: length of @data
2d3b65
- *
2d3b65
- * Computes the HMAC for a binary @data of @length. This is a
2d3b65
- * convenience wrapper for g_hmac_new(), g_hmac_get_string()
2d3b65
- * and g_hmac_unref().
2d3b65
- *
2d3b65
- * The hexadecimal string returned will be in lower case.
2d3b65
- *
2d3b65
- * Returns: the HMAC of the binary data as a string in hexadecimal.
2d3b65
- *   The returned string should be freed with g_free() when done using it.
2d3b65
- *
2d3b65
- * Since: 2.30
2d3b65
- */
2d3b65
-gchar *
2d3b65
-g_compute_hmac_for_data (GChecksumType  digest_type,
2d3b65
-                         const guchar  *key,
2d3b65
-                         gsize          key_len,
2d3b65
-                         const guchar  *data,
2d3b65
-                         gsize          length)
2d3b65
-{
2d3b65
-  GHmac *hmac;
2d3b65
-  gchar *retval;
2d3b65
-
2d3b65
-  g_return_val_if_fail (length == 0 || data != NULL, NULL);
2d3b65
-
2d3b65
-  hmac = g_hmac_new (digest_type, key, key_len);
2d3b65
-  if (!hmac)
2d3b65
-    return NULL;
2d3b65
-
2d3b65
-  g_hmac_update (hmac, data, length);
2d3b65
-  retval = g_strdup (g_hmac_get_string (hmac));
2d3b65
-  g_hmac_unref (hmac);
2d3b65
-
2d3b65
-  return retval;
2d3b65
-}
2d3b65
-
2d3b65
-/**
2d3b65
- * g_compute_hmac_for_bytes:
2d3b65
- * @digest_type: a #GChecksumType to use for the HMAC
2d3b65
- * @key: the key to use in the HMAC
2d3b65
- * @data: binary blob to compute the HMAC of
2d3b65
- *
2d3b65
- * Computes the HMAC for a binary @data. This is a
2d3b65
- * convenience wrapper for g_hmac_new(), g_hmac_get_string()
2d3b65
- * and g_hmac_unref().
2d3b65
- *
2d3b65
- * The hexadecimal string returned will be in lower case.
2d3b65
- *
2d3b65
- * Returns: the HMAC of the binary data as a string in hexadecimal.
2d3b65
- *   The returned string should be freed with g_free() when done using it.
2d3b65
- *
2d3b65
- * Since: 2.50
2d3b65
- */
2d3b65
-gchar *
2d3b65
-g_compute_hmac_for_bytes (GChecksumType  digest_type,
2d3b65
-                          GBytes        *key,
2d3b65
-                          GBytes        *data)
2d3b65
-{
2d3b65
-  gconstpointer byte_data;
2d3b65
-  gsize length;
2d3b65
-  gconstpointer key_data;
2d3b65
-  gsize key_len;
2d3b65
-
2d3b65
-  g_return_val_if_fail (data != NULL, NULL);
2d3b65
-  g_return_val_if_fail (key != NULL, NULL);
2d3b65
-
2d3b65
-  byte_data = g_bytes_get_data (data, &length);
2d3b65
-  key_data = g_bytes_get_data (key, &key_len);
2d3b65
-  return g_compute_hmac_for_data (digest_type, key_data, key_len, byte_data, length);
2d3b65
-}
2d3b65
-
2d3b65
-
2d3b65
-/**
2d3b65
- * g_compute_hmac_for_string:
2d3b65
- * @digest_type: a #GChecksumType to use for the HMAC
2d3b65
- * @key: (array length=key_len): the key to use in the HMAC
2d3b65
- * @key_len: the length of the key
2d3b65
- * @str: the string to compute the HMAC for
2d3b65
- * @length: the length of the string, or -1 if the string is nul-terminated
2d3b65
- *
2d3b65
- * Computes the HMAC for a string.
2d3b65
- *
2d3b65
- * The hexadecimal string returned will be in lower case.
2d3b65
- *
2d3b65
- * Returns: the HMAC as a hexadecimal string.
2d3b65
- *     The returned string should be freed with g_free()
2d3b65
- *     when done using it.
2d3b65
- *
2d3b65
- * Since: 2.30
2d3b65
- */
2d3b65
-gchar *
2d3b65
-g_compute_hmac_for_string (GChecksumType  digest_type,
2d3b65
-                           const guchar  *key,
2d3b65
-                           gsize          key_len,
2d3b65
-                           const gchar   *str,
2d3b65
-                           gssize         length)
2d3b65
-{
2d3b65
-  g_return_val_if_fail (length == 0 || str != NULL, NULL);
2d3b65
-
2d3b65
-  if (length < 0)
2d3b65
-    length = strlen (str);
2d3b65
-
2d3b65
-  return g_compute_hmac_for_data (digest_type, key, key_len,
2d3b65
-                                  (const guchar *) str, length);
2d3b65
-}
2d3b65
diff --git a/glib/meson.build b/glib/meson.build
3d08d3
index c81e99f9c..306a67f13 100644
2d3b65
--- a/glib/meson.build
2d3b65
+++ b/glib/meson.build
2d3b65
@@ -138,6 +138,7 @@ glib_sources = files(
2d3b65
   'ggettext.c',
2d3b65
   'ghash.c',
2d3b65
   'ghmac.c',
2d3b65
+  'ghmac-utils.c',
2d3b65
   'ghook.c',
2d3b65
   'ghostutils.c',
2d3b65
   'giochannel.c',
2d3b65
-- 
3d08d3
2.31.1
2d3b65
3d08d3
From 1cc432d6e9080621e1f2822a14589b258f1f813c Mon Sep 17 00:00:00 2001
2d3b65
From: Colin Walters <walters@verbum.org>
2d3b65
Date: Fri, 7 Jun 2019 19:36:54 +0000
3d08d3
Subject: [PATCH 2/3] Add a gnutls backend for GHmac
2d3b65
2d3b65
For RHEL we want apps to use FIPS-certified crypto libraries,
2d3b65
and HMAC apparently counts as "keyed" and hence needs to
2d3b65
be validated.
2d3b65
2d3b65
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1630260
2d3b65
Replaces: https://gitlab.gnome.org/GNOME/glib/merge_requests/897
2d3b65
2d3b65
This is a build-time option that backs the GHmac API with GnuTLS.
2d3b65
Most distributors ship glib-networking built with GnuTLS, and
2d3b65
most apps use glib-networking, so this isn't a net-new library
2d3b65
in most cases.
2d3b65
3d08d3
=======================================================================
3d08d3
3d08d3
mcatanzaro note:
3d08d3
3d08d3
I've updated Colin's original patch with several enhancements:
3d08d3
3d08d3
Implement g_hmac_copy() using gnutls_hmac_copy(), which didn't exist
3d08d3
when Colin developed this patch.
3d08d3
3d08d3
Removed use of GSlice
3d08d3
3d08d3
Better error checking in g_hmac_new(). It is possible for
3d08d3
gnutls_hmac_init() to fail if running in FIPS mode and an MD5 digest is
3d08d3
requested. In this case, we should return NULL rather than returning a
3d08d3
broken GHmac with a NULL gnutls_hmac_hd_t. This was leading to a later
3d08d3
null pointer dereference inside gnutls_hmac_update(). Applications are
3d08d3
responsible for checking to ensure the return value of g_hmac_new() is
3d08d3
not NULL since it is annotated as nullable. Added documentation to
3d08d3
indicate this possibility.
3d08d3
3d08d3
Properly handle length -1 in g_hmac_update(). This means we've been
3d08d3
given a NUL-terminated string and should use strlen(). GnuTLS doesn't
3d08d3
accept -1, so let's call strlen() ourselves.
3d08d3
3d08d3
Crash the application with g_error() if gnutls_hmac() fails for any
3d08d3
reason. This is necessary because g_hmac_update() is not fallible, so we
3d08d3
have no way to indicate error. Crashing seems better than returning the
3d08d3
wrong result later when g_hmac_get_string() or g_hmac_get_digest() is
3d08d3
later called. (Those functions are also not fallible.) Fortunately, I
3d08d3
don't think this error should actually be hit in practice.
3d08d3
3d08d3
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/903
2d3b65
---
3d08d3
 glib/Makefile.am        |   8 +-
3d08d3
 glib/gchecksum.c        |   9 +-
3d08d3
 glib/gchecksumprivate.h |  32 +++++++
3d08d3
 glib/ghmac-gnutls.c     | 182 ++++++++++++++++++++++++++++++++++++++++
3d08d3
 glib/ghmac.c            |  13 +++
2d3b65
 glib/meson.build        |  10 ++-
2d3b65
 meson.build             |   7 ++
2d3b65
 meson_options.txt       |   5 ++
3d08d3
 8 files changed, 258 insertions(+), 8 deletions(-)
2d3b65
 create mode 100644 glib/gchecksumprivate.h
2d3b65
 create mode 100644 glib/ghmac-gnutls.c
2d3b65
2d3b65
diff --git a/glib/Makefile.am b/glib/Makefile.am
3d08d3
index 43fa17051..1175bbe40 100644
2d3b65
--- a/glib/Makefile.am
2d3b65
+++ b/glib/Makefile.am
2d3b65
@@ -125,7 +125,7 @@ libglib_2_0_la_SOURCES = 	\
2d3b65
 	gfileutils.c		\
2d3b65
 	ggettext.c		\
2d3b65
 	ghash.c			\
2d3b65
-	ghmac.c			\
2d3b65
+	ghmac-gnutls.c		\
2d3b65
 	ghmac-utils.c		\
2d3b65
 	ghook.c			\
2d3b65
 	ghostutils.c		\
3d08d3
@@ -352,11 +352,15 @@ pcre_lib = pcre/libpcre.la
2d3b65
 pcre_inc =
2d3b65
 endif
2d3b65
 
2d3b65
-libglib_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS) $(LIBSYSTEMD_CFLAGS)
2d3b65
+gnutls_libs = $(shell pkg-config --libs gnutls)
2d3b65
+gnutls_cflags = $(shell pkg-config --cflags gnutls)
2d3b65
+
2d3b65
+libglib_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS) $(LIBSYSTEMD_CFLAGS) $(gnutls_cflags)
2d3b65
 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)
2d3b65
 libglib_2_0_la_DEPENDENCIES = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ $(glib_win32_res) $(glib_def)
2d3b65
 
3d08d3
 libglib_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \
3d08d3
+         $(gnutls_libs) \
2d3b65
 	 $(glib_win32_res_ldflag) \
2d3b65
 	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
2d3b65
 	-export-dynamic $(no_undefined)
2d3b65
diff --git a/glib/gchecksum.c b/glib/gchecksum.c
2d3b65
index 40b1d50e2..2f59d4a66 100644
2d3b65
--- a/glib/gchecksum.c
2d3b65
+++ b/glib/gchecksum.c
2d3b65
@@ -20,7 +20,7 @@
2d3b65
 
2d3b65
 #include <string.h>
2d3b65
 
2d3b65
-#include "gchecksum.h"
2d3b65
+#include "gchecksumprivate.h"
2d3b65
 
2d3b65
 #include "gslice.h"
2d3b65
 #include "gmem.h"
2d3b65
@@ -173,9 +173,9 @@ sha_byte_reverse (guint32 *buffer,
2d3b65
 }
2d3b65
 #endif /* G_BYTE_ORDER == G_BIG_ENDIAN */
2d3b65
 
2d3b65
-static gchar *
2d3b65
-digest_to_string (guint8 *digest,
2d3b65
-                  gsize   digest_len)
2d3b65
+gchar *
2d3b65
+gchecksum_digest_to_string (guint8 *digest,
2d3b65
+                            gsize   digest_len)
2d3b65
 {
2d3b65
   gint len = digest_len * 2;
2d3b65
   gint i;
2d3b65
@@ -195,6 +195,7 @@ digest_to_string (guint8 *digest,
2d3b65
 
2d3b65
   return retval;
2d3b65
 }
2d3b65
+#define digest_to_string gchecksum_digest_to_string
2d3b65
 
2d3b65
 /*
2d3b65
  * MD5 Checksum
2d3b65
diff --git a/glib/gchecksumprivate.h b/glib/gchecksumprivate.h
2d3b65
new file mode 100644
2d3b65
index 000000000..86c7a3b61
2d3b65
--- /dev/null
2d3b65
+++ b/glib/gchecksumprivate.h
2d3b65
@@ -0,0 +1,32 @@
2d3b65
+/* gstdioprivate.h - Private GLib stdio functions
2d3b65
+ *
2d3b65
+ * Copyright 2017 Руслан Ижбулатов
2d3b65
+ *
2d3b65
+ * This library is free software; you can redistribute it and/or
2d3b65
+ * modify it under the terms of the GNU Lesser General Public
2d3b65
+ * License as published by the Free Software Foundation; either
2d3b65
+ * version 2.1 of the License, or (at your option) any later version.
2d3b65
+ *
2d3b65
+ * This library is distributed in the hope that it will be useful,
2d3b65
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2d3b65
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2d3b65
+ * Lesser General Public License for more details.
2d3b65
+ *
2d3b65
+ * You should have received a copy of the GNU Lesser General Public License
2d3b65
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
2d3b65
+ */
2d3b65
+
2d3b65
+#ifndef __G_CHECKSUMPRIVATE_H__
2d3b65
+#define __G_CHECKSUMPRIVATE_H__
2d3b65
+
2d3b65
+#include "gchecksum.h"
2d3b65
+
2d3b65
+G_BEGIN_DECLS
2d3b65
+
2d3b65
+gchar *
2d3b65
+gchecksum_digest_to_string (guint8 *digest,
2d3b65
+                            gsize   digest_len);
2d3b65
+
2d3b65
+G_END_DECLS
2d3b65
+
2d3b65
+#endif
2d3b65
\ No newline at end of file
2d3b65
diff --git a/glib/ghmac-gnutls.c b/glib/ghmac-gnutls.c
2d3b65
new file mode 100644
3d08d3
index 000000000..522b9b302
2d3b65
--- /dev/null
2d3b65
+++ b/glib/ghmac-gnutls.c
3d08d3
@@ -0,0 +1,182 @@
2d3b65
+/* ghmac.h - data hashing functions
2d3b65
+ *
2d3b65
+ * Copyright (C) 2011  Collabora Ltd.
2d3b65
+ * Copyright (C) 2019  Red Hat, Inc.
2d3b65
+ *
2d3b65
+ * This library is free software; you can redistribute it and/or
2d3b65
+ * modify it under the terms of the GNU Lesser General Public
2d3b65
+ * License as published by the Free Software Foundation; either
2d3b65
+ * version 2.1 of the License, or (at your option) any later version.
2d3b65
+ *
2d3b65
+ * This library is distributed in the hope that it will be useful,
2d3b65
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2d3b65
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2d3b65
+ * Lesser General Public License for more details.
2d3b65
+ *
2d3b65
+ * You should have received a copy of the GNU Lesser General Public License
2d3b65
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
2d3b65
+ */
2d3b65
+
2d3b65
+#include "config.h"
2d3b65
+
2d3b65
+#include <string.h>
2d3b65
+#include <gnutls/crypto.h>
2d3b65
+
2d3b65
+#include "ghmac.h"
2d3b65
+
2d3b65
+#include "glib/galloca.h"
2d3b65
+#include "gatomic.h"
2d3b65
+#include "gslice.h"
2d3b65
+#include "gmem.h"
2d3b65
+#include "gstrfuncs.h"
2d3b65
+#include "gchecksumprivate.h"
2d3b65
+#include "gtestutils.h"
2d3b65
+#include "gtypes.h"
2d3b65
+#include "glibintl.h"
2d3b65
+
2d3b65
+struct _GHmac
2d3b65
+{
2d3b65
+  int ref_count;
2d3b65
+  GChecksumType digest_type;
2d3b65
+  gnutls_hmac_hd_t hmac;
2d3b65
+  gchar *digest_str;
2d3b65
+};
2d3b65
+
2d3b65
+GHmac *
2d3b65
+g_hmac_new (GChecksumType  digest_type,
2d3b65
+            const guchar  *key,
2d3b65
+            gsize          key_len)
2d3b65
+{
2d3b65
+  gnutls_mac_algorithm_t algo;
3d08d3
+  GHmac *hmac = g_new0 (GHmac, 1);
3d08d3
+  int ret;
3d08d3
+
2d3b65
+  hmac->ref_count = 1;
3d08d3
+  hmac->digest_type = digest_type;
2d3b65
+
2d3b65
+  switch (digest_type)
2d3b65
+    {
2d3b65
+    case G_CHECKSUM_MD5:
2d3b65
+      algo = GNUTLS_MAC_MD5;
2d3b65
+      break;
2d3b65
+    case G_CHECKSUM_SHA1:
2d3b65
+      algo = GNUTLS_MAC_SHA1;
2d3b65
+      break;
2d3b65
+    case G_CHECKSUM_SHA256:
2d3b65
+      algo = GNUTLS_MAC_SHA256;
2d3b65
+      break;
2d3b65
+    case G_CHECKSUM_SHA384:
2d3b65
+      algo = GNUTLS_MAC_SHA384;
2d3b65
+      break;
2d3b65
+    case G_CHECKSUM_SHA512:
2d3b65
+      algo = GNUTLS_MAC_SHA512;
2d3b65
+      break;
2d3b65
+    default:
2d3b65
+      g_return_val_if_reached (NULL);
2d3b65
+    }
2d3b65
+
3d08d3
+  ret = gnutls_hmac_init (&hmac->hmac, algo, key, key_len);
3d08d3
+  if (ret != 0)
3d08d3
+    {
3d08d3
+      /* There is no way to report an error here, but one possible cause of
3d08d3
+       * failure is that the requested digest may be disabled by FIPS mode.
3d08d3
+       */
3d08d3
+      g_free (hmac->hmac);
3d08d3
+      return NULL;
3d08d3
+    }
2d3b65
+
2d3b65
+  return hmac;
2d3b65
+}
2d3b65
+
2d3b65
+GHmac *
2d3b65
+g_hmac_copy (const GHmac *hmac)
2d3b65
+{
bd1e7a
+  GHmac *copy;
bd1e7a
+
bd1e7a
+  g_return_val_if_fail (hmac != NULL, NULL);
bd1e7a
+
3d08d3
+  copy = g_new0 (GHmac, 1);
bd1e7a
+  copy->ref_count = 1;
bd1e7a
+  copy->digest_type = hmac->digest_type;
bd1e7a
+  copy->hmac = gnutls_hmac_copy (hmac->hmac);
bd1e7a
+
3d08d3
+  /* g_hmac_copy is not allowed to fail, so we'll have to crash on error. */
3d08d3
+  if (!copy->hmac)
3d08d3
+    g_error ("gnutls_hmac_copy failed");
3d08d3
+
bd1e7a
+  return copy;
2d3b65
+}
2d3b65
+
2d3b65
+GHmac *
2d3b65
+g_hmac_ref (GHmac *hmac)
2d3b65
+{
2d3b65
+  g_return_val_if_fail (hmac != NULL, NULL);
2d3b65
+
2d3b65
+  g_atomic_int_inc (&hmac->ref_count);
2d3b65
+
2d3b65
+  return hmac;
2d3b65
+}
2d3b65
+
2d3b65
+void
2d3b65
+g_hmac_unref (GHmac *hmac)
2d3b65
+{
2d3b65
+  g_return_if_fail (hmac != NULL);
2d3b65
+
2d3b65
+  if (g_atomic_int_dec_and_test (&hmac->ref_count))
2d3b65
+    {
2d3b65
+      gnutls_hmac_deinit (hmac->hmac, NULL);
2d3b65
+      g_free (hmac->digest_str);
3d08d3
+      g_free (hmac);
2d3b65
+    }
2d3b65
+}
2d3b65
+
2d3b65
+
2d3b65
+void
2d3b65
+g_hmac_update (GHmac        *hmac,
2d3b65
+               const guchar *data,
2d3b65
+               gssize        length)
2d3b65
+{
3d08d3
+  int ret;
3d08d3
+
2d3b65
+  g_return_if_fail (hmac != NULL);
2d3b65
+  g_return_if_fail (length == 0 || data != NULL);
2d3b65
+
3d08d3
+  if (length == -1)
3d08d3
+    length = strlen ((const char *)data);
3d08d3
+
3d08d3
+  /* g_hmac_update is not allowed to fail, so we'll have to crash on error. */
3d08d3
+  ret = gnutls_hmac (hmac->hmac, data, length);
3d08d3
+  if (ret != 0)
3d08d3
+    g_error ("gnutls_hmac failed: %s", gnutls_strerror (ret));
2d3b65
+}
2d3b65
+
2d3b65
+const gchar *
2d3b65
+g_hmac_get_string (GHmac *hmac)
2d3b65
+{
2d3b65
+  guint8 *buffer;
2d3b65
+  gsize digest_len;
2d3b65
+
2d3b65
+  g_return_val_if_fail (hmac != NULL, NULL);
2d3b65
+
2d3b65
+  if (hmac->digest_str)
2d3b65
+    return hmac->digest_str;
2d3b65
+
2d3b65
+  digest_len = g_checksum_type_get_length (hmac->digest_type);
2d3b65
+  buffer = g_alloca (digest_len);
2d3b65
+
2d3b65
+  gnutls_hmac_output (hmac->hmac, buffer);
2d3b65
+  hmac->digest_str = gchecksum_digest_to_string (buffer, digest_len);
2d3b65
+  return hmac->digest_str;
2d3b65
+}
2d3b65
+
2d3b65
+
2d3b65
+void
2d3b65
+g_hmac_get_digest (GHmac  *hmac,
2d3b65
+                   guint8 *buffer,
2d3b65
+                   gsize  *digest_len)
2d3b65
+{
2d3b65
+  g_return_if_fail (hmac != NULL);
2d3b65
+
2d3b65
+  gnutls_hmac_output (hmac->hmac, buffer);
2d3b65
+  *digest_len = g_checksum_type_get_length (hmac->digest_type);
2d3b65
+}
2d3b65
diff --git a/glib/ghmac.c b/glib/ghmac.c
3d08d3
index 7db38e34a..b03a5aea7 100644
2d3b65
--- a/glib/ghmac.c
2d3b65
+++ b/glib/ghmac.c
2d3b65
@@ -33,6 +33,7 @@
2d3b65
 #include "gtypes.h"
2d3b65
 #include "glibintl.h"
2d3b65
 
2d3b65
+#error "build configuration error"
2d3b65
 
2d3b65
 /**
2d3b65
  * SECTION:hmac
3d08d3
@@ -84,6 +85,18 @@ struct _GHmac
3d08d3
  * Support for digests of type %G_CHECKSUM_SHA512 has been added in GLib 2.42.
3d08d3
  * Support for %G_CHECKSUM_SHA384 was added in GLib 2.52.
3d08d3
  *
3d08d3
+ * Note that #GHmac creation may fail, in which case this function will
3d08d3
+ * return %NULL. Since there is no error parameter, it is not possible
3d08d3
+ * to indicate why.
3d08d3
+ *
3d08d3
+ * In Fedora, CentOS Stream, and Red Hat Enterprise Linux, GLib is
3d08d3
+ * configured to use GnuTLS to implement #GHmac in order to support FIPS
3d08d3
+ * compliance. This introduces additional failure possibilities that are
3d08d3
+ * not present in upstream GLib. For example, the creation of a #GHmac
3d08d3
+ * will fail if @digest_type is %G_CHECKSUM_MD5 and the system is
3d08d3
+ * running in FIPS mode. #GHmac creation may also fail if GLib is unable
3d08d3
+ * to load GnuTLS.
3d08d3
+ *
3d08d3
  * Returns: the newly created #GHmac, or %NULL.
3d08d3
  *   Use g_hmac_unref() to free the memory allocated by it.
3d08d3
  *
2d3b65
diff --git a/glib/meson.build b/glib/meson.build
3d08d3
index 306a67f13..07d41456d 100644
2d3b65
--- a/glib/meson.build
2d3b65
+++ b/glib/meson.build
3d08d3
@@ -127,6 +127,7 @@ glib_sources = files(
3d08d3
   'gbytes.c',
3d08d3
   'gcharset.c',
3d08d3
   'gchecksum.c',
3d08d3
+  'gchecksumprivate.h',
3d08d3
   'gconvert.c',
3d08d3
   'gdataset.c',
3d08d3
   'gdate.c',
3d08d3
@@ -137,7 +138,6 @@ glib_sources = files(
2d3b65
   'gfileutils.c',
2d3b65
   'ggettext.c',
2d3b65
   'ghash.c',
2d3b65
-  'ghmac.c',
2d3b65
   'ghmac-utils.c',
2d3b65
   'ghook.c',
2d3b65
   'ghostutils.c',
3d08d3
@@ -223,6 +223,12 @@ else
2d3b65
   glib_dtrace_hdr = []
2d3b65
 endif
2d3b65
 
2d3b65
+if get_option('gnutls')
2d3b65
+  glib_sources += files('ghmac-gnutls.c')
2d3b65
+else
2d3b65
+  glib_sources += files('ghmac.c')
2d3b65
+endif
2d3b65
+
2d3b65
 pcre_static_args = []
2d3b65
 
2d3b65
 if use_pcre_static_flag
3d08d3
@@ -239,7 +245,7 @@ libglib = library('glib-2.0',
2d3b65
   link_args : platform_ldflags + noseh_link_args,
2d3b65
   include_directories : configinc,
2d3b65
   link_with : [charset_lib, gnulib_lib],
2d3b65
-  dependencies : [pcre, thread_dep, libintl, librt] + libiconv + platform_deps,
3d08d3
+  dependencies : [pcre, thread_dep, libintl, librt] + libgnutls_dep + libiconv + platform_deps,
2d3b65
   c_args : ['-DG_LOG_DOMAIN="GLib"', '-DGLIB_COMPILATION'] + pcre_static_args + glib_hidden_visibility_args
2d3b65
 )
2d3b65
 
2d3b65
diff --git a/meson.build b/meson.build
3d08d3
index 0cefee51d..eaf8d3900 100644
2d3b65
--- a/meson.build
2d3b65
+++ b/meson.build
2d3b65
@@ -1596,6 +1596,13 @@ if host_system == 'linux' and get_option('libmount')
2d3b65
   libmount_dep = [dependency('mount', version : '>=2.23', required : true)]
2d3b65
 endif
2d3b65
 
2d3b65
+# gnutls is used optionally by ghmac
2d3b65
+libgnutls_dep = []
2d3b65
+if get_option('gnutls')
bd1e7a
+  libgnutls_dep = [dependency('gnutls', version : '>=3.6.9', required : true)]
2d3b65
+  glib_conf.set('HAVE_GNUTLS', 1)
2d3b65
+endif
2d3b65
+
2d3b65
 if host_system == 'windows'
2d3b65
   winsock2 = cc.find_library('ws2_32')
2d3b65
 endif
2d3b65
diff --git a/meson_options.txt b/meson_options.txt
2d3b65
index 4504c6858..d18c42a36 100644
2d3b65
--- a/meson_options.txt
2d3b65
+++ b/meson_options.txt
2d3b65
@@ -34,6 +34,11 @@ option('libmount',
2d3b65
        value : true,
2d3b65
        description : 'build with libmount support')
2d3b65
 
2d3b65
+option('gnutls',
2d3b65
+       type : 'boolean',
2d3b65
+       value : false,
2d3b65
+       description : 'build with gnutls support')
2d3b65
+
2d3b65
 option('internal_pcre',
2d3b65
        type : 'boolean',
2d3b65
        value : false,
2d3b65
-- 
3d08d3
2.31.1
3d08d3
3d08d3
From 20e550351e9914e78a73b4ca0e9866f1a39dca51 Mon Sep 17 00:00:00 2001
3d08d3
From: Michael Catanzaro <mcatanzaro@redhat.com>
3d08d3
Date: Wed, 16 Jun 2021 20:46:24 -0500
3d08d3
Subject: [PATCH 3/3] Add test for GHmac in FIPS mode
3d08d3
3d08d3
This will test a few problems that we hit recently:
3d08d3
3d08d3
g_hmac_copy() is broken, https://bugzilla.redhat.com/show_bug.cgi?id=1786538
3d08d3
3d08d3
Crash in g_hmac_update() in FIPS mode, https://bugzilla.redhat.com/show_bug.cgi?id=1971533
3d08d3
3d08d3
Crash when passing -1 length to g_hmac_update() (discovered in #1971533)
3d08d3
3d08d3
We'll also test to ensure MD5 fails, and stop compiling the other MD5
3d08d3
tests.
3d08d3
---
3d08d3
 glib/tests/hmac.c | 139 +++++++++++-----------------------------------
3d08d3
 1 file changed, 32 insertions(+), 107 deletions(-)
3d08d3
3d08d3
diff --git a/glib/tests/hmac.c b/glib/tests/hmac.c
3d08d3
index 3ac3206df..31a1c77d3 100644
3d08d3
--- a/glib/tests/hmac.c
3d08d3
+++ b/glib/tests/hmac.c
3d08d3
@@ -1,87 +1,9 @@
3d08d3
+#include "config.h"
3d08d3
+
3d08d3
 #include <glib.h>
3d08d3
 #include <string.h>
3d08d3
 #include <stdlib.h>
3d08d3
 
3d08d3
-/* HMAC-MD5 test vectors as per RFC 2202 */
3d08d3
-
3d08d3
-/* Test 1 */
3d08d3
-guint8 key_md5_test1[] = {
3d08d3
-    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
3d08d3
-    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
3d08d3
-guint8 result_md5_test1[] = {
3d08d3
-    0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 0x13, 0xf4,
3d08d3
-    0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d };
3d08d3
-
3d08d3
-/* Test 2 */
3d08d3
-guint8 result_md5_test2[] = {
3d08d3
-    0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 0xea, 0xa8,
3d08d3
-    0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 };
3d08d3
-
3d08d3
-/* Test 3 */
3d08d3
-guint8 key_md5_test3[] = {
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
3d08d3
-guint8 data_md5_test3[] = {
3d08d3
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
3d08d3
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
3d08d3
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
3d08d3
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
3d08d3
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd };
3d08d3
-guint8 result_md5_test3[] = {
3d08d3
-    0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, 0xdb, 0xb8,
3d08d3
-    0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 };
3d08d3
-
3d08d3
-/* Test 4 */
3d08d3
-guint8 key_md5_test4[] = {
3d08d3
-    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
3d08d3
-    0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
3d08d3
-    0x15, 0x16, 0x17, 0x18, 0x19 };
3d08d3
-guint8 data_md5_test4[] = {
3d08d3
-    0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
3d08d3
-    0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
3d08d3
-    0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
3d08d3
-    0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
3d08d3
-    0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd };
3d08d3
-guint8 result_md5_test4[] = {
3d08d3
-    0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, 0x3a, 0x75,
3d08d3
-    0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 };
3d08d3
-
3d08d3
-/* Test 5 */
3d08d3
-guint8 key_md5_test5[] = {
3d08d3
-    0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
3d08d3
-    0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
3d08d3
-guint8 result_md5_test5[] = {
3d08d3
-    0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, 0xf9, 0xba,
3d08d3
-    0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c };
3d08d3
-
3d08d3
-/* Test 6 */
3d08d3
-guint8 key_md5_test6[] = {
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
3d08d3
-guint8 result_md5_test6[] = {
3d08d3
-    0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, 0x0b, 0x62,
3d08d3
-    0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd };
3d08d3
-
3d08d3
-/* Test 6 */
3d08d3
-guint8 key_md5_test7[] = {
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3d08d3
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
3d08d3
-guint8 result_md5_test7[] = {
3d08d3
-    0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, 0x1f, 0xb1,
3d08d3
-    0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e };
3d08d3
-
3d08d3
 /* HMAC-SHA1, HMAC-SHA256, HMAC-SHA384 and HMAC-SHA512 test vectors
3d08d3
  * as per RFCs 2202 and 4868.
3d08d3
  *
3d08d3
@@ -299,25 +221,6 @@ typedef struct {
3d08d3
   gconstpointer result;
3d08d3
 } HmacCase;
3d08d3
 
3d08d3
-HmacCase hmac_md5_tests[] = {
3d08d3
-  { G_CHECKSUM_MD5, key_md5_test1, 16, "Hi There", 8, result_md5_test1 },
3d08d3
-  { G_CHECKSUM_MD5, "Jefe", 4, "what do ya want for nothing?", 28,
3d08d3
-      result_md5_test2 },
3d08d3
-  { G_CHECKSUM_MD5, key_md5_test3, 16, data_md5_test3, 50,
3d08d3
-      result_md5_test3 },
3d08d3
-  { G_CHECKSUM_MD5, key_md5_test4, 25, data_md5_test4, 50,
3d08d3
-      result_md5_test4 },
3d08d3
-  { G_CHECKSUM_MD5, key_md5_test5, 16, "Test With Truncation", 20,
3d08d3
-      result_md5_test5 },
3d08d3
-  { G_CHECKSUM_MD5, key_md5_test6, 80,
3d08d3
-      "Test Using Larger Than Block-Size Key - Hash Key First", 54,
3d08d3
-      result_md5_test6 },
3d08d3
-  { G_CHECKSUM_MD5, key_md5_test7, 80,
3d08d3
-      "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
3d08d3
-      73, result_md5_test7 },
3d08d3
-  { -1, NULL, 0, NULL, 0, NULL },
3d08d3
-};
3d08d3
-
3d08d3
 HmacCase hmac_sha1_tests[] = {
3d08d3
   { G_CHECKSUM_SHA1, key_sha_test1, 20, "Hi There", 8, result_sha1_test1 },
3d08d3
   { G_CHECKSUM_SHA1, "Jefe", 4, "what do ya want for nothing?", 28,
3d08d3
@@ -493,11 +396,40 @@ test_hmac_for_bytes (void)
3d08d3
   g_bytes_unref (data);
3d08d3
 }
3d08d3
 
3d08d3
+static void
3d08d3
+test_gnutls_fips_mode (void)
3d08d3
+{
3d08d3
+  GHmac *hmac;
3d08d3
+  GHmac *copy;
3d08d3
+
3d08d3
+  /* No MD5 in FIPS mode. */
3d08d3
+  hmac = g_hmac_new (G_CHECKSUM_MD5, "abc123", sizeof ("abc123"));
3d08d3
+  g_assert_null (hmac);
3d08d3
+
3d08d3
+  /* SHA-256 should be good. */
3d08d3
+  hmac = g_hmac_new (G_CHECKSUM_SHA256, "abc123", sizeof ("abc123"));
3d08d3
+  g_assert_nonnull (hmac);
3d08d3
+
3d08d3
+  /* Ensure g_hmac_update() does not crash when called with -1. */
3d08d3
+  g_hmac_update (hmac, "You win again, gravity!", -1);
3d08d3
+
3d08d3
+  /* Ensure g_hmac_copy() does not crash. */
3d08d3
+  copy = g_hmac_copy (hmac);
3d08d3
+  g_assert_nonnull (hmac);
3d08d3
+  g_hmac_unref (hmac);
3d08d3
+
3d08d3
+  g_assert_cmpstr (g_hmac_get_string (copy), ==, "795ba6900bcb22e8ce65c2ec02db4e85697da921deb960ee3143bf88a4a60f83");
3d08d3
+  g_hmac_unref (copy);
3d08d3
+}
3d08d3
+
3d08d3
 int
3d08d3
 main (int argc,
3d08d3
     char **argv)
3d08d3
 {
3d08d3
   int i;
3d08d3
+
3d08d3
+  g_setenv ("GNUTLS_FORCE_FIPS_MODE", "1", FALSE);
3d08d3
+
3d08d3
   g_test_init (&argc, &argv, NULL);
3d08d3
 
3d08d3
   for (i = 0 ; hmac_sha1_tests[i].key_len > 0 ; i++)
3d08d3
@@ -532,19 +464,12 @@ main (int argc,
3d08d3
       g_free (name);
3d08d3
     }
3d08d3
 
3d08d3
-  for (i = 0 ; hmac_md5_tests[i].key_len > 0 ; i++)
3d08d3
-    {
3d08d3
-      gchar *name = g_strdup_printf ("/hmac/md5-%d", i + 1);
3d08d3
-      g_test_add_data_func (name, hmac_md5_tests + i,
3d08d3
-        (void (*)(const void *)) test_hmac);
3d08d3
-      g_free (name);
3d08d3
-    }
3d08d3
-
3d08d3
   g_test_add_func ("/hmac/ref-unref", test_hmac_ref_unref);
3d08d3
   g_test_add_func ("/hmac/copy", test_hmac_copy);
3d08d3
   g_test_add_func ("/hmac/for-data", test_hmac_for_data);
3d08d3
   g_test_add_func ("/hmac/for-string", test_hmac_for_string);
3d08d3
   g_test_add_func ("/hmac/for-bytes", test_hmac_for_bytes);
3d08d3
+  g_test_add_func ("/hmac/gnutls-fips-mode", test_gnutls_fips_mode);
3d08d3
 
3d08d3
   return g_test_run ();
3d08d3
 }
3d08d3
-- 
3d08d3
2.31.1
2d3b65