NIIBE Yutaka <gni...@fsij.org> wrote: > Here are changes for gcry_pk_hash_* functions. > > This change includes stop rejecting non-compliant cases. > > With LIBGCRYPT_FORCE_FIPS_MODE=true, "make check" result 7 failures. > > FAIL: basic > FAIL: t-kem > FAIL: dsa-rfc6979 > FAIL: curves > FAIL: t-cv25519 > FAIL: t-x448 > FAIL: basic-disable-all-hwf
To support old behavior, I introduced GCRYCTL_FIPS_REJECT_NON_FIPS. --
>From e52adf0948c60b2e9accd7996fcece0f9b443763 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka <gni...@fsij.org> Date: Thu, 19 Dec 2024 11:30:28 +0900 Subject: [PATCH 3/3] fips: Introduce GCRYCTL_FIPS_REJECT_NON_FIPS. * 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 <gni...@fsij.org> --- 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(-) diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index ddf9cbe1..fe0a1eb2 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -645,7 +645,12 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, 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) { diff --git a/cipher/pubkey.c b/cipher/pubkey.c index e2e54199..11bf1ec9 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -510,7 +510,12 @@ prepare_datasexp_to_be_signed (const char *tmpl, gcry_md_hd_t hd, 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 char *tmpl, gcry_md_hd_t hd, 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, const char *tmpl, gcry_md_hd_t hd_orig, 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, const char *tmpl, gcry_md_hd_t hd_orig, 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 diff --git a/src/fips.c b/src/fips.c index d3eaf85f..7ae89503 100644 --- a/src/fips.c +++ b/src/fips.c @@ -69,14 +69,29 @@ 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) { diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h index aa49d766..d52a1b1b 100644 --- a/src/gcrypt-int.h +++ b/src/gcrypt-int.h @@ -298,6 +298,12 @@ void _gcry_set_log_handler (gcry_handler_log_t f, void *opaque); 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 \ @@ -306,7 +312,8 @@ unsigned long _gcry_thread_context_get_fsi (void); _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. */ diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 2ed9914b..4a882c55 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -336,7 +336,8 @@ enum gcry_ctl_cmds GCRYCTL_FIPS_SERVICE_INDICATOR_MD = 86, GCRYCTL_FIPS_SERVICE_INDICATOR_PK_FLAGS = 87, GCRYCTL_MD_CUSTOMIZE = 88, - GCRYCTL_FIPS_SERVICE_INDICATOR = 89 + GCRYCTL_FIPS_SERVICE_INDICATOR = 89, + GCRYCTL_FIPS_REJECT_NON_FIPS = 90 }; /* Perform various operations defined by CMD. */ @@ -1979,7 +1980,30 @@ void gcry_log_debugsxp (const char *text, gcry_sexp_t sexp); 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 diff --git a/src/global.c b/src/global.c index ce2541d4..a5a48cb5 100644 --- a/src/global.c +++ b/src/global.c @@ -791,6 +791,13 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr) 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 diff --git a/tests/t-fips-service-ind.c b/tests/t-fips-service-ind.c index 9a22d696..d092bfae 100644 --- a/tests/t-fips-service-ind.c +++ b/tests/t-fips-service-ind.c @@ -1138,6 +1138,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_kdf_derive (); check_hash_buffer (); check_hash_buffers (); -- 2.39.5
_______________________________________________ Gcrypt-devel mailing list Gcrypt-devel@gnupg.org https://lists.gnupg.org/mailman/listinfo/gcrypt-devel