#ifdef USE_CRYPTO
free_key_ctx_bi (&ks->static_key);
#ifdef USE_SSL
- if (ks->ssl_ctx && free_ssl_ctx)
+ if (tls_ctx_initialised(&ks->ssl_ctx) && free_ssl_ctx)
{
- SSL_CTX_free (ks->ssl_ctx);
+ tls_ctx_free (&ks->ssl_ctx);
free_key_ctx_bi (&ks->tls_auth_key);
}
#endif /* USE_SSL */
{
const struct options *options = &c->options;
- if (!c->c1.ks.ssl_ctx)
+ if (!tls_ctx_initialised(&c->c1.ks.ssl_ctx))
{
/*
* Initialize the OpenSSL library's global
* SSL context.
*/
- c->c1.ks.ssl_ctx = init_ssl (options);
- if (!c->c1.ks.ssl_ctx)
+ init_ssl (options, &(c->c1.ks.ssl_ctx));
+ if (!tls_ctx_initialised(&c->c1.ks.ssl_ctx))
{
#if P2MP
switch (auth_retry_get ())
if (packet_id_long_form)
to.crypto_flags_or = CO_PACKET_ID_LONG_FORM;
- to.ssl_ctx = c->c1.ks.ssl_ctx;
+ to.ssl_ctx = c->c1.ks.ssl_ctx.ctx;
to.key_type = c->c1.ks.key_type;
to.server = options->tls_server;
to.key_method = options->key_method;
#ifdef USE_SSL
/* our global SSL context */
- SSL_CTX *ssl_ctx;
+ struct tls_root_ctx ssl_ctx;
/* optional authentication HMAC key for TLS control channel */
struct key_ctx_bi tls_auth_key;
#endif
-/*
- * OpenSSL callback to get a temporary RSA key, mostly
- * used for export ciphers.
- */
-static RSA *
-tmp_rsa_cb (SSL * s, int is_export, int keylength)
-{
- static RSA *rsa_tmp = NULL;
- if (rsa_tmp == NULL)
- {
- msg (D_HANDSHAKE, "Generating temp (%d bit) RSA key", keylength);
- rsa_tmp = RSA_generate_key (keylength, RSA_F4, NULL, NULL);
- }
- return (rsa_tmp);
-}
-
/*
* Cert hash functions
*/
* Initialize SSL context.
* All files are in PEM format.
*/
-SSL_CTX *
-init_ssl (const struct options *options)
+void
+init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
{
SSL_CTX *ctx = NULL;
DH *dh;
bool using_cert_file = false;
X509 *my_cert = NULL;
- ERR_clear_error ();
+ ASSERT(NULL != new_ctx);
+
+ tls_clear_error();
if (options->tls_server)
{
- ctx = SSL_CTX_new (TLSv1_server_method ());
- if (ctx == NULL)
- msg (M_SSLERR, "SSL_CTX_new TLSv1_server_method");
-
- SSL_CTX_set_tmp_rsa_callback (ctx, tmp_rsa_cb);
+ tls_ctx_server_new(new_ctx);
+ ctx = new_ctx->ctx;
#if ENABLE_INLINE_FILES
if (!strcmp (options->dh_file, INLINE_FILE_TAG) && options->dh_file_inline)
}
else /* if client */
{
- ctx = SSL_CTX_new (TLSv1_client_method ());
- if (ctx == NULL)
- msg (M_SSLERR, "SSL_CTX_new TLSv1_client_method");
+ tls_ctx_client_new(new_ctx);
+ ctx = new_ctx->ctx;
}
/* Set SSL options */
}
done:
- ERR_clear_error ();
+ tls_clear_error ();
+
if (my_cert)
X509_free(my_cert);
- return ctx;
+
+ return;
err:
- if (ctx)
- {
- SSL_CTX_free (ctx);
- ctx = NULL;
- }
+ tls_ctx_free (new_ctx);
goto done;
}
void init_ssl_lib (void);
void free_ssl_lib (void);
-/* Build master SSL_CTX object that serves for the whole of openvpn instantiation */
-SSL_CTX *init_ssl (const struct options *options);
+/**
+ * Build master SSL context object that serves for the whole of OpenVPN
+ * instantiation
+ */
+void init_ssl (const struct options *options, struct tls_root_ctx *ctx);
struct tls_multi *tls_multi_init (struct tls_options *tls_options);
*/
void tls_clear_error();
+/**
+ * Initialise a library-specific TLS context for a server.
+ *
+ * @param ctx TLS context to initialise
+ */
+void tls_ctx_server_new(struct tls_root_ctx *ctx);
+
+/**
+ * Initialises a library-specific TLS context for a client.
+ *
+ * @param ctx TLS context to initialise
+ */
+void tls_ctx_client_new(struct tls_root_ctx *ctx);
+
+/**
+ * Frees the library-specific TLSv1 context
+ *
+ * @param ctx TLS context to free
+ */
+void tls_ctx_free(struct tls_root_ctx *ctx);
+
+/**
+ * Checks whether the given TLS context is initialised
+ *
+ * @param ctx TLS context to check
+ *
+ * @return true if the context is initialised, false if not.
+ */
+bool tls_ctx_initialised(struct tls_root_ctx *ctx);
+
/*
* Show the TLS ciphers that are available for us to use in the OpenSSL
* library.
ERR_clear_error ();
}
+/*
+ * OpenSSL callback to get a temporary RSA key, mostly
+ * used for export ciphers.
+ */
+static RSA *
+tmp_rsa_cb (SSL * s, int is_export, int keylength)
+{
+ static RSA *rsa_tmp = NULL;
+ if (rsa_tmp == NULL)
+ {
+ msg (D_HANDSHAKE, "Generating temp (%d bit) RSA key", keylength);
+ rsa_tmp = RSA_generate_key (keylength, RSA_F4, NULL, NULL);
+ }
+ return (rsa_tmp);
+}
+
+void
+tls_ctx_server_new(struct tls_root_ctx *ctx)
+{
+ ASSERT(NULL != ctx);
+
+ ctx->ctx = SSL_CTX_new (TLSv1_server_method ());
+
+ if (ctx->ctx == NULL)
+ msg (M_SSLERR, "SSL_CTX_new TLSv1_server_method");
+
+ SSL_CTX_set_tmp_rsa_callback (ctx->ctx, tmp_rsa_cb);
+}
+
+void
+tls_ctx_client_new(struct tls_root_ctx *ctx)
+{
+ ASSERT(NULL != ctx);
+
+ ctx->ctx = SSL_CTX_new (TLSv1_client_method ());
+
+ if (ctx->ctx == NULL)
+ msg (M_SSLERR, "SSL_CTX_new TLSv1_client_method");
+}
+
+void
+tls_ctx_free(struct tls_root_ctx *ctx)
+{
+ ASSERT(NULL != ctx);
+ if (NULL != ctx->ctx)
+ SSL_CTX_free (ctx->ctx);
+ ctx->ctx = NULL;
+}
+
+bool tls_ctx_initialised(struct tls_root_ctx *ctx)
+{
+ ASSERT(NULL != ctx);
+ return NULL != ctx->ctx;
+}
+
void
show_available_tls_ciphers ()
{
#include <openssl/ssl.h>
+/**
+ * Structure that wraps the TLS context. Contents differ depending on the
+ * SSL library used.
+ */
+struct tls_root_ctx {
+ SSL_CTX *ctx;
+};
+
/**
* Allocate space in SSL objects in which to store a struct tls_session
* pointer back to parent.