mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-05-28 04:03:29 -04:00
Initialize the xkey provider and use it in SSL context
- Add function to check when external key is in use
- Load xkey provider into a custom library context when required
- Use the custom libctx in SSL CTX when external key is in use
As no keys are yet loaded through the provider,
no functionality gets delegated to it as yet.
v2 changes: Provider loading is reworked to activate only when external
keys are in use
This was 2/9 in v1
Signed-off-by: Selva Nair <selva.nair@gmail.com>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <20211214165928.30676-6-selva.nair@gmail.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg23432.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
ab3a8e5c28
commit
4b85c488ec
8 changed files with 134 additions and 3 deletions
|
|
@ -760,6 +760,14 @@ int EVP_PKEY_get_group_name(EVP_PKEY *pkey, char *gname, size_t gname_sz,
|
|||
#define EVP_CIPHER_get0_name EVP_CIPHER_name
|
||||
#define EVP_CIPHER_CTX_get_mode EVP_CIPHER_CTX_mode
|
||||
|
||||
/** Reduce SSL_CTX_new_ex() to SSL_CTX_new() for OpenSSL < 3 */
|
||||
#define SSL_CTX_new_ex(libctx, propq, method) \
|
||||
SSL_CTX_new((method))
|
||||
|
||||
/* Some safe typedefs to avoid too many ifdefs */
|
||||
typedef void OSSL_LIB_CTX;
|
||||
typedef void OSSL_PROVIDER;
|
||||
|
||||
/* Mimics the functions but only when the default context without
|
||||
* options is chosen */
|
||||
static inline const EVP_CIPHER *
|
||||
|
|
|
|||
|
|
@ -5286,6 +5286,22 @@ show_compression_warning(struct compress_options *info)
|
|||
}
|
||||
#endif
|
||||
|
||||
bool key_is_external(const struct options *options)
|
||||
{
|
||||
bool ret = false;
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
ret = ret || (options->management_flags & MF_EXTERNAL_KEY);
|
||||
#endif
|
||||
#ifdef ENABLE_PKCS11
|
||||
ret = ret || (options->pkcs11_providers[0] != NULL);
|
||||
#endif
|
||||
#ifdef ENABLE_CRYPTOAPI
|
||||
ret = ret || options->cryptoapi_cert;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
add_option(struct options *options,
|
||||
char *p[],
|
||||
|
|
|
|||
|
|
@ -862,4 +862,6 @@ void options_string_import(struct options *options,
|
|||
unsigned int *option_types_found,
|
||||
struct env_set *es);
|
||||
|
||||
bool key_is_external(const struct options *options);
|
||||
|
||||
#endif /* ifndef OPTIONS_H */
|
||||
|
|
|
|||
|
|
@ -604,6 +604,11 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx, bool in_ch
|
|||
|
||||
tls_clear_error();
|
||||
|
||||
if (key_is_external(options))
|
||||
{
|
||||
load_xkey_provider();
|
||||
}
|
||||
|
||||
if (options->tls_server)
|
||||
{
|
||||
tls_ctx_server_new(new_ctx);
|
||||
|
|
|
|||
|
|
@ -627,4 +627,10 @@ show_available_tls_ciphers(const char *cipher_list,
|
|||
bool
|
||||
tls_session_generate_data_channel_keys(struct tls_session *session);
|
||||
|
||||
/**
|
||||
* Load ovpn.xkey provider used for external key signing
|
||||
*/
|
||||
void
|
||||
load_xkey_provider(void);
|
||||
|
||||
#endif /* ifndef OPENVPN_SSL_H */
|
||||
|
|
|
|||
|
|
@ -1549,4 +1549,10 @@ get_ssl_library_version(void)
|
|||
return mbedtls_version;
|
||||
}
|
||||
|
||||
void
|
||||
load_xkey_provider(void)
|
||||
{
|
||||
return; /* no external key provider in mbedTLS build */
|
||||
}
|
||||
|
||||
#endif /* defined(ENABLE_CRYPTO_MBEDTLS) */
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "ssl_common.h"
|
||||
#include "base64.h"
|
||||
#include "openssl_compat.h"
|
||||
#include "xkey_common.h"
|
||||
|
||||
#ifdef ENABLE_CRYPTOAPI
|
||||
#include "cryptoapi.h"
|
||||
|
|
@ -69,6 +70,10 @@
|
|||
#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.
|
||||
|
|
@ -113,7 +118,7 @@ tls_ctx_server_new(struct tls_root_ctx *ctx)
|
|||
{
|
||||
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)
|
||||
{
|
||||
|
|
@ -131,7 +136,7 @@ tls_ctx_client_new(struct tls_root_ctx *ctx)
|
|||
{
|
||||
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)
|
||||
{
|
||||
|
|
@ -150,6 +155,7 @@ tls_ctx_free(struct tls_root_ctx *ctx)
|
|||
ASSERT(NULL != ctx);
|
||||
SSL_CTX_free(ctx->ctx);
|
||||
ctx->ctx = NULL;
|
||||
unload_xkey_provider(); /* in case it is loaded */
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -2284,4 +2290,87 @@ get_ssl_library_version(void)
|
|||
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) */
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include <openssl/opensslv.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000010L && !defined(DISABLE_XKEY_PROVIDER)
|
||||
#define HAVE_XKEY_PROVIDER 1
|
||||
|
||||
#include <openssl/provider.h>
|
||||
#include <openssl/core_dispatch.h>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue