openssl_main_t *om = &openssl_main;
openssl_ctx_t **ctx;
- pool_get (om->ctx_pool[thread_index], ctx);
+ pool_get_aligned_safe (om->ctx_pool[thread_index], ctx, 0);
+
if (!(*ctx))
*ctx = clib_mem_alloc (sizeof (openssl_ctx_t));
openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
/* Cleanup ssl ctx unless migrated */
- if (!ctx->is_migrated)
+ if (!(ctx->flags & TLS_CONN_F_MIGRATED))
{
- if (SSL_is_init_finished (oc->ssl) && !ctx->is_passive_close)
+ if (SSL_is_init_finished (oc->ssl) &&
+ !(ctx->flags & TLS_CONN_F_PASSIVE_CLOSE))
SSL_shutdown (oc->ssl);
SSL_free (oc->ssl);
vec_free (ctx->srv_hostname);
-
+ SSL_CTX_free (oc->client_ssl_ctx);
#ifdef HAVE_OPENSSL_ASYNC
openssl_evt_free (ctx->evt_index, ctx->c_thread_index);
#endif
session_handle_t sh;
openssl_ctx_t **oc;
- pool_get (om->ctx_pool[thread_index], oc);
+ pool_get_aligned_safe (om->ctx_pool[thread_index], oc, 0);
/* Free the old instance instead of looking for an empty spot */
if (*oc)
clib_mem_free (*oc);
return -1;
static int
-openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl)
+openssl_read_from_ssl_into_fifo (svm_fifo_t *f, SSL *ssl, u32 max_len)
{
int read, rv, n_fs, i;
const int n_segs = 2;
if (!max_enq)
return 0;
+ max_enq = clib_min (max_len, max_enq);
n_fs = svm_fifo_provision_chunks (f, fs, n_segs, max_enq);
if (n_fs < 0)
return 0;
return 0;
}
- for (i = 1; i < n_fs; i++)
+ if (read == (int) fs[0].len)
{
- rv = SSL_read (ssl, fs[i].data, fs[i].len);
- read += rv > 0 ? rv : 0;
-
- if (rv < (int) fs[i].len)
+ for (i = 1; i < n_fs; i++)
{
- ossl_check_err_is_fatal (ssl, rv);
- break;
+ rv = SSL_read (ssl, fs[i].data, fs[i].len);
+ read += rv > 0 ? rv : 0;
+
+ if (rv < (int) fs[i].len)
+ {
+ ossl_check_err_is_fatal (ssl, rv);
+ break;
+ }
}
}
-
svm_fifo_enqueue_nocopy (f, read);
return read;
static void
openssl_handle_handshake_failure (tls_ctx_t * ctx)
{
- session_t *app_session;
+ /* Failed to renegotiate handshake */
+ if (ctx->flags & TLS_CONN_F_HS_DONE)
+ {
+ tls_notify_app_io_error (ctx);
+ tls_disconnect_transport (ctx);
+ return;
+ }
if (SSL_is_server (((openssl_ctx_t *) ctx)->ssl))
{
- /*
- * Cleanup pre-allocated app session and close transport
- */
- app_session =
- session_get_if_valid (ctx->c_s_index, ctx->c_thread_index);
- if (app_session)
- {
- session_free (app_session);
- ctx->no_app_session = 1;
- ctx->c_s_index = SESSION_INVALID_INDEX;
- tls_disconnect_transport (ctx);
- }
+ ctx->flags |= TLS_CONN_F_NO_APP_SESSION;
+ tls_disconnect_transport (ctx);
}
else
{
while (SSL_in_init (oc->ssl))
{
- if (ctx->resume)
+ if (ctx->flags & TLS_CONN_F_RESUME)
{
- ctx->resume = 0;
+ ctx->flags &= ~TLS_CONN_F_RESUME;
}
else if (!svm_fifo_max_dequeue_cons (tls_session->rx_fifo))
break;
if (SSL_in_init (oc->ssl))
return -1;
+ /* Renegotiated handshake, app must not be notified */
+ if (PREDICT_FALSE (ctx->flags & TLS_CONN_F_HS_DONE))
+ return 0;
+
/*
* Handshake complete
*/
return -1;
}
}
- tls_notify_app_connected (ctx, SESSION_E_NONE);
+ if (tls_notify_app_connected (ctx, SESSION_E_NONE))
+ {
+ tls_disconnect_transport (ctx);
+ return -1;
+ }
}
else
{
/* Need to check transport status */
- if (ctx->is_passive_close)
+ if (ctx->flags & TLS_CONN_F_PASSIVE_CLOSE)
{
openssl_handle_handshake_failure (ctx);
return -1;
return -1;
}
}
-
+ ctx->flags |= TLS_CONN_F_HS_DONE;
TLS_DBG (1, "Handshake for %u complete. TLS cipher is %s",
oc->openssl_ctx_index, SSL_get_cipher (oc->ssl));
return rv;
check_tls_fifo:
- if (PREDICT_FALSE (ctx->app_closed && BIO_ctrl_pending (oc->rbio) <= 0))
+ if (PREDICT_FALSE ((ctx->flags & TLS_CONN_F_APP_CLOSED) &&
+ BIO_ctrl_pending (oc->rbio) <= 0))
openssl_confirm_app_close (ctx);
/* Deschedule and wait for deq notification if fifo is almost full */
if (read)
tls_add_vpp_q_tx_evt (us);
- if (PREDICT_FALSE (ctx->app_closed &&
+ if (PREDICT_FALSE ((ctx->flags & TLS_CONN_F_APP_CLOSED) &&
!svm_fifo_max_enqueue_prod (us->rx_fifo)))
openssl_confirm_app_close (ctx);
openssl_ctx_read_tls (tls_ctx_t *ctx, session_t *tls_session)
{
openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
+ const u32 max_len = 128 << 10;
session_t *app_session;
- int read;
svm_fifo_t *f;
+ int read;
if (PREDICT_FALSE (SSL_in_init (oc->ssl)))
{
if (openssl_ctx_handshake_rx (ctx, tls_session) < 0)
return 0;
+
+ /* Application might force a session pool realloc on accept */
+ tls_session = session_get_from_handle (ctx->tls_session_handle);
}
app_session = session_get_from_handle (ctx->app_session_handle);
f = app_session->rx_fifo;
- read = openssl_read_from_ssl_into_fifo (f, oc->ssl);
+ read = openssl_read_from_ssl_into_fifo (f, oc->ssl, max_len);
/* Unrecoverable protocol error. Reset connection */
if (PREDICT_FALSE (read < 0))
return 0;
}
- /* If handshake just completed, session may still be in accepting state */
- if (read && app_session->session_state >= SESSION_STATE_READY)
+ if (read)
tls_notify_app_enqueue (ctx, app_session);
if ((SSL_pending (oc->ssl) > 0) ||
}
static int
-openssl_set_ckpair (SSL *ssl_connection, u32 ckpair_index)
+openssl_set_ckpair (SSL *ssl, u32 ckpair_index)
{
app_cert_key_pair_t *ckpair;
BIO *cert_bio;
EVP_PKEY *pkey;
X509 *srvcert;
+ /* Configure a ckpair index only if non-default/test provided */
+ if (ckpair_index == 0)
+ return 0;
+
ckpair = app_cert_key_pair_get_if_valid (ckpair_index);
if (!ckpair)
return -1;
clib_warning ("unable to parse certificate");
return -1;
}
- SSL_use_certificate (ssl_connection, srvcert);
+ SSL_use_certificate (ssl, srvcert);
BIO_free (cert_bio);
cert_bio = BIO_new (BIO_s_mem ());
clib_warning ("unable to parse pkey");
return -1;
}
- SSL_use_PrivateKey (ssl_connection, pkey);
+ SSL_use_PrivateKey (ssl, pkey);
BIO_free (cert_bio);
TLS_DBG (1, "TLS client using ckpair index: %d", ckpair_index);
return 0;
}
static int
-openssl_ctx_init_verify (tls_ctx_t *ctx, int set_hostname_verification,
- int set_hostname_strict_check)
+openssl_client_init_verify (SSL *ssl, const char *srv_hostname,
+ int set_hostname_verification,
+ int set_hostname_strict_check)
{
- openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
- SSL *ssl = oc->ssl;
-
if (set_hostname_verification)
{
X509_VERIFY_PARAM *param = SSL_get0_param (ssl);
X509_VERIFY_PARAM_set_hostflags (param,
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
- if (!X509_VERIFY_PARAM_set1_host (param,
- (const char *) ctx->srv_hostname, 0))
+ if (!X509_VERIFY_PARAM_set1_host (param, srv_hostname, 0))
{
TLS_DBG (1, "Couldn't set hostname for verification");
return -1;
}
SSL_set_verify (ssl, SSL_VERIFY_PEER, 0);
}
- if (!SSL_set_tlsext_host_name (ssl, ctx->srv_hostname))
+ if (!SSL_set_tlsext_host_name (ssl, srv_hostname))
{
TLS_DBG (1, "Couldn't set hostname");
return -1;
return -1;
}
- oc->ssl_ctx = SSL_CTX_new (method);
- if (oc->ssl_ctx == NULL)
+ oc->client_ssl_ctx = SSL_CTX_new (method);
+ if (oc->client_ssl_ctx == NULL)
{
TLS_DBG (1, "SSL_CTX_new returned null");
return -1;
}
- SSL_CTX_set_ecdh_auto (oc->ssl_ctx, 1);
- SSL_CTX_set_mode (oc->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
+ SSL_CTX_set_ecdh_auto (oc->client_ssl_ctx, 1);
+ SSL_CTX_set_mode (oc->client_ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
#ifdef HAVE_OPENSSL_ASYNC
if (om->async)
- SSL_CTX_set_mode (oc->ssl_ctx, SSL_MODE_ASYNC);
+ SSL_CTX_set_mode (oc->client_ssl_ctx, SSL_MODE_ASYNC);
#endif
- rv = SSL_CTX_set_cipher_list (oc->ssl_ctx, (const char *) om->ciphers);
+ rv =
+ SSL_CTX_set_cipher_list (oc->client_ssl_ctx, (const char *) om->ciphers);
if (rv != 1)
{
TLS_DBG (1, "Couldn't set cipher");
return -1;
}
- SSL_CTX_set_options (oc->ssl_ctx, flags);
- SSL_CTX_set_cert_store (oc->ssl_ctx, om->cert_store);
+ SSL_CTX_set_options (oc->client_ssl_ctx, flags);
+ SSL_CTX_set1_cert_store (oc->client_ssl_ctx, om->cert_store);
- oc->ssl = SSL_new (oc->ssl_ctx);
+ oc->ssl = SSL_new (oc->client_ssl_ctx);
if (oc->ssl == NULL)
{
TLS_DBG (1, "Couldn't initialize ssl struct");
SSL_set_bio (oc->ssl, oc->wbio, oc->rbio);
SSL_set_connect_state (oc->ssl);
- /* Hostname validation and strict check by name, are disable by default */
- rv = openssl_ctx_init_verify (ctx, 0, 0);
+ /* Hostname validation and strict check by name are disabled by default */
+ rv = openssl_client_init_verify (oc->ssl, (const char *) ctx->srv_hostname,
+ 0, 0);
if (rv)
{
TLS_DBG (1, "ERROR:verify init failed:%d", rv);
return 0;
}
+static int
+openssl_transport_reset (tls_ctx_t *ctx)
+{
+ if (!openssl_handshake_is_over (ctx))
+ {
+ openssl_handle_handshake_failure (ctx);
+ return 0;
+ }
+
+ session_transport_reset_notify (&ctx->connection);
+ session_transport_closed_notify (&ctx->connection);
+ tls_disconnect_transport (ctx);
+
+ return 0;
+}
+
static int
openssl_app_close (tls_ctx_t * ctx)
{
if (BIO_ctrl_pending (oc->rbio) <= 0
&& !svm_fifo_max_dequeue_cons (app_session->tx_fifo))
openssl_confirm_app_close (ctx);
- else
- ctx->app_closed = 1;
return 0;
}
.ctx_start_listen = openssl_start_listen,
.ctx_stop_listen = openssl_stop_listen,
.ctx_transport_close = openssl_transport_close,
+ .ctx_transport_reset = openssl_transport_reset,
.ctx_app_close = openssl_app_close,
.ctx_reinit_cachain = openssl_reinit_ca_chain,
};
return error;
}
-/* *INDENT-OFF* */
VLIB_INIT_FUNCTION (tls_openssl_init) =
{
.runs_after = VLIB_INITS("tls_init"),
};
-/* *INDENT-ON* */
#ifdef HAVE_OPENSSL_ASYNC
static clib_error_t *
return 0;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (tls_openssl_set_command, static) =
{
.path = "tls openssl set",
.short_help = "tls openssl set [engine <engine name>] [alg [algorithm] [async]",
.function = tls_openssl_set_command_fn,
};
-/* *INDENT-ON* */
#endif
-/* *INDENT-OFF* */
VLIB_PLUGIN_REGISTER () = {
.version = VPP_BUILD_VER,
.description = "Transport Layer Security (TLS) Engine, OpenSSL Based",
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON