#include "ssl_common.h"
#include "base64.h"
#include "openssl_compat.h"
+#include "xkey_common.h"
#ifdef ENABLE_CRYPTOAPI
#include "cryptoapi.h"
#include <openssl/applink.c>
#endif
+static OSSL_LIB_CTX *tls_libctx;
+
+static void unload_xkey_provider(void);
+
/*
* Allocate space in SSL objects in which to store a struct tls_session
* pointer back to parent.
{
ASSERT(NULL != ctx);
- ctx->ctx = SSL_CTX_new(SSLv23_server_method());
+ ctx->ctx = SSL_CTX_new_ex(tls_libctx, NULL, SSLv23_server_method());
if (ctx->ctx == NULL)
{
{
ASSERT(NULL != ctx);
- ctx->ctx = SSL_CTX_new(SSLv23_client_method());
+ ctx->ctx = SSL_CTX_new_ex(tls_libctx, NULL, SSLv23_client_method());
if (ctx->ctx == NULL)
{
ASSERT(NULL != ctx);
SSL_CTX_free(ctx->ctx);
ctx->ctx = NULL;
+ unload_xkey_provider(); /* in case it is loaded */
}
bool
return OpenSSL_version(OPENSSL_VERSION);
}
+
+/** Some helper routines for provider load/unload */
+#ifdef HAVE_XKEY_PROVIDER
+static int
+provider_load(OSSL_PROVIDER *prov, void *dest_libctx)
+{
+ const char *name = OSSL_PROVIDER_get0_name(prov);
+ OSSL_PROVIDER_load(dest_libctx, name);
+ return 1;
+}
+
+static int
+provider_unload(OSSL_PROVIDER *prov, void *unused)
+{
+ (void) unused;
+ OSSL_PROVIDER_unload(prov);
+ return 1;
+}
+#endif /* HAVE_XKEY_PROVIDER */
+
+/**
+ * Setup ovpn.xey provider for signing with external keys.
+ * It is loaded into a custom library context so as not to pollute
+ * the default context. Alternatively we could override any
+ * system-wide property query set on the default context. But we
+ * want to avoid that.
+ */
+void
+load_xkey_provider(void)
+{
+#ifdef HAVE_XKEY_PROVIDER
+
+ /* Make a new library context for use in TLS context */
+ if (!tls_libctx)
+ {
+ tls_libctx = OSSL_LIB_CTX_new();
+ check_malloc_return(tls_libctx);
+
+ /* Load all providers in default LIBCTX into this libctx.
+ * OpenSSL has a child libctx functionality to automate this,
+ * but currently that is usable only from within providers.
+ * So we do something close to it manually here.
+ */
+ OSSL_PROVIDER_do_all(NULL, provider_load, tls_libctx);
+ }
+
+ if (!OSSL_PROVIDER_available(tls_libctx, "ovpn.xkey"))
+ {
+ OSSL_PROVIDER_add_builtin(tls_libctx, "ovpn.xkey", xkey_provider_init);
+ if (!OSSL_PROVIDER_load(tls_libctx, "ovpn.xkey"))
+ {
+ msg(M_NONFATAL, "ERROR: failed loading external key provider: "
+ "Signing with external keys will not work.");
+ }
+ }
+
+ /* We only implement minimal functionality in ovpn.xkey, so we do not want
+ * methods in xkey to be picked unless absolutely required (i.e, when the key
+ * is external). Ensure this by setting a default propquery for the custom
+ * libctx that unprefers, but does not forbid, ovpn.xkey. See also man page
+ * of "property" in OpenSSL 3.0.
+ */
+ EVP_set_default_properties(tls_libctx, "?provider!=ovpn.xkey");
+
+#endif /* HAVE_XKEY_PROVIDER */
+}
+
+/**
+ * Undo steps in load_xkey_provider
+ */
+static void
+unload_xkey_provider(void)
+{
+#ifdef HAVE_XKEY_PROVIDER
+ if (tls_libctx)
+ {
+ OSSL_PROVIDER_do_all(tls_libctx, provider_unload, NULL);
+ OSSL_LIB_CTX_free(tls_libctx);
+ }
+#endif /* HAVE_XKEY_PROVIDER */
+ tls_libctx = NULL;
+}
+
#endif /* defined(ENABLE_CRYPTO_OPENSSL) */