16 #include <openssl/ssl.h> 17 #include <openssl/conf.h> 18 #include <openssl/err.h> 20 #ifdef HAVE_OPENSSL_ASYNC 21 #include <openssl/async.h> 25 #include <vpp/app/version.h> 30 #define MAX_CRYPTO_LEN 64 45 (*ctx)->ctx.c_thread_index = thread_index;
48 (*ctx)->openssl_ctx_index = ctx - tm->
ctx_pool[thread_index];
49 return ((*ctx)->openssl_ctx_index);
58 SSL_shutdown (oc->
ssl);
62 #ifdef HAVE_OPENSSL_ASYNC 130 while ((c = c->
next) && read < enq_max)
133 rv = BIO_read (bio, c->
data, enq_now);
134 read += rv > 0 ? rv : 0;
148 u32 enq_now, enq_max;
167 while ((c = c->
next) && read < enq_max)
170 rv = SSL_read (ssl, c->
data, enq_now);
171 read += rv > 0 ? rv : 0;
195 while ((c = c->
next) && wrote < len)
198 rv = BIO_write (bio, c->
data, deq_now);
199 wrote += rv > 0 ? rv : 0;
223 while ((c = c->
next) && wrote < len)
226 rv = SSL_write (ssl, c->
data, deq_now);
227 wrote += rv > 0 ? rv : 0;
257 if (BIO_ctrl_pending (oc->
rbio) <= 0)
272 #ifdef HAVE_OPENSSL_ASYNC 280 SSL_get_async_status (oc->
ssl, &estatus);
281 if (estatus == ASYNC_STATUS_EAGAIN)
311 ctx->no_app_session = 1;
331 while (SSL_in_init (oc->
ssl))
340 rv = SSL_do_handshake (oc->
ssl);
341 err = SSL_get_error (oc->
ssl, rv);
343 #ifdef HAVE_OPENSSL_ASYNC 344 if (err == SSL_ERROR_WANT_ASYNC)
350 if (err == SSL_ERROR_SSL)
353 ERR_error_string (ERR_get_error (), buf);
362 if (err != SSL_ERROR_WANT_WRITE)
366 SSL_state_string_long (oc->
ssl));
368 if (SSL_in_init (oc->
ssl))
374 if (!SSL_is_server (oc->
ssl))
379 if ((rv = SSL_get_verify_result (oc->
ssl)) != X509_V_OK)
381 TLS_DBG (1,
" failed verify: %s\n",
382 X509_verify_cert_error_string (rv));
404 TLS_DBG (1,
"Handshake for %u complete. TLS cipher is %s",
421 int wrote = 0, read, max_buf = 4 *
TLS_CHUNK_SIZE, max_space, n_pending;
422 u32 deq_max, to_write, enq_max;
435 max_space = max_buf - BIO_ctrl_pending (oc->
rbio);
436 max_space = (max_space < 0) ? 0 : max_space;
448 if ((n_pending = BIO_ctrl_pending (oc->
rbio)) <= 0)
455 goto maybe_reschedule;
460 goto maybe_reschedule;
478 app_session->
flags |= SESSION_F_CUSTOM_TX;
488 u32 deq_max, to_write;
503 max_space = max_buf - BIO_ctrl_pending (oc->
wbio);
504 max_space = max_space < 0 ? 0 : max_space;
505 to_write =
clib_min (deq_max, max_space);
521 if (BIO_ctrl_pending (oc->
wbio) <= 0)
537 if (SSL_pending (oc->
ssl) > 0)
546 long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
550 const SSL_METHOD *method;
553 method = SSLv23_client_method ();
556 TLS_DBG (1,
"SSLv23_method returned null");
560 oc->
ssl_ctx = SSL_CTX_new (method);
563 TLS_DBG (1,
"SSL_CTX_new returned null");
567 SSL_CTX_set_ecdh_auto (oc->
ssl_ctx, 1);
568 SSL_CTX_set_mode (oc->
ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
569 #ifdef HAVE_OPENSSL_ASYNC 571 SSL_CTX_set_mode (oc->
ssl_ctx, SSL_MODE_ASYNC);
573 rv = SSL_CTX_set_cipher_list (oc->
ssl_ctx, (
const char *) om->
ciphers);
576 TLS_DBG (1,
"Couldn't set cipher");
580 SSL_CTX_set_options (oc->
ssl_ctx, flags);
586 TLS_DBG (1,
"Couldn't initialize ssl struct");
590 oc->
rbio = BIO_new (BIO_s_mem ());
591 oc->
wbio = BIO_new (BIO_s_mem ());
593 BIO_set_mem_eof_return (oc->
rbio, -1);
594 BIO_set_mem_eof_return (oc->
wbio, -1);
597 SSL_set_connect_state (oc->
ssl);
602 TLS_DBG (1,
"Couldn't set hostname");
609 TLS_DBG (1,
"Initiating handshake for [%u]%u", ctx->c_thread_index,
614 #ifdef HAVE_OPENSSL_ASYNC 619 rv = SSL_do_handshake (oc->
ssl);
620 err = SSL_get_error (oc->
ssl, rv);
622 #ifdef HAVE_OPENSSL_ASYNC 623 if (err == SSL_ERROR_WANT_ASYNC)
630 if (err != SSL_ERROR_WANT_WRITE)
634 TLS_DBG (2,
"tls state for [%u]%u is su", ctx->c_thread_index,
642 const SSL_METHOD *method;
652 long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
659 if (!ckpair->
cert || !ckpair->
key)
661 TLS_DBG (1,
"tls cert and/or key not configured %d",
662 lctx->parent_app_wrk_index);
666 method = SSLv23_method ();
667 ssl_ctx = SSL_CTX_new (method);
674 SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
675 #ifdef HAVE_OPENSSL_ASYNC 678 SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ASYNC);
682 SSL_CTX_set_options (ssl_ctx, flags);
683 SSL_CTX_set_ecdh_auto (ssl_ctx, 1);
685 rv = SSL_CTX_set_cipher_list (ssl_ctx, (
const char *) om->
ciphers);
688 TLS_DBG (1,
"Couldn't set cipher");
695 cert_bio = BIO_new (BIO_s_mem ());
697 srvcert = PEM_read_bio_X509 (cert_bio, NULL, NULL, NULL);
703 SSL_CTX_use_certificate (ssl_ctx, srvcert);
706 cert_bio = BIO_new (BIO_s_mem ());
708 pkey = PEM_read_bio_PrivateKey (cert_bio, NULL, NULL, NULL);
714 SSL_CTX_use_PrivateKey (ssl_ctx, pkey);
724 lctx->tls_ssl_ctx = olc_index;
736 olc_index = lctx->tls_ssl_ctx;
740 EVP_PKEY_free (olc->
pkey);
752 u32 olc_index = ctx->tls_ssl_ctx;
763 TLS_DBG (1,
"Couldn't initialize ssl struct");
767 oc->
rbio = BIO_new (BIO_s_mem ());
768 oc->
wbio = BIO_new (BIO_s_mem ());
770 BIO_set_mem_eof_return (oc->
rbio, -1);
771 BIO_set_mem_eof_return (oc->
wbio, -1);
774 SSL_set_accept_state (oc->
ssl);
776 TLS_DBG (1,
"Initiating handshake for [%u]%u", ctx->c_thread_index,
780 #ifdef HAVE_OPENSSL_ASYNC 785 rv = SSL_do_handshake (oc->
ssl);
786 err = SSL_get_error (oc->
ssl, rv);
788 #ifdef HAVE_OPENSSL_ASYNC 789 if (err == SSL_ERROR_WANT_ASYNC)
796 if (err != SSL_ERROR_WANT_WRITE)
800 TLS_DBG (2,
"tls state for [%u]%u is su", ctx->c_thread_index,
811 return SSL_is_init_finished (mc->
ssl);
817 #ifdef HAVE_OPENSSL_ASYNC 839 if (BIO_ctrl_pending (oc->
rbio) <= 0
874 clib_warning (
"Could not initialize TLS CA certificates");
884 #if OPENSSL_VERSION_NUMBER >= 0x30000000L 897 cert_bio = BIO_new (BIO_s_mem ());
899 testcert = PEM_read_bio_X509 (cert_bio, NULL, NULL, NULL);
905 X509_STORE_add_cert (om->
cert_store, testcert);
908 return (rv < 0 ? -1 : 0);
925 om->
ciphers[
i] = toupper (ciphers[i]);
944 SSL_load_error_strings ();
960 (
"ALL:!ADH:!LOW:!EXP:!MD5:!RC4-SHA:!DES-CBC3-SHA:@STRENGTH");
971 #ifdef HAVE_OPENSSL_ASYNC 977 char *engine_name = NULL;
978 char *engine_alg = NULL;
979 char *ciphers = NULL;
980 u8 engine_name_set = 0;
988 (0,
"engine has started, and no config is accepted");
993 if (
unformat (input,
"engine %s", &engine_name))
1001 else if (
unformat (input,
"alg %s", &engine_alg))
1004 engine_alg[i] = toupper (engine_alg[i]);
1006 else if (
unformat (input,
"ciphers %s", &ciphers))
1016 if (!engine_name_set)
1043 .path =
"tls openssl set",
1044 .short_help =
"tls openssl set [engine <engine name>] [alg [algorithm] [async]",
1045 .function = tls_openssl_set_command_fn,
1052 .version = VPP_BUILD_VER,
1053 .description =
"Transport Layer Security (TLS) Engine, OpenSSL Based",
u32 length
length of chunk in bytes
tls_main_t * vnet_tls_get_main(void)
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
openssl_listen_ctx_t * lctx_pool
int tls_notify_app_connected(tls_ctx_t *ctx, session_error_t err)
static int openssl_transport_close(tls_ctx_t *ctx)
static u8 openssl_handshake_is_over(tls_ctx_t *ctx)
static u32 svm_fifo_max_enqueue_prod(svm_fifo_t *f)
Maximum number of bytes that can be enqueued into fifo.
vl_api_wireguard_peer_flags_t flags
void tls_disconnect_transport(tls_ctx_t *ctx)
static void openssl_handle_handshake_failure(tls_ctx_t *ctx)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
svm_fifo_t * rx_fifo
Pointers to rx/tx buffers.
int tls_add_vpp_q_builtin_rx_evt(session_t *s)
static session_t * session_get_if_valid(u64 si, u32 thread_index)
static u32 openssl_ctx_alloc(void)
int tls_openssl_set_ciphers(char *ciphers)
static void openssl_listen_ctx_free(openssl_listen_ctx_t *lctx)
void svm_fifo_enqueue_nocopy(svm_fifo_t *f, u32 len)
Advance tail.
static void openssl_ctx_free(tls_ctx_t *ctx)
clib_error_t * tls_openssl_api_init(vlib_main_t *vm)
static int openssl_write_from_fifo_into_ssl(svm_fifo_t *f, SSL *ssl, u32 len)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
void tls_register_engine(const tls_engine_vft_t *vft, crypto_engine_type_t type)
static u8 * svm_fifo_tail(svm_fifo_t *f)
Fifo tail pointer getter.
void session_transport_closing_notify(transport_connection_t *tc)
Notification from transport that connection is being closed.
#define VLIB_INIT_FUNCTION(x)
static svm_fifo_chunk_t * svm_fifo_head_chunk(svm_fifo_t *f)
Fifo head chunk getter.
static u32 svm_fifo_max_dequeue_cons(svm_fifo_t *f)
Fifo max bytes to dequeue optimized for consumer.
#define clib_error_return(e, args...)
static int openssl_stop_listen(tls_ctx_t *lctx)
int openssl_engine_register(char *engine_name, char *algorithm, int async)
#define SESSION_INVALID_HANDLE
static u8 * svm_fifo_head(svm_fifo_t *f)
Fifo head pointer getter.
int tls_init_ca_chain(void)
int session_dequeue_notify(session_t *s)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
int vpp_tls_async_update_event(tls_ctx_t *ctx, int eagain)
static session_t * session_get_from_handle(session_handle_t handle)
struct svm_fifo_chunk_ * next
pointer to next chunk in linked-lists
static int openssl_write_from_fifo_into_bio(svm_fifo_t *f, BIO *bio, u32 len)
int vpp_openssl_is_inflight(tls_ctx_t *ctx)
tls_ctx_t * openssl_ctx_get(u32 ctx_index)
#define SESSION_INVALID_INDEX
static const char test_srv_crt_rsa[]
clib_error_t * vnet_session_enable_disable(vlib_main_t *vm, u8 is_en)
static int openssl_ctx_init_client(tls_ctx_t *ctx)
app_cert_key_pair_t * app_cert_key_pair_get_if_valid(u32 index)
static u8 svm_fifo_needs_deq_ntf(svm_fifo_t *f, u32 n_last_deq)
Check if fifo needs dequeue notification.
static int openssl_read_from_ssl_into_fifo(svm_fifo_t *f, SSL *ssl)
static_always_inline uword vlib_get_thread_index(void)
static int openssl_app_close(tls_ctx_t *ctx)
sll srl srl sll sra u16x4 i
#define vec_free(V)
Free vector's memory (no header).
void session_free(session_t *s)
openssl_ctx_t *** ctx_pool
#define clib_warning(format, args...)
static int openssl_try_handshake_write(openssl_ctx_t *oc, session_t *tls_session)
static int openssl_ctx_read(tls_ctx_t *ctx, session_t *tls_session)
openssl_main_t openssl_main
int tls_add_vpp_q_tx_evt(session_t *s)
transport_connection_t connection
static int openssl_ctx_write(tls_ctx_t *ctx, session_t *app_session, transport_send_params_t *sp)
transport_snd_flags_t flags
#define VLIB_CLI_COMMAND(x,...)
#define pool_put_index(p, i)
Free pool element with given index.
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
static void openssl_confirm_app_close(tls_ctx_t *ctx)
int openssl_resume_handler(tls_ctx_t *ctx, session_t *tls_session)
static clib_error_t * tls_openssl_init(vlib_main_t *vm)
u8 data[0]
start of chunk data
static void svm_fifo_add_want_deq_ntf(svm_fifo_t *f, u8 ntf_type)
Set specific want notification flag.
static void * clib_mem_alloc(uword size)
int vpp_tls_async_init_event(tls_ctx_t *ctx, openssl_resume_handler *handler, session_t *session)
tls_ctx_t * openssl_ctx_get_w_thread(u32 ctx_index, u8 thread_index)
u32 svm_fifo_max_read_chunk(svm_fifo_t *f)
Max contiguous chunk of data that can be read.
static int openssl_ctx_init_server(tls_ctx_t *ctx)
int svm_fifo_fill_chunk_list(svm_fifo_t *f)
Ensure the whole fifo size is writeable.
int openssl_evt_free(int event_index, u8 thread_index)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
volatile u8 session_state
State in session layer state machine.
int tls_async_openssl_callback(SSL *s, void *cb_arg)
void session_transport_closed_notify(transport_connection_t *tc)
Notification from transport that it is closed.
static int openssl_start_listen(tls_ctx_t *lctx)
int openssl_ctx_handshake_rx(tls_ctx_t *ctx, session_t *tls_session)
int tls_notify_app_accept(tls_ctx_t *ctx)
void tls_notify_app_enqueue(tls_ctx_t *ctx, session_t *app_session)
static int openssl_try_handshake_read(openssl_ctx_t *oc, session_t *tls_session)
static vlib_thread_main_t * vlib_get_thread_main()
openssl_listen_ctx_t * openssl_lctx_get(u32 lctx_index)
u32 svm_fifo_max_write_chunk(svm_fifo_t *f)
Max contiguous chunk of data that can be written.
static u32 openssl_listen_ctx_alloc(void)
int svm_fifo_dequeue_drop(svm_fifo_t *f, u32 len)
Dequeue and drop bytes from fifo.
struct _svm_fifo svm_fifo_t
static void transport_connection_deschedule(transport_connection_t *tc)
#define TLS_DBG(_lvl, _fmt, _args...)
static int openssl_read_from_bio_into_fifo(svm_fifo_t *f, BIO *bio, u32 enq_max)
static svm_fifo_chunk_t * svm_fifo_tail_chunk(svm_fifo_t *f)
Fifo tail chunk getter.
static const u32 test_srv_crt_rsa_len