SHA256
8
0
forked from pool/libgcrypt
Files
libgcrypt/libgcrypt-fips-Rejection-by-GCRYCTL_FIPS_REJECT_NON_FIPS-not-by-open-flags.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

499 lines
17 KiB
Diff

From d060dd58b82882dec0d8bfcc593536bc0083b4b1 Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Fri, 20 Dec 2024 09:38:13 +0900
Subject: [PATCH 14/19] fips: Rejection by GCRYCTL_FIPS_REJECT_NON_FIPS, not by
open flags.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* src/gcrypt.h.in (GCRY_CIPHER_FLAG_REJECT_NON_FIPS): Remove.
(GCRY_MD_FLAG_REJECT_NON_FIPS): Remove.
(GCRY_MAC_FLAG_REJECT_NON_FIPS): Remove.
* tests/t-fips-service-ind.c: Update tests with
GCRYCTL_FIPS_REJECT_NON_FIPS.
* cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey): Use
fips_check_rejection.
* cipher/mac.c (mac_open): Likewise.
* cipher/md.c (struct gcry_md_context): Remove reject_non_fips.
(md_open, md_enable): Use fips_check_rejection.
(_gcry_md_enable, md_copy): Likewise.
--
GnuPG-bug-id: 7338
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: Lucas Mülling <lucas.mulling@suse.com>
---
cipher/cipher.c | 8 ++--
cipher/mac.c | 5 +--
cipher/md.c | 81 ++++++++++++++++++++++++++++++--------
src/gcrypt.h.in | 7 +---
tests/t-fips-service-ind.c | 59 +++++++++++----------------
5 files changed, 94 insertions(+), 66 deletions(-)
Index: libgcrypt-1.11.0/cipher/cipher.c
===================================================================
--- libgcrypt-1.11.0.orig/cipher/cipher.c
+++ libgcrypt-1.11.0/cipher/cipher.c
@@ -510,7 +510,6 @@ _gcry_cipher_open_internal (gcry_cipher_
int algo, int mode, unsigned int flags)
{
int secure = !!(flags & GCRY_CIPHER_SECURE);
- int reject_non_fips = !!(flags & GCRY_CIPHER_FLAG_REJECT_NON_FIPS);
gcry_cipher_spec_t *spec;
gcry_cipher_hd_t h = NULL;
gcry_err_code_t err;
@@ -526,7 +525,7 @@ _gcry_cipher_open_internal (gcry_cipher_
err = GPG_ERR_CIPHER_ALGO;
else if (!spec->flags.fips && fips_mode ())
{
- if (reject_non_fips)
+ if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_CIPHER))
err = GPG_ERR_CIPHER_ALGO;
else
{
@@ -544,8 +543,7 @@ _gcry_cipher_open_internal (gcry_cipher_
| GCRY_CIPHER_ENABLE_SYNC
| GCRY_CIPHER_CBC_CTS
| GCRY_CIPHER_CBC_MAC
- | GCRY_CIPHER_EXTENDED
- | GCRY_CIPHER_FLAG_REJECT_NON_FIPS))
+ | GCRY_CIPHER_EXTENDED))
|| ((flags & GCRY_CIPHER_CBC_CTS) && (flags & GCRY_CIPHER_CBC_MAC))))
err = GPG_ERR_CIPHER_ALGO;
@@ -776,7 +774,7 @@ cipher_setkey (gcry_cipher_hd_t c, byte
Key Generation Requirements" for details. */
if (buf_eq_const (key, key + keylen, keylen))
{
- if ((c->flags & GCRY_CIPHER_FLAG_REJECT_NON_FIPS))
+ if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_CIPHER))
return GPG_ERR_WEAK_KEY;
else
fips_service_indicator_mark_non_compliant ();
Index: libgcrypt-1.11.0/cipher/mac.c
===================================================================
--- libgcrypt-1.11.0.orig/cipher/mac.c
+++ libgcrypt-1.11.0/cipher/mac.c
@@ -519,7 +519,6 @@ mac_open (gcry_mac_hd_t * hd, int algo,
gcry_err_code_t err;
gcry_mac_hd_t h;
int secure = !!(flags & GCRY_MAC_FLAG_SECURE);
- int reject_non_fips = !!(flags & GCRY_MAC_FLAG_REJECT_NON_FIPS);
spec = spec_from_algo (algo);
if (!spec)
@@ -528,7 +527,7 @@ mac_open (gcry_mac_hd_t * hd, int algo,
return GPG_ERR_MAC_ALGO;
else if (!spec->flags.fips && fips_mode ())
{
- if (reject_non_fips)
+ if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MAC))
return GPG_ERR_MAC_ALGO;
else
fips_service_indicator_mark_non_compliant ();
@@ -650,7 +649,7 @@ _gcry_mac_open (gcry_mac_hd_t * h, int a
gcry_err_code_t rc;
gcry_mac_hd_t hd = NULL;
- if ((flags & ~(GCRY_MAC_FLAG_SECURE | GCRY_MAC_FLAG_REJECT_NON_FIPS)))
+ if ((flags & ~GCRY_MAC_FLAG_SECURE))
rc = GPG_ERR_INV_ARG;
else
rc = mac_open (&hd, algo, flags, ctx);
Index: libgcrypt-1.11.0/cipher/md.c
===================================================================
--- libgcrypt-1.11.0.orig/cipher/md.c
+++ libgcrypt-1.11.0/cipher/md.c
@@ -275,7 +275,6 @@ struct gcry_md_context
unsigned int finalized:1;
unsigned int bugemu1:1;
unsigned int hmac:1;
- unsigned int reject_non_fips:1;
} flags;
size_t actual_handle_size; /* Allocated size of this handle. */
FILE *debug;
@@ -509,7 +508,6 @@ md_open (gcry_md_hd_t *h, int algo, unsi
ctx->flags.secure = secure;
ctx->flags.hmac = hmac;
ctx->flags.bugemu1 = !!(flags & GCRY_MD_FLAG_BUGEMU1);
- ctx->flags.reject_non_fips = !!(flags & GCRY_MD_FLAG_REJECT_NON_FIPS);
}
if (! err)
@@ -544,14 +542,11 @@ _gcry_md_open (gcry_md_hd_t *h, int algo
if ((flags & ~(GCRY_MD_FLAG_SECURE
| GCRY_MD_FLAG_HMAC
- | GCRY_MD_FLAG_REJECT_NON_FIPS
| GCRY_MD_FLAG_BUGEMU1)))
rc = GPG_ERR_INV_ARG;
else
rc = md_open (&hd, algo, flags);
- *h = rc? NULL : hd;
-
if (!rc && fips_mode ())
{
GcryDigestEntry *entry = hd->ctx->list;
@@ -566,9 +561,26 @@ _gcry_md_open (gcry_md_hd_t *h, int algo
}
if (!is_compliant_algo)
- fips_service_indicator_mark_non_compliant ();
+ {
+ int reject = 0;
+
+ if (algo == GCRY_MD_MD5)
+ reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_MD5);
+ else
+ reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_OTHERS);
+
+ if (reject)
+ {
+ md_close (hd);
+ hd = NULL;
+ rc = GPG_ERR_DIGEST_ALGO;
+ }
+ else
+ fips_service_indicator_mark_non_compliant ();
+ }
}
+ *h = rc? NULL : hd;
return rc;
}
@@ -581,12 +593,17 @@ md_enable (gcry_md_hd_t hd, int algorith
const gcry_md_spec_t *spec;
GcryDigestEntry *entry;
gcry_err_code_t err = 0;
- int reject_non_fips = h->flags.reject_non_fips;
+ int reject;
for (entry = h->list; entry; entry = entry->next)
if (entry->spec->algo == algorithm)
return 0; /* Already enabled */
+ if (algorithm == GCRY_MD_MD5)
+ reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_MD5);
+ else
+ reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_OTHERS);
+
spec = spec_from_algo (algorithm);
if (!spec)
{
@@ -598,7 +615,7 @@ md_enable (gcry_md_hd_t hd, int algorith
err = GPG_ERR_DIGEST_ALGO;
/* Any non-FIPS algorithm should go this way */
- if (!err && reject_non_fips && !spec->flags.fips && fips_mode ())
+ if (!err && reject && !spec->flags.fips && fips_mode ())
err = GPG_ERR_DIGEST_ALGO;
if (!err && h->flags.hmac && spec->read == NULL)
@@ -657,7 +674,19 @@ _gcry_md_enable (gcry_md_hd_t hd, int al
}
if (!is_compliant_algo)
- fips_service_indicator_mark_non_compliant ();
+ {
+ int reject = 0;
+
+ if (algorithm == GCRY_MD_MD5)
+ reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_MD5);
+ else
+ reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_OTHERS);
+
+ if (reject)
+ rc = GPG_ERR_DIGEST_ALGO;
+ else
+ fips_service_indicator_mark_non_compliant ();
+ }
}
return rc;
@@ -667,13 +696,14 @@ _gcry_md_enable (gcry_md_hd_t hd, int al
static gcry_err_code_t
md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
{
- gcry_err_code_t err = 0;
+ gcry_err_code_t rc = 0;
struct gcry_md_context *a = ahd->ctx;
struct gcry_md_context *b;
GcryDigestEntry *ar, *br;
gcry_md_hd_t bhd;
size_t n;
int is_compliant_algo = 1;
+ int reject = 0;
if (ahd->bufpos)
md_write (ahd, NULL, 0);
@@ -686,7 +716,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t
if (!bhd)
{
- err = gpg_err_code_from_syserror ();
+ rc = gpg_err_code_from_syserror ();
goto leave;
}
@@ -715,12 +745,20 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t
br = xtrymalloc (ar->actual_struct_size);
if (!br)
{
- err = gpg_err_code_from_syserror ();
+ rc = gpg_err_code_from_syserror ();
md_close (bhd);
goto leave;
}
- is_compliant_algo &= spec->flags.fips;
+ if (!spec->flags.fips)
+ {
+ is_compliant_algo = 0;
+
+ if (spec->algo == GCRY_MD_MD5)
+ reject |= fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_MD5);
+ else
+ reject |= fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_OTHERS);
+ }
memcpy (br, ar, ar->actual_struct_size);
br->next = b->list;
@@ -730,13 +768,22 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t
if (a->debug)
md_start_debug (bhd, "unknown");
- *b_hd = bhd;
+ if (!is_compliant_algo && fips_mode ())
+ {
+ if (reject)
+ {
+ rc = GPG_ERR_DIGEST_ALGO;
+ md_close (bhd);
+ }
+ else
+ fips_service_indicator_mark_non_compliant ();
+ }
- if (!is_compliant_algo)
- fips_service_indicator_mark_non_compliant ();
+ if (!rc)
+ *b_hd = bhd;
leave:
- return err;
+ return rc;
}
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
@@ -995,8 +995,7 @@ enum gcry_cipher_flags
GCRY_CIPHER_ENABLE_SYNC = 2, /* Enable CFB sync mode. */
GCRY_CIPHER_CBC_CTS = 4, /* Enable CBC cipher text stealing (CTS). */
GCRY_CIPHER_CBC_MAC = 8, /* Enable CBC message auth. code (MAC). */
- GCRY_CIPHER_EXTENDED = 16, /* Enable extended AES-WRAP. */
- GCRY_CIPHER_FLAG_REJECT_NON_FIPS = 32 /* Reject non-FIPS-compliant algo. */
+ GCRY_CIPHER_EXTENDED = 16 /* Enable extended AES-WRAP. */
};
/* Methods used for AEAD IV generation. */
@@ -1322,7 +1321,6 @@ enum gcry_md_flags
{
GCRY_MD_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */
GCRY_MD_FLAG_HMAC = 2, /* Make an HMAC out of this algorithm. */
- GCRY_MD_FLAG_REJECT_NON_FIPS = 4, /* Reject non-FIPS-compliant algo. */
GCRY_MD_FLAG_BUGEMU1 = 0x0100
};
@@ -1564,8 +1562,7 @@ enum gcry_mac_algos
/* Flags used with the open function. */
enum gcry_mac_flags
{
- GCRY_MAC_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */
- GCRY_MAC_FLAG_REJECT_NON_FIPS = 2 /* Reject non-FIPS-compliant algo. */
+ GCRY_MAC_FLAG_SECURE = 1 /* Allocate all buffers in "secure" memory. */
};
/* Create a MAC handle for algorithm ALGO. FLAGS may be given as an bitwise 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
@@ -250,7 +250,7 @@ check_pk_hash_sign_verify (void)
/* Check gcry_cipher_open, gcry_cipher_setkey, gcry_cipher_encrypt,
gcry_cipher_decrypt, gcry_cipher_close API. */
static void
-check_cipher_o_s_e_d_c (void)
+check_cipher_o_s_e_d_c (int reject)
{
static struct {
int algo;
@@ -258,18 +258,12 @@ check_cipher_o_s_e_d_c (void)
int keylen;
const char *expect;
int expect_failure;
- unsigned int flags;
} tv[] = {
#if USE_DES
{ GCRY_CIPHER_3DES,
"\xe3\x34\x7a\x6b\x0b\xc1\x15\x2c\x64\x2a\x25\xcb\xd3\xbc\x31\xab"
"\xfb\xa1\x62\xa8\x1f\x19\x7c\x15", 24,
"\x3f\x1a\xb8\x83\x18\x8b\xb5\x97", 1 },
- { GCRY_CIPHER_3DES,
- "\xe3\x34\x7a\x6b\x0b\xc1\x15\x2c\x64\x2a\x25\xcb\xd3\xbc\x31\xab"
- "\xfb\xa1\x62\xa8\x1f\x19\x7c\x15", 24,
- "\x3f\x1a\xb8\x83\x18\x8b\xb5\x97",
- 1, GCRY_CIPHER_FLAG_REJECT_NON_FIPS },
#endif
{ GCRY_CIPHER_AES,
"\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
@@ -297,12 +291,10 @@ check_cipher_o_s_e_d_c (void)
assert (blklen != 0);
assert (blklen <= ptlen);
assert (blklen <= DIM (out));
- err = gcry_cipher_open (&h, tv[tvidx].algo, GCRY_CIPHER_MODE_ECB,
- tv[tvidx].flags);
+ err = gcry_cipher_open (&h, tv[tvidx].algo, GCRY_CIPHER_MODE_ECB, 0);
if (err)
{
- if (in_fips_mode && (tv[tvidx].flags & GCRY_CIPHER_FLAG_REJECT_NON_FIPS)
- && tv[tvidx].expect_failure)
+ if (in_fips_mode && reject && tv[tvidx].expect_failure)
/* Here, an error is expected */
;
else
@@ -312,8 +304,7 @@ check_cipher_o_s_e_d_c (void)
}
else
{
- if (in_fips_mode && (tv[tvidx].flags & GCRY_CIPHER_FLAG_REJECT_NON_FIPS)
- && tv[tvidx].expect_failure)
+ if (in_fips_mode && reject && tv[tvidx].expect_failure)
/* This case, an error is expected, but we observed success */
fail ("gcry_cipher_open test %d unexpectedly succeeded\n", tvidx);
}
@@ -398,7 +389,7 @@ check_cipher_o_s_e_d_c (void)
/* Check gcry_mac_open, gcry_mac_write, gcry_mac_write, gcry_mac_read,
gcry_mac_close API. */
static void
-check_mac_o_w_r_c (void)
+check_mac_o_w_r_c (int reject)
{
static struct {
int algo;
@@ -408,14 +399,10 @@ check_mac_o_w_r_c (void)
int keylen;
const char *expect;
int expect_failure;
- unsigned int flags;
} tv[] = {
#if USE_MD5
{ GCRY_MAC_HMAC_MD5, "hmac input abc", 14, "hmac key input", 14,
"\x0d\x72\xd0\x60\xaf\x34\xf2\xca\x33\x58\xa9\xcc\xd3\x5a\xac\xb5", 1 },
- { GCRY_MAC_HMAC_MD5, "hmac input abc", 14, "hmac key input", 14,
- "\x0d\x72\xd0\x60\xaf\x34\xf2\xca\x33\x58\xa9\xcc\xd3\x5a\xac\xb5", 1,
- GCRY_MAC_FLAG_REJECT_NON_FIPS },
#endif
#if USE_SHA1
{ GCRY_MAC_HMAC_SHA1, "hmac input abc", 14, "hmac key input", 14,
@@ -471,11 +458,10 @@ check_mac_o_w_r_c (void)
expectlen = gcry_mac_get_algo_maclen (tv[tvidx].algo);
assert (expectlen != 0);
assert (expectlen <= DIM (mac));
- err = gcry_mac_open (&h, tv[tvidx].algo, tv[tvidx].flags, NULL);
+ err = gcry_mac_open (&h, tv[tvidx].algo, 0, NULL);
if (err)
{
- if (in_fips_mode && (tv[tvidx].flags & GCRY_MAC_FLAG_REJECT_NON_FIPS)
- && tv[tvidx].expect_failure)
+ if (in_fips_mode && reject && tv[tvidx].expect_failure)
/* Here, an error is expected */
;
else
@@ -485,8 +471,7 @@ check_mac_o_w_r_c (void)
}
else
{
- if (in_fips_mode && (tv[tvidx].flags & GCRY_MAC_FLAG_REJECT_NON_FIPS)
- && tv[tvidx].expect_failure)
+ if (in_fips_mode && reject && tv[tvidx].expect_failure)
/* This case, an error is expected, but we observed success */
fail ("gcry_mac_open test %d unexpectedly succeeded\n", tvidx);
}
@@ -563,7 +548,7 @@ check_mac_o_w_r_c (void)
/* Check gcry_md_open, gcry_md_write, gcry_md_write, gcry_md_read,
gcry_md_close API. */
static void
-check_md_o_w_r_c (void)
+check_md_o_w_r_c (int reject)
{
static struct {
int algo;
@@ -571,14 +556,10 @@ check_md_o_w_r_c (void)
int datalen;
const char *expect;
int expect_failure;
- unsigned int flags;
} tv[] = {
#if USE_MD5
{ GCRY_MD_MD5, "abc", 3,
"\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72", 1 },
- { GCRY_MD_MD5, "abc", 3,
- "\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72", 1,
- GCRY_MD_FLAG_REJECT_NON_FIPS },
#endif
#if USE_SHA1
{ GCRY_MD_SHA1, "abc", 3,
@@ -632,11 +613,10 @@ check_md_o_w_r_c (void)
expectlen = gcry_md_get_algo_dlen (tv[tvidx].algo);
assert (expectlen != 0);
- err = gcry_md_open (&h, tv[tvidx].algo, tv[tvidx].flags);
+ err = gcry_md_open (&h, tv[tvidx].algo, 0);
if (err)
{
- if (in_fips_mode && (tv[tvidx].flags & GCRY_MD_FLAG_REJECT_NON_FIPS)
- && tv[tvidx].expect_failure)
+ if (in_fips_mode && reject && tv[tvidx].expect_failure)
/* Here, an error is expected */
;
else
@@ -646,8 +626,7 @@ check_md_o_w_r_c (void)
}
else
{
- if (in_fips_mode && (tv[tvidx].flags & GCRY_MD_FLAG_REJECT_NON_FIPS)
- && tv[tvidx].expect_failure)
+ if (in_fips_mode && reject && tv[tvidx].expect_failure)
/* This case, an error is expected, but we observed success */
fail ("gcry_md_open test %d unexpectedly succeeded\n", tvidx);
}
@@ -1011,10 +990,18 @@ main (int argc, char **argv)
check_digests ();
check_kdf_derive ();
- check_md_o_w_r_c ();
- check_mac_o_w_r_c ();
- check_cipher_o_s_e_d_c ();
+ check_md_o_w_r_c (0);
+ check_mac_o_w_r_c (0);
+ check_cipher_o_s_e_d_c (0);
check_pk_hash_sign_verify ();
+ xgcry_control ((GCRYCTL_FIPS_REJECT_NON_FIPS,
+ (GCRY_FIPS_FLAG_REJECT_MD_MD5
+ | GCRY_FIPS_FLAG_REJECT_COMPAT110)));
+
+ check_md_o_w_r_c (1);
+ check_mac_o_w_r_c (1);
+ check_cipher_o_s_e_d_c (1);
+
return !!error_count;
}