tls: add openssl engine

Change-Id: I6c215858d2c9c620787632b570950b15274c0df2
Signed-off-by: Florin Coras <fcoras@cisco.com>
This commit is contained in:
Florin Coras
2018-03-09 13:05:53 -08:00
committed by Dave Barach
parent 46c1c11ba0
commit 58d36f02b4
14 changed files with 1028 additions and 191 deletions

View File

@ -231,6 +231,7 @@ PLUGIN_ENABLED(srv6am)
PLUGIN_ENABLED(srv6as)
PLUGIN_ENABLED(stn)
PLUGIN_ENABLED(tlsmbedtls)
PLUGIN_ENABLED(tlsopenssl)
###############################################################################
# Dependency checks
@ -306,6 +307,12 @@ AM_COND_IF([ENABLE_TLSMBEDTLS_PLUGIN],
], [])
])
AM_COND_IF([WITH_LIBSSL], [],
[
AC_MSG_WARN([openssl not enabled. Disabling tlsopenssl plugin])
enable_tlsopenssl_plugin=no
AM_CONDITIONAL(ENABLE_TLSOPENSSL_PLUGIN, false)
])
###############################################################################
# JAVA

View File

@ -115,6 +115,10 @@ if ENABLE_TLSMBEDTLS_PLUGIN
include tlsmbedtls.am
endif
if ENABLE_TLSOPENSSL_PLUGIN
include tlsopenssl.am
endif
include ../suffix-rules.mk
# Remove *.la files

View File

@ -28,6 +28,7 @@
typedef struct tls_ctx_mbedtls_
{
tls_ctx_t ctx; /**< First */
u32 mbedtls_ctx_index;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt srvcert;
@ -40,6 +41,8 @@ typedef struct mbedtls_main_
mbedtls_ctr_drbg_context *ctr_drbgs;
mbedtls_entropy_context *entropy_pools;
mbedtls_x509_crt cacert;
u8 **rx_bufs;
u8 **tx_bufs;
} mbedtls_main_t;
static mbedtls_main_t mbedtls_main;
@ -64,7 +67,7 @@ mbedtls_free_fn (void *ptr)
}
#endif
u32
static u32
mbedtls_ctx_alloc (void)
{
u8 thread_index = vlib_get_thread_index ();
@ -77,10 +80,12 @@ mbedtls_ctx_alloc (void)
memset (*ctx, 0, sizeof (mbedtls_ctx_t));
(*ctx)->ctx.c_thread_index = thread_index;
return ctx - tm->ctx_pool[thread_index];
(*ctx)->ctx.tls_ctx_engine = TLS_ENGINE_MBEDTLS;
(*ctx)->mbedtls_ctx_index = ctx - tm->ctx_pool[thread_index];
return ((*ctx)->mbedtls_ctx_index);
}
void
static void
mbedtls_ctx_free (tls_ctx_t * ctx)
{
mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
@ -95,11 +100,11 @@ mbedtls_ctx_free (tls_ctx_t * ctx)
mbedtls_ssl_free (&mc->ssl);
mbedtls_ssl_config_free (&mc->conf);
pool_put_index (mbedtls_main.ctx_pool[vlib_get_thread_index ()],
ctx->tls_ctx_idx);
pool_put_index (mbedtls_main.ctx_pool[ctx->c_thread_index],
mc->mbedtls_ctx_index);
}
tls_ctx_t *
static tls_ctx_t *
mbedtls_ctx_get (u32 ctx_index)
{
mbedtls_ctx_t **ctx;
@ -108,7 +113,7 @@ mbedtls_ctx_get (u32 ctx_index)
return &(*ctx)->ctx;
}
tls_ctx_t *
static tls_ctx_t *
mbedtls_ctx_get_w_thread (u32 ctx_index, u8 thread_index)
{
mbedtls_ctx_t **ctx;
@ -233,7 +238,7 @@ mbedtls_ctx_init_client (tls_ctx_t * ctx)
return -1;
}
ctx_ptr = uword_to_pointer (ctx->tls_ctx_idx, void *);
ctx_ptr = uword_to_pointer (mc->mbedtls_ctx_index, void *);
mbedtls_ssl_set_bio (&mc->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_CLIENT);
@ -241,7 +246,7 @@ mbedtls_ctx_init_client (tls_ctx_t * ctx)
* 2. Do the first 2 steps in the handshake.
*/
TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
ctx->tls_ctx_idx);
mc->mbedtls_ctx_index);
while (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
{
rv = mbedtls_ssl_handshake_step (&mc->ssl);
@ -249,7 +254,7 @@ mbedtls_ctx_init_client (tls_ctx_t * ctx)
break;
}
TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
ctx->tls_ctx_idx, mc->ssl.state);
mc->mbedtls_ctx_index, mc->ssl.state);
return 0;
}
@ -332,7 +337,7 @@ mbedtls_ctx_init_server (tls_ctx_t * ctx)
}
mbedtls_ssl_session_reset (&mc->ssl);
ctx_ptr = uword_to_pointer (ctx->tls_ctx_idx, void *);
ctx_ptr = uword_to_pointer (mc->mbedtls_ctx_index, void *);
mbedtls_ssl_set_bio (&mc->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_SERVER);
@ -340,7 +345,7 @@ mbedtls_ctx_init_server (tls_ctx_t * ctx)
* 3. Start handshake state machine
*/
TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
ctx->tls_ctx_idx);
mc->mbedtls_ctx_index);
while (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
{
rv = mbedtls_ssl_handshake_step (&mc->ssl);
@ -349,7 +354,7 @@ mbedtls_ctx_init_server (tls_ctx_t * ctx)
}
TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
ctx->tls_ctx_idx, mc->ssl.state);
mc->mbedtls_ctx_index, mc->ssl.state);
return 0;
exit:
@ -357,7 +362,7 @@ exit:
}
static int
mbedtls_handshake_rx (tls_ctx_t * ctx)
mbedtls_ctx_handshake_rx (tls_ctx_t * ctx)
{
mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
u32 flags;
@ -368,10 +373,10 @@ mbedtls_handshake_rx (tls_ctx_t * ctx)
if (rv != 0)
break;
}
TLS_DBG (2, "tls state for %u is %u", ctx->tls_ctx_idx, mc->ssl.state);
TLS_DBG (2, "tls state for %u is %u", mc->mbedtls_ctx_index, mc->ssl.state);
if (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
return HANDSHAKE_NOT_OVER;
return 0;
/*
* Handshake complete
@ -392,32 +397,120 @@ mbedtls_handshake_rx (tls_ctx_t * ctx)
* Presence of hostname enforces strict certificate verification
*/
if (ctx->srv_hostname)
return CLIENT_HANDSHAKE_FAIL;
{
tls_notify_app_connected (ctx, /* is failed */ 0);
return -1;
}
}
rv = CLIENT_HANDSHAKE_OK;
tls_notify_app_connected (ctx, /* is failed */ 0);
}
else
{
rv = SERVER_HANDSHAKE_OK;
tls_notify_app_accept (ctx);
}
TLS_DBG (1, "Handshake for %u complete. TLS cipher is %x",
ctx->tls_ctx_idx, mc->ssl.session->ciphersuite);
return rv;
mc->mbedtls_ctx_index, mc->ssl.session->ciphersuite);
return 0;
}
static int
mbedtls_write (tls_ctx_t * ctx, u8 * buf, u32 len)
mbedtls_ctx_write (tls_ctx_t * ctx, stream_session_t * app_session)
{
mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
return mbedtls_ssl_write (&mc->ssl, buf, len);
u8 thread_index = ctx->c_thread_index;
mbedtls_main_t *mm = &mbedtls_main;
u32 enq_max, deq_max, deq_now;
stream_session_t *tls_session;
int wrote;
ASSERT (mc->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
deq_max = svm_fifo_max_dequeue (app_session->server_tx_fifo);
if (!deq_max)
return 0;
tls_session = session_get_from_handle (ctx->tls_session_handle);
enq_max = svm_fifo_max_enqueue (tls_session->server_tx_fifo);
deq_now = clib_min (deq_max, TLS_CHUNK_SIZE);
if (PREDICT_FALSE (enq_max == 0))
{
tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
return 0;
}
vec_validate (mm->tx_bufs[thread_index], deq_now);
svm_fifo_peek (app_session->server_tx_fifo, 0, deq_now,
mm->tx_bufs[thread_index]);
wrote = mbedtls_ssl_write (&mc->ssl, mm->tx_bufs[thread_index], deq_now);
if (wrote <= 0)
{
tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
return 0;
}
svm_fifo_dequeue_drop (app_session->server_tx_fifo, wrote);
vec_reset_length (mm->tx_bufs[thread_index]);
tls_add_vpp_q_evt (tls_session->server_tx_fifo, FIFO_EVENT_APP_TX);
if (deq_now < deq_max)
tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
return 0;
}
static int
mbedtls_read (tls_ctx_t * ctx, u8 * buf, u32 len)
mbedtls_ctx_read (tls_ctx_t * ctx, stream_session_t * tls_session)
{
mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
return mbedtls_ssl_read (&mc->ssl, buf, len);
mbedtls_main_t *mm = &mbedtls_main;
u8 thread_index = ctx->c_thread_index;
u32 deq_max, enq_max, enq_now;
stream_session_t *app_session;
int read, enq;
if (PREDICT_FALSE (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER))
{
mbedtls_ctx_handshake_rx (ctx);
return 0;
}
deq_max = svm_fifo_max_dequeue (tls_session->server_rx_fifo);
if (!deq_max)
return 0;
app_session = session_get_from_handle (ctx->app_session_handle);
enq_max = svm_fifo_max_enqueue (app_session->server_rx_fifo);
enq_now = clib_min (enq_max, TLS_CHUNK_SIZE);
if (PREDICT_FALSE (enq_now == 0))
{
tls_add_vpp_q_evt (tls_session->server_rx_fifo, FIFO_EVENT_BUILTIN_RX);
return 0;
}
vec_validate (mm->rx_bufs[thread_index], enq_now);
read = mbedtls_ssl_read (&mc->ssl, mm->rx_bufs[thread_index], enq_now);
if (read <= 0)
{
tls_add_vpp_q_evt (tls_session->server_rx_fifo, FIFO_EVENT_BUILTIN_RX);
return 0;
}
enq = svm_fifo_enqueue_nowait (app_session->server_rx_fifo, read,
mm->rx_bufs[thread_index]);
ASSERT (enq == read);
vec_reset_length (mm->rx_bufs[thread_index]);
if (svm_fifo_max_dequeue (tls_session->server_rx_fifo))
tls_add_vpp_q_evt (tls_session->server_rx_fifo, FIFO_EVENT_BUILTIN_RX);
if (enq > 0)
tls_notify_app_enqueue (ctx, app_session);
return enq;
}
static u8
@ -434,9 +527,8 @@ const static tls_engine_vft_t mbedtls_engine = {
.ctx_get_w_thread = mbedtls_ctx_get_w_thread,
.ctx_init_server = mbedtls_ctx_init_server,
.ctx_init_client = mbedtls_ctx_init_client,
.ctx_handshake_rx = mbedtls_handshake_rx,
.ctx_write = mbedtls_write,
.ctx_read = mbedtls_read,
.ctx_write = mbedtls_ctx_write,
.ctx_read = mbedtls_ctx_read,
.ctx_handshake_is_over = mbedtls_handshake_is_over,
};
@ -526,6 +618,9 @@ tls_mbedtls_init (vlib_main_t * vm)
}
vec_validate (mm->ctx_pool, num_threads - 1);
vec_validate (mm->rx_bufs, num_threads - 1);
vec_validate (mm->tx_bufs, num_threads - 1);
tls_register_engine (&mbedtls_engine, TLS_ENGINE_MBEDTLS);
return 0;
}

21
src/plugins/tlsopenssl.am Normal file
View File

@ -0,0 +1,21 @@
# Copyright (c) 2018 Cisco Systems, Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
vppplugins_LTLIBRARIES += tlsopenssl_plugin.la
tlsopenssl_plugin_la_SOURCES = tlsopenssl/tls_openssl.c
tlsopenssl_plugin_la_LDFLAGS = $(AM_LDFLAGS) -lssl -lcrypto
tlsopenssl_plugin_la_CFLAGS = $(AM_CFLAGS)
# vi:syntax=automake

File diff suppressed because it is too large Load Diff

View File

@ -167,6 +167,49 @@ svm_fifo_newest_ooo_segment_reset (svm_fifo_t * f)
f->ooos_newest = OOO_SEGMENT_INVALID_INDEX;
}
/**
* Max contiguous chunk of data that can be read
*/
always_inline u32
svm_fifo_max_read_chunk (svm_fifo_t * f)
{
return ((f->tail > f->head) ? (f->tail - f->head) : (f->nitems - f->head));
}
/**
* Max contiguous chunk of data that can be written
*/
always_inline u32
svm_fifo_max_write_chunk (svm_fifo_t * f)
{
return ((f->tail >= f->head) ? (f->nitems - f->tail) : (f->head - f->tail));
}
/**
* Advance tail pointer
*
* Useful for moving tail pointer after external enqueue.
*/
always_inline void
svm_fifo_enqueue_nocopy (svm_fifo_t * f, u32 bytes)
{
ASSERT (bytes <= svm_fifo_max_enqueue (f));
f->tail = (f->tail + bytes) % f->nitems;
f->cursize += bytes;
}
always_inline u8 *
svm_fifo_head (svm_fifo_t * f)
{
return (f->data + f->head);
}
always_inline u8 *
svm_fifo_tail (svm_fifo_t * f)
{
return (f->data + f->tail);
}
always_inline u32
ooo_segment_distance_from_tail (svm_fifo_t * f, u32 pos)
{

View File

@ -458,8 +458,8 @@ echo_clients_attach (u8 * appns_id, u64 appns_flags, u64 appns_secret)
options[APP_OPTIONS_TX_FIFO_SIZE] = ecm->fifo_size;
options[APP_OPTIONS_PRIVATE_SEGMENT_COUNT] = ecm->private_segment_count;
options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = prealloc_fifos;
options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
options[APP_OPTIONS_TLS_ENGINE] = ecm->tls_engine;
if (appns_id)
{
options[APP_OPTIONS_FLAGS] |= appns_flags;
@ -575,6 +575,8 @@ echo_clients_command_fn (vlib_main_t * vm,
ecm->test_bytes = 0;
ecm->test_failed = 0;
ecm->vlib_main = vm;
ecm->tls_engine = TLS_ENGINE_OPENSSL;
if (thread_main->n_vlib_mains > 1)
clib_spinlock_init (&ecm->sessions_lock);
vec_free (ecm->connect_uri);
@ -632,6 +634,8 @@ echo_clients_command_fn (vlib_main_t * vm,
ecm->no_output = 1;
else if (unformat (input, "test-bytes"))
ecm->test_bytes = 1;
else if (unformat (input, "tls-engine %d", &ecm->tls_engine))
;
else
return clib_error_return (0, "failed: unknown input `%U'",
format_unformat_error, input);

View File

@ -64,7 +64,7 @@ typedef struct
u32 connections_per_batch; /**< Connections to rx/tx at once */
u32 private_segment_count; /**< Number of private fifo segs */
u32 private_segment_size; /**< size of private fifo segs */
u32 tls_engine; /**< TLS engine mbedtls/openssl */
/*
* Test state variables
*/

View File

@ -40,7 +40,7 @@ typedef struct
u32 private_segment_count; /**< Number of private segments */
u32 private_segment_size; /**< Size of private segments */
char *server_uri; /**< Server URI */
u32 tls_engine; /**< TLS engine: mbedtls/openssl */
/*
* Test state
*/
@ -295,6 +295,7 @@ echo_server_attach (u8 * appns_id, u64 appns_flags, u64 appns_secret)
a->options[APP_OPTIONS_RX_FIFO_SIZE] = esm->fifo_size;
a->options[APP_OPTIONS_TX_FIFO_SIZE] = esm->fifo_size;
a->options[APP_OPTIONS_PRIVATE_SEGMENT_COUNT] = esm->private_segment_count;
a->options[APP_OPTIONS_TLS_ENGINE] = esm->tls_engine;
a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] =
esm->prealloc_fifos ? esm->prealloc_fifos : 1;
@ -408,6 +409,7 @@ echo_server_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
esm->prealloc_fifos = 0;
esm->private_segment_count = 0;
esm->private_segment_size = 0;
esm->tls_engine = TLS_ENGINE_OPENSSL;
vec_free (esm->server_uri);
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
@ -446,6 +448,8 @@ echo_server_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
;
else if (unformat (input, "stop"))
is_stop = 1;
else if (unformat (input, "tls-engine %d", &esm->tls_engine))
;
else
return clib_error_return (0, "failed: unknown input `%U'",
format_unformat_error, input);

View File

@ -305,6 +305,8 @@ application_init (application_t * app, u32 api_client_index, u64 * options,
props->tx_fifo_size = options[APP_OPTIONS_TX_FIFO_SIZE];
if (options[APP_OPTIONS_EVT_QUEUE_SIZE])
props->evt_q_size = options[APP_OPTIONS_EVT_QUEUE_SIZE];
if (options[APP_OPTIONS_TLS_ENGINE])
app->tls_engine = options[APP_OPTIONS_TLS_ENGINE];
props->segment_type = seg_type;
first_seg_size = options[APP_OPTIONS_SEGMENT_SIZE];

View File

@ -125,6 +125,9 @@ typedef struct _application
/** PEM encoded key */
u8 *tls_key;
/** Preferred tls engine */
u8 tls_engine;
} application_t;
#define APP_INVALID_INDEX ((u32)~0)

View File

@ -21,6 +21,7 @@
#include <vnet/session/session.h>
#include <vnet/session/application.h>
#include <vnet/session/transport.h>
#include <vnet/tls/tls.h>
typedef struct _vnet_app_attach_args_t
{
@ -124,6 +125,7 @@ typedef enum
APP_OPTIONS_NAMESPACE_SECRET,
APP_OPTIONS_PROXY_TRANSPORT,
APP_OPTIONS_ACCEPT_COOKIE,
APP_OPTIONS_TLS_ENGINE,
APP_OPTIONS_N_OPTIONS
} app_attach_options_index_t;

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@ typedef CLIB_PACKED (struct tls_cxt_id_
session_handle_t tls_session_handle;
u32 listener_ctx_index;
u8 tcp_is_ip4;
u8 tls_engine_id;
}) tls_ctx_id_t;
/* *INDENT-ON* */
@ -60,7 +61,8 @@ typedef struct tls_ctx_
#define tls_session_handle c_tls_ctx_id.tls_session_handle
#define listener_ctx_index c_tls_ctx_id.listener_ctx_index
#define tcp_is_ip4 c_tls_ctx_id.tcp_is_ip4
#define tls_ctx_idx c_c_index
#define tls_ctx_engine c_tls_ctx_id.tls_engine_id
#define tls_ctx_handle c_c_index
/* Temporary storage for session open opaque. Overwritten once
* underlying tcp connection is established */
#define parent_app_api_context c_s_index
@ -75,6 +77,8 @@ typedef struct tls_main_
tls_ctx_t *listener_ctx_pool;
tls_ctx_t *half_open_ctx_pool;
clib_rwlock_t half_open_rwlock;
u8 **rx_bufs;
u8 **tx_bufs;
/*
* Config
@ -91,22 +95,14 @@ typedef struct tls_engine_vft_
tls_ctx_t *(*ctx_get_w_thread) (u32 ctx_index, u8 thread_index);
int (*ctx_init_client) (tls_ctx_t * ctx);
int (*ctx_init_server) (tls_ctx_t * ctx);
int (*ctx_read) (tls_ctx_t * ctx, u8 * buf, u32 len);
int (*ctx_write) (tls_ctx_t * ctx, u8 * buf, u32 len);
int (*ctx_handshake_rx) (tls_ctx_t * ctx);
int (*ctx_read) (tls_ctx_t * ctx, stream_session_t * tls_session);
int (*ctx_write) (tls_ctx_t * ctx, stream_session_t * app_session);
u8 (*ctx_handshake_is_over) (tls_ctx_t * ctx);
} tls_engine_vft_t;
enum tls_handshake_results_
{
HANDSHAKE_NOT_OVER,
CLIENT_HANDSHAKE_OK,
CLIENT_HANDSHAKE_FAIL,
SERVER_HANDSHAKE_OK
};
typedef enum tls_engine_type_
{
TLS_ENGINE_NONE,
TLS_ENGINE_MBEDTLS,
TLS_ENGINE_OPENSSL,
TLS_N_ENGINES
@ -116,7 +112,9 @@ tls_main_t *vnet_tls_get_main (void);
void tls_register_engine (const tls_engine_vft_t * vft,
tls_engine_type_t type);
int tls_add_vpp_q_evt (svm_fifo_t * f, u8 evt_type);
int tls_notify_app_accept (tls_ctx_t * ctx);
int tls_notify_app_connected (tls_ctx_t * ctx, u8 is_failed);
void tls_notify_app_enqueue (tls_ctx_t * ctx, stream_session_t * app_session);
#endif /* SRC_VNET_TLS_TLS_H_ */
/*
* fd.io coding-style-patch-verification: ON