LCOV - code coverage report
Current view: top level - plugins/tlsopenssl - tls_openssl.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 388 513 75.6 %
Date: 2023-10-26 01:39:38 Functions: 32 36 88.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <openssl/ssl.h>
      17             : #include <openssl/conf.h>
      18             : #include <openssl/err.h>
      19             : 
      20             : #ifdef HAVE_OPENSSL_ASYNC
      21             : #include <openssl/async.h>
      22             : #endif
      23             : #include <dlfcn.h>
      24             : #include <vnet/plugin/plugin.h>
      25             : #include <vpp/app/version.h>
      26             : #include <vnet/tls/tls.h>
      27             : #include <ctype.h>
      28             : #include <tlsopenssl/tls_openssl.h>
      29             : #include <tlsopenssl/tls_bios.h>
      30             : #include <openssl/x509_vfy.h>
      31             : #include <openssl/x509v3.h>
      32             : 
      33             : #define MAX_CRYPTO_LEN 64
      34             : 
      35             : openssl_main_t openssl_main;
      36             : 
      37             : static u32
      38           6 : openssl_ctx_alloc_w_thread (u32 thread_index)
      39             : {
      40           6 :   openssl_main_t *om = &openssl_main;
      41             :   openssl_ctx_t **ctx;
      42             : 
      43           6 :   pool_get_aligned_safe (om->ctx_pool[thread_index], ctx, 0);
      44             : 
      45           6 :   if (!(*ctx))
      46           6 :     *ctx = clib_mem_alloc (sizeof (openssl_ctx_t));
      47             : 
      48           6 :   clib_memset (*ctx, 0, sizeof (openssl_ctx_t));
      49           6 :   (*ctx)->ctx.c_thread_index = thread_index;
      50           6 :   (*ctx)->ctx.tls_ctx_engine = CRYPTO_ENGINE_OPENSSL;
      51           6 :   (*ctx)->ctx.app_session_handle = SESSION_INVALID_HANDLE;
      52           6 :   (*ctx)->openssl_ctx_index = ctx - om->ctx_pool[thread_index];
      53           6 :   return ((*ctx)->openssl_ctx_index);
      54             : }
      55             : 
      56             : static u32
      57           5 : openssl_ctx_alloc (void)
      58             : {
      59           5 :   return openssl_ctx_alloc_w_thread (vlib_get_thread_index ());
      60             : }
      61             : 
      62             : static void
      63           4 : openssl_ctx_free (tls_ctx_t * ctx)
      64             : {
      65           4 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
      66             : 
      67             :   /* Cleanup ssl ctx unless migrated */
      68           4 :   if (!ctx->is_migrated)
      69             :     {
      70           4 :       if (SSL_is_init_finished (oc->ssl) && !ctx->is_passive_close)
      71           2 :         SSL_shutdown (oc->ssl);
      72             : 
      73           4 :       SSL_free (oc->ssl);
      74           4 :       vec_free (ctx->srv_hostname);
      75           4 :       SSL_CTX_free (oc->client_ssl_ctx);
      76             : #ifdef HAVE_OPENSSL_ASYNC
      77             :   openssl_evt_free (ctx->evt_index, ctx->c_thread_index);
      78             : #endif
      79             :     }
      80             : 
      81           4 :   pool_put_index (openssl_main.ctx_pool[ctx->c_thread_index],
      82             :                   oc->openssl_ctx_index);
      83           4 : }
      84             : 
      85             : static void *
      86           0 : openssl_ctx_detach (tls_ctx_t *ctx)
      87             : {
      88           0 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx, *oc_copy;
      89             : 
      90           0 :   oc_copy = clib_mem_alloc (sizeof (*oc_copy));
      91           0 :   clib_memcpy (oc_copy, oc, sizeof (*oc));
      92             : 
      93           0 :   return oc_copy;
      94             : }
      95             : 
      96             : static u32
      97           0 : openssl_ctx_attach (u32 thread_index, void *ctx_ptr)
      98             : {
      99           0 :   openssl_main_t *om = &openssl_main;
     100             :   session_handle_t sh;
     101             :   openssl_ctx_t **oc;
     102             : 
     103           0 :   pool_get_aligned_safe (om->ctx_pool[thread_index], oc, 0);
     104             :   /* Free the old instance instead of looking for an empty spot */
     105           0 :   if (*oc)
     106           0 :     clib_mem_free (*oc);
     107             : 
     108           0 :   *oc = ctx_ptr;
     109           0 :   (*oc)->openssl_ctx_index = oc - om->ctx_pool[thread_index];
     110           0 :   (*oc)->ctx.c_thread_index = thread_index;
     111             : 
     112           0 :   sh = (*oc)->ctx.tls_session_handle;
     113           0 :   BIO_set_data ((*oc)->rbio, uword_to_pointer (sh, void *));
     114           0 :   BIO_set_data ((*oc)->wbio, uword_to_pointer (sh, void *));
     115             : 
     116           0 :   return ((*oc)->openssl_ctx_index);
     117             : }
     118             : 
     119             : tls_ctx_t *
     120     1275000 : openssl_ctx_get (u32 ctx_index)
     121             : {
     122             :   openssl_ctx_t **ctx;
     123     1275000 :   ctx = pool_elt_at_index (openssl_main.ctx_pool[vlib_get_thread_index ()],
     124             :                            ctx_index);
     125     1275000 :   return &(*ctx)->ctx;
     126             : }
     127             : 
     128             : tls_ctx_t *
     129     1274850 : openssl_ctx_get_w_thread (u32 ctx_index, u8 thread_index)
     130             : {
     131             :   openssl_ctx_t **ctx;
     132     1274850 :   ctx = pool_elt_at_index (openssl_main.ctx_pool[thread_index], ctx_index);
     133     1274850 :   return &(*ctx)->ctx;
     134             : }
     135             : 
     136             : static u32
     137           3 : openssl_listen_ctx_alloc (void)
     138             : {
     139           3 :   openssl_main_t *om = &openssl_main;
     140             :   openssl_listen_ctx_t *lctx;
     141             : 
     142           3 :   pool_get (om->lctx_pool, lctx);
     143             : 
     144           3 :   clib_memset (lctx, 0, sizeof (openssl_listen_ctx_t));
     145           3 :   lctx->openssl_lctx_index = lctx - om->lctx_pool;
     146           3 :   return lctx->openssl_lctx_index;
     147             : }
     148             : 
     149             : static void
     150           3 : openssl_listen_ctx_free (openssl_listen_ctx_t * lctx)
     151             : {
     152           3 :   pool_put_index (openssl_main.lctx_pool, lctx->openssl_lctx_index);
     153           3 : }
     154             : 
     155             : openssl_listen_ctx_t *
     156           9 : openssl_lctx_get (u32 lctx_index)
     157             : {
     158           9 :   return pool_elt_at_index (openssl_main.lctx_pool, lctx_index);
     159             : }
     160             : 
     161             : #define ossl_check_err_is_fatal(_ssl, _rv)                                    \
     162             :   if (PREDICT_FALSE (_rv < 0 && SSL_get_error (_ssl, _rv) == SSL_ERROR_SSL))  \
     163             :     return -1;
     164             : 
     165             : static int
     166        1513 : openssl_read_from_ssl_into_fifo (svm_fifo_t *f, SSL *ssl, u32 max_len)
     167        1513 : {
     168             :   int read, rv, n_fs, i;
     169        1513 :   const int n_segs = 2;
     170        1513 :   svm_fifo_seg_t fs[n_segs];
     171             :   u32 max_enq;
     172             : 
     173        1513 :   max_enq = svm_fifo_max_enqueue_prod (f);
     174        1513 :   if (!max_enq)
     175           0 :     return 0;
     176             : 
     177        1513 :   max_enq = clib_min (max_len, max_enq);
     178        1513 :   n_fs = svm_fifo_provision_chunks (f, fs, n_segs, max_enq);
     179        1513 :   if (n_fs < 0)
     180           0 :     return 0;
     181             : 
     182             :   /* Return early if we can't read anything */
     183        1513 :   read = SSL_read (ssl, fs[0].data, fs[0].len);
     184        1513 :   if (read <= 0)
     185             :     {
     186         563 :       ossl_check_err_is_fatal (ssl, read);
     187         563 :       return 0;
     188             :     }
     189             : 
     190         950 :   if (read == (int) fs[0].len)
     191             :     {
     192         249 :       for (i = 1; i < n_fs; i++)
     193             :         {
     194         249 :           rv = SSL_read (ssl, fs[i].data, fs[i].len);
     195         249 :           read += rv > 0 ? rv : 0;
     196             : 
     197         249 :           if (rv < (int) fs[i].len)
     198             :             {
     199         249 :               ossl_check_err_is_fatal (ssl, rv);
     200         249 :               break;
     201             :             }
     202             :         }
     203             :     }
     204         950 :   svm_fifo_enqueue_nocopy (f, read);
     205             : 
     206         950 :   return read;
     207             : }
     208             : 
     209             : static int
     210         583 : openssl_write_from_fifo_into_ssl (svm_fifo_t *f, SSL *ssl, u32 max_len)
     211         583 : {
     212         583 :   int wrote = 0, rv, i = 0, len;
     213         583 :   u32 n_segs = 2;
     214         583 :   svm_fifo_seg_t fs[n_segs];
     215             : 
     216         583 :   len = svm_fifo_segments (f, 0, fs, &n_segs, max_len);
     217         583 :   if (len <= 0)
     218           0 :     return 0;
     219             : 
     220        1134 :   while (wrote < len && i < n_segs)
     221             :     {
     222        1030 :       rv = SSL_write (ssl, fs[i].data, fs[i].len);
     223        1030 :       wrote += (rv > 0) ? rv : 0;
     224        1030 :       if (rv < (int) fs[i].len)
     225             :         {
     226         479 :           ossl_check_err_is_fatal (ssl, rv);
     227         479 :           break;
     228             :         }
     229         551 :       i++;
     230             :     }
     231             : 
     232         583 :   if (wrote)
     233         583 :     svm_fifo_dequeue_drop (f, wrote);
     234             : 
     235         583 :   return wrote;
     236             : }
     237             : 
     238             : #ifdef HAVE_OPENSSL_ASYNC
     239             : static int
     240             : openssl_check_async_status (tls_ctx_t * ctx, openssl_resume_handler * handler,
     241             :                             session_t * session)
     242             : {
     243             :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
     244             :   int estatus;
     245             : 
     246             :   SSL_get_async_status (oc->ssl, &estatus);
     247             :   if (estatus == ASYNC_STATUS_EAGAIN)
     248             :     {
     249             :       vpp_tls_async_update_event (ctx, 1);
     250             :     }
     251             :   else
     252             :     {
     253             :       vpp_tls_async_update_event (ctx, 0);
     254             :     }
     255             : 
     256             :   return 1;
     257             : 
     258             : }
     259             : 
     260             : #endif
     261             : 
     262             : static void
     263           0 : openssl_handle_handshake_failure (tls_ctx_t * ctx)
     264             : {
     265             :   session_t *app_session;
     266             : 
     267           0 :   if (SSL_is_server (((openssl_ctx_t *) ctx)->ssl))
     268             :     {
     269             :       /*
     270             :        * Cleanup pre-allocated app session and close transport
     271             :        */
     272             :       app_session =
     273           0 :         session_get_if_valid (ctx->c_s_index, ctx->c_thread_index);
     274           0 :       if (app_session)
     275             :         {
     276           0 :           session_free (app_session);
     277           0 :           ctx->c_s_index = SESSION_INVALID_INDEX;
     278           0 :           tls_disconnect_transport (ctx);
     279             :         }
     280           0 :       ctx->no_app_session = 1;
     281             :     }
     282             :   else
     283             :     {
     284             :       /*
     285             :        * Also handles cleanup of the pre-allocated session
     286             :        */
     287           0 :       tls_notify_app_connected (ctx, SESSION_E_TLS_HANDSHAKE);
     288           0 :       tls_disconnect_transport (ctx);
     289             :     }
     290           0 : }
     291             : 
     292             : int
     293          12 : openssl_ctx_handshake_rx (tls_ctx_t * ctx, session_t * tls_session)
     294             : {
     295          12 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
     296          12 :   int rv = 0, err;
     297             : 
     298          15 :   while (SSL_in_init (oc->ssl))
     299             :     {
     300          15 :       if (ctx->resume)
     301             :         {
     302           0 :           ctx->resume = 0;
     303             :         }
     304          15 :       else if (!svm_fifo_max_dequeue_cons (tls_session->rx_fifo))
     305           5 :         break;
     306             : 
     307          10 :       rv = SSL_do_handshake (oc->ssl);
     308          10 :       err = SSL_get_error (oc->ssl, rv);
     309             : 
     310             : #ifdef HAVE_OPENSSL_ASYNC
     311             :       if (err == SSL_ERROR_WANT_ASYNC)
     312             :         {
     313             :           openssl_check_async_status (ctx, openssl_ctx_handshake_rx,
     314             :                                       tls_session);
     315             :         }
     316             : #endif
     317          10 :       if (err == SSL_ERROR_SSL)
     318             :         {
     319             :           char buf[512];
     320           0 :           ERR_error_string (ERR_get_error (), buf);
     321           0 :           clib_warning ("Err: %s", buf);
     322             : 
     323           0 :           openssl_handle_handshake_failure (ctx);
     324           0 :           return -1;
     325             :         }
     326             : 
     327          10 :       if (err != SSL_ERROR_WANT_WRITE && err != SSL_ERROR_WANT_READ)
     328           7 :         break;
     329             :     }
     330             :   TLS_DBG (2, "tls state for %u is %s", oc->openssl_ctx_index,
     331             :            SSL_state_string_long (oc->ssl));
     332             : 
     333          12 :   if (SSL_in_init (oc->ssl))
     334           6 :     return -1;
     335             : 
     336             :   /*
     337             :    * Handshake complete
     338             :    */
     339           6 :   if (!SSL_is_server (oc->ssl))
     340             :     {
     341             :       /*
     342             :        * Verify server certificate
     343             :        */
     344           3 :       if ((rv = SSL_get_verify_result (oc->ssl)) != X509_V_OK)
     345             :         {
     346             :           TLS_DBG (1, " failed verify: %s\n",
     347             :                    X509_verify_cert_error_string (rv));
     348             : 
     349             :           /*
     350             :            * Presence of hostname enforces strict certificate verification
     351             :            */
     352           3 :           if (ctx->srv_hostname)
     353             :             {
     354           0 :               openssl_handle_handshake_failure (ctx);
     355           0 :               return -1;
     356             :             }
     357             :         }
     358           3 :       if (tls_notify_app_connected (ctx, SESSION_E_NONE))
     359             :         {
     360           0 :           tls_disconnect_transport (ctx);
     361           0 :           return -1;
     362             :         }
     363             :     }
     364             :   else
     365             :     {
     366             :       /* Need to check transport status */
     367           3 :       if (ctx->is_passive_close)
     368             :         {
     369           0 :           openssl_handle_handshake_failure (ctx);
     370           0 :           return -1;
     371             :         }
     372             : 
     373             :       /* Accept failed, cleanup */
     374           3 :       if (tls_notify_app_accept (ctx))
     375             :         {
     376           0 :           ctx->c_s_index = SESSION_INVALID_INDEX;
     377           0 :           tls_disconnect_transport (ctx);
     378           0 :           return -1;
     379             :         }
     380             :     }
     381             : 
     382             :   TLS_DBG (1, "Handshake for %u complete. TLS cipher is %s",
     383             :            oc->openssl_ctx_index, SSL_get_cipher (oc->ssl));
     384           6 :   return rv;
     385             : }
     386             : 
     387             : static void
     388           6 : openssl_confirm_app_close (tls_ctx_t * ctx)
     389             : {
     390           6 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
     391           6 :   SSL_shutdown (oc->ssl);
     392           6 :   tls_disconnect_transport (ctx);
     393           6 :   session_transport_closed_notify (&ctx->connection);
     394           6 : }
     395             : 
     396             : static int
     397     1273220 : openssl_ctx_write_tls (tls_ctx_t *ctx, session_t *app_session,
     398             :                        transport_send_params_t *sp)
     399             : {
     400     1273220 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
     401             :   u32 deq_max, space, enq_buf;
     402             :   session_t *ts;
     403     1273220 :   int wrote = 0;
     404             :   svm_fifo_t *f;
     405             : 
     406     1273220 :   ts = session_get_from_handle (ctx->tls_session_handle);
     407     1273220 :   space = svm_fifo_max_enqueue_prod (ts->tx_fifo);
     408             :   /* Leave a bit of extra space for tls ctrl data, if any needed */
     409     1273220 :   space = clib_max ((int) space - TLSO_CTRL_BYTES, 0);
     410             : 
     411     1273220 :   f = app_session->tx_fifo;
     412             : 
     413     1273220 :   deq_max = svm_fifo_max_dequeue_cons (f);
     414     1273220 :   deq_max = clib_min (deq_max, space);
     415     1273220 :   if (!deq_max)
     416     1272640 :     goto check_tls_fifo;
     417             : 
     418         583 :   deq_max = clib_min (deq_max, sp->max_burst_size);
     419             : 
     420             :   /* Make sure tcp's tx fifo can actually buffer all bytes to be dequeued.
     421             :    * If under memory pressure, tls's fifo segment might not be able to
     422             :    * allocate the chunks needed. This also avoids errors from the underlying
     423             :    * custom bio to the ssl infra which at times can get stuck. */
     424         583 :   if (svm_fifo_provision_chunks (ts->tx_fifo, 0, 0, deq_max + TLSO_CTRL_BYTES))
     425           0 :     goto check_tls_fifo;
     426             : 
     427         583 :   wrote = openssl_write_from_fifo_into_ssl (f, oc->ssl, deq_max);
     428             : 
     429             :   /* Unrecoverable protocol error. Reset connection */
     430         583 :   if (PREDICT_FALSE (wrote < 0))
     431             :     {
     432           0 :       tls_notify_app_io_error (ctx);
     433           0 :       return 0;
     434             :     }
     435             : 
     436         583 :   if (!wrote)
     437           0 :     goto check_tls_fifo;
     438             : 
     439         583 :   if (svm_fifo_needs_deq_ntf (f, wrote))
     440         358 :     session_dequeue_notify (app_session);
     441             : 
     442         225 : check_tls_fifo:
     443             : 
     444     1273220 :   if (PREDICT_FALSE (ctx->app_closed && BIO_ctrl_pending (oc->rbio) <= 0))
     445           0 :     openssl_confirm_app_close (ctx);
     446             : 
     447             :   /* Deschedule and wait for deq notification if fifo is almost full */
     448     1273220 :   enq_buf = clib_min (svm_fifo_size (ts->tx_fifo) / 2, TLSO_MIN_ENQ_SPACE);
     449     1273220 :   if (space < wrote + enq_buf)
     450             :     {
     451          43 :       svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
     452          43 :       transport_connection_deschedule (&ctx->connection);
     453          43 :       sp->flags |= TRANSPORT_SND_F_DESCHED;
     454             :     }
     455             :   else
     456             :     /* Request tx reschedule of the app session */
     457     1273180 :     app_session->flags |= SESSION_F_CUSTOM_TX;
     458             : 
     459     1273220 :   return wrote;
     460             : }
     461             : 
     462             : static int
     463          58 : openssl_ctx_write_dtls (tls_ctx_t *ctx, session_t *app_session,
     464             :                         transport_send_params_t *sp)
     465             : {
     466          58 :   openssl_main_t *om = &openssl_main;
     467          58 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
     468          58 :   u32 read = 0, to_deq, dgram_sz, enq_max;
     469             :   session_dgram_pre_hdr_t hdr;
     470             :   session_t *us;
     471             :   int wrote, rv;
     472             :   u8 *buf;
     473             : 
     474          58 :   us = session_get_from_handle (ctx->tls_session_handle);
     475          58 :   to_deq = svm_fifo_max_dequeue_cons (app_session->tx_fifo);
     476          58 :   buf = om->tx_bufs[ctx->c_thread_index];
     477             : 
     478        1058 :   while (to_deq > 0)
     479             :     {
     480             :       /* Peeking only pre-header dgram because the session is connected */
     481        1051 :       rv = svm_fifo_peek (app_session->tx_fifo, 0, sizeof (hdr), (u8 *) &hdr);
     482        1051 :       ASSERT (rv == sizeof (hdr) && hdr.data_length < vec_len (buf));
     483        1051 :       ASSERT (to_deq >= hdr.data_length + SESSION_CONN_HDR_LEN);
     484             : 
     485        1051 :       dgram_sz = hdr.data_length + SESSION_CONN_HDR_LEN;
     486        1051 :       enq_max = dgram_sz + TLSO_CTRL_BYTES;
     487        2051 :       if (svm_fifo_max_enqueue_prod (us->tx_fifo) < enq_max ||
     488        1000 :           svm_fifo_provision_chunks (us->tx_fifo, 0, 0, enq_max))
     489             :         {
     490          51 :           svm_fifo_add_want_deq_ntf (us->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
     491          51 :           transport_connection_deschedule (&ctx->connection);
     492          51 :           sp->flags |= TRANSPORT_SND_F_DESCHED;
     493          51 :           goto done;
     494             :         }
     495             : 
     496        1000 :       rv = svm_fifo_peek (app_session->tx_fifo, SESSION_CONN_HDR_LEN,
     497             :                           hdr.data_length, buf);
     498        1000 :       ASSERT (rv == hdr.data_length);
     499        1000 :       svm_fifo_dequeue_drop (app_session->tx_fifo, dgram_sz);
     500             : 
     501        1000 :       wrote = SSL_write (oc->ssl, buf, rv);
     502        1000 :       ASSERT (wrote > 0);
     503             : 
     504        1000 :       read += rv;
     505        1000 :       to_deq -= dgram_sz;
     506             :     }
     507             : 
     508           7 : done:
     509             : 
     510          58 :   if (svm_fifo_needs_deq_ntf (app_session->tx_fifo, read))
     511           0 :     session_dequeue_notify (app_session);
     512             : 
     513          58 :   if (read)
     514          58 :     tls_add_vpp_q_tx_evt (us);
     515             : 
     516          58 :   if (PREDICT_FALSE (ctx->app_closed &&
     517             :                      !svm_fifo_max_enqueue_prod (us->rx_fifo)))
     518           0 :     openssl_confirm_app_close (ctx);
     519             : 
     520          58 :   return read;
     521             : }
     522             : 
     523             : static inline int
     524     1273280 : openssl_ctx_write (tls_ctx_t *ctx, session_t *app_session,
     525             :                    transport_send_params_t *sp)
     526             : {
     527     1273280 :   if (ctx->tls_type == TRANSPORT_PROTO_TLS)
     528     1273220 :     return openssl_ctx_write_tls (ctx, app_session, sp);
     529             :   else
     530          58 :     return openssl_ctx_write_dtls (ctx, app_session, sp);
     531             : }
     532             : 
     533             : static inline int
     534        1517 : openssl_ctx_read_tls (tls_ctx_t *ctx, session_t *tls_session)
     535             : {
     536        1517 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
     537        1517 :   const u32 max_len = 128 << 10;
     538             :   session_t *app_session;
     539             :   svm_fifo_t *f;
     540             :   int read;
     541             : 
     542        1517 :   if (PREDICT_FALSE (SSL_in_init (oc->ssl)))
     543             :     {
     544           8 :       if (openssl_ctx_handshake_rx (ctx, tls_session) < 0)
     545           4 :         return 0;
     546             : 
     547             :       /* Application might force a session pool realloc on accept */
     548           4 :       tls_session = session_get_from_handle (ctx->tls_session_handle);
     549             :     }
     550             : 
     551        1513 :   app_session = session_get_from_handle (ctx->app_session_handle);
     552        1513 :   f = app_session->rx_fifo;
     553             : 
     554        1513 :   read = openssl_read_from_ssl_into_fifo (f, oc->ssl, max_len);
     555             : 
     556             :   /* Unrecoverable protocol error. Reset connection */
     557        1513 :   if (PREDICT_FALSE (read < 0))
     558             :     {
     559           0 :       tls_notify_app_io_error (ctx);
     560           0 :       return 0;
     561             :     }
     562             : 
     563        1513 :   if (read)
     564         950 :     tls_notify_app_enqueue (ctx, app_session);
     565             : 
     566        3026 :   if ((SSL_pending (oc->ssl) > 0) ||
     567        1513 :       svm_fifo_max_dequeue_cons (tls_session->rx_fifo))
     568         879 :     tls_add_vpp_q_builtin_rx_evt (tls_session);
     569             : 
     570        1513 :   return read;
     571             : }
     572             : 
     573             : static inline int
     574          90 : openssl_ctx_read_dtls (tls_ctx_t *ctx, session_t *us)
     575             : {
     576          90 :   openssl_main_t *om = &openssl_main;
     577          90 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
     578             :   session_dgram_hdr_t hdr;
     579             :   session_t *app_session;
     580          90 :   u32 wrote = 0;
     581             :   int read, rv;
     582             :   u8 *buf;
     583             : 
     584          90 :   if (PREDICT_FALSE (SSL_in_init (oc->ssl)))
     585             :     {
     586           4 :       u32 us_index = us->session_index;
     587           4 :       if (openssl_ctx_handshake_rx (ctx, us) < 0)
     588           2 :         return 0;
     589             :       /* Session pool might grow when allocating the app's session */
     590           2 :       us = session_get (us_index, ctx->c_thread_index);
     591             :     }
     592             : 
     593          88 :   buf = om->rx_bufs[ctx->c_thread_index];
     594          88 :   app_session = session_get_from_handle (ctx->app_session_handle);
     595          88 :   svm_fifo_fill_chunk_list (app_session->rx_fifo);
     596             : 
     597        1088 :   while (svm_fifo_max_dequeue_cons (us->rx_fifo) > 0)
     598             :     {
     599        1001 :       if (svm_fifo_max_enqueue_prod (app_session->rx_fifo) < DTLSO_MAX_DGRAM)
     600             :         {
     601           0 :           tls_add_vpp_q_builtin_rx_evt (us);
     602           1 :           goto done;
     603             :         }
     604             : 
     605        1001 :       read = SSL_read (oc->ssl, buf, vec_len (buf));
     606        1001 :       if (PREDICT_FALSE (read <= 0))
     607             :         {
     608           1 :           if (read < 0)
     609           0 :             tls_add_vpp_q_builtin_rx_evt (us);
     610           1 :           goto done;
     611             :         }
     612        1000 :       wrote += read;
     613             : 
     614        1000 :       hdr.data_length = read;
     615        1000 :       hdr.data_offset = 0;
     616             : 
     617        1000 :       svm_fifo_seg_t segs[2] = { { (u8 *) &hdr, sizeof (hdr) },
     618             :                                  { buf, read } };
     619             : 
     620        1000 :       rv = svm_fifo_enqueue_segments (app_session->rx_fifo, segs, 2,
     621             :                                       0 /* allow partial */);
     622        1000 :       ASSERT (rv > 0);
     623             :     }
     624             : 
     625          87 : done:
     626             : 
     627             :   /* If handshake just completed, session may still be in accepting state */
     628          88 :   if (app_session->session_state >= SESSION_STATE_READY)
     629          87 :     tls_notify_app_enqueue (ctx, app_session);
     630             : 
     631          88 :   return wrote;
     632             : }
     633             : 
     634             : static inline int
     635        1607 : openssl_ctx_read (tls_ctx_t *ctx, session_t *ts)
     636             : {
     637        1607 :   if (ctx->tls_type == TRANSPORT_PROTO_TLS)
     638        1517 :     return openssl_ctx_read_tls (ctx, ts);
     639             :   else
     640          90 :     return openssl_ctx_read_dtls (ctx, ts);
     641             : }
     642             : 
     643             : static int
     644           3 : openssl_set_ckpair (SSL *ssl, u32 ckpair_index)
     645             : {
     646             :   app_cert_key_pair_t *ckpair;
     647             :   BIO *cert_bio;
     648             :   EVP_PKEY *pkey;
     649             :   X509 *srvcert;
     650             : 
     651             :   /* Configure a ckpair index only if non-default/test provided */
     652           3 :   if (ckpair_index == 0)
     653           0 :     return 0;
     654             : 
     655           3 :   ckpair = app_cert_key_pair_get_if_valid (ckpair_index);
     656           3 :   if (!ckpair)
     657           0 :     return -1;
     658             : 
     659           3 :   if (!ckpair->cert || !ckpair->key)
     660             :     {
     661             :       TLS_DBG (1, "tls cert and/or key not configured");
     662           0 :       return -1;
     663             :     }
     664             :   /*
     665             :    * Set the key and cert
     666             :    */
     667           3 :   cert_bio = BIO_new (BIO_s_mem ());
     668           3 :   BIO_write (cert_bio, ckpair->cert, vec_len (ckpair->cert));
     669           3 :   srvcert = PEM_read_bio_X509 (cert_bio, NULL, NULL, NULL);
     670           3 :   if (!srvcert)
     671             :     {
     672           0 :       clib_warning ("unable to parse certificate");
     673           0 :       return -1;
     674             :     }
     675           3 :   SSL_use_certificate (ssl, srvcert);
     676           3 :   BIO_free (cert_bio);
     677             : 
     678           3 :   cert_bio = BIO_new (BIO_s_mem ());
     679           3 :   BIO_write (cert_bio, ckpair->key, vec_len (ckpair->key));
     680           3 :   pkey = PEM_read_bio_PrivateKey (cert_bio, NULL, NULL, NULL);
     681           3 :   if (!pkey)
     682             :     {
     683           0 :       clib_warning ("unable to parse pkey");
     684           0 :       return -1;
     685             :     }
     686           3 :   SSL_use_PrivateKey (ssl, pkey);
     687           3 :   BIO_free (cert_bio);
     688             :   TLS_DBG (1, "TLS client using ckpair index: %d", ckpair_index);
     689           3 :   return 0;
     690             : }
     691             : 
     692             : static int
     693           3 : openssl_client_init_verify (SSL *ssl, const char *srv_hostname,
     694             :                             int set_hostname_verification,
     695             :                             int set_hostname_strict_check)
     696             : {
     697           3 :   if (set_hostname_verification)
     698             :     {
     699           0 :       X509_VERIFY_PARAM *param = SSL_get0_param (ssl);
     700           0 :       if (!param)
     701             :         {
     702             :           TLS_DBG (1, "Couldn't fetch SSL param");
     703           0 :           return -1;
     704             :         }
     705             : 
     706           0 :       if (set_hostname_strict_check)
     707           0 :         X509_VERIFY_PARAM_set_hostflags (param,
     708             :                                          X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
     709             : 
     710           0 :       if (!X509_VERIFY_PARAM_set1_host (param, srv_hostname, 0))
     711             :         {
     712             :           TLS_DBG (1, "Couldn't set hostname for verification");
     713           0 :           return -1;
     714             :         }
     715           0 :       SSL_set_verify (ssl, SSL_VERIFY_PEER, 0);
     716             :     }
     717           3 :   if (!SSL_set_tlsext_host_name (ssl, srv_hostname))
     718             :     {
     719             :       TLS_DBG (1, "Couldn't set hostname");
     720           0 :       return -1;
     721             :     }
     722           3 :   return 0;
     723             : }
     724             : 
     725             : static int
     726           3 : openssl_ctx_init_client (tls_ctx_t * ctx)
     727             : {
     728           3 :   long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
     729           3 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
     730           3 :   openssl_main_t *om = &openssl_main;
     731             :   const SSL_METHOD *method;
     732             :   int rv, err;
     733             : 
     734           3 :   method = ctx->tls_type == TRANSPORT_PROTO_TLS ? SSLv23_client_method () :
     735           1 :                                                   DTLS_client_method ();
     736           3 :   if (method == NULL)
     737             :     {
     738             :       TLS_DBG (1, "(D)TLS_method returned null");
     739           0 :       return -1;
     740             :     }
     741             : 
     742           3 :   oc->client_ssl_ctx = SSL_CTX_new (method);
     743           3 :   if (oc->client_ssl_ctx == NULL)
     744             :     {
     745             :       TLS_DBG (1, "SSL_CTX_new returned null");
     746           0 :       return -1;
     747             :     }
     748             : 
     749             :   SSL_CTX_set_ecdh_auto (oc->client_ssl_ctx, 1);
     750           3 :   SSL_CTX_set_mode (oc->client_ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
     751             : #ifdef HAVE_OPENSSL_ASYNC
     752             :   if (om->async)
     753             :     SSL_CTX_set_mode (oc->client_ssl_ctx, SSL_MODE_ASYNC);
     754             : #endif
     755             :   rv =
     756           3 :     SSL_CTX_set_cipher_list (oc->client_ssl_ctx, (const char *) om->ciphers);
     757           3 :   if (rv != 1)
     758             :     {
     759             :       TLS_DBG (1, "Couldn't set cipher");
     760           0 :       return -1;
     761             :     }
     762             : 
     763           3 :   SSL_CTX_set_options (oc->client_ssl_ctx, flags);
     764           3 :   SSL_CTX_set1_cert_store (oc->client_ssl_ctx, om->cert_store);
     765             : 
     766           3 :   oc->ssl = SSL_new (oc->client_ssl_ctx);
     767           3 :   if (oc->ssl == NULL)
     768             :     {
     769             :       TLS_DBG (1, "Couldn't initialize ssl struct");
     770           0 :       return -1;
     771             :     }
     772             : 
     773           3 :   if (ctx->tls_type == TRANSPORT_PROTO_TLS)
     774             :     {
     775           2 :       oc->rbio = BIO_new_tls (ctx->tls_session_handle);
     776           2 :       oc->wbio = BIO_new_tls (ctx->tls_session_handle);
     777             :     }
     778             :   else
     779             :     {
     780           1 :       oc->rbio = BIO_new_dtls (ctx->tls_session_handle);
     781           1 :       oc->wbio = BIO_new_dtls (ctx->tls_session_handle);
     782             :     }
     783             : 
     784           3 :   SSL_set_bio (oc->ssl, oc->wbio, oc->rbio);
     785           3 :   SSL_set_connect_state (oc->ssl);
     786             : 
     787             :   /* Hostname validation and strict check by name are disabled by default */
     788           3 :   rv = openssl_client_init_verify (oc->ssl, (const char *) ctx->srv_hostname,
     789             :                                    0, 0);
     790           3 :   if (rv)
     791             :     {
     792             :       TLS_DBG (1, "ERROR:verify init failed:%d", rv);
     793           0 :       return -1;
     794             :     }
     795           3 :   if (openssl_set_ckpair (oc->ssl, ctx->ckpair_index))
     796             :     {
     797             :       TLS_DBG (1, "Couldn't set client certificate-key pair");
     798             :     }
     799             : 
     800             :   /*
     801             :    * 2. Do the first steps in the handshake.
     802             :    */
     803             :   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
     804             :            oc->openssl_ctx_index);
     805             : 
     806             : #ifdef HAVE_OPENSSL_ASYNC
     807             :   session_t *tls_session = session_get_from_handle (ctx->tls_session_handle);
     808             :   vpp_tls_async_init_event (ctx, openssl_ctx_handshake_rx, tls_session);
     809             : #endif
     810             :   while (1)
     811             :     {
     812           3 :       rv = SSL_do_handshake (oc->ssl);
     813           3 :       err = SSL_get_error (oc->ssl, rv);
     814             : #ifdef HAVE_OPENSSL_ASYNC
     815             :       if (err == SSL_ERROR_WANT_ASYNC)
     816             :         {
     817             :           openssl_check_async_status (ctx, openssl_ctx_handshake_rx,
     818             :                                       tls_session);
     819             :           break;
     820             :         }
     821             : #endif
     822           3 :       if (err != SSL_ERROR_WANT_WRITE)
     823           3 :         break;
     824             :     }
     825             : 
     826             :   TLS_DBG (2, "tls state for [%u]%u is su", ctx->c_thread_index,
     827             :            oc->openssl_ctx_index, SSL_state_string_long (oc->ssl));
     828           3 :   return 0;
     829             : }
     830             : 
     831             : static int
     832           3 : openssl_start_listen (tls_ctx_t * lctx)
     833             : {
     834             :   const SSL_METHOD *method;
     835             :   SSL_CTX *ssl_ctx;
     836             :   int rv;
     837             :   BIO *cert_bio;
     838             :   X509 *srvcert;
     839             :   EVP_PKEY *pkey;
     840             :   u32 olc_index;
     841             :   openssl_listen_ctx_t *olc;
     842             :   app_cert_key_pair_t *ckpair;
     843             : 
     844           3 :   long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
     845           3 :   openssl_main_t *om = &openssl_main;
     846             : 
     847           3 :   ckpair = app_cert_key_pair_get_if_valid (lctx->ckpair_index);
     848           3 :   if (!ckpair)
     849           0 :     return -1;
     850             : 
     851           3 :   if (!ckpair->cert || !ckpair->key)
     852             :     {
     853             :       TLS_DBG (1, "tls cert and/or key not configured %d",
     854             :                lctx->parent_app_wrk_index);
     855           0 :       return -1;
     856             :     }
     857             : 
     858           3 :   method = lctx->tls_type == TRANSPORT_PROTO_TLS ? SSLv23_server_method () :
     859           1 :                                                    DTLS_server_method ();
     860           3 :   ssl_ctx = SSL_CTX_new (method);
     861           3 :   if (!ssl_ctx)
     862             :     {
     863           0 :       clib_warning ("Unable to create SSL context");
     864           0 :       return -1;
     865             :     }
     866             : 
     867           3 :   SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
     868             : #ifdef HAVE_OPENSSL_ASYNC
     869             :   if (om->async)
     870             :     {
     871             :       SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ASYNC);
     872             :       SSL_CTX_set_async_callback (ssl_ctx, tls_async_openssl_callback);
     873             :     }
     874             : #endif
     875           3 :   SSL_CTX_set_options (ssl_ctx, flags);
     876             :   SSL_CTX_set_ecdh_auto (ssl_ctx, 1);
     877             : 
     878           3 :   rv = SSL_CTX_set_cipher_list (ssl_ctx, (const char *) om->ciphers);
     879           3 :   if (rv != 1)
     880             :     {
     881             :       TLS_DBG (1, "Couldn't set cipher");
     882           0 :       return -1;
     883             :     }
     884             : 
     885             :   /* use the default OpenSSL built-in DH parameters */
     886           3 :   rv = SSL_CTX_set_dh_auto (ssl_ctx, 1);
     887           3 :   if (rv != 1)
     888             :     {
     889             :       TLS_DBG (1, "Couldn't set temp DH parameters");
     890           0 :       return -1;
     891             :     }
     892             : 
     893             :   /*
     894             :    * Set the key and cert
     895             :    */
     896           3 :   cert_bio = BIO_new (BIO_s_mem ());
     897           3 :   if (!cert_bio)
     898             :     {
     899           0 :       clib_warning ("unable to allocate memory");
     900           0 :       return -1;
     901             :     }
     902           3 :   BIO_write (cert_bio, ckpair->cert, vec_len (ckpair->cert));
     903           3 :   srvcert = PEM_read_bio_X509 (cert_bio, NULL, NULL, NULL);
     904           3 :   if (!srvcert)
     905             :     {
     906           0 :       clib_warning ("unable to parse certificate");
     907           0 :       goto err;
     908             :     }
     909           3 :   rv = SSL_CTX_use_certificate (ssl_ctx, srvcert);
     910           3 :   if (rv != 1)
     911             :     {
     912           0 :       clib_warning ("unable to use SSL certificate");
     913           0 :       goto err;
     914             :     }
     915             : 
     916           3 :   BIO_free (cert_bio);
     917             : 
     918           3 :   cert_bio = BIO_new (BIO_s_mem ());
     919           3 :   if (!cert_bio)
     920             :     {
     921           0 :       clib_warning ("unable to allocate memory");
     922           0 :       return -1;
     923             :     }
     924           3 :   BIO_write (cert_bio, ckpair->key, vec_len (ckpair->key));
     925           3 :   pkey = PEM_read_bio_PrivateKey (cert_bio, NULL, NULL, NULL);
     926           3 :   if (!pkey)
     927             :     {
     928           0 :       clib_warning ("unable to parse pkey");
     929           0 :       goto err;
     930             :     }
     931           3 :   rv = SSL_CTX_use_PrivateKey (ssl_ctx, pkey);
     932           3 :   if (rv != 1)
     933             :     {
     934           0 :       clib_warning ("unable to use SSL PrivateKey");
     935           0 :       goto err;
     936             :     }
     937             : 
     938           3 :   BIO_free (cert_bio);
     939             : 
     940           3 :   olc_index = openssl_listen_ctx_alloc ();
     941           3 :   olc = openssl_lctx_get (olc_index);
     942           3 :   olc->ssl_ctx = ssl_ctx;
     943           3 :   olc->srvcert = srvcert;
     944           3 :   olc->pkey = pkey;
     945             : 
     946             :   /* store SSL_CTX into TLS level structure */
     947           3 :   lctx->tls_ssl_ctx = olc_index;
     948             : 
     949           3 :   return 0;
     950             : 
     951           0 : err:
     952           0 :   if (cert_bio)
     953           0 :     BIO_free (cert_bio);
     954           0 :   return -1;
     955             : }
     956             : 
     957             : static int
     958           3 : openssl_stop_listen (tls_ctx_t * lctx)
     959             : {
     960             :   u32 olc_index;
     961             :   openssl_listen_ctx_t *olc;
     962             : 
     963           3 :   olc_index = lctx->tls_ssl_ctx;
     964           3 :   olc = openssl_lctx_get (olc_index);
     965             : 
     966           3 :   X509_free (olc->srvcert);
     967           3 :   EVP_PKEY_free (olc->pkey);
     968             : 
     969           3 :   SSL_CTX_free (olc->ssl_ctx);
     970           3 :   openssl_listen_ctx_free (olc);
     971             : 
     972           3 :   return 0;
     973             : }
     974             : 
     975             : static int
     976           3 : openssl_ctx_init_server (tls_ctx_t * ctx)
     977             : {
     978           3 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
     979           3 :   u32 olc_index = ctx->tls_ssl_ctx;
     980             :   openssl_listen_ctx_t *olc;
     981             :   int rv, err;
     982             : 
     983             :   /* Start a new connection */
     984             : 
     985           3 :   olc = openssl_lctx_get (olc_index);
     986           3 :   oc->ssl = SSL_new (olc->ssl_ctx);
     987           3 :   if (oc->ssl == NULL)
     988             :     {
     989             :       TLS_DBG (1, "Couldn't initialize ssl struct");
     990           0 :       return -1;
     991             :     }
     992             : 
     993           3 :   if (ctx->tls_type == TRANSPORT_PROTO_TLS)
     994             :     {
     995           2 :       oc->rbio = BIO_new_tls (ctx->tls_session_handle);
     996           2 :       oc->wbio = BIO_new_tls (ctx->tls_session_handle);
     997             :     }
     998             :   else
     999             :     {
    1000           1 :       oc->rbio = BIO_new_dtls (ctx->tls_session_handle);
    1001           1 :       oc->wbio = BIO_new_dtls (ctx->tls_session_handle);
    1002             :     }
    1003             : 
    1004           3 :   SSL_set_bio (oc->ssl, oc->wbio, oc->rbio);
    1005           3 :   SSL_set_accept_state (oc->ssl);
    1006             : 
    1007             :   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
    1008             :            oc->openssl_ctx_index);
    1009             : 
    1010             : #ifdef HAVE_OPENSSL_ASYNC
    1011             :   session_t *tls_session = session_get_from_handle (ctx->tls_session_handle);
    1012             :   vpp_tls_async_init_event (ctx, openssl_ctx_handshake_rx, tls_session);
    1013             : #endif
    1014             :   while (1)
    1015             :     {
    1016           3 :       rv = SSL_do_handshake (oc->ssl);
    1017           3 :       err = SSL_get_error (oc->ssl, rv);
    1018             : #ifdef HAVE_OPENSSL_ASYNC
    1019             :       if (err == SSL_ERROR_WANT_ASYNC)
    1020             :         {
    1021             :           openssl_check_async_status (ctx, openssl_ctx_handshake_rx,
    1022             :                                       tls_session);
    1023             :           break;
    1024             :         }
    1025             : #endif
    1026           3 :       if (err != SSL_ERROR_WANT_WRITE)
    1027           3 :         break;
    1028             :     }
    1029             : 
    1030             :   TLS_DBG (2, "tls state for [%u]%u is su", ctx->c_thread_index,
    1031             :            oc->openssl_ctx_index, SSL_state_string_long (oc->ssl));
    1032           3 :   return 0;
    1033             : }
    1034             : 
    1035             : static u8
    1036           2 : openssl_handshake_is_over (tls_ctx_t * ctx)
    1037             : {
    1038           2 :   openssl_ctx_t *mc = (openssl_ctx_t *) ctx;
    1039           2 :   if (!mc->ssl)
    1040           0 :     return 0;
    1041           2 :   return SSL_is_init_finished (mc->ssl);
    1042             : }
    1043             : 
    1044             : static int
    1045           2 : openssl_transport_close (tls_ctx_t * ctx)
    1046             : {
    1047             : #ifdef HAVE_OPENSSL_ASYNC
    1048             :   if (vpp_openssl_is_inflight (ctx))
    1049             :     return 0;
    1050             : #endif
    1051             : 
    1052           2 :   if (!openssl_handshake_is_over (ctx))
    1053             :     {
    1054           0 :       openssl_handle_handshake_failure (ctx);
    1055           0 :       return 0;
    1056             :     }
    1057           2 :   session_transport_closing_notify (&ctx->connection);
    1058           2 :   return 0;
    1059             : }
    1060             : 
    1061             : static int
    1062           6 : openssl_app_close (tls_ctx_t * ctx)
    1063             : {
    1064           6 :   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
    1065             :   session_t *app_session;
    1066             : 
    1067             :   /* Wait for all data to be written to tcp */
    1068           6 :   app_session = session_get_from_handle (ctx->app_session_handle);
    1069           6 :   if (BIO_ctrl_pending (oc->rbio) <= 0
    1070           6 :       && !svm_fifo_max_dequeue_cons (app_session->tx_fifo))
    1071           6 :     openssl_confirm_app_close (ctx);
    1072             :   else
    1073           0 :     ctx->app_closed = 1;
    1074           6 :   return 0;
    1075             : }
    1076             : 
    1077             : int
    1078         575 : tls_init_ca_chain (void)
    1079             : {
    1080         575 :   openssl_main_t *om = &openssl_main;
    1081         575 :   tls_main_t *tm = vnet_tls_get_main ();
    1082             :   BIO *cert_bio;
    1083             :   X509 *testcert;
    1084             :   int rv;
    1085             : 
    1086         575 :   if (access (tm->ca_cert_path, F_OK | R_OK) == -1)
    1087             :     {
    1088           0 :       clib_warning ("Could not initialize TLS CA certificates");
    1089           0 :       return -1;
    1090             :     }
    1091             : 
    1092         575 :   if (!(om->cert_store = X509_STORE_new ()))
    1093             :     {
    1094           0 :       clib_warning ("failed to create cert store");
    1095           0 :       return -1;
    1096             :     }
    1097             : 
    1098             : #if OPENSSL_VERSION_NUMBER >= 0x30000000L
    1099             :   rv = X509_STORE_load_file (om->cert_store, tm->ca_cert_path);
    1100             : #else
    1101         575 :   rv = X509_STORE_load_locations (om->cert_store, tm->ca_cert_path, 0);
    1102             : #endif
    1103             : 
    1104         575 :   if (rv < 0)
    1105             :     {
    1106           0 :       clib_warning ("failed to load ca certificate");
    1107             :     }
    1108             : 
    1109         575 :   if (tm->use_test_cert_in_ca)
    1110             :     {
    1111           0 :       cert_bio = BIO_new (BIO_s_mem ());
    1112           0 :       BIO_write (cert_bio, test_srv_crt_rsa, test_srv_crt_rsa_len);
    1113           0 :       testcert = PEM_read_bio_X509 (cert_bio, NULL, NULL, NULL);
    1114           0 :       if (!testcert)
    1115             :         {
    1116           0 :           clib_warning ("unable to parse certificate");
    1117           0 :           return -1;
    1118             :         }
    1119           0 :       X509_STORE_add_cert (om->cert_store, testcert);
    1120           0 :       rv = 0;
    1121             :     }
    1122         575 :   return (rv < 0 ? -1 : 0);
    1123             : }
    1124             : 
    1125             : int
    1126           0 : openssl_reinit_ca_chain (void)
    1127             : {
    1128           0 :   openssl_main_t *om = &openssl_main;
    1129             : 
    1130             :   /* Remove/free existing x509_store */
    1131           0 :   if (om->cert_store)
    1132             :     {
    1133           0 :       X509_STORE_free (om->cert_store);
    1134             :     }
    1135           0 :   return tls_init_ca_chain ();
    1136             : }
    1137             : 
    1138             : const static tls_engine_vft_t openssl_engine = {
    1139             :   .ctx_alloc = openssl_ctx_alloc,
    1140             :   .ctx_alloc_w_thread = openssl_ctx_alloc_w_thread,
    1141             :   .ctx_free = openssl_ctx_free,
    1142             :   .ctx_attach = openssl_ctx_attach,
    1143             :   .ctx_detach = openssl_ctx_detach,
    1144             :   .ctx_get = openssl_ctx_get,
    1145             :   .ctx_get_w_thread = openssl_ctx_get_w_thread,
    1146             :   .ctx_init_server = openssl_ctx_init_server,
    1147             :   .ctx_init_client = openssl_ctx_init_client,
    1148             :   .ctx_write = openssl_ctx_write,
    1149             :   .ctx_read = openssl_ctx_read,
    1150             :   .ctx_handshake_is_over = openssl_handshake_is_over,
    1151             :   .ctx_start_listen = openssl_start_listen,
    1152             :   .ctx_stop_listen = openssl_stop_listen,
    1153             :   .ctx_transport_close = openssl_transport_close,
    1154             :   .ctx_app_close = openssl_app_close,
    1155             :   .ctx_reinit_cachain = openssl_reinit_ca_chain,
    1156             : };
    1157             : 
    1158             : int
    1159         575 : tls_openssl_set_ciphers (char *ciphers)
    1160             : {
    1161         575 :   openssl_main_t *om = &openssl_main;
    1162             :   int i;
    1163             : 
    1164         575 :   if (!ciphers)
    1165             :     {
    1166           0 :       return -1;
    1167             :     }
    1168             : 
    1169         575 :   vec_validate (om->ciphers, strlen (ciphers));
    1170       32775 :   for (i = 0; i < vec_len (om->ciphers) - 1; i++)
    1171             :     {
    1172       32200 :       om->ciphers[i] = toupper (ciphers[i]);
    1173             :     }
    1174             : 
    1175         575 :   return 0;
    1176             : 
    1177             : }
    1178             : 
    1179             : static clib_error_t *
    1180         575 : tls_openssl_init (vlib_main_t * vm)
    1181             : {
    1182         575 :   vlib_thread_main_t *vtm = vlib_get_thread_main ();
    1183         575 :   openssl_main_t *om = &openssl_main;
    1184         575 :   clib_error_t *error = 0;
    1185             :   u32 num_threads, i;
    1186             : 
    1187         575 :   error = tls_openssl_api_init (vm);
    1188         575 :   num_threads = 1 /* main thread */  + vtm->n_threads;
    1189             : 
    1190         575 :   SSL_library_init ();
    1191         575 :   SSL_load_error_strings ();
    1192             : 
    1193         575 :   vec_validate (om->ctx_pool, num_threads - 1);
    1194         575 :   vec_validate (om->rx_bufs, num_threads - 1);
    1195         575 :   vec_validate (om->tx_bufs, num_threads - 1);
    1196        1205 :   for (i = 0; i < num_threads; i++)
    1197             :     {
    1198         630 :       vec_validate (om->rx_bufs[i], DTLSO_MAX_DGRAM);
    1199         630 :       vec_validate (om->tx_bufs[i], DTLSO_MAX_DGRAM);
    1200             :     }
    1201         575 :   tls_register_engine (&openssl_engine, CRYPTO_ENGINE_OPENSSL);
    1202             : 
    1203         575 :   om->engine_init = 0;
    1204             : 
    1205             :   /* default ciphers */
    1206         575 :   tls_openssl_set_ciphers
    1207             :     ("ALL:!ADH:!LOW:!EXP:!MD5:!RC4-SHA:!DES-CBC3-SHA:@STRENGTH");
    1208             : 
    1209         575 :   if (tls_init_ca_chain ())
    1210             :     {
    1211           0 :       clib_warning ("failed to initialize TLS CA chain");
    1212           0 :       return 0;
    1213             :     }
    1214             : 
    1215         575 :   return error;
    1216             : }
    1217             : /* *INDENT-OFF* */
    1218        1151 : VLIB_INIT_FUNCTION (tls_openssl_init) =
    1219             : {
    1220             :   .runs_after = VLIB_INITS("tls_init"),
    1221             : };
    1222             : /* *INDENT-ON* */
    1223             : 
    1224             : #ifdef HAVE_OPENSSL_ASYNC
    1225             : static clib_error_t *
    1226             : tls_openssl_set_command_fn (vlib_main_t * vm, unformat_input_t * input,
    1227             :                             vlib_cli_command_t * cmd)
    1228             : {
    1229             :   openssl_main_t *om = &openssl_main;
    1230             :   char *engine_name = NULL;
    1231             :   char *engine_alg = NULL;
    1232             :   char *ciphers = NULL;
    1233             :   u8 engine_name_set = 0;
    1234             :   int i, async = 0;
    1235             : 
    1236             :   /* By present, it is not allowed to configure engine again after running */
    1237             :   if (om->engine_init)
    1238             :     {
    1239             :       clib_warning ("engine has started!\n");
    1240             :       return clib_error_return
    1241             :         (0, "engine has started, and no config is accepted");
    1242             :     }
    1243             : 
    1244             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1245             :     {
    1246             :       if (unformat (input, "engine %s", &engine_name))
    1247             :         {
    1248             :           engine_name_set = 1;
    1249             :         }
    1250             :       else if (unformat (input, "async"))
    1251             :         {
    1252             :           async = 1;
    1253             :         }
    1254             :       else if (unformat (input, "alg %s", &engine_alg))
    1255             :         {
    1256             :           for (i = 0; i < strnlen (engine_alg, MAX_CRYPTO_LEN); i++)
    1257             :             engine_alg[i] = toupper (engine_alg[i]);
    1258             :         }
    1259             :       else if (unformat (input, "ciphers %s", &ciphers))
    1260             :         {
    1261             :           tls_openssl_set_ciphers (ciphers);
    1262             :         }
    1263             :       else
    1264             :         return clib_error_return (0, "failed: unknown input `%U'",
    1265             :                                   format_unformat_error, input);
    1266             :     }
    1267             : 
    1268             :   /* reset parameters if engine is not configured */
    1269             :   if (!engine_name_set)
    1270             :     {
    1271             :       clib_warning ("No engine provided! \n");
    1272             :       async = 0;
    1273             :     }
    1274             :   else
    1275             :     {
    1276             :       vnet_session_enable_disable (vm, 1);
    1277             :       if (openssl_engine_register (engine_name, engine_alg, async) < 0)
    1278             :         {
    1279             :           return clib_error_return (0, "Failed to register %s polling",
    1280             :                                     engine_name);
    1281             :         }
    1282             :       else
    1283             :         {
    1284             :           vlib_cli_output (vm, "Successfully register engine %s\n",
    1285             :                            engine_name);
    1286             :         }
    1287             :     }
    1288             :   om->async = async;
    1289             : 
    1290             :   return 0;
    1291             : }
    1292             : 
    1293             : /* *INDENT-OFF* */
    1294             : VLIB_CLI_COMMAND (tls_openssl_set_command, static) =
    1295             : {
    1296             :   .path = "tls openssl set",
    1297             :   .short_help = "tls openssl set [engine <engine name>] [alg [algorithm] [async]",
    1298             :   .function = tls_openssl_set_command_fn,
    1299             : };
    1300             : /* *INDENT-ON* */
    1301             : #endif
    1302             : 
    1303             : /* *INDENT-OFF* */
    1304             : VLIB_PLUGIN_REGISTER () = {
    1305             :     .version = VPP_BUILD_VER,
    1306             :     .description = "Transport Layer Security (TLS) Engine, OpenSSL Based",
    1307             : };
    1308             : /* *INDENT-ON* */
    1309             : 
    1310             : /*
    1311             :  * fd.io coding-style-patch-verification: ON
    1312             :  *
    1313             :  * Local Variables:
    1314             :  * eval: (c-set-style "gnu")
    1315             :  * End:
    1316             :  */

Generated by: LCOV version 1.14