From 0abefeee6d8c62b188d09dd066c862d1ae6c91ef Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 6 Jun 2019 17:06:55 +0000 Subject: [PATCH] ghmac: Abort in FIPS mode See https://bugzilla.redhat.com/show_bug.cgi?id=1630260 --- glib/ghmac.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/glib/ghmac.c b/glib/ghmac.c index af9b6744ae..88665e5eb7 100644 --- a/glib/ghmac.c +++ b/glib/ghmac.c @@ -61,6 +61,64 @@ struct _GHmac GChecksum *digesto; }; +#ifdef __linux__ +#include +#endif + +static gboolean +fips_mode_enabled (void) +{ +#ifdef __linux__ +/* A onceinit must start zero valued, so we redefine truth by shifting it by 1 */ +#define ENABLED 2 +#define DISABLED 1 + static gsize fips_enabled = 0; + static const char fips_path[] = "/proc/sys/crypto/fips_enabled"; + + if (g_once_init_enter (&fips_enabled)) + { + int fd = open (fips_path, O_RDONLY | O_CLOEXEC); + + gsize ret = DISABLED; + if (fd < 0) + { + /* If the path doesn't exist, we are running on a very old kernel, + * or one without the FIPS module enabled. Or (probably most likely) + * running in a chroot without /proc mounted. We could try to + * detect the situation where e.g. /usr/lib/os-release exists and + * systemd is running and the kernel is new enough (i.e. looks like RHEL8) + * but...for now let's just ignore ENOENT. + */ + } + else + { + char buf[1]; + int r; + do + { + r = read (fd, buf, sizeof(buf)); + } + while (r < 0 && errno == EINTR); + if (r != 1) + { + const char *errmsg = g_strerror (errno); + g_error ("Failed to read() from %s: %s", fips_path, errmsg); + } + if (buf[0] == '1') + ret = ENABLED; + else if (buf[0] != '0') + g_error ("%s has unexpected value '%c'", fips_path, buf[0]); + g_once_init_leave (&fips_enabled, ret); + } + } + return fips_enabled == ENABLED; +#undef ENABLED +#undef DISABLED +#else + return FALSE; +#endif +} + /** * g_hmac_new: * @digest_type: the desired type of digest @@ -101,6 +159,15 @@ g_hmac_new (GChecksumType digest_type, gsize i, len; gsize block_size; + /* The API says this can return NULL but that will only happen + * in OOM conditions, and GLib aborts in other OOM conditions, + * and at least one real-world user of this API (cockpit) + * was observed to not check for NULL, so...let's abort with a clear + * error message rather than causing apps to segfault. + */ + if (fips_mode_enabled ()) + g_error ("g_hmac_new() is not available in FIPS mode"); + checksum = g_checksum_new (digest_type); g_return_val_if_fail (checksum != NULL, NULL); -- GitLab