SHA256
8
0
forked from pool/libgcrypt
Files
libgcrypt/libgcrypt-fips-Introduce-GCRYCTL_FIPS_REJECT_NON_FIPS.patch
Pedro Monreal Gonzalez b5b243be7f - Security fix [bsc#1221107, CVE-2024-2236]
* Add --enable-marvin-workaround to spec to enable workaround
  * Fix  timing based side-channel in RSA implementation ( Marvin attack ) 
  * Add libgcrypt-CVE-2024-2236.patch

OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=193
2025-06-10 07:06:49 +00:00

262 lines
9.2 KiB
Diff
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From e52adf0948c60b2e9accd7996fcece0f9b443763 Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Thu, 19 Dec 2024 11:30:28 +0900
Subject: [PATCH 12/19] fips: Introduce GCRYCTL_FIPS_REJECT_NON_FIPS.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* src/gcrypt.h.in (GCRYCTL_FIPS_REJECT_NON_FIPS): New.
(GCRY_FIPS_FLAG_REJECT_*): New.
* src/fips.c (struct gcry_thread_context): Add flags_reject_non_fips.
(the_tc): Add initial value.
(_gcry_thread_context_set_reject): New.
(_gcry_thread_context_check_rejection): New.
* src/gcrypt-int.h (fips_check_rejection): New.
* src/global.c (_gcry_vcontrol): Handle GCRYCTL_FIPS_REJECT_NON_FIPS.
* tests/t-fips-service-ind.c (main): Use GCRYCTL_FIPS_REJECT_NON_FIPS.
--
GnuPG-bug-id: 7338
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: Lucas Mülling <lucas.mulling@suse.com>
---
cipher/ecc-curves.c | 7 ++++++-
cipher/pubkey.c | 34 ++++++++++++++++++++++++++--------
src/fips.c | 17 ++++++++++++++++-
src/gcrypt-int.h | 9 ++++++++-
src/gcrypt.h.in | 28 ++++++++++++++++++++++++++--
src/global.c | 7 +++++++
tests/t-fips-service-ind.c | 2 ++
7 files changed, 91 insertions(+), 13 deletions(-)
Index: libgcrypt-1.11.0/cipher/ecc-curves.c
===================================================================
--- libgcrypt-1.11.0.orig/cipher/ecc-curves.c
+++ libgcrypt-1.11.0/cipher/ecc-curves.c
@@ -645,7 +645,12 @@ _gcry_ecc_fill_in_curve (unsigned int nb
possible to bypass this check by specifying the curve parameters
directly. */
if (fips_mode () && !domain_parms[idx].fips )
- fips_service_indicator_mark_non_compliant ();
+ {
+ if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK))
+ return GPG_ERR_NOT_SUPPORTED;
+ else
+ fips_service_indicator_mark_non_compliant ();
+ }
switch (domain_parms[idx].model)
{
Index: libgcrypt-1.11.0/cipher/pubkey.c
===================================================================
--- libgcrypt-1.11.0.orig/cipher/pubkey.c
+++ libgcrypt-1.11.0/cipher/pubkey.c
@@ -510,7 +510,12 @@ prepare_datasexp_to_be_signed (const cha
algo = _gcry_md_get_algo (hd);
if (fips_mode () && algo == GCRY_MD_SHA1)
- fips_service_indicator_mark_non_compliant ();
+ {
+ if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK))
+ return GPG_ERR_DIGEST_ALGO;
+ else
+ fips_service_indicator_mark_non_compliant ();
+ }
digest_name = _gcry_md_algo_name (algo);
digest_size = (int)_gcry_md_get_algo_dlen (algo);
@@ -538,7 +543,12 @@ prepare_datasexp_to_be_signed (const cha
return GPG_ERR_DIGEST_ALGO;
}
else if (fips_mode () && algo == GCRY_MD_SHA1)
- fips_service_indicator_mark_non_compliant ();
+ {
+ if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK))
+ return GPG_ERR_DIGEST_ALGO;
+ else
+ fips_service_indicator_mark_non_compliant ();
+ }
digest_size = (int)_gcry_md_get_algo_dlen (algo);
digest = _gcry_md_read (hd, algo);
@@ -611,11 +621,15 @@ _gcry_pk_sign_md (gcry_sexp_t *r_sig, co
if (rc)
goto leave;
- if (!spec->flags.fips && fips_mode ())
- fips_service_indicator_mark_non_compliant ();
-
if (spec->flags.disabled)
rc = GPG_ERR_PUBKEY_ALGO;
+ else if (!spec->flags.fips && fips_mode ())
+ {
+ if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK))
+ return GPG_ERR_PUBKEY_ALGO;
+ else
+ fips_service_indicator_mark_non_compliant ();
+ }
else if (spec->sign)
rc = spec->sign (r_sig, s_data, keyparms);
else
@@ -689,11 +703,15 @@ _gcry_pk_verify_md (gcry_sexp_t s_sig, c
if (rc)
goto leave;
- if (!spec->flags.fips && fips_mode ())
- fips_service_indicator_mark_non_compliant ();
-
if (spec->flags.disabled)
rc = GPG_ERR_PUBKEY_ALGO;
+ else if (!spec->flags.fips && fips_mode ())
+ {
+ if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK))
+ return GPG_ERR_PUBKEY_ALGO;
+ else
+ fips_service_indicator_mark_non_compliant ();
+ }
else if (spec->verify)
rc = spec->verify (s_sig, s_data, keyparms);
else
Index: libgcrypt-1.11.0/src/fips.c
===================================================================
--- libgcrypt-1.11.0.orig/src/fips.c
+++ libgcrypt-1.11.0/src/fips.c
@@ -70,15 +70,30 @@ static enum module_states current_state;
struct gcry_thread_context {
unsigned long fips_service_indicator;
+ unsigned int flags_reject_non_fips;
};
#ifdef HAVE_GCC_STORAGE_CLASS__THREAD
-static __thread struct gcry_thread_context the_tc;
+static __thread struct gcry_thread_context the_tc = {
+ 0, GCRY_FIPS_FLAG_REJECT_DEFAULT
+};
#else
#error libgcrypt requires thread-local storage to support FIPS mode
#endif
void
+_gcry_thread_context_set_reject (unsigned int flags)
+{
+ the_tc.flags_reject_non_fips = flags;
+}
+
+int
+_gcry_thread_context_check_rejection (unsigned int flag)
+{
+ return !!(the_tc.flags_reject_non_fips & flag);
+}
+
+void
_gcry_thread_context_set_fsi (unsigned long fsi)
{
the_tc.fips_service_indicator = fsi;
Index: libgcrypt-1.11.0/src/gcrypt-int.h
===================================================================
--- libgcrypt-1.11.0.orig/src/gcrypt-int.h
+++ libgcrypt-1.11.0/src/gcrypt-int.h
@@ -297,6 +297,12 @@ 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_reject (unsigned int flags);
+int _gcry_thread_context_check_rejection (unsigned int flag);
+
+#define fips_check_rejection(flag) \
+ _gcry_thread_context_check_rejection (flag)
+
void _gcry_thread_context_set_fsi (unsigned long fsi);
unsigned long _gcry_thread_context_get_fsi (void);
#define fips_service_indicator_init() do \
@@ -305,7 +311,8 @@ unsigned long _gcry_thread_context_get_f
_gcry_thread_context_set_fsi (0); \
} while (0)
/* Should be used only when fips_mode()==TRUE. */
-#define fips_service_indicator_mark_non_compliant() _gcry_thread_context_set_fsi (1)
+#define fips_service_indicator_mark_non_compliant() \
+ _gcry_thread_context_set_fsi (1)
/* Return a pointer to a string containing a description of the error
code in the error value ERR. */
Index: libgcrypt-1.11.0/src/gcrypt.h.in
===================================================================
--- libgcrypt-1.11.0.orig/src/gcrypt.h.in
+++ libgcrypt-1.11.0/src/gcrypt.h.in
@@ -338,7 +338,8 @@ enum gcry_ctl_cmds
GCRYCTL_MD_CUSTOMIZE = 88,
GCRYCTL_FIPS_SERVICE_INDICATOR_PK = 89,
GCRYCTL_FIPS_SERVICE_INDICATOR_HASH = 90,
- GCRYCTL_FIPS_SERVICE_INDICATOR = 91
+ GCRYCTL_FIPS_SERVICE_INDICATOR = 91,
+ GCRYCTL_FIPS_REJECT_NON_FIPS = 92
};
/* Perform various operations defined by CMD. */
@@ -1971,7 +1972,30 @@ void gcry_log_debugsxp (const char *text
char *gcry_get_config (int mode, const char *what);
/* Convinience macro to access the FIPS service indicator. */
-#define gcry_get_fips_service_indicator() gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR)
+#define gcry_get_fips_service_indicator() \
+ gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR)
+
+#define GCRY_FIPS_FLAG_REJECT_KDF (1 << 0)
+#define GCRY_FIPS_FLAG_REJECT_MD_MD5 (1 << 1)
+#define GCRY_FIPS_FLAG_REJECT_MD_OTHERS (1 << 2)
+#define GCRY_FIPS_FLAG_REJECT_MAC (1 << 3)
+#define GCRY_FIPS_FLAG_REJECT_CIPHER (1 << 4)
+#define GCRY_FIPS_FLAG_REJECT_PK (1 << 5)
+
+#define GCRY_FIPS_FLAG_REJECT_MD \
+ (GCRY_FIPS_FLAG_REJECT_MD_MD5 | GCRY_FIPS_FLAG_REJECT_MD_OTHERS)
+
+/* Note: Don't reject MD5 */
+#define GCRY_FIPS_FLAG_REJECT_COMPAT110 \
+ (GCRY_FIPS_FLAG_REJECT_MD_OTHERS \
+ | GCRY_FIPS_FLAG_REJECT_MAC \
+ | GCRY_FIPS_FLAG_REJECT_CIPHER \
+ | GCRY_FIPS_FLAG_REJECT_KDF \
+ | GCRY_FIPS_FLAG_REJECT_PK)
+
+#define GCRY_FIPS_FLAG_REJECT_DEFAULT \
+ GCRY_FIPS_FLAG_REJECT_COMPAT110
+
/* Log levels used by the internal logging facility. */
enum gcry_log_levels
Index: libgcrypt-1.11.0/src/global.c
===================================================================
--- libgcrypt-1.11.0.orig/src/global.c
+++ libgcrypt-1.11.0/src/global.c
@@ -791,6 +791,13 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd,
rc = _gcry_fips_indicator ();
break;
+ case GCRYCTL_FIPS_REJECT_NON_FIPS:
+ {
+ unsigned int flags = va_arg (arg_ptr, unsigned int);
+ _gcry_thread_context_set_reject (flags);
+ }
+ break;
+
case GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER:
/* Get FIPS Service Indicator for a given symmetric algorithm and
* optional mode. Returns GPG_ERR_NO_ERROR if algorithm is allowed or
Index: libgcrypt-1.11.0/tests/t-fips-service-ind.c
===================================================================
--- libgcrypt-1.11.0.orig/tests/t-fips-service-ind.c
+++ libgcrypt-1.11.0/tests/t-fips-service-ind.c
@@ -1007,6 +1007,8 @@ main (int argc, char **argv)
if (debug)
xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+ xgcry_control ((GCRYCTL_FIPS_REJECT_NON_FIPS, 0));
+
check_digests ();
check_kdf_derive ();
check_md_o_w_r_c ();