diff --git a/conf/plugins/openssl.opt b/conf/plugins/openssl.opt index 55d8dcaa1..e8a60c8a9 100644 --- a/conf/plugins/openssl.opt +++ b/conf/plugins/openssl.opt @@ -3,3 +3,16 @@ charon.plugins.openssl.engine_id = pkcs11 charon.plugins.openssl.fips_mode = 0 Set OpenSSL FIPS mode: disabled(0), enabled(1), Suite B enabled(2). + + Set OpenSSL FIPS mode. With OpenSSL before 3.0, the supported values are + disabled(0), enabled(1) and Suite B enabled(2). With OpenSSL 3+, any value + other than 0 will explicitly load the fips and base providers (_load_legacy_ + will be ignored). The latter still requires the config in fipsmodule.cnf + (e.g. for the module's MAC), but allows explicitly loading the provider if + it's not activated in that config. + +charon.plugins.openssl.load_legacy = yes + Load the legacy provider in OpenSSL 3+ for algorithms like MD4, DES, or + Blowfish (the first two are required for EAP-MSCHAPv2). If disabled, the + default provider is loaded, or those configured in the OpenSSL config (e.g. + the fips provider). diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index 49b77f8ac..c93ea6048 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -31,6 +32,9 @@ #ifndef OPENSSL_NO_ECDH #include #endif +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif #include "openssl_plugin.h" #include "openssl_util.h" @@ -70,6 +74,13 @@ struct private_openssl_plugin_t { * public functions */ openssl_plugin_t public; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + /** + * Loaded providers + */ + array_t *providers; +#endif }; /** @@ -876,6 +887,15 @@ METHOD(plugin_t, get_features, int, METHOD(plugin_t, destroy, void, private_openssl_plugin_t *this) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PROVIDER *provider; + while (array_remove(this->providers, ARRAY_TAIL, &provider)) + { + OSSL_PROVIDER_unload(provider); + } + array_destroy(this->providers); +#endif /* OPENSSL_VERSION_NUMBER */ + /* OpenSSL 1.1.0 cleans up itself at exit and while OPENSSL_cleanup() exists we * can't call it as we couldn't re-initialize the library (as required by the * unit tests and the Android app) */ @@ -896,6 +916,31 @@ METHOD(plugin_t, destroy, void, free(this); } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +typedef struct { + char names[BUF_LEN]; + int len; +} ossl_provider_names_t; + +/** + * Callback to produce a list of the names of loaded providers + */ +static int concat_ossl_providers(OSSL_PROVIDER *provider, void *cbdata) +{ + ossl_provider_names_t *data = cbdata; + int len; + + len = snprintf(&data->names[data->len], sizeof(data->names) - data->len, + " %s", OSSL_PROVIDER_get0_name(provider)); + if (len < (sizeof(data->names) - data->len)) + { + data->len += len; + return 1; + } + return 0; +} +#endif + /* * see header file */ @@ -911,15 +956,16 @@ plugin_t *openssl_plugin_create() { if (FIPS_mode() != fips_mode && !FIPS_mode_set(fips_mode)) { - DBG1(DBG_LIB, "unable to set openssl FIPS mode(%d) from (%d)", + DBG1(DBG_LIB, "unable to set OpenSSL FIPS mode(%d) from (%d)", fips_mode, FIPS_mode()); return NULL; } } -#else +#elif OPENSSL_VERSION_NUMBER < 0x30000000L + /* OpenSSL 3.0+ is handled below */ if (fips_mode) { - DBG1(DBG_LIB, "openssl FIPS mode(%d) unavailable", fips_mode); + DBG1(DBG_LIB, "OpenSSL FIPS mode(%d) unavailable", fips_mode); return NULL; } #endif @@ -952,11 +998,43 @@ plugin_t *openssl_plugin_create() #endif /* OPENSSL_NO_ENGINE */ #endif /* OPENSSL_VERSION_NUMBER */ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + if (fips_mode) + { + OSSL_PROVIDER *fips; + + fips = OSSL_PROVIDER_load(NULL, "fips"); + if (!fips) + { + DBG1(DBG_LIB, "unable to load OpenSSL FIPS provider"); + return NULL; + } + array_insert_create(&this->providers, ARRAY_TAIL, fips); + /* explicitly load the base provider containing encoding functions */ + array_insert_create(&this->providers, ARRAY_TAIL, + OSSL_PROVIDER_load(NULL, "base")); + } + else if (lib->settings->get_bool(lib->settings, "%s.plugins.openssl.load_legacy", + TRUE, lib->ns)) + { + /* load the legacy provider for algorithms like MD4, DES, BF etc. */ + array_insert_create(&this->providers, ARRAY_TAIL, + OSSL_PROVIDER_load(NULL, "legacy")); + /* explicitly load the default provider, as mentioned by crypto(7) */ + array_insert_create(&this->providers, ARRAY_TAIL, + OSSL_PROVIDER_load(NULL, "default")); + } + ossl_provider_names_t data = {}; + OSSL_PROVIDER_do_all(NULL, concat_ossl_providers, &data); + dbg(DBG_LIB, strpfx(lib->ns, "charon") ? 1 : 2, + "providers loaded by OpenSSL:%s", data.names); +#endif /* OPENSSL_VERSION_NUMBER */ + #ifdef OPENSSL_FIPS /* we do this here as it may have been enabled via openssl.conf */ fips_mode = FIPS_mode(); dbg(DBG_LIB, strpfx(lib->ns, "charon") ? 1 : 2, - "openssl FIPS mode(%d) - %sabled ", fips_mode, fips_mode ? "en" : "dis"); + "OpenSSL FIPS mode(%d) - %sabled ", fips_mode, fips_mode ? "en" : "dis"); #endif /* OPENSSL_FIPS */ #if OPENSSL_VERSION_NUMBER < 0x1010100fL