diff options
Diffstat (limited to 'src/plugins/tlsopenssl/tls_openssl.c')
-rw-r--r-- | src/plugins/tlsopenssl/tls_openssl.c | 211 |
1 files changed, 169 insertions, 42 deletions
diff --git a/src/plugins/tlsopenssl/tls_openssl.c b/src/plugins/tlsopenssl/tls_openssl.c index c8e685f20c5..d7adbed3269 100644 --- a/src/plugins/tlsopenssl/tls_openssl.c +++ b/src/plugins/tlsopenssl/tls_openssl.c @@ -74,9 +74,16 @@ openssl_ctx_free (tls_ctx_t * ctx) 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 + + if (openssl_main.async) + { + openssl_evt_free (oc->evt_index[SSL_ASYNC_EVT_INIT], + ctx->c_thread_index); + openssl_evt_free (oc->evt_index[SSL_ASYNC_EVT_RD], + ctx->c_thread_index); + openssl_evt_free (oc->evt_index[SSL_ASYNC_EVT_WR], + ctx->c_thread_index); + } } pool_put_index (openssl_main.ctx_pool[ctx->c_thread_index], @@ -159,17 +166,43 @@ openssl_lctx_get (u32 lctx_index) return pool_elt_at_index (openssl_main.lctx_pool, lctx_index); } -#define ossl_check_err_is_fatal(_ssl, _rv) \ - if (PREDICT_FALSE (_rv < 0 && SSL_get_error (_ssl, _rv) == SSL_ERROR_SSL)) \ - return -1; - static int -openssl_read_from_ssl_into_fifo (svm_fifo_t *f, SSL *ssl, u32 max_len) +openssl_handle_want_async (tls_ctx_t *ctx, int evt_type, + transport_send_params_t *sp, int size) +{ + int ret; + openssl_ctx_t *oc = (openssl_ctx_t *) ctx; + + if (evt_type >= SSL_ASYNC_EVT_MAX || evt_type == 0) + { + clib_warning ("return 0 [illegal evt_type value:%d]\n", evt_type); + return 0; + } + + if (evt_type == SSL_ASYNC_EVT_WR) + { + /* de-schedule transport connection */ + transport_connection_deschedule (&ctx->connection); + sp->flags |= TRANSPORT_SND_F_DESCHED; + oc->total_async_write = size; + } + ret = vpp_tls_async_enqueue_event (oc, evt_type, sp, size); + + return ret; +} + +int +openssl_read_from_ssl_into_fifo (svm_fifo_t *f, tls_ctx_t *ctx, u32 max_len) { int read, rv, n_fs, i; + openssl_ctx_t *oc = (openssl_ctx_t *) ctx; const int n_segs = 2; svm_fifo_seg_t fs[n_segs]; u32 max_enq; + SSL *ssl = oc->ssl; + + if (ctx->flags & TLS_CONN_F_ASYNC_RD) + return 0; max_enq = svm_fifo_max_enqueue_prod (f); if (!max_enq) @@ -184,6 +217,12 @@ openssl_read_from_ssl_into_fifo (svm_fifo_t *f, SSL *ssl, u32 max_len) read = SSL_read (ssl, fs[0].data, fs[0].len); if (read <= 0) { + if (openssl_main.async && SSL_want_async (oc->ssl)) + { + ctx->flags |= TLS_CONN_F_ASYNC_RD; + openssl_handle_want_async (ctx, SSL_ASYNC_EVT_RD, NULL, 0); + return 0; + } ossl_check_err_is_fatal (ssl, read); return 0; } @@ -208,11 +247,14 @@ openssl_read_from_ssl_into_fifo (svm_fifo_t *f, SSL *ssl, u32 max_len) } static int -openssl_write_from_fifo_into_ssl (svm_fifo_t *f, SSL *ssl, u32 max_len) +openssl_write_from_fifo_into_ssl (svm_fifo_t *f, tls_ctx_t *ctx, + transport_send_params_t *sp, u32 max_len) { int wrote = 0, rv, i = 0, len; u32 n_segs = 2; svm_fifo_seg_t fs[n_segs]; + openssl_ctx_t *oc = (openssl_ctx_t *) ctx; + SSL *ssl = oc->ssl; len = svm_fifo_segments (f, 0, fs, &n_segs, max_len); if (len <= 0) @@ -230,6 +272,11 @@ openssl_write_from_fifo_into_ssl (svm_fifo_t *f, SSL *ssl, u32 max_len) i++; } + if (openssl_main.async && SSL_want_async (ssl)) + { + openssl_handle_want_async (ctx, SSL_ASYNC_EVT_WR, sp, max_len); + return 0; + } if (wrote) svm_fifo_dequeue_drop (f, wrote); @@ -247,11 +294,15 @@ openssl_check_async_status (tls_ctx_t * ctx, openssl_resume_handler * handler, SSL_get_async_status (oc->ssl, &estatus); if (estatus == ASYNC_STATUS_EAGAIN) { - vpp_tls_async_update_event (ctx, 1); + vpp_tls_async_update_event (ctx, 1, SSL_ASYNC_EVT_INIT); + vpp_tls_async_update_event (ctx, 1, SSL_ASYNC_EVT_RD); + vpp_tls_async_update_event (ctx, 1, SSL_ASYNC_EVT_WR); } else { - vpp_tls_async_update_event (ctx, 0); + vpp_tls_async_update_event (ctx, 0, SSL_ASYNC_EVT_INIT); + vpp_tls_async_update_event (ctx, 0, SSL_ASYNC_EVT_RD); + vpp_tls_async_update_event (ctx, 0, SSL_ASYNC_EVT_WR); } return 1; @@ -260,8 +311,8 @@ openssl_check_async_status (tls_ctx_t * ctx, openssl_resume_handler * handler, #endif -static void -openssl_handle_handshake_failure (tls_ctx_t * ctx) +void +openssl_handle_handshake_failure (tls_ctx_t *ctx) { /* Failed to renegotiate handshake */ if (ctx->flags & TLS_CONN_F_HS_DONE) @@ -304,19 +355,17 @@ openssl_ctx_handshake_rx (tls_ctx_t * ctx, session_t * tls_session) rv = SSL_do_handshake (oc->ssl); err = SSL_get_error (oc->ssl, rv); -#ifdef HAVE_OPENSSL_ASYNC - if (err == SSL_ERROR_WANT_ASYNC) + if (openssl_main.async && err == SSL_ERROR_WANT_ASYNC) { - openssl_check_async_status (ctx, openssl_ctx_handshake_rx, - tls_session); + openssl_handle_want_async (ctx, SSL_ASYNC_EVT_INIT, NULL, 0); + return -1; } -#endif + if (err == SSL_ERROR_SSL) { char buf[512]; ERR_error_string (ERR_get_error (), buf); clib_warning ("Err: %s", buf); - openssl_handle_handshake_failure (ctx); return -1; } @@ -385,8 +434,8 @@ openssl_ctx_handshake_rx (tls_ctx_t * ctx, session_t * tls_session) return rv; } -static void -openssl_confirm_app_close (tls_ctx_t * ctx) +void +openssl_confirm_app_close (tls_ctx_t *ctx) { openssl_ctx_t *oc = (openssl_ctx_t *) ctx; SSL_shutdown (oc->ssl); @@ -425,7 +474,7 @@ openssl_ctx_write_tls (tls_ctx_t *ctx, session_t *app_session, if (svm_fifo_provision_chunks (ts->tx_fifo, 0, 0, deq_max + TLSO_CTRL_BYTES)) goto check_tls_fifo; - wrote = openssl_write_from_fifo_into_ssl (f, oc->ssl, deq_max); + wrote = openssl_write_from_fifo_into_ssl (f, ctx, sp, deq_max); /* Unrecoverable protocol error. Reset connection */ if (PREDICT_FALSE (wrote < 0)) @@ -556,7 +605,7 @@ openssl_ctx_read_tls (tls_ctx_t *ctx, session_t *tls_session) 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, max_len); + read = openssl_read_from_ssl_into_fifo (f, ctx, max_len); /* Unrecoverable protocol error. Reset connection */ if (PREDICT_FALSE (read < 0)) @@ -753,10 +802,9 @@ openssl_ctx_init_client (tls_ctx_t * ctx) 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->client_ssl_ctx, SSL_MODE_ASYNC); -#endif + rv = SSL_CTX_set_cipher_list (oc->client_ssl_ctx, (const char *) om->ciphers); if (rv != 1) @@ -801,7 +849,17 @@ openssl_ctx_init_client (tls_ctx_t * ctx) { TLS_DBG (1, "Couldn't set client certificate-key pair"); } - + /* Set TLS Record size */ + if (om->record_size) + { + rv = SSL_CTX_set_max_send_fragment (oc->client_ssl_ctx, om->record_size); + if (rv != 1) + { + TLS_DBG (1, "Couldn't set TLS record-size"); + return -1; + } + TLS_DBG (1, "Using TLS record-size of %d", om->record_size); + } /* * 2. Do the first steps in the handshake. */ @@ -810,7 +868,7 @@ openssl_ctx_init_client (tls_ctx_t * ctx) #ifdef HAVE_OPENSSL_ASYNC session_t *tls_session = session_get_from_handle (ctx->tls_session_handle); - vpp_tls_async_init_event (ctx, openssl_ctx_handshake_rx, tls_session); + vpp_tls_async_init_events (ctx, openssl_ctx_handshake_rx, tls_session); #endif while (1) { @@ -828,7 +886,7 @@ openssl_ctx_init_client (tls_ctx_t * ctx) break; } - TLS_DBG (2, "tls state for [%u]%u is su", ctx->c_thread_index, + TLS_DBG (2, "tls state for [%u]%u is %s", ctx->c_thread_index, oc->openssl_ctx_index, SSL_state_string_long (oc->ssl)); return 0; } @@ -895,6 +953,39 @@ openssl_start_listen (tls_ctx_t * lctx) return -1; } + /* Set TLS Record size */ + if (om->record_size) + { + rv = SSL_CTX_set_max_send_fragment (ssl_ctx, om->record_size); + if (rv != 1) + { + TLS_DBG (1, "Couldn't set TLS record-size"); + return -1; + } + } + + /* Set TLS Record Split size */ + if (om->record_split_size) + { + rv = SSL_CTX_set_split_send_fragment (ssl_ctx, om->record_split_size); + if (rv != 1) + { + TLS_DBG (1, "Couldn't set TLS record-split-size"); + return -1; + } + } + + /* Set TLS Max Pipeline count */ + if (om->max_pipelines) + { + rv = SSL_CTX_set_max_pipelines (ssl_ctx, om->max_pipelines); + if (rv != 1) + { + TLS_DBG (1, "Couldn't set TLS max-pipelines"); + return -1; + } + } + /* * Set the key and cert */ @@ -1012,22 +1103,23 @@ openssl_ctx_init_server (tls_ctx_t * ctx) TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index, oc->openssl_ctx_index); -#ifdef HAVE_OPENSSL_ASYNC - session_t *tls_session = session_get_from_handle (ctx->tls_session_handle); - vpp_tls_async_init_event (ctx, openssl_ctx_handshake_rx, tls_session); -#endif + if (openssl_main.async) + { + session_t *tls_session = + session_get_from_handle (ctx->tls_session_handle); + vpp_tls_async_init_events (ctx, openssl_ctx_handshake_rx, tls_session); + } + while (1) { rv = SSL_do_handshake (oc->ssl); err = SSL_get_error (oc->ssl, rv); -#ifdef HAVE_OPENSSL_ASYNC - if (err == SSL_ERROR_WANT_ASYNC) + if (openssl_main.async && err == SSL_ERROR_WANT_ASYNC) { - openssl_check_async_status (ctx, openssl_ctx_handshake_rx, - tls_session); + openssl_handle_want_async (ctx, SSL_ASYNC_EVT_INIT, NULL, 0); + break; } -#endif if (err != SSL_ERROR_WANT_WRITE) break; } @@ -1040,10 +1132,8 @@ openssl_ctx_init_server (tls_ctx_t * ctx) static int openssl_transport_close (tls_ctx_t * ctx) { -#ifdef HAVE_OPENSSL_ASYNC - if (vpp_openssl_is_inflight (ctx)) + if (openssl_main.async && vpp_openssl_is_inflight (ctx)) return 0; -#endif if (!(ctx->flags & TLS_CONN_F_HS_DONE)) { @@ -1224,7 +1314,6 @@ VLIB_INIT_FUNCTION (tls_openssl_init) = .runs_after = VLIB_INITS("tls_init"), }; -#ifdef HAVE_OPENSSL_ASYNC static clib_error_t * tls_openssl_set_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -1302,7 +1391,45 @@ VLIB_CLI_COMMAND (tls_openssl_set_command, static) = .short_help = "tls openssl set [engine <engine name>] [alg [algorithm] [async]", .function = tls_openssl_set_command_fn, }; -#endif + +static clib_error_t * +tls_openssl_set_tls_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + openssl_main_t *om = &openssl_main; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "record-size %U", unformat_memory_size, + &om->record_size)) + { + clib_warning ("Using TLS record-size of %d", om->record_size); + } + else if (unformat (input, "record-split-size %U", unformat_memory_size, + &om->record_split_size)) + { + clib_warning ("Using TLS record-split-size of %d", + om->record_split_size); + } + else if (unformat (input, "max-pipelines %U", unformat_memory_size, + &om->max_pipelines)) + { + clib_warning ("Using TLS max-pipelines of %d", om->max_pipelines); + } + else + return clib_error_return (0, "failed: unknown input `%U'", + format_unformat_error, input); + } + + return 0; +} + +VLIB_CLI_COMMAND (tls_openssl_set_tls, static) = { + .path = "tls openssl set-tls", + .short_help = "tls openssl set-tls [record-size <size>] [record-split-size " + "<size>] [max-pipelines <size>]", + .function = tls_openssl_set_tls_fn, +}; VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, |