glib2/SOURCES/ghmac-gnutls.patch
2021-09-09 17:38:49 +00:00

710 lines
20 KiB
Diff

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