From 3a853db582eefdb09941da24cf1acd09e2dd512e Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Thu, 13 Aug 2026 09:28:05 +0000 Subject: [PATCH] MEDIUM: ssl: add fips_mode() config condition predicate Add a new "fips_mode()" predicate usable in .if/.elif configuration conditional blocks and with the "-cc" command line option. It evaluates to true when the loaded SSL library is currently running in FIPS mode. The check relies on a new openssl_fips_mode() helper in tools.c, following the same pattern as openssl_compare_current_version() and awslc_compare_current_api(). Two APIs are used depending on the SSL library: - FIPS_mode(), implemented by OpenSSL 1.0.x/1.1.x (including FIPS-validated builds) and by compatible libraries such as AWS-LC. - EVP_default_properties_is_fips_enabled(), for OpenSSL 3.0 and above, where FIPS_mode() was removed in favor of a provider-based FIPS model. It reports whether the default library context currently resolves algorithm fetches to the FIPS provider, which is the closest 3.x equivalent. The predicate is a no-op (always false) with any other SSL library, or when built without SSL support. This lets configurations, and reg-tests in particular, detect and adapt to (or skip) TLS constructs that are rejected by HAProxy's own FIPS compliance checks (src/fips.c) when FIPS mode is active, e.g. non-ECDHE TLS 1.2 cipher suites. --- doc/configuration.txt | 3 +++ include/haproxy/cfgcond-t.h | 1 + include/haproxy/tools.h | 2 ++ src/cfgcond.c | 10 ++++++++++ src/tools.c | 26 ++++++++++++++++++++++++++ 5 files changed, 42 insertions(+) diff --git a/doc/configuration.txt b/doc/configuration.txt index 9cc90a9a7..06a54d09c 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1208,6 +1208,9 @@ The list of currently supported predicates is the following: in the features list reported by "haproxy -vv" (which means a appears after a '+') + - fips_mode() : returns true if the loaded SSL library is + currently running in FIPS mode. + - openssl_version_atleast() : returns true if the current openssl version is at least as recent as otherwise false. diff --git a/include/haproxy/cfgcond-t.h b/include/haproxy/cfgcond-t.h index 73635bfd3..f5e094e1d 100644 --- a/include/haproxy/cfgcond-t.h +++ b/include/haproxy/cfgcond-t.h @@ -57,6 +57,7 @@ enum cond_predicate { CFG_PRED_AWSLC_API_ATLEAST, // "awslc_api_atleast" CFG_PRED_AWSLC_API_BEFORE, // "awslc_api_before" CFG_PRED_ENABLED, // "enabled" + CFG_PRED_FIPS_MODE, // "fips_mode" }; /* types for condition terms */ diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index c4d95d096..0cb7f345e 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -1472,6 +1472,8 @@ int awslc_compare_current_api(const char *version); int openssl_compare_current_version(const char *version); /* compare the current OpenSSL name to a string */ int openssl_compare_current_name(const char *name); +/* returns whether the SSL library is currently running in FIPS mode */ +int openssl_fips_mode(void); /* vma helpers */ void vma_set_name(void *addr, size_t size, const char *type, const char *name); diff --git a/src/cfgcond.c b/src/cfgcond.c index f012e6040..25a2c5473 100644 --- a/src/cfgcond.c +++ b/src/cfgcond.c @@ -32,6 +32,7 @@ const struct cond_pred_kw cond_predicates[] = { { "awslc_api_atleast", CFG_PRED_AWSLC_API_ATLEAST, ARG1(1, STR) }, { "awslc_api_before", CFG_PRED_AWSLC_API_BEFORE, ARG1(1, STR) }, { "enabled", CFG_PRED_ENABLED, ARG1(1, STR) }, + { "fips_mode", CFG_PRED_FIPS_MODE, 0 }, { NULL, CFG_PRED_NONE, 0 } }; @@ -321,6 +322,15 @@ int cfg_eval_cond_term(const struct cfg_cond_term *term, char **err) ret = cfg_eval_cond_enabled(term->args[0].data.str.area) != 0; break; } + case CFG_PRED_FIPS_MODE: { // checks if the SSL library is currently running in FIPS mode + int fipsret = openssl_fips_mode(); + + /* < -1 (i.e. -2) means the loaded SSL library doesn't support + * FIPS mode at all, in which case the condition is simply false. + */ + ret = fipsret > 0; + break; + } default: memprintf(err, "internal error: unhandled conditional expression predicate '%s'", term->pred->word); break; diff --git a/src/tools.c b/src/tools.c index c19f6fc27..7783a89fc 100644 --- a/src/tools.c +++ b/src/tools.c @@ -7465,6 +7465,32 @@ int openssl_compare_current_name(const char *name) return 1; } +/* + * This function returns whether the SSL library currently loaded is running + * in FIPS mode. + * + * FIPS_mode() is implemented by OpenSSL 1.0.x/1.1.x (including + * FIPS-validated builds) as well as by libraries providing a compatible API + * such as AWS-LC. It was removed in OpenSSL 3.0, replaced by a provider-based + * FIPS model: EVP_default_properties_is_fips_enabled() reports whether the + * default library context currently resolves algorithm fetches to the FIPS + * provider, which is the closest 3.x equivalent. + * + * 1 : FIPS mode is enabled + * 0 : FIPS mode is disabled + * -2 : not applicable, the loaded SSL library does not support FIPS mode + */ +int openssl_fips_mode(void) +{ +#if defined(USE_OPENSSL) && (HA_OPENSSL_VERSION_NUMBER < 0x3000000fL) + return FIPS_mode() ? 1 : 0; +#elif defined(USE_OPENSSL) && (HA_OPENSSL_VERSION_NUMBER >= 0x3000000fL) + return EVP_default_properties_is_fips_enabled(NULL) ? 1 : 0; +#else + return -2; +#endif +} + /* prctl/PR_SET_VMA wrapper to easily give a name to virtual memory areas, * knowing their address and size. * -- 2.47.3