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

Generated by: LCOV version 1.14