Merge branch 'openssl-providers'

Optionally load the legacy provider in OpenSSL 3 (enabled, by default) to
make algorithms like MD4 and DES available, which we require for
EAP-MSCHAPv2.  Allow explicitly loading the fips provider via existing
fips_mode option.  The loaded providers, whether influenced by the above
options or not, are logged.

Closes strongswan/strongswan#759
This commit is contained in:
Tobias Brunner 2021-12-08 11:34:46 +01:00
commit b158c08c4b
2 changed files with 95 additions and 4 deletions

View File

@ -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).

View File

@ -16,6 +16,7 @@
#include <library.h>
#include <utils/debug.h>
#include <collections/array.h>
#include <threading/thread.h>
#include <threading/mutex.h>
#include <threading/thread_value.h>
@ -31,6 +32,9 @@
#ifndef OPENSSL_NO_ECDH
#include <openssl/ec.h>
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
#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