[Openvpn-devel,v6,OSSL,3.0] Allow loading of non default providers
Commit Message
This allows OpenVPN to load non-default providers. This is mainly
useful for loading the legacy provider with --providers legacy default
Patch v4: use spaces to seperate providers, unload providers.
Patch v5: General cleanup, rename option to --providers, add
option to usage() and add an entry to Changes.rst
Patch v6: allow --providers also to be used (and be ignored) with mbed TLS
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
---
Changes.rst | 7 +++++++
doc/man-sections/generic-options.rst | 12 +++++++++++
src/openvpn/crypto_backend.h | 15 ++++++++++++++
src/openvpn/crypto_mbedtls.c | 13 ++++++++++++
src/openvpn/crypto_mbedtls.h | 3 +++
src/openvpn/crypto_openssl.c | 30 ++++++++++++++++++++++++++++
src/openvpn/crypto_openssl.h | 9 +++++++++
src/openvpn/openvpn.c | 13 ++++++++++++
src/openvpn/options.c | 8 ++++++++
src/openvpn/options.h | 9 +++++++++
10 files changed, 119 insertions(+)
Comments
Acked-by: Gert Doering <gert@greenie.muc.de>
I tool Selva's patch, and added my own for the change v5->v6 (which
is really just moving the #ifdef to the other side of the block,
so the options.c code is always compiled in).
Tested on 1.1 ("unsurprisingly, no change") and 3.0 builds ("my test
cases against 2.3 servers with BF-CBC are working again").
Code change also looks reasonable. In it goes!
A few minor whitespace fixes ("type* var" vs. "type *var").
Your patch has been applied to the master branch.
commit 8a636779d9a28dc8040448483dc4a8af05d5c37f
Author: Arne Schwabe
Date: Fri Nov 12 14:02:31 2021 +0100
Allow loading of non default providers
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Selva Nair <selva.nair@gmail.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20211112130231.3799480-1-arne@rfc2549.org>
URL: https://www.mail-archive.com/search?l=mid&q=20211112130231.3799480-1-arne@rfc2549.org
Signed-off-by: Gert Doering <gert@greenie.muc.de>
--
kind regards,
Gert Doering
@@ -50,6 +50,13 @@ Compatibility mode (``--compat-mode``)
with older peers. The options ``--compat-mode`` allows UIs to provide users
with an easy way to still connect to older servers.
+OpenSSL 3.0 support
+ OpenSSL 3.0 has been added. Most of OpenSSL 3.0 changes are not user visible but
+ improve general compatibility with OpenSSL 3.0. ``--tls-cert-profile insecure``
+ has been added to allow selecting the lowest OpenSSL security level (not
+ recommended, use only if you must). OpenSSL 3.0 no longer supports the Blowfish
+ (and other deprecated) algorithm by default and the new option ``--providers``
+ allows loading the legacy provider to renable these algorithms.
Deprecated features
-------------------
@@ -280,6 +280,18 @@ which mode OpenVPN is configured as.
This option solves the problem by persisting keys across :code:`SIGUSR1`
resets, so they don't need to be re-read.
+--providers providers
+ Load the list of (OpenSSL) providers. This is mainly useful for using an
+ external provider for key management like tpm2-openssl or to load the
+ legacy provider with
+
+ ::
+
+ --providers legacy default
+
+ Behaviour of changing this option between SIGHUP might not be well behaving.
+ If you need to change/add/remove this option, fully restart OpenVPN.
+
--remap-usr1 signal
Control whether internally or externally generated :code:`SIGUSR1` signals
are remapped to :code:`SIGHUP` (restart without persisting state) or
@@ -78,6 +78,21 @@ void crypto_clear_error(void);
*/
void crypto_init_lib_engine(const char *engine_name);
+
+/**
+ * Load the given (OpenSSL) providers
+ * @param provider name of providers to load
+ * @return reference to the loaded provider
+ */
+provider_t *crypto_load_provider(const char *provider);
+
+/**
+ * Unloads the given (OpenSSL) provider
+ * @param provname name of the provider to unload
+ * @param provider pointer to the provider to unload
+ */
+void crypto_unload_provider(const char* provname, provider_t *provider);
+
#ifdef DMALLOC
/*
* OpenSSL memory debugging. If dmalloc debugging is enabled, tell
@@ -69,6 +69,19 @@ crypto_init_lib_engine(const char *engine_name)
"available");
}
+provider_t *crypto_load_provider(const char *provider)
+{
+ if (provider)
+ {
+ msg(M_WARN, "Note: mbed TLS provider functionality is not available");
+ }
+ return NULL;
+}
+
+void crypto_unload_provider(const char* provname, provider_t *provider)
+{
+}
+
/*
*
* Functions related to the core crypto library
@@ -48,6 +48,9 @@ typedef mbedtls_md_context_t md_ctx_t;
/** Generic HMAC %context. */
typedef mbedtls_md_context_t hmac_ctx_t;
+/* Use a dummy type for the provider */
+typedef void provider_t;
+
/** Maximum length of an IV */
#define OPENVPN_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH
@@ -54,6 +54,9 @@
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
#include <openssl/kdf.h>
#endif
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/provider.h>
+#endif
#if defined(_WIN32) && defined(OPENSSL_NO_EC)
#error Windows build with OPENSSL_NO_EC: disabling EC key is not supported.
@@ -149,6 +152,33 @@ crypto_init_lib_engine(const char *engine_name)
#endif
}
+provider_t *
+crypto_load_provider(const char *provider)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ /* Load providers into the default (NULL) library context */
+ OSSL_PROVIDER* prov = OSSL_PROVIDER_load(NULL, provider);
+ if (!prov)
+ {
+ crypto_msg(M_FATAL, "failed to load provider '%s'", provider);
+ }
+ return prov;
+#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
+ msg(M_WARN, "Note: OpenSSL provider functionality is not available");
+ return NULL;
+#endif
+}
+
+void crypto_unload_provider(const char* provname, provider_t *provider)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ if (!OSSL_PROVIDER_unload(provider))
+ {
+ crypto_msg(M_FATAL, "failed to unload provider '%s'", provname);
+ }
+#endif
+}
+
/*
*
* Functions related to the core crypto library
@@ -33,6 +33,10 @@
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/provider.h>
+#endif
+
/** Generic cipher key type %context. */
typedef EVP_CIPHER cipher_kt_t;
@@ -49,12 +53,17 @@ typedef EVP_MD_CTX md_ctx_t;
/** Generic HMAC %context. */
#if OPENSSL_VERSION_NUMBER < 0x30000000L
typedef HMAC_CTX hmac_ctx_t;
+
+/* Use a dummy type for the provider */
+typedef void provider_t;
#else
typedef struct {
OSSL_PARAM params[3];
uint8_t key[EVP_MAX_KEY_LENGTH];
EVP_MAC_CTX *ctx;
} hmac_ctx_t;
+
+typedef OSSL_PROVIDER provider_t;
#endif
/** Maximum length of an IV */
@@ -112,10 +112,23 @@ void init_early(struct context *c)
/* init verbosity and mute levels */
init_verb_mute(c, IVM_LEVEL_1);
+ /* Initialise OpenSSL provider, this needs to be initialised this
+ * early since option post-processing and also openssl info
+ * printing depends on it */
+ for (int j=1; j < MAX_PARMS && c->options.providers.names[j]; j++)
+ {
+ c->options.providers.providers[j] =
+ crypto_load_provider(c->options.providers.names[j]);
+ }
}
static void uninit_early(struct context *c)
{
+ for (int j=1; j < MAX_PARMS && c->options.providers.providers[j]; j++)
+ {
+ crypto_unload_provider(c->options.providers.names[j],
+ c->options.providers.providers[j]);
+ }
net_ctx_free(&c->net_ctx);
}
@@ -581,6 +581,7 @@ static const char usage_message[] =
" : Use --show-tls to see a list of supported TLS ciphers (suites).\n"
"--tls-cert-profile p : Set the allowed certificate crypto algorithm profile\n"
" (default=legacy).\n"
+ "--providers l : A list l of OpenSSL providers to load.\n"
"--tls-timeout n : Packet retransmit timeout on TLS control channel\n"
" if no ACK from remote within n seconds (default=%d).\n"
"--reneg-bytes n : Renegotiate data chan. key after n bytes sent and recvd.\n"
@@ -8158,6 +8159,13 @@ add_option(struct options *options,
}
}
#endif /* ENABLE_CRYPTO_MBEDTLS */
+ else if (streq(p[0], "providers") && p[1])
+ {
+ for (size_t j = 1; j < MAX_PARMS && p[j] != NULL;j++)
+ {
+ options->providers.names[j] = p[j];
+ }
+ }
#ifdef ENABLE_PREDICTION_RESISTANCE
else if (streq(p[0], "use-prediction-resistance") && !p[1])
{
@@ -179,6 +179,14 @@ struct remote_list
struct remote_entry *array[CONNECTION_LIST_SIZE];
};
+struct provider_list
+{
+ /* Names of the providers */
+ const char *names[MAX_PARMS];
+ /* Pointers to the loaded providers to unload them */
+ provider_t *providers[MAX_PARMS];
+};
+
enum vlan_acceptable_frames
{
VLAN_ONLY_TAGGED,
@@ -519,6 +527,7 @@ struct options
const char *ncp_ciphers;
const char *authname;
const char *engine;
+ struct provider_list providers;
bool replay;
bool mute_replay_warnings;
int replay_window;