File libgcrypt-FIPS-SLI-Implement-new-FIPS-service-indicator-for-gcry_md_open-API.patch of Package libgcrypt.38414
From 9757e280794f537efc82c4eaa9a2944ece6a068a Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Thu, 12 Dec 2024 11:40:31 +0900
Subject: [PATCH 12/24] fips,md: Implement new FIPS service indicator for
gcry_md_open API.
* src/gcrypt.h.in (GCRY_MD_FLAG_FIPS_NO_REJECTION): Remove.
(GCRY_MD_FLAG_REJECT_NON_FIPS): New.
* cipher/md.c (struct gcry_md_context): Add reject_non_fips.
(md_enable): Remove NO_REJECT argument.
(md_open): Change the FLAGS handling.
(_gcry_md_open): Add checking of FIPS compliance against ALGO.
(_gcry_md_enable): Likewise.
(_gcry_md_hash_buffer): Follow the change of md_open change
which now defaults to no rejection.
(_gcry_md_hash_buffers_extract): Likewise.
* src/visibility.c (gcry_md_open): Add fips_service_indicator_init.
(gcry_md_enable): Likewise.
(gcry_md_setkey): Don't reject but mark non-compliance.
* tests/t-kdf.c (check_fips_gcry_kdf_derive): Add a test with
non-compliant hash function.
* cipher/mac-hmac.c (_gcry_mac_type_spec_hmac_md5): It's not
compliant.
* cipher/md5.c (gcry_md_oid_spec_t oid_spec_md5): It's not compliant.
* tests/t-digest.c (check_hash_buffer, check_hash_buffers): MD5
tests enabled.
--
See 6376 for the MD5 compliance change in the past. This commit
reverts the change in:
dc4a60e2d70bc52ba2955f8e676341d675ab89a0
GnuPG-bug-id: 7338
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: Lucas Mulling <lucas.mulling@suse.com>
---
cipher/mac-hmac.c | 2 +-
cipher/md.c | 57 +++++++++++++++++++++++++++++++++++++++--------
cipher/md5.c | 2 +-
src/gcrypt.h.in | 2 +-
src/visibility.c | 6 +++--
tests/t-digest.c | 6 ++---
tests/t-kdf.c | 12 ++++++++++
7 files changed, 69 insertions(+), 18 deletions(-)
Index: libgcrypt-1.10.3/cipher/mac-hmac.c
===================================================================
--- libgcrypt-1.10.3.orig/cipher/mac-hmac.c
+++ libgcrypt-1.10.3/cipher/mac-hmac.c
@@ -1413,7 +1413,7 @@ const gcry_mac_spec_t _gcry_mac_type_spe
#endif
#if USE_MD5
const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5 = {
- GCRY_MAC_HMAC_MD5, {0, 1}, "HMAC_MD5",
+ GCRY_MAC_HMAC_MD5, {0, 0}, "HMAC_MD5",
&hmac_ops
};
#endif
Index: libgcrypt-1.10.3/cipher/md.c
===================================================================
--- libgcrypt-1.10.3.orig/cipher/md.c
+++ libgcrypt-1.10.3/cipher/md.c
@@ -266,6 +266,7 @@ 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;
@@ -276,7 +277,7 @@ struct gcry_md_context
#define CTX_MAGIC_NORMAL 0x11071961
#define CTX_MAGIC_SECURE 0x16917011
-static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo, int no_reject);
+static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo);
static void md_close (gcry_md_hd_t a);
static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen);
static byte *md_read( gcry_md_hd_t a, int algo );
@@ -499,6 +500,7 @@ 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)
@@ -508,8 +510,7 @@ md_open (gcry_md_hd_t *h, int algo, unsi
if (algo)
{
- err = md_enable (hd, algo,
- !!(flags & GCRY_MD_FLAG_FIPS_NO_REJECTION));
+ err = md_enable (hd, algo);
if (err)
md_close (hd);
}
@@ -534,24 +535,44 @@ _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;
+ /* No ENTRY means that ALGO==0.
+ It's not yet known, if it's FIPS compliant or not. */
+ int is_compliant_algo = 1;
+
+ if (entry)
+ {
+ const gcry_md_spec_t *spec = entry->spec;
+ is_compliant_algo = spec->flags.fips;
+ }
+
+ if (!is_compliant_algo)
+ fips_service_indicator_mark_non_compliant ();
+ }
+
return rc;
}
static gcry_err_code_t
-md_enable (gcry_md_hd_t hd, int algorithm, int no_reject)
+md_enable (gcry_md_hd_t hd, int algorithm)
{
struct gcry_md_context *h = hd->ctx;
const gcry_md_spec_t *spec;
GcryDigestEntry *entry;
gcry_err_code_t err = 0;
+ int reject_non_fips = h->flags.reject_non_fips;
for (entry = h->list; entry; entry = entry->next)
if (entry->spec->algo == algorithm)
@@ -568,7 +589,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 && !no_reject && !spec->flags.fips && fips_mode ())
+ if (!err && reject_non_fips && !spec->flags.fips && fips_mode ())
err = GPG_ERR_DIGEST_ALGO;
if (!err && h->flags.hmac && spec->read == NULL)
@@ -611,7 +632,26 @@ md_enable (gcry_md_hd_t hd, int algorith
gcry_err_code_t
_gcry_md_enable (gcry_md_hd_t hd, int algorithm)
{
- return md_enable (hd, algorithm, 0);
+ gcry_err_code_t rc;
+
+ rc = md_enable (hd, algorithm);
+ if (!rc && fips_mode ())
+ {
+ GcryDigestEntry *entry = hd->ctx->list;
+ /* No ENTRY means, something goes wrong. */
+ int is_compliant_algo = 0;
+
+ if (entry)
+ {
+ const gcry_md_spec_t *spec = entry->spec;
+ is_compliant_algo = spec->flags.fips;
+ }
+
+ if (!is_compliant_algo)
+ fips_service_indicator_mark_non_compliant ();
+ }
+
+ return rc;
}
@@ -1214,7 +1254,7 @@ _gcry_md_hash_buffer (int algo, void *di
gcry_md_hd_t h;
gpg_err_code_t err;
- err = md_open (&h, algo, GCRY_MD_FLAG_FIPS_NO_REJECTION);
+ err = md_open (&h, algo, 0);
if (err)
log_bug ("gcry_md_open failed for algo %d: %s",
algo, gpg_strerror (gcry_error(err)));
@@ -1292,8 +1332,7 @@ _gcry_md_hash_buffers_extract (int algo,
gcry_md_hd_t h;
gpg_err_code_t rc;
- rc = md_open (&h, algo, ((hmac? GCRY_MD_FLAG_HMAC:0)
- | GCRY_MD_FLAG_FIPS_NO_REJECTION));
+ rc = md_open (&h, algo, (hmac? GCRY_MD_FLAG_HMAC:0));
if (rc)
return rc;
Index: libgcrypt-1.10.3/cipher/md5.c
===================================================================
--- libgcrypt-1.10.3.orig/cipher/md5.c
+++ libgcrypt-1.10.3/cipher/md5.c
@@ -314,7 +314,7 @@ static const gcry_md_oid_spec_t oid_spec
const gcry_md_spec_t _gcry_digest_spec_md5 =
{
- GCRY_MD_MD5, {0, 1},
+ GCRY_MD_MD5, {0, 0},
"MD5", asn, DIM (asn), oid_spec_md5, 16,
md5_init, _gcry_md_block_write, md5_final, md5_read, NULL,
NULL,
Index: libgcrypt-1.10.3/src/gcrypt.h.in
===================================================================
--- libgcrypt-1.10.3.orig/src/gcrypt.h.in
+++ libgcrypt-1.10.3/src/gcrypt.h.in
@@ -1296,7 +1296,7 @@ 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_FIPS_NO_REJECTION = 4, /* Don't reject for FIPS. */
+ GCRY_MD_FLAG_REJECT_NON_FIPS = 4, /* Reject non-FIPS-compliant algo. */
GCRY_MD_FLAG_BUGEMU1 = 0x0100
};
Index: libgcrypt-1.10.3/src/visibility.c
===================================================================
--- libgcrypt-1.10.3.orig/src/visibility.c
+++ libgcrypt-1.10.3/src/visibility.c
@@ -1188,7 +1188,7 @@ gcry_md_open (gcry_md_hd_t *h, int algo,
*h = NULL;
return gpg_error (fips_not_operational ());
}
-
+ fips_service_indicator_init ();
return gpg_error (_gcry_md_open (h, algo, flags));
}
@@ -1203,6 +1203,7 @@ gcry_md_enable (gcry_md_hd_t hd, int alg
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
+ fips_service_indicator_init ();
return gpg_error (_gcry_md_enable (hd, algo));
}
@@ -1349,8 +1350,9 @@ gcry_md_setkey (gcry_md_hd_t hd, const v
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
+ fips_service_indicator_init ();
if (fips_mode () && keylen < 14)
- return GPG_ERR_INV_VALUE;
+ fips_service_indicator_mark_non_compliant ();
return gpg_error (_gcry_md_setkey (hd, key, keylen));
}
Index: libgcrypt-1.10.3/tests/t-digest.c
===================================================================
--- libgcrypt-1.10.3.orig/tests/t-digest.c
+++ libgcrypt-1.10.3/tests/t-digest.c
@@ -48,8 +48,7 @@ check_hash_buffer (void)
const char *expect;
int expect_failure;
} tv[] = {
-#undef ENABLE_THIS_AFTER_T6376_CHANGE_REVISED
-#if USE_MD5 && defined(ENABLE_THIS_AFTER_T6376_CHANGE_REVISED)
+#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 },
#endif
@@ -156,8 +155,7 @@ check_hash_buffers (void)
const char *expect;
int expect_failure;
} tv[] = {
-#undef ENABLE_THIS_AFTER_T6376_CHANGE_REVISED
-#if USE_MD5 && defined(ENABLE_THIS_AFTER_T6376_CHANGE_REVISED)
+#if USE_MD5
{ GCRY_MD_MD5, "abc", 3,
"key", 3,
"\xd2\xfe\x98\x06\x3f\x87\x6b\x03\x19\x3a\xfb\x49\xb4\x97\x95\x91", 1 },
Index: libgcrypt-1.10.3/tests/t-kdf.c
===================================================================
--- libgcrypt-1.10.3.orig/tests/t-kdf.c
+++ libgcrypt-1.10.3/tests/t-kdf.c
@@ -1637,6 +1637,18 @@ check_fips_gcry_kdf_derive (void)
"\xd8\x36\x62",
1 /* not-compliant because key size too small */
},
+ {
+ "passwordPASSWORDpassword", 24,
+ GCRY_KDF_PBKDF2, GCRY_MD_BLAKE2B_512,
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+ 4096,
+ 60,
+ "\xa4\x6b\x53\x35\xdb\xdd\xa3\xd2\x5d\x19\xbb\x11\xfe\xdd\xd9\x9e"
+ "\x45\x2a\x7c\x34\x47\x41\x98\xca\x31\x74\xb6\x34\x22\xac\x83\xb0"
+ "\x38\x6e\xf5\x93\x0f\xf5\x16\x46\x0b\x97\xdc\x6c\x27\x5b\xe7\x25"
+ "\xc2\xcb\xec\x50\x02\xc6\x52\x8b\x34\x68\x53\x65",
+ 1 /* not-compliant because subalgo is not the one of approved */
+ }
};
int tvidx;