File libgcrypt-FIPS-SLI-Introduce-an-internal-API-for-FIPS-service-indicator.patch of Package libgcrypt.38414

From e1cf3123282525693b646499eb7efe4f2be4010a Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Thu, 5 Dec 2024 11:06:37 +0900
Subject: [PATCH 01/24] fips: Introduce an internal API for FIPS service
 indicator.

* configure.ac (HAVE_GCC_STORAGE_CLASS__THREAD): New.
* src/fips.c (struct gcry_thread_context): New.
(_gcry_thread_context_set_fsi, _gcry_thread_context_get_fsi): New.
* src/gcrypt-int.h (fips_service_indicator_init): New macro.
(fips_service_indicator_mark_success): New macro.
* tests/Makefile.am (tests_bin): Add t-thread-local.
* tests/t-thread-local.c: New.

--

GnuPG-bug-id: 7340
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: Lucas Mulling <lucas.mulling@suse.com>
---
 configure.ac           |  14 +++
 src/fips.c             |  21 ++++-
 src/gcrypt-int.h       |  12 +++
 tests/Makefile.am      |   2 +-
 tests/t-thread-local.c | 196 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 243 insertions(+), 2 deletions(-)
 create mode 100644 tests/t-thread-local.c

Index: libgcrypt-1.10.3/configure.ac
===================================================================
--- libgcrypt-1.10.3.orig/configure.ac
+++ libgcrypt-1.10.3/configure.ac
@@ -1495,6 +1495,20 @@ if test "$gcry_cv_gcc_attribute_sysv_abi
    fi
 fi
 
+#
+# Check whether compiler support '__thread' storage class specifier.
+#
+AC_CACHE_CHECK([whether compiler supports '__thread' storage class specifier],
+       [gcry_cv_gcc_storage_class__thread],
+       [gcry_cv_gcc_storage_class__thread=no
+        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <stdlib.h>],
+          [static  __thread  int bar;]
+          )],
+          [gcry_cv_gcc_storage_class__thread=yes])])
+if test "$gcry_cv_gcc_storage_class__thread" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_STORAGE_CLASS__THREAD,1,
+     [Defined if compiler supports "__thread" storage class specifier])
+fi
 
 # Restore flags.
 CFLAGS=$_gcc_cflags_save;
Index: libgcrypt-1.10.3/src/fips.c
===================================================================
--- libgcrypt-1.10.3.orig/src/fips.c
+++ libgcrypt-1.10.3/src/fips.c
@@ -67,10 +67,29 @@ GPGRT_LOCK_DEFINE (fsm_lock);
    used while in fips mode. Change this only while holding fsm_lock. */
 static enum module_states current_state;
 
+struct gcry_thread_context {
+  unsigned long fips_service_indicator;
+};
+
+#ifdef HAVE_GCC_STORAGE_CLASS__THREAD
+static __thread struct gcry_thread_context the_tc;
+#else
+#error libgcrypt requires thread-local storage to support FIPS mode
+#endif
+
+void
+_gcry_thread_context_set_fsi (unsigned long fsi)
+{
+  the_tc.fips_service_indicator = fsi;
+}
+
+unsigned long
+_gcry_thread_context_get_fsi (void)
+{
+  return the_tc.fips_service_indicator;
+}
 
 
-
-
 static void fips_new_state (enum module_states new_state);
 
 
Index: libgcrypt-1.10.3/src/gcrypt-int.h
===================================================================
--- libgcrypt-1.10.3.orig/src/gcrypt-int.h
+++ libgcrypt-1.10.3/src/gcrypt-int.h
@@ -265,6 +265,18 @@ void _gcry_set_log_handler (gcry_handler
 void _gcry_set_gettext_handler (const char *(*f)(const char*));
 void _gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data);
 
+void _gcry_thread_context_set_fsi (unsigned long fsi);
+unsigned long _gcry_thread_context_get_fsi (void);
+#define fips_service_indicator_init() do \
+  {                                      \
+    if (fips_mode ())                    \
+      _gcry_thread_context_set_fsi (1);  \
+  } while (0)
+#define fips_service_indicator_mark_success(is_compliant) do \
+  {                                                          \
+    if (is_compliant && fips_mode ())                        \
+      _gcry_thread_context_set_fsi (0);                      \
+  } while (0)
 
 /* Return a pointer to a string containing a description of the error
    code in the error value ERR.  */
Index: libgcrypt-1.10.3/tests/Makefile.am
===================================================================
--- libgcrypt-1.10.3.orig/tests/Makefile.am
+++ libgcrypt-1.10.3/tests/Makefile.am
@@ -25,7 +25,7 @@ tests_bin = \
         version t-secmem mpitests t-sexp t-convert \
 	t-mpi-bit t-mpi-point t-lock \
 	prime basic keygen pubkey hmac hashtest t-kdf keygrip \
-	aeswrap random
+	aeswrap random t-thread-local
 
 if USE_RSA
 tests_bin += pkcs1v2 t-rsa-pss t-rsa-15 t-rsa-testparm
Index: libgcrypt-1.10.3/tests/t-thread-local.c
===================================================================
--- /dev/null
+++ libgcrypt-1.10.3/tests/t-thread-local.c
@@ -0,0 +1,196 @@
+/* t-mlkem.c - Check the thread local storage
+ * Copyright (C) 2024 g10 Code GmbH
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt 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.
+ *
+ * Libgcrypt 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 program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+/* For now, this program simply test __thread storage class specifier.
+ * After we implement thread local context for libgcrypt, we will
+ * modity to test the feature.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#if HAVE_PTHREAD
+# include <pthread.h>
+#endif
+
+#define PGM "t-thread-local"
+
+#include "t-common.h"
+#include "../src/gcrypt-testapi.h"
+
+/* Mingw requires us to include windows.h after winsock2.h which is
+   included by gcrypt.h.  */
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+#ifdef _WIN32
+# define THREAD_RET_TYPE  DWORD WINAPI
+# define THREAD_RET_VALUE 0
+#else
+# define THREAD_RET_TYPE  void *
+# define THREAD_RET_VALUE NULL
+#endif
+
+#define N_TESTS 1
+
+#define N_THREADS 19
+
+static __thread unsigned long t;
+
+struct thread_arg_s
+{
+  int no;
+};
+
+#if defined(HAVE_PTHREAD) || defined(_WIN32)
+/* Checking the local storage thread.  */
+static THREAD_RET_TYPE
+check_ls_thread (void *argarg)
+{
+  struct thread_arg_s *arg = argarg;
+
+  t = arg->no;
+  info ("a thread update the local storage: %lu", t);
+
+  gcry_free (arg);
+  return THREAD_RET_VALUE;
+}
+#endif
+
+static void
+check_thread_local (void)
+{
+  struct thread_arg_s *arg;
+
+#ifdef _WIN32
+  HANDLE threads[N_THREADS];
+  int i;
+  int rc;
+
+  t = N_THREADS;
+  for (i=0; i < N_THREADS; i++)
+    {
+      arg = gcry_xmalloc (sizeof *arg);
+      arg->no = i;
+      threads[i] = CreateThread (NULL, 0, check_ls_thread, arg, 0, NULL);
+      if (!threads[i])
+        die ("error creating a thread %d: rc=%d",
+             i, (int)GetLastError ());
+    }
+
+  for (i=0; i < N_THREADS; i++)
+    {
+      rc = WaitForSingleObject (threads[i], INFINITE);
+      if (rc == WAIT_OBJECT_0)
+        info ("a thread %d has terminated", i);
+      else
+        fail ("waiting for a thread %d failed: %d",
+              i, (int)GetLastError ());
+      CloseHandle (threads[i]);
+    }
+
+#elif HAVE_PTHREAD
+  pthread_t threads[N_THREADS];
+  int rc, i;
+
+  t = N_THREADS;
+  for (i=0; i < N_THREADS; i++)
+    {
+      arg = gcry_xmalloc (sizeof *arg);
+      arg->no = i;
+      pthread_create (&threads[i], NULL, check_ls_thread, arg);
+    }
+
+  for (i=0; i < N_THREADS; i++)
+    {
+      rc = pthread_join (threads[i], NULL);
+      if (rc)
+        fail ("pthread_join failed for a thread %d: %s",
+              i, strerror (errno));
+      else
+        info ("a thread %d has terminated", i);
+    }
+#else
+  (void)arg;
+#endif /*!_WIN32*/
+  if (t != N_THREADS)
+    fail ("failed t=%lu\n", t);
+  else
+    info ("success");
+}
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc)
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [options]\n"
+                 "Options:\n"
+                 "  --verbose       print timings etc.\n"
+                 "  --debug         flyswatter\n",
+                 stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strncmp (*argv, "--", 2))
+        die ("unknown option '%s'", *argv);
+    }
+
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  if (!gcry_check_version (GCRYPT_VERSION))
+    die ("version mismatch\n");
+  if (debug)
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  check_thread_local ();
+
+  return !!error_count;
+}
openSUSE Build Service is sponsored by