LCOV - code coverage report
Current view: top level - vnet/tls - tls.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 432 632 68.4 %
Date: 2023-10-26 01:39:38 Functions: 60 79 75.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018-2019 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 <vnet/session/application_interface.h>
      17             : #include <vppinfra/lock.h>
      18             : #include <vnet/tls/tls.h>
      19             : 
      20             : static tls_main_t tls_main;
      21             : static tls_engine_vft_t *tls_vfts;
      22             : 
      23             : #define TLS_INVALID_HANDLE      ~0
      24             : #define TLS_IDX_MASK            0x00FFFFFF
      25             : #define TLS_ENGINE_TYPE_SHIFT   28
      26             : 
      27             : void tls_disconnect (u32 ctx_handle, u32 thread_index);
      28             : 
      29             : void
      30           6 : tls_disconnect_transport (tls_ctx_t * ctx)
      31             : {
      32           6 :   vnet_disconnect_args_t a = {
      33           6 :     .handle = ctx->tls_session_handle,
      34           6 :     .app_index = tls_main.app_index,
      35             :   };
      36             : 
      37           6 :   if (vnet_disconnect_session (&a))
      38           0 :     clib_warning ("disconnect returned");
      39           6 : }
      40             : 
      41             : crypto_engine_type_t
      42           0 : tls_get_available_engine (void)
      43             : {
      44             :   int i;
      45           0 :   for (i = 0; i < vec_len (tls_vfts); i++)
      46             :     {
      47           0 :       if (tls_vfts[i].ctx_alloc)
      48           0 :         return i;
      49             :     }
      50           0 :   return CRYPTO_ENGINE_NONE;
      51             : }
      52             : 
      53             : int
      54           0 : tls_add_vpp_q_rx_evt (session_t * s)
      55             : {
      56           0 :   if (svm_fifo_set_event (s->rx_fifo))
      57           0 :     session_send_io_evt_to_thread (s->rx_fifo, SESSION_IO_EVT_RX);
      58           0 :   return 0;
      59             : }
      60             : 
      61             : int
      62         879 : tls_add_vpp_q_builtin_rx_evt (session_t * s)
      63             : {
      64         879 :   session_enqueue_notify (s);
      65         879 :   return 0;
      66             : }
      67             : 
      68             : int
      69          58 : tls_add_vpp_q_tx_evt (session_t * s)
      70             : {
      71          58 :   if (svm_fifo_set_event (s->tx_fifo))
      72           0 :     session_send_io_evt_to_thread (s->tx_fifo, SESSION_IO_EVT_TX);
      73          58 :   return 0;
      74             : }
      75             : 
      76             : static inline int
      77        1037 : tls_add_app_q_evt (app_worker_t *app_wrk, session_t *app_session)
      78             : {
      79        1037 :   app_worker_add_event (app_wrk, app_session, SESSION_IO_EVT_RX);
      80        1037 :   return 0;
      81             : }
      82             : 
      83             : u32
      84           3 : tls_listener_ctx_alloc (void)
      85             : {
      86           3 :   tls_main_t *tm = &tls_main;
      87             :   tls_ctx_t *ctx;
      88             : 
      89           3 :   pool_get (tm->listener_ctx_pool, ctx);
      90           3 :   clib_memset (ctx, 0, sizeof (*ctx));
      91           3 :   return ctx - tm->listener_ctx_pool;
      92             : }
      93             : 
      94             : void
      95           3 : tls_listener_ctx_free (tls_ctx_t * ctx)
      96             : {
      97             :   if (CLIB_DEBUG)
      98           3 :     memset (ctx, 0xfb, sizeof (*ctx));
      99           3 :   pool_put (tls_main.listener_ctx_pool, ctx);
     100           3 : }
     101             : 
     102             : tls_ctx_t *
     103          24 : tls_listener_ctx_get (u32 ctx_index)
     104             : {
     105          24 :   return pool_elt_at_index (tls_main.listener_ctx_pool, ctx_index);
     106             : }
     107             : 
     108             : u32
     109           0 : tls_listener_ctx_index (tls_ctx_t * ctx)
     110             : {
     111           0 :   return (ctx - tls_main.listener_ctx_pool);
     112             : }
     113             : 
     114             : u32
     115           2 : tls_ctx_half_open_alloc (void)
     116             : {
     117           2 :   tls_main_t *tm = &tls_main;
     118             :   tls_ctx_t *ctx;
     119             : 
     120           2 :   pool_get_aligned_safe (tm->half_open_ctx_pool, ctx, CLIB_CACHE_LINE_BYTES);
     121             : 
     122           2 :   clib_memset (ctx, 0, sizeof (*ctx));
     123           2 :   ctx->c_c_index = ctx - tm->half_open_ctx_pool;
     124           2 :   ctx->c_thread_index = transport_cl_thread ();
     125             : 
     126           2 :   return ctx->c_c_index;
     127             : }
     128             : 
     129             : void
     130           2 : tls_ctx_half_open_free (u32 ho_index)
     131             : {
     132           2 :   pool_put_index (tls_main.half_open_ctx_pool, ho_index);
     133           2 : }
     134             : 
     135             : tls_ctx_t *
     136           8 : tls_ctx_half_open_get (u32 ctx_index)
     137             : {
     138           8 :   tls_main_t *tm = &tls_main;
     139           8 :   return pool_elt_at_index (tm->half_open_ctx_pool, ctx_index);
     140             : }
     141             : 
     142             : void
     143        1037 : tls_notify_app_enqueue (tls_ctx_t * ctx, session_t * app_session)
     144             : {
     145             :   app_worker_t *app_wrk;
     146        1037 :   app_wrk = app_worker_get_if_valid (app_session->app_wrk_index);
     147        1037 :   if (PREDICT_TRUE (app_wrk != 0))
     148        1037 :     tls_add_app_q_evt (app_wrk, app_session);
     149        1037 : }
     150             : 
     151             : int
     152           3 : tls_notify_app_accept (tls_ctx_t * ctx)
     153             : {
     154             :   session_t *app_listener, *app_session;
     155             :   app_worker_t *app_wrk;
     156             :   tls_ctx_t *lctx;
     157             :   int rv;
     158             : 
     159           3 :   lctx = tls_listener_ctx_get (ctx->listener_ctx_index);
     160           3 :   app_listener = listen_session_get_from_handle (lctx->app_session_handle);
     161             : 
     162           3 :   app_session = session_get (ctx->c_s_index, ctx->c_thread_index);
     163           3 :   app_session->app_wrk_index = ctx->parent_app_wrk_index;
     164           3 :   app_session->connection_index = ctx->tls_ctx_handle;
     165           3 :   app_session->session_type = app_listener->session_type;
     166           3 :   app_session->listener_handle = listen_session_get_handle (app_listener);
     167           3 :   app_session->session_state = SESSION_STATE_ACCEPTING;
     168             : 
     169           3 :   if ((rv = app_worker_init_accepted (app_session)))
     170             :     {
     171             :       TLS_DBG (1, "failed to allocate fifos");
     172           0 :       session_free (app_session);
     173           0 :       return rv;
     174             :     }
     175           3 :   ctx->app_session_handle = session_handle (app_session);
     176           3 :   ctx->parent_app_wrk_index = app_session->app_wrk_index;
     177           3 :   app_wrk = app_worker_get (app_session->app_wrk_index);
     178           3 :   return app_worker_accept_notify (app_wrk, app_session);
     179             : }
     180             : 
     181             : int
     182           3 : tls_notify_app_connected (tls_ctx_t * ctx, session_error_t err)
     183             : {
     184             :   u32 parent_app_api_ctx;
     185             :   session_t *app_session;
     186             :   app_worker_t *app_wrk;
     187             : 
     188           3 :   app_wrk = app_worker_get_if_valid (ctx->parent_app_wrk_index);
     189           3 :   if (!app_wrk)
     190             :     {
     191           0 :       if (ctx->tls_type == TRANSPORT_PROTO_TLS)
     192           0 :         session_free (session_get (ctx->c_s_index, ctx->c_thread_index));
     193           0 :       ctx->no_app_session = 1;
     194           0 :       return -1;
     195             :     }
     196             : 
     197           3 :   if (err)
     198             :     {
     199             :       /* Free app session pre-allocated when transport was established */
     200           0 :       if (ctx->tls_type == TRANSPORT_PROTO_TLS)
     201           0 :         session_free (session_get (ctx->c_s_index, ctx->c_thread_index));
     202           0 :       ctx->no_app_session = 1;
     203           0 :       goto send_reply;
     204             :     }
     205             : 
     206             :   /* For DTLS the app session is not preallocated because the underlying udp
     207             :    * session might migrate to a different worker during the handshake */
     208           3 :   if (ctx->tls_type == TRANSPORT_PROTO_DTLS)
     209             :     {
     210             :       session_type_t st;
     211             :       /* Cleanup half-open session as we don't get notification from udp */
     212           1 :       session_half_open_delete_notify (&ctx->connection);
     213           1 :       app_session = session_alloc (ctx->c_thread_index);
     214           1 :       app_session->session_state = SESSION_STATE_CREATED;
     215           1 :       ctx->c_s_index = app_session->session_index;
     216             :       st =
     217           1 :         session_type_from_proto_and_ip (TRANSPORT_PROTO_DTLS, ctx->tcp_is_ip4);
     218           1 :       app_session->session_type = st;
     219           1 :       app_session->connection_index = ctx->tls_ctx_handle;
     220             :     }
     221             :   else
     222             :     {
     223           2 :       app_session = session_get (ctx->c_s_index, ctx->c_thread_index);
     224             :     }
     225             : 
     226           3 :   app_session->app_wrk_index = ctx->parent_app_wrk_index;
     227           3 :   app_session->opaque = ctx->parent_app_api_context;
     228             : 
     229           3 :   if ((err = app_worker_init_connected (app_wrk, app_session)))
     230             :     {
     231           0 :       app_worker_connect_notify (app_wrk, 0, err, ctx->parent_app_api_context);
     232           0 :       ctx->no_app_session = 1;
     233           0 :       session_free (app_session);
     234           0 :       return -1;
     235             :     }
     236             : 
     237           3 :   app_session->session_state = SESSION_STATE_READY;
     238           3 :   parent_app_api_ctx = ctx->parent_app_api_context;
     239           3 :   ctx->app_session_handle = session_handle (app_session);
     240             : 
     241           3 :   if (app_worker_connect_notify (app_wrk, app_session, SESSION_E_NONE,
     242             :                                  parent_app_api_ctx))
     243             :     {
     244             :       TLS_DBG (1, "failed to notify app");
     245           0 :       session_free (session_get (ctx->c_s_index, ctx->c_thread_index));
     246           0 :       ctx->no_app_session = 1;
     247           0 :       return -1;
     248             :     }
     249             : 
     250           3 :   return 0;
     251             : 
     252           0 : send_reply:
     253           0 :   return app_worker_connect_notify (app_wrk, 0, err,
     254             :                                     ctx->parent_app_api_context);
     255             : }
     256             : 
     257             : static inline void
     258     2549840 : tls_ctx_parse_handle (u32 ctx_handle, u32 * ctx_index, u32 * engine_type)
     259             : {
     260     2549840 :   *ctx_index = ctx_handle & TLS_IDX_MASK;
     261     2549840 :   *engine_type = ctx_handle >> TLS_ENGINE_TYPE_SHIFT;
     262     2549840 : }
     263             : 
     264             : static inline crypto_engine_type_t
     265           6 : tls_get_engine_type (crypto_engine_type_t requested,
     266             :                      crypto_engine_type_t preferred)
     267             : {
     268           6 :   if (requested != CRYPTO_ENGINE_NONE)
     269             :     {
     270           0 :       if (tls_vfts[requested].ctx_alloc)
     271           0 :         return requested;
     272           0 :       return CRYPTO_ENGINE_NONE;
     273             :     }
     274           6 :   if (!tls_vfts[preferred].ctx_alloc)
     275           0 :     return tls_get_available_engine ();
     276           6 :   return preferred;
     277             : }
     278             : 
     279             : static inline u32
     280           5 : tls_ctx_alloc (crypto_engine_type_t engine_type)
     281             : {
     282             :   u32 ctx_index;
     283           5 :   ctx_index = tls_vfts[engine_type].ctx_alloc ();
     284           5 :   return (((u32) engine_type << TLS_ENGINE_TYPE_SHIFT) | ctx_index);
     285             : }
     286             : 
     287             : static inline u32
     288           1 : tls_ctx_alloc_w_thread (crypto_engine_type_t engine_type, u32 thread_index)
     289             : {
     290             :   u32 ctx_index;
     291           1 :   ctx_index = tls_vfts[engine_type].ctx_alloc_w_thread (thread_index);
     292           1 :   return (((u32) engine_type << TLS_ENGINE_TYPE_SHIFT) | ctx_index);
     293             : }
     294             : 
     295             : static inline u32
     296           0 : tls_ctx_attach (crypto_engine_type_t engine_type, u32 thread_index, void *ctx)
     297             : {
     298             :   u32 ctx_index;
     299           0 :   ctx_index = tls_vfts[engine_type].ctx_attach (thread_index, ctx);
     300           0 :   return (((u32) engine_type << TLS_ENGINE_TYPE_SHIFT) | ctx_index);
     301             : }
     302             : 
     303             : static inline void *
     304           0 : tls_ctx_detach (tls_ctx_t *ctx)
     305             : {
     306           0 :   return tls_vfts[ctx->tls_ctx_engine].ctx_detach (ctx);
     307             : }
     308             : 
     309             : static inline tls_ctx_t *
     310     1275000 : tls_ctx_get (u32 ctx_handle)
     311             : {
     312             :   u32 ctx_index, engine_type;
     313     1275000 :   tls_ctx_parse_handle (ctx_handle, &ctx_index, &engine_type);
     314     1275000 :   return tls_vfts[engine_type].ctx_get (ctx_index);
     315             : }
     316             : 
     317             : static inline tls_ctx_t *
     318     1274850 : tls_ctx_get_w_thread (u32 ctx_handle, u8 thread_index)
     319             : {
     320             :   u32 ctx_index, engine_type;
     321     1274850 :   tls_ctx_parse_handle (ctx_handle, &ctx_index, &engine_type);
     322     1274850 :   return tls_vfts[engine_type].ctx_get_w_thread (ctx_index, thread_index);
     323             : }
     324             : 
     325             : static inline int
     326           3 : tls_ctx_init_server (tls_ctx_t * ctx)
     327             : {
     328           3 :   return tls_vfts[ctx->tls_ctx_engine].ctx_init_server (ctx);
     329             : }
     330             : 
     331             : static inline int
     332           3 : tls_ctx_init_client (tls_ctx_t * ctx)
     333             : {
     334           3 :   return tls_vfts[ctx->tls_ctx_engine].ctx_init_client (ctx);
     335             : }
     336             : 
     337             : static inline int
     338     1273280 : tls_ctx_write (tls_ctx_t * ctx, session_t * app_session,
     339             :                transport_send_params_t * sp)
     340             : {
     341             :   u32 n_wrote;
     342             : 
     343     1273280 :   sp->max_burst_size = sp->max_burst_size * TRANSPORT_PACER_MIN_MSS;
     344     1273280 :   n_wrote = tls_vfts[ctx->tls_ctx_engine].ctx_write (ctx, app_session, sp);
     345     1273280 :   sp->bytes_dequeued = n_wrote;
     346     1273280 :   return n_wrote > 0 ? clib_max (n_wrote / TRANSPORT_PACER_MIN_MSS, 1) : 0;
     347             : }
     348             : 
     349             : static inline int
     350        1607 : tls_ctx_read (tls_ctx_t * ctx, session_t * tls_session)
     351             : {
     352        1607 :   return tls_vfts[ctx->tls_ctx_engine].ctx_read (ctx, tls_session);
     353             : }
     354             : 
     355             : static inline int
     356           2 : tls_ctx_transport_close (tls_ctx_t * ctx)
     357             : {
     358           2 :   return tls_vfts[ctx->tls_ctx_engine].ctx_transport_close (ctx);
     359             : }
     360             : 
     361             : static inline int
     362           6 : tls_ctx_app_close (tls_ctx_t * ctx)
     363             : {
     364           6 :   return tls_vfts[ctx->tls_ctx_engine].ctx_app_close (ctx);
     365             : }
     366             : 
     367             : void
     368           4 : tls_ctx_free (tls_ctx_t * ctx)
     369             : {
     370           4 :   tls_vfts[ctx->tls_ctx_engine].ctx_free (ctx);
     371           4 : }
     372             : 
     373             : u8
     374           0 : tls_ctx_handshake_is_over (tls_ctx_t * ctx)
     375             : {
     376           0 :   return tls_vfts[ctx->tls_ctx_engine].ctx_handshake_is_over (ctx);
     377             : }
     378             : 
     379             : int
     380           0 : tls_reinit_ca_chain (crypto_engine_type_t tls_engine_id)
     381             : {
     382           0 :   return tls_vfts[tls_engine_id].ctx_reinit_cachain ();
     383             : }
     384             : 
     385             : void
     386           0 : tls_notify_app_io_error (tls_ctx_t *ctx)
     387             : {
     388           0 :   ASSERT (tls_ctx_handshake_is_over (ctx));
     389             : 
     390           0 :   session_transport_reset_notify (&ctx->connection);
     391           0 :   session_transport_closed_notify (&ctx->connection);
     392           0 :   tls_disconnect_transport (ctx);
     393           0 : }
     394             : 
     395             : void
     396           0 : tls_session_reset_callback (session_t * s)
     397             : {
     398             :   tls_ctx_t *ctx;
     399             :   transport_connection_t *tc;
     400             :   session_t *app_session;
     401             : 
     402           0 :   ctx = tls_ctx_get (s->opaque);
     403           0 :   ctx->is_passive_close = 1;
     404           0 :   tc = &ctx->connection;
     405           0 :   if (tls_ctx_handshake_is_over (ctx))
     406             :     {
     407           0 :       session_transport_reset_notify (tc);
     408           0 :       session_transport_closed_notify (tc);
     409           0 :       tls_disconnect_transport (ctx);
     410             :     }
     411             :   else
     412           0 :     if ((app_session =
     413           0 :          session_get_if_valid (ctx->c_s_index, ctx->c_thread_index)))
     414             :     {
     415           0 :       session_free (app_session);
     416           0 :       ctx->c_s_index = SESSION_INVALID_INDEX;
     417           0 :       tls_disconnect_transport (ctx);
     418             :     }
     419           0 : }
     420             : 
     421             : static void
     422           2 : tls_session_cleanup_ho (session_t *s)
     423             : {
     424             :   tls_ctx_t *ctx;
     425             :   u32 ho_index;
     426             : 
     427             :   /* session opaque stores the opaque passed on connect */
     428           2 :   ho_index = s->opaque;
     429           2 :   ctx = tls_ctx_half_open_get (ho_index);
     430           2 :   session_half_open_delete_notify (&ctx->connection);
     431           2 :   tls_ctx_half_open_free (ho_index);
     432           2 : }
     433             : 
     434             : int
     435           3 : tls_add_segment_callback (u32 client_index, u64 segment_handle)
     436             : {
     437             :   /* No-op for builtin */
     438           3 :   return 0;
     439             : }
     440             : 
     441             : int
     442           0 : tls_del_segment_callback (u32 client_index, u64 segment_handle)
     443             : {
     444           0 :   return 0;
     445             : }
     446             : 
     447             : void
     448           2 : tls_session_disconnect_callback (session_t * tls_session)
     449             : {
     450             :   tls_ctx_t *ctx;
     451             : 
     452             :   TLS_DBG (1, "TCP disconnecting handle %x session %u", tls_session->opaque,
     453             :            tls_session->session_index);
     454             : 
     455           2 :   ASSERT (tls_session->thread_index == vlib_get_thread_index ()
     456             :           || vlib_thread_is_main_w_barrier ());
     457             : 
     458           2 :   ctx = tls_ctx_get_w_thread (tls_session->opaque, tls_session->thread_index);
     459           2 :   ctx->is_passive_close = 1;
     460           2 :   tls_ctx_transport_close (ctx);
     461           2 : }
     462             : 
     463             : int
     464           3 : tls_session_accept_callback (session_t * tls_session)
     465             : {
     466             :   session_t *tls_listener, *app_session;
     467             :   tls_ctx_t *lctx, *ctx;
     468             :   u32 ctx_handle;
     469             :   int rv;
     470             : 
     471             :   tls_listener =
     472           3 :     listen_session_get_from_handle (tls_session->listener_handle);
     473           3 :   lctx = tls_listener_ctx_get (tls_listener->opaque);
     474             : 
     475           3 :   ctx_handle = tls_ctx_alloc (lctx->tls_ctx_engine);
     476           3 :   ctx = tls_ctx_get (ctx_handle);
     477           3 :   memcpy (ctx, lctx, sizeof (*lctx));
     478           3 :   ctx->c_thread_index = vlib_get_thread_index ();
     479           3 :   ctx->tls_ctx_handle = ctx_handle;
     480           3 :   tls_session->session_state = SESSION_STATE_READY;
     481           3 :   tls_session->opaque = ctx_handle;
     482           3 :   ctx->tls_session_handle = session_handle (tls_session);
     483           3 :   ctx->listener_ctx_index = tls_listener->opaque;
     484           3 :   ctx->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
     485           3 :   ctx->ckpair_index = lctx->ckpair_index;
     486             : 
     487             :   /* Preallocate app session. Avoids allocating a session post handshake
     488             :    * on tls_session rx and potentially invalidating the session pool */
     489           3 :   app_session = session_alloc (ctx->c_thread_index);
     490           3 :   app_session->session_state = SESSION_STATE_CREATED;
     491           3 :   app_session->session_type =
     492           3 :     session_type_from_proto_and_ip (TRANSPORT_PROTO_TLS, ctx->tcp_is_ip4);
     493           3 :   app_session->connection_index = ctx->tls_ctx_handle;
     494           3 :   ctx->c_s_index = app_session->session_index;
     495             : 
     496             :   TLS_DBG (1, "Accept on listener %u new connection [%u]%x",
     497             :            tls_listener->opaque, vlib_get_thread_index (), ctx_handle);
     498             : 
     499           3 :   rv = tls_ctx_init_server (ctx);
     500           3 :   if (rv)
     501             :     {
     502           0 :       session_free (app_session);
     503           0 :       tls_ctx_free (ctx);
     504             :     }
     505             : 
     506           3 :   return rv;
     507             : }
     508             : 
     509             : int
     510        1607 : tls_app_rx_callback (session_t * tls_session)
     511             : {
     512             :   tls_ctx_t *ctx;
     513             : 
     514             :   /* DTLS session migrating, wait for next notification */
     515        1607 :   if (PREDICT_FALSE (tls_session->flags & SESSION_F_IS_MIGRATING))
     516           0 :     return 0;
     517             : 
     518        1607 :   ctx = tls_ctx_get (tls_session->opaque);
     519        1607 :   if (PREDICT_FALSE (ctx->no_app_session || ctx->app_closed))
     520             :     {
     521             :       TLS_DBG (1, "Local App closed");
     522           0 :       return 0;
     523             :     }
     524        1607 :   tls_ctx_read (ctx, tls_session);
     525        1607 :   return 0;
     526             : }
     527             : 
     528             : int
     529          94 : tls_app_tx_callback (session_t * tls_session)
     530             : {
     531             :   tls_ctx_t *ctx;
     532             : 
     533          94 :   ctx = tls_ctx_get (tls_session->opaque);
     534          94 :   transport_connection_reschedule (&ctx->connection);
     535             : 
     536          94 :   return 0;
     537             : }
     538             : 
     539             : int
     540           2 : tls_session_connected_cb (u32 tls_app_index, u32 ho_ctx_index,
     541             :                           session_t *tls_session, session_error_t err)
     542             : {
     543             :   session_t *app_session;
     544             :   tls_ctx_t *ho_ctx, *ctx;
     545             :   session_type_t st;
     546             :   u32 ctx_handle;
     547             :   int rv;
     548             : 
     549           2 :   ho_ctx = tls_ctx_half_open_get (ho_ctx_index);
     550             : 
     551           2 :   ctx_handle = tls_ctx_alloc (ho_ctx->tls_ctx_engine);
     552           2 :   ctx = tls_ctx_get (ctx_handle);
     553           2 :   clib_memcpy_fast (ctx, ho_ctx, sizeof (*ctx));
     554             :   /* Half-open freed on tcp half-open cleanup notification */
     555             : 
     556           2 :   ctx->c_thread_index = vlib_get_thread_index ();
     557           2 :   ctx->tls_ctx_handle = ctx_handle;
     558           2 :   ctx->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
     559             : 
     560             :   TLS_DBG (1, "TCP connect for %u returned %u. New connection [%u]%x",
     561             :            ho_ctx_index, err, vlib_get_thread_index (),
     562             :            (ctx) ? ctx_handle : ~0);
     563             : 
     564           2 :   ctx->tls_session_handle = session_handle (tls_session);
     565           2 :   tls_session->opaque = ctx_handle;
     566           2 :   tls_session->session_state = SESSION_STATE_READY;
     567             : 
     568             :   /* Preallocate app session. Avoids allocating a session post handshake
     569             :    * on tls_session rx and potentially invalidating the session pool */
     570           2 :   app_session = session_alloc (ctx->c_thread_index);
     571           2 :   app_session->session_state = SESSION_STATE_CREATED;
     572           2 :   ctx->c_s_index = app_session->session_index;
     573           2 :   st = session_type_from_proto_and_ip (TRANSPORT_PROTO_TLS, ctx->tcp_is_ip4);
     574           2 :   app_session->session_type = st;
     575           2 :   app_session->connection_index = ctx->tls_ctx_handle;
     576             : 
     577           2 :   rv = tls_ctx_init_client (ctx);
     578           2 :   if (rv)
     579             :     {
     580           0 :       session_free (app_session);
     581           0 :       tls_ctx_free (ctx);
     582             :     }
     583             : 
     584           2 :   return rv;
     585             : }
     586             : 
     587             : int
     588           1 : dtls_session_connected_cb (u32 app_wrk_index, u32 ctx_handle, session_t *us,
     589             :                            session_error_t err)
     590             : {
     591             :   tls_ctx_t *ctx;
     592             : 
     593           1 :   ctx = tls_ctx_get_w_thread (ctx_handle, transport_cl_thread ());
     594             : 
     595           1 :   ctx->tls_session_handle = session_handle (us);
     596           1 :   ctx->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
     597           1 :   us->opaque = ctx_handle;
     598             : 
     599             :   /* We don't preallocate the app session because the udp session might
     600             :    * actually migrate to a different worker at the end of the handshake */
     601             : 
     602           1 :   return tls_ctx_init_client (ctx);
     603             : }
     604             : 
     605             : int
     606           3 : tls_session_connected_callback (u32 tls_app_index, u32 ho_ctx_index,
     607             :                                 session_t *tls_session, session_error_t err)
     608             : {
     609           3 :   if (err)
     610             :     {
     611             :       app_worker_t *app_wrk;
     612             :       tls_ctx_t *ho_ctx;
     613             :       u32 api_context;
     614             : 
     615           0 :       ho_ctx = tls_ctx_half_open_get (ho_ctx_index);
     616           0 :       app_wrk = app_worker_get_if_valid (ho_ctx->parent_app_wrk_index);
     617           0 :       if (app_wrk)
     618             :         {
     619           0 :           api_context = ho_ctx->parent_app_api_context;
     620           0 :           app_worker_connect_notify (app_wrk, 0, err, api_context);
     621             :         }
     622             : 
     623           0 :       return 0;
     624             :     }
     625             : 
     626           3 :   if (session_get_transport_proto (tls_session) == TRANSPORT_PROTO_TCP)
     627           2 :     return tls_session_connected_cb (tls_app_index, ho_ctx_index, tls_session,
     628             :                                      err);
     629             :   else
     630           1 :     return dtls_session_connected_cb (tls_app_index, ho_ctx_index, tls_session,
     631             :                                       err);
     632             : }
     633             : 
     634             : static void
     635           8 : tls_app_session_cleanup (session_t * s, session_cleanup_ntf_t ntf)
     636             : {
     637             :   tls_ctx_t *ctx;
     638             : 
     639           8 :   if (ntf == SESSION_CLEANUP_TRANSPORT)
     640             :     {
     641             :       /* Allow cleanup of tcp session */
     642           4 :       if (s->session_state == SESSION_STATE_TRANSPORT_DELETED)
     643           4 :         session_close (s);
     644           4 :       return;
     645             :     }
     646             : 
     647           4 :   ctx = tls_ctx_get (s->opaque);
     648           4 :   if (!ctx->no_app_session)
     649           4 :     session_transport_delete_notify (&ctx->connection);
     650           4 :   tls_ctx_free (ctx);
     651             : }
     652             : 
     653             : static void
     654           0 : dtls_migrate_ctx (void *arg)
     655             : {
     656           0 :   tls_ctx_t *ctx = (tls_ctx_t *) arg;
     657             :   u32 ctx_handle, thread_index;
     658             :   session_t *us;
     659             : 
     660           0 :   thread_index = session_thread_from_handle (ctx->tls_session_handle);
     661           0 :   ASSERT (thread_index == vlib_get_thread_index ());
     662             : 
     663           0 :   ctx_handle = tls_ctx_attach (ctx->tls_ctx_engine, thread_index, ctx);
     664           0 :   ctx = tls_ctx_get_w_thread (ctx_handle, thread_index);
     665           0 :   ctx->tls_ctx_handle = ctx_handle;
     666             : 
     667           0 :   us = session_get_from_handle (ctx->tls_session_handle);
     668           0 :   us->opaque = ctx_handle;
     669           0 :   us->flags &= ~SESSION_F_IS_MIGRATING;
     670             : 
     671             :   /* Probably the app detached while the session was migrating. Cleanup */
     672           0 :   if (session_half_open_migrated_notify (&ctx->connection))
     673             :     {
     674           0 :       ctx->no_app_session = 1;
     675           0 :       tls_disconnect (ctx->tls_ctx_handle, vlib_get_thread_index ());
     676           0 :       return;
     677             :     }
     678             : 
     679           0 :   if (svm_fifo_max_dequeue (us->tx_fifo))
     680           0 :     session_send_io_evt_to_thread (us->tx_fifo, SESSION_IO_EVT_TX);
     681             : }
     682             : 
     683             : static void
     684           0 : dtls_session_migrate_callback (session_t *us, session_handle_t new_sh)
     685             : {
     686           0 :   u32 new_thread = session_thread_from_handle (new_sh);
     687             :   tls_ctx_t *ctx, *cloned_ctx;
     688             : 
     689             :   /* Migrate dtls context to new thread */
     690           0 :   ctx = tls_ctx_get_w_thread (us->opaque, us->thread_index);
     691           0 :   ctx->tls_session_handle = new_sh;
     692           0 :   cloned_ctx = tls_ctx_detach (ctx);
     693           0 :   ctx->is_migrated = 1;
     694           0 :   session_half_open_migrate_notify (&ctx->connection);
     695             : 
     696           0 :   session_send_rpc_evt_to_thread (new_thread, dtls_migrate_ctx,
     697             :                                   (void *) cloned_ctx);
     698             : 
     699           0 :   tls_ctx_free (ctx);
     700           0 : }
     701             : 
     702             : static session_cb_vft_t tls_app_cb_vft = {
     703             :   .session_accept_callback = tls_session_accept_callback,
     704             :   .session_disconnect_callback = tls_session_disconnect_callback,
     705             :   .session_connected_callback = tls_session_connected_callback,
     706             :   .session_reset_callback = tls_session_reset_callback,
     707             :   .half_open_cleanup_callback = tls_session_cleanup_ho,
     708             :   .add_segment_callback = tls_add_segment_callback,
     709             :   .del_segment_callback = tls_del_segment_callback,
     710             :   .builtin_app_rx_callback = tls_app_rx_callback,
     711             :   .builtin_app_tx_callback = tls_app_tx_callback,
     712             :   .session_migrate_callback = dtls_session_migrate_callback,
     713             :   .session_cleanup_callback = tls_app_session_cleanup,
     714             : };
     715             : 
     716             : int
     717           2 : tls_connect (transport_endpoint_cfg_t * tep)
     718             : {
     719           2 :   vnet_connect_args_t _cargs = { {}, }, *cargs = &_cargs;
     720             :   transport_endpt_crypto_cfg_t *ccfg;
     721             :   crypto_engine_type_t engine_type;
     722             :   session_endpoint_cfg_t *sep;
     723           2 :   tls_main_t *tm = &tls_main;
     724             :   app_worker_t *app_wrk;
     725             :   application_t *app;
     726             :   tls_ctx_t *ctx;
     727             :   u32 ctx_index;
     728             :   int rv;
     729             : 
     730           2 :   sep = (session_endpoint_cfg_t *) tep;
     731           2 :   if (!sep->ext_cfg)
     732           0 :     return SESSION_E_NOEXTCFG;
     733             : 
     734           2 :   app_wrk = app_worker_get (sep->app_wrk_index);
     735           2 :   app = application_get (app_wrk->app_index);
     736             : 
     737           2 :   ccfg = &sep->ext_cfg->crypto;
     738           2 :   engine_type = tls_get_engine_type (ccfg->crypto_engine, app->tls_engine);
     739           2 :   if (engine_type == CRYPTO_ENGINE_NONE)
     740             :     {
     741           0 :       clib_warning ("No tls engine_type available");
     742           0 :       return SESSION_E_NOCRYPTOENG;
     743             :     }
     744             : 
     745           2 :   ctx_index = tls_ctx_half_open_alloc ();
     746           2 :   ctx = tls_ctx_half_open_get (ctx_index);
     747           2 :   ctx->parent_app_wrk_index = sep->app_wrk_index;
     748           2 :   ctx->parent_app_api_context = sep->opaque;
     749           2 :   ctx->tcp_is_ip4 = sep->is_ip4;
     750           2 :   ctx->tls_type = sep->transport_proto;
     751           2 :   ctx->ckpair_index = ccfg->ckpair_index;
     752           2 :   ctx->c_proto = TRANSPORT_PROTO_TLS;
     753           2 :   ctx->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
     754           2 :   if (ccfg->hostname[0])
     755             :     {
     756           0 :       ctx->srv_hostname = format (0, "%s", ccfg->hostname);
     757           0 :       vec_terminate_c_string (ctx->srv_hostname);
     758             :     }
     759             : 
     760           2 :   ctx->tls_ctx_engine = engine_type;
     761             : 
     762           2 :   clib_memcpy_fast (&cargs->sep, sep, sizeof (session_endpoint_t));
     763           2 :   cargs->sep.transport_proto = TRANSPORT_PROTO_TCP;
     764           2 :   cargs->app_index = tm->app_index;
     765           2 :   cargs->api_context = ctx_index;
     766           2 :   cargs->sep_ext.ns_index = app->ns_index;
     767           2 :   if ((rv = vnet_connect (cargs)))
     768           0 :     return rv;
     769             : 
     770             :   /* Track half-open tcp session in case we need to clean it up */
     771           2 :   ctx->tls_session_handle = cargs->sh;
     772             : 
     773             :   TLS_DBG (1, "New connect request %u engine %d", ctx_index, engine_type);
     774           2 :   return ctx_index;
     775             : }
     776             : 
     777             : void
     778           6 : tls_disconnect (u32 ctx_handle, u32 thread_index)
     779             : {
     780             :   tls_ctx_t *ctx;
     781             : 
     782             :   TLS_DBG (1, "Disconnecting %x", ctx_handle);
     783             : 
     784           6 :   ctx = tls_ctx_get (ctx_handle);
     785           6 :   tls_ctx_app_close (ctx);
     786           6 : }
     787             : 
     788             : u32
     789           3 : tls_start_listen (u32 app_listener_index, transport_endpoint_cfg_t *tep)
     790             : {
     791           3 :   vnet_listen_args_t _bargs, *args = &_bargs;
     792             :   transport_endpt_crypto_cfg_t *ccfg;
     793             :   app_worker_t *app_wrk;
     794           3 :   tls_main_t *tm = &tls_main;
     795             :   session_handle_t tls_al_handle;
     796             :   session_endpoint_cfg_t *sep;
     797             :   session_t *tls_listener;
     798             :   session_t *app_listener;
     799             :   crypto_engine_type_t engine_type;
     800             :   application_t *app;
     801             :   app_listener_t *al;
     802             :   tls_ctx_t *lctx;
     803             :   u32 lctx_index;
     804             :   int rv;
     805             : 
     806           3 :   sep = (session_endpoint_cfg_t *) tep;
     807           3 :   if (!sep->ext_cfg)
     808           0 :     return SESSION_E_NOEXTCFG;
     809             : 
     810           3 :   app_wrk = app_worker_get (sep->app_wrk_index);
     811           3 :   app = application_get (app_wrk->app_index);
     812             : 
     813           3 :   ccfg = &sep->ext_cfg->crypto;
     814           3 :   engine_type = tls_get_engine_type (ccfg->crypto_engine, app->tls_engine);
     815           3 :   if (engine_type == CRYPTO_ENGINE_NONE)
     816             :     {
     817           0 :       clib_warning ("No tls engine_type available");
     818           0 :       return SESSION_E_NOCRYPTOENG;
     819             :     }
     820             : 
     821           3 :   clib_memset (args, 0, sizeof (*args));
     822           3 :   args->app_index = tm->app_index;
     823           3 :   args->sep_ext = *sep;
     824           3 :   args->sep_ext.ns_index = app->ns_index;
     825           3 :   args->sep_ext.transport_proto = TRANSPORT_PROTO_TCP;
     826           3 :   if (sep->transport_proto == TRANSPORT_PROTO_DTLS)
     827             :     {
     828           1 :       args->sep_ext.transport_proto = TRANSPORT_PROTO_UDP;
     829           1 :       args->sep_ext.transport_flags = TRANSPORT_CFG_F_CONNECTED;
     830             :     }
     831           3 :   if ((rv = vnet_listen (args)))
     832           0 :     return rv;
     833             : 
     834           3 :   lctx_index = tls_listener_ctx_alloc ();
     835           3 :   tls_al_handle = args->handle;
     836           3 :   al = app_listener_get_w_handle (tls_al_handle);
     837           3 :   tls_listener = app_listener_get_session (al);
     838           3 :   tls_listener->opaque = lctx_index;
     839             : 
     840           3 :   app_listener = listen_session_get (app_listener_index);
     841             : 
     842           3 :   lctx = tls_listener_ctx_get (lctx_index);
     843           3 :   lctx->parent_app_wrk_index = sep->app_wrk_index;
     844           3 :   lctx->tls_session_handle = tls_al_handle;
     845           3 :   lctx->app_session_handle = listen_session_get_handle (app_listener);
     846           3 :   lctx->tcp_is_ip4 = sep->is_ip4;
     847           3 :   lctx->tls_ctx_engine = engine_type;
     848           3 :   lctx->tls_type = sep->transport_proto;
     849           3 :   lctx->ckpair_index = ccfg->ckpair_index;
     850           3 :   lctx->c_s_index = app_listener_index;
     851           3 :   lctx->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
     852             : 
     853           3 :   if (tls_vfts[engine_type].ctx_start_listen (lctx))
     854             :     {
     855           0 :       vnet_unlisten_args_t a = {
     856           0 :         .handle = lctx->tls_session_handle,
     857           0 :         .app_index = tls_main.app_index,
     858             :         .wrk_map_index = 0
     859             :       };
     860           0 :       if ((vnet_unlisten (&a)))
     861           0 :         clib_warning ("unlisten returned");
     862           0 :       tls_listener_ctx_free (lctx);
     863           0 :       lctx_index = SESSION_INVALID_INDEX;
     864             :     }
     865             : 
     866             :   TLS_DBG (1, "Started listening %d, engine type %d", lctx_index,
     867             :            engine_type);
     868           3 :   return lctx_index;
     869             : }
     870             : 
     871             : u32
     872           3 : tls_stop_listen (u32 lctx_index)
     873             : {
     874           3 :   session_endpoint_t sep = SESSION_ENDPOINT_NULL;
     875             :   crypto_engine_type_t engine_type;
     876             :   transport_connection_t *lc;
     877             :   tls_ctx_t *lctx;
     878             :   session_t *ls;
     879             :   int rv;
     880             : 
     881           3 :   lctx = tls_listener_ctx_get (lctx_index);
     882             : 
     883             :   /* Cleanup listener from session lookup table */
     884           3 :   ls = session_get_from_handle (lctx->tls_session_handle);
     885           3 :   lc = session_get_transport (ls);
     886             : 
     887           3 :   sep.fib_index = lc->fib_index;
     888           3 :   sep.port = lc->lcl_port;
     889           3 :   sep.is_ip4 = lc->is_ip4;
     890           3 :   sep.transport_proto = lctx->tls_type;
     891           3 :   clib_memcpy (&sep.ip, &lc->lcl_ip, sizeof (lc->lcl_ip));
     892           3 :   session_lookup_del_session_endpoint2 (&sep);
     893             : 
     894           3 :   vnet_unlisten_args_t a = {
     895           3 :     .handle = lctx->tls_session_handle,
     896           3 :     .app_index = tls_main.app_index,
     897             :     .wrk_map_index = 0          /* default wrk */
     898             :   };
     899           3 :   if ((rv = vnet_unlisten (&a)))
     900           0 :     clib_warning ("unlisten returned %d", rv);
     901             : 
     902           3 :   engine_type = lctx->tls_ctx_engine;
     903           3 :   tls_vfts[engine_type].ctx_stop_listen (lctx);
     904             : 
     905           3 :   tls_listener_ctx_free (lctx);
     906           3 :   return 0;
     907             : }
     908             : 
     909             : transport_connection_t *
     910     1274830 : tls_connection_get (u32 ctx_index, u32 thread_index)
     911             : {
     912             :   tls_ctx_t *ctx;
     913     1274830 :   ctx = tls_ctx_get_w_thread (ctx_index, thread_index);
     914     1274830 :   return &ctx->connection;
     915             : }
     916             : 
     917             : transport_connection_t *
     918           9 : tls_listener_get (u32 listener_index)
     919             : {
     920             :   tls_ctx_t *ctx;
     921           9 :   ctx = tls_listener_ctx_get (listener_index);
     922           9 :   return &ctx->connection;
     923             : }
     924             : 
     925             : static transport_connection_t *
     926           2 : tls_half_open_get (u32 ho_index)
     927             : {
     928             :   tls_ctx_t *ctx;
     929           2 :   ctx = tls_ctx_half_open_get (ho_index);
     930           2 :   return &ctx->connection;
     931             : }
     932             : 
     933             : static void
     934           0 : tls_cleanup_ho (u32 ho_index)
     935             : {
     936             :   tls_ctx_t *ctx;
     937             : 
     938           0 :   ctx = tls_ctx_half_open_get (ho_index);
     939           0 :   session_cleanup_half_open (ctx->tls_session_handle);
     940           0 :   tls_ctx_half_open_free (ho_index);
     941           0 : }
     942             : 
     943             : int
     944     1273280 : tls_custom_tx_callback (void *session, transport_send_params_t * sp)
     945             : {
     946     1273280 :   session_t *as = (session_t *) session;
     947             :   tls_ctx_t *ctx;
     948             : 
     949     1273280 :   if (PREDICT_FALSE (as->session_state >= SESSION_STATE_TRANSPORT_CLOSED ||
     950             :                      as->session_state <= SESSION_STATE_ACCEPTING))
     951             :     {
     952           0 :       sp->flags |= TRANSPORT_SND_F_DESCHED;
     953           0 :       return 0;
     954             :     }
     955             : 
     956     1273280 :   ctx = tls_ctx_get (as->connection_index);
     957     1273280 :   return tls_ctx_write (ctx, as, sp);
     958             : }
     959             : 
     960             : u8 *
     961           2 : format_tls_ctx (u8 * s, va_list * args)
     962             : {
     963             :   u32 tcp_si, tcp_ti, ctx_index, ctx_engine;
     964           2 :   tls_ctx_t *ctx = va_arg (*args, tls_ctx_t *);
     965             :   char *proto;
     966             : 
     967           2 :   proto = ctx->tls_type == TRANSPORT_PROTO_TLS ? "TLS" : "DTLS";
     968           2 :   session_parse_handle (ctx->tls_session_handle, &tcp_si, &tcp_ti);
     969           2 :   tls_ctx_parse_handle (ctx->tls_ctx_handle, &ctx_index, &ctx_engine);
     970             :   s =
     971           2 :     format (s, "[%d:%d][%s] app_wrk %u index %u engine %u ts %d:%d",
     972             :             ctx->c_thread_index, ctx->c_s_index, proto,
     973             :             ctx->parent_app_wrk_index, ctx_index, ctx_engine, tcp_ti, tcp_si);
     974             : 
     975           2 :   return s;
     976             : }
     977             : 
     978             : static u8 *
     979           0 : format_tls_listener_ctx (u8 * s, va_list * args)
     980             : {
     981             :   session_t *tls_listener;
     982             :   app_listener_t *al;
     983             :   tls_ctx_t *ctx;
     984             :   char *proto;
     985             : 
     986           0 :   ctx = va_arg (*args, tls_ctx_t *);
     987             : 
     988           0 :   proto = ctx->tls_type == TRANSPORT_PROTO_TLS ? "TLS" : "DTLS";
     989           0 :   al = app_listener_get_w_handle (ctx->tls_session_handle);
     990           0 :   tls_listener = app_listener_get_session (al);
     991           0 :   s = format (s, "[%d:%d][%s] app_wrk %u engine %u ts %d:%d",
     992             :               ctx->c_thread_index, ctx->c_s_index, proto,
     993           0 :               ctx->parent_app_wrk_index, ctx->tls_ctx_engine,
     994           0 :               tls_listener->thread_index, tls_listener->session_index);
     995             : 
     996           0 :   return s;
     997             : }
     998             : 
     999             : static u8 *
    1000           2 : format_tls_ctx_state (u8 * s, va_list * args)
    1001             : {
    1002             :   tls_ctx_t *ctx;
    1003             :   session_t *ts;
    1004             : 
    1005           2 :   ctx = va_arg (*args, tls_ctx_t *);
    1006           2 :   ts = session_get (ctx->c_s_index, ctx->c_thread_index);
    1007           2 :   if (ts->session_state == SESSION_STATE_LISTENING)
    1008           0 :     s = format (s, "%s", "LISTEN");
    1009             :   else
    1010             :     {
    1011           2 :       if (ts->session_state >= SESSION_STATE_TRANSPORT_CLOSED)
    1012           2 :         s = format (s, "%s", "CLOSED");
    1013           0 :       else if (ts->session_state == SESSION_STATE_APP_CLOSED)
    1014           0 :         s = format (s, "%s", "APP-CLOSED");
    1015           0 :       else if (ts->session_state >= SESSION_STATE_TRANSPORT_CLOSING)
    1016           0 :         s = format (s, "%s", "CLOSING");
    1017           0 :       else if (tls_ctx_handshake_is_over (ctx))
    1018           0 :         s = format (s, "%s", "ESTABLISHED");
    1019             :       else
    1020           0 :         s = format (s, "%s", "HANDSHAKE");
    1021             :     }
    1022             : 
    1023           2 :   return s;
    1024             : }
    1025             : 
    1026             : u8 *
    1027           2 : format_tls_connection (u8 * s, va_list * args)
    1028             : {
    1029           2 :   u32 ctx_index = va_arg (*args, u32);
    1030           2 :   u32 thread_index = va_arg (*args, u32);
    1031           2 :   u32 verbose = va_arg (*args, u32);
    1032             :   tls_ctx_t *ctx;
    1033             : 
    1034           2 :   ctx = tls_ctx_get_w_thread (ctx_index, thread_index);
    1035           2 :   if (!ctx)
    1036           0 :     return s;
    1037             : 
    1038           2 :   s = format (s, "%-" SESSION_CLI_ID_LEN "U", format_tls_ctx, ctx);
    1039           2 :   if (verbose)
    1040             :     {
    1041           2 :       s = format (s, "%-" SESSION_CLI_STATE_LEN "U", format_tls_ctx_state,
    1042             :                   ctx);
    1043           2 :       if (verbose > 1)
    1044           2 :         s = format (s, "\n");
    1045             :     }
    1046           2 :   return s;
    1047             : }
    1048             : 
    1049             : u8 *
    1050           0 : format_tls_listener (u8 * s, va_list * args)
    1051             : {
    1052           0 :   u32 tc_index = va_arg (*args, u32);
    1053           0 :   u32 __clib_unused thread_index = va_arg (*args, u32);
    1054           0 :   u32 verbose = va_arg (*args, u32);
    1055           0 :   tls_ctx_t *ctx = tls_listener_ctx_get (tc_index);
    1056             : 
    1057           0 :   s = format (s, "%-" SESSION_CLI_ID_LEN "U", format_tls_listener_ctx, ctx);
    1058           0 :   if (verbose)
    1059           0 :     s = format (s, "%-" SESSION_CLI_STATE_LEN "U", format_tls_ctx_state, ctx);
    1060           0 :   return s;
    1061             : }
    1062             : 
    1063             : u8 *
    1064           0 : format_tls_half_open (u8 * s, va_list * args)
    1065             : {
    1066           0 :   u32 ho_index = va_arg (*args, u32);
    1067           0 :   u32 __clib_unused thread_index = va_arg (*args, u32);
    1068           0 :   u32 __clib_unused verbose = va_arg (*args, u32);
    1069             :   session_t *tcp_ho;
    1070             :   tls_ctx_t *ho_ctx;
    1071             : 
    1072           0 :   ho_ctx = tls_ctx_half_open_get (ho_index);
    1073             : 
    1074           0 :   tcp_ho = session_get_from_handle (ho_ctx->tls_session_handle);
    1075           0 :   s = format (s, "[%d:%d][%s] half-open app_wrk %u engine %u ts %d:%d",
    1076             :               ho_ctx->c_thread_index, ho_ctx->c_s_index, "TLS",
    1077           0 :               ho_ctx->parent_app_wrk_index, ho_ctx->tls_ctx_engine,
    1078           0 :               tcp_ho->thread_index, tcp_ho->session_index);
    1079             : 
    1080           0 :   return s;
    1081             : }
    1082             : 
    1083             : static void
    1084           9 : tls_transport_endpoint_get (u32 ctx_handle, u32 thread_index,
    1085             :                             transport_endpoint_t * tep, u8 is_lcl)
    1086             : {
    1087           9 :   tls_ctx_t *ctx = tls_ctx_get_w_thread (ctx_handle, thread_index);
    1088             :   session_t *tcp_session;
    1089             : 
    1090           9 :   tcp_session = session_get_from_handle (ctx->tls_session_handle);
    1091           9 :   session_get_endpoint (tcp_session, tep, is_lcl);
    1092           9 : }
    1093             : 
    1094             : static void
    1095           3 : tls_transport_listener_endpoint_get (u32 ctx_handle,
    1096             :                                      transport_endpoint_t * tep, u8 is_lcl)
    1097             : {
    1098             :   session_t *tls_listener;
    1099             :   app_listener_t *al;
    1100           3 :   tls_ctx_t *ctx = tls_listener_ctx_get (ctx_handle);
    1101             : 
    1102           3 :   al = app_listener_get_w_handle (ctx->tls_session_handle);
    1103           3 :   tls_listener = app_listener_get_session (al);
    1104           3 :   session_get_endpoint (tls_listener, tep, is_lcl);
    1105           3 : }
    1106             : 
    1107             : static clib_error_t *
    1108          57 : tls_enable (vlib_main_t * vm, u8 is_en)
    1109             : {
    1110          57 :   vnet_app_detach_args_t _da, *da = &_da;
    1111          57 :   vnet_app_attach_args_t _a, *a = &_a;
    1112             :   u64 options[APP_OPTIONS_N_OPTIONS];
    1113          57 :   tls_main_t *tm = &tls_main;
    1114          57 :   u32 fifo_size = 512 << 10;
    1115             : 
    1116          57 :   if (!is_en)
    1117             :     {
    1118           8 :       da->app_index = tm->app_index;
    1119           8 :       da->api_client_index = APP_INVALID_INDEX;
    1120           8 :       vnet_application_detach (da);
    1121           8 :       return 0;
    1122             :     }
    1123             : 
    1124          49 :   fifo_size = tm->fifo_size ? tm->fifo_size : fifo_size;
    1125             : 
    1126          49 :   clib_memset (a, 0, sizeof (*a));
    1127          49 :   clib_memset (options, 0, sizeof (options));
    1128             : 
    1129          49 :   a->session_cb_vft = &tls_app_cb_vft;
    1130          49 :   a->api_client_index = APP_INVALID_INDEX;
    1131          49 :   a->options = options;
    1132          49 :   a->name = format (0, "tls");
    1133          49 :   a->options[APP_OPTIONS_SEGMENT_SIZE] = tm->first_seg_size;
    1134          49 :   a->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = tm->add_seg_size;
    1135          49 :   a->options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
    1136          49 :   a->options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
    1137          49 :   a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
    1138          49 :   a->options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
    1139          49 :   a->options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_TRANSPORT_APP;
    1140             : 
    1141          49 :   if (vnet_application_attach (a))
    1142             :     {
    1143           0 :       clib_warning ("failed to attach tls app");
    1144           0 :       return clib_error_return (0, "failed to attach tls app");
    1145             :     }
    1146             : 
    1147          49 :   tm->app_index = a->app_index;
    1148          49 :   vec_free (a->name);
    1149             : 
    1150          49 :   return 0;
    1151             : }
    1152             : 
    1153             : static const transport_proto_vft_t tls_proto = {
    1154             :   .enable = tls_enable,
    1155             :   .connect = tls_connect,
    1156             :   .close = tls_disconnect,
    1157             :   .start_listen = tls_start_listen,
    1158             :   .stop_listen = tls_stop_listen,
    1159             :   .get_connection = tls_connection_get,
    1160             :   .get_listener = tls_listener_get,
    1161             :   .get_half_open = tls_half_open_get,
    1162             :   .cleanup_ho = tls_cleanup_ho,
    1163             :   .custom_tx = tls_custom_tx_callback,
    1164             :   .format_connection = format_tls_connection,
    1165             :   .format_half_open = format_tls_half_open,
    1166             :   .format_listener = format_tls_listener,
    1167             :   .get_transport_endpoint = tls_transport_endpoint_get,
    1168             :   .get_transport_listener_endpoint = tls_transport_listener_endpoint_get,
    1169             :   .transport_options = {
    1170             :     .name = "tls",
    1171             :     .short_name = "J",
    1172             :     .tx_type = TRANSPORT_TX_INTERNAL,
    1173             :     .service_type = TRANSPORT_SERVICE_VC,
    1174             :   },
    1175             : };
    1176             : 
    1177             : int
    1178           1 : dtls_connect (transport_endpoint_cfg_t *tep)
    1179             : {
    1180           1 :   vnet_connect_args_t _cargs = { {}, }, *cargs = &_cargs;
    1181             :   transport_endpt_crypto_cfg_t *ccfg;
    1182             :   crypto_engine_type_t engine_type;
    1183             :   session_endpoint_cfg_t *sep;
    1184           1 :   tls_main_t *tm = &tls_main;
    1185             :   app_worker_t *app_wrk;
    1186             :   application_t *app;
    1187             :   tls_ctx_t *ctx;
    1188             :   u32 ctx_handle;
    1189             :   int rv;
    1190             : 
    1191           1 :   sep = (session_endpoint_cfg_t *) tep;
    1192           1 :   if (!sep->ext_cfg)
    1193           0 :     return -1;
    1194             : 
    1195           1 :   app_wrk = app_worker_get (sep->app_wrk_index);
    1196           1 :   app = application_get (app_wrk->app_index);
    1197             : 
    1198           1 :   ccfg = &sep->ext_cfg->crypto;
    1199           1 :   engine_type = tls_get_engine_type (ccfg->crypto_engine, app->tls_engine);
    1200           1 :   if (engine_type == CRYPTO_ENGINE_NONE)
    1201             :     {
    1202           0 :       clib_warning ("No tls engine_type available");
    1203           0 :       return -1;
    1204             :     }
    1205             : 
    1206           1 :   ctx_handle = tls_ctx_alloc_w_thread (engine_type, transport_cl_thread ());
    1207           1 :   ctx = tls_ctx_get_w_thread (ctx_handle, transport_cl_thread ());
    1208           1 :   ctx->parent_app_wrk_index = sep->app_wrk_index;
    1209           1 :   ctx->parent_app_api_context = sep->opaque;
    1210           1 :   ctx->tcp_is_ip4 = sep->is_ip4;
    1211           1 :   ctx->ckpair_index = ccfg->ckpair_index;
    1212           1 :   ctx->tls_type = sep->transport_proto;
    1213           1 :   ctx->tls_ctx_handle = ctx_handle;
    1214           1 :   ctx->c_proto = TRANSPORT_PROTO_DTLS;
    1215           1 :   ctx->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
    1216           1 :   if (ccfg->hostname[0])
    1217             :     {
    1218           0 :       ctx->srv_hostname = format (0, "%s", ccfg->hostname);
    1219           0 :       vec_terminate_c_string (ctx->srv_hostname);
    1220             :     }
    1221             : 
    1222           1 :   ctx->tls_ctx_engine = engine_type;
    1223             : 
    1224           1 :   clib_memcpy_fast (&cargs->sep, sep, sizeof (session_endpoint_t));
    1225           1 :   cargs->sep.transport_proto = TRANSPORT_PROTO_UDP;
    1226           1 :   cargs->app_index = tm->app_index;
    1227           1 :   cargs->api_context = ctx_handle;
    1228           1 :   cargs->sep_ext.ns_index = app->ns_index;
    1229           1 :   cargs->sep_ext.transport_flags = TRANSPORT_CFG_F_CONNECTED;
    1230           1 :   if ((rv = vnet_connect (cargs)))
    1231           0 :     return rv;
    1232             : 
    1233             :   TLS_DBG (1, "New DTLS connect request %x engine %d", ctx_handle,
    1234             :            engine_type);
    1235           1 :   return ctx_handle;
    1236             : }
    1237             : 
    1238             : static transport_connection_t *
    1239           1 : dtls_half_open_get (u32 ho_index)
    1240             : {
    1241             :   tls_ctx_t *ho_ctx;
    1242           1 :   ho_ctx = tls_ctx_get_w_thread (ho_index, transport_cl_thread ());
    1243           1 :   return &ho_ctx->connection;
    1244             : }
    1245             : 
    1246             : static void
    1247           0 : dtls_cleanup_callback (u32 ctx_index, u32 thread_index)
    1248             : {
    1249             :   /* No op */
    1250           0 : }
    1251             : 
    1252             : static void
    1253           0 : dtls_cleanup_ho (u32 ho_index)
    1254             : {
    1255             :   tls_ctx_t *ctx;
    1256           0 :   ctx = tls_ctx_get_w_thread (ho_index, transport_cl_thread ());
    1257           0 :   tls_ctx_free (ctx);
    1258           0 : }
    1259             : 
    1260             : u8 *
    1261           0 : format_dtls_half_open (u8 *s, va_list *args)
    1262             : {
    1263           0 :   u32 ho_index = va_arg (*args, u32);
    1264           0 :   u32 __clib_unused thread_index = va_arg (*args, u32);
    1265             :   tls_ctx_t *ho_ctx;
    1266             :   session_t *us;
    1267             : 
    1268           0 :   ho_ctx = tls_ctx_get_w_thread (ho_index, transport_cl_thread ());
    1269             : 
    1270           0 :   us = session_get_from_handle (ho_ctx->tls_session_handle);
    1271           0 :   s = format (s, "[%d:%d][%s] half-open app_wrk %u engine %u us %d:%d",
    1272             :               ho_ctx->c_thread_index, ho_ctx->c_s_index, "DTLS",
    1273           0 :               ho_ctx->parent_app_wrk_index, ho_ctx->tls_ctx_engine,
    1274           0 :               us->thread_index, us->session_index);
    1275             : 
    1276           0 :   return s;
    1277             : }
    1278             : 
    1279             : static const transport_proto_vft_t dtls_proto = {
    1280             :   .enable = 0,
    1281             :   .connect = dtls_connect,
    1282             :   .close = tls_disconnect,
    1283             :   .start_listen = tls_start_listen,
    1284             :   .stop_listen = tls_stop_listen,
    1285             :   .get_connection = tls_connection_get,
    1286             :   .get_listener = tls_listener_get,
    1287             :   .get_half_open = dtls_half_open_get,
    1288             :   .custom_tx = tls_custom_tx_callback,
    1289             :   .cleanup = dtls_cleanup_callback,
    1290             :   .cleanup_ho = dtls_cleanup_ho,
    1291             :   .format_connection = format_tls_connection,
    1292             :   .format_half_open = format_dtls_half_open,
    1293             :   .format_listener = format_tls_listener,
    1294             :   .get_transport_endpoint = tls_transport_endpoint_get,
    1295             :   .get_transport_listener_endpoint = tls_transport_listener_endpoint_get,
    1296             :   .transport_options = {
    1297             :     .name = "dtls",
    1298             :     .short_name = "D",
    1299             :     .tx_type = TRANSPORT_TX_INTERNAL,
    1300             :     .service_type = TRANSPORT_SERVICE_VC,
    1301             :   },
    1302             : };
    1303             : 
    1304             : void
    1305        1150 : tls_register_engine (const tls_engine_vft_t * vft, crypto_engine_type_t type)
    1306             : {
    1307        1150 :   vec_validate (tls_vfts, type);
    1308        1150 :   tls_vfts[type] = *vft;
    1309        1150 : }
    1310             : 
    1311             : static clib_error_t *
    1312         575 : tls_init (vlib_main_t * vm)
    1313             : {
    1314         575 :   vlib_thread_main_t *vtm = vlib_get_thread_main ();
    1315         575 :   tls_main_t *tm = &tls_main;
    1316             :   u32 num_threads;
    1317             : 
    1318         575 :   num_threads = 1 /* main thread */  + vtm->n_threads;
    1319             : 
    1320         575 :   if (!tm->ca_cert_path)
    1321         575 :     tm->ca_cert_path = TLS_CA_CERT_PATH;
    1322             : 
    1323         575 :   vec_validate (tm->rx_bufs, num_threads - 1);
    1324         575 :   vec_validate (tm->tx_bufs, num_threads - 1);
    1325             : 
    1326         575 :   tm->first_seg_size = 32 << 20;
    1327         575 :   tm->add_seg_size = 256 << 20;
    1328             : 
    1329         575 :   transport_register_protocol (TRANSPORT_PROTO_TLS, &tls_proto,
    1330             :                                FIB_PROTOCOL_IP4, ~0);
    1331         575 :   transport_register_protocol (TRANSPORT_PROTO_TLS, &tls_proto,
    1332             :                                FIB_PROTOCOL_IP6, ~0);
    1333             : 
    1334         575 :   transport_register_protocol (TRANSPORT_PROTO_DTLS, &dtls_proto,
    1335             :                                FIB_PROTOCOL_IP4, ~0);
    1336         575 :   transport_register_protocol (TRANSPORT_PROTO_DTLS, &dtls_proto,
    1337             :                                FIB_PROTOCOL_IP6, ~0);
    1338         575 :   return 0;
    1339             : }
    1340             : 
    1341       79487 : VLIB_INIT_FUNCTION (tls_init);
    1342             : 
    1343             : static clib_error_t *
    1344         575 : tls_config_fn (vlib_main_t * vm, unformat_input_t * input)
    1345             : {
    1346         575 :   tls_main_t *tm = &tls_main;
    1347             :   uword tmp;
    1348         575 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1349             :     {
    1350           0 :       if (unformat (input, "use-test-cert-in-ca"))
    1351           0 :         tm->use_test_cert_in_ca = 1;
    1352           0 :       else if (unformat (input, "ca-cert-path %s", &tm->ca_cert_path))
    1353             :         ;
    1354           0 :       else if (unformat (input, "first-segment-size %U", unformat_memory_size,
    1355             :                          &tm->first_seg_size))
    1356             :         ;
    1357           0 :       else if (unformat (input, "add-segment-size %U", unformat_memory_size,
    1358             :                          &tm->add_seg_size))
    1359             :         ;
    1360           0 :       else if (unformat (input, "fifo-size %U", unformat_memory_size, &tmp))
    1361             :         {
    1362           0 :           if (tmp >= 0x100000000ULL)
    1363             :             {
    1364           0 :               return clib_error_return
    1365             :                 (0, "fifo-size %llu (0x%llx) too large", tmp, tmp);
    1366             :             }
    1367           0 :           tm->fifo_size = tmp;
    1368             :         }
    1369             :       else
    1370           0 :         return clib_error_return (0, "unknown input `%U'",
    1371             :                                   format_unformat_error, input);
    1372             :     }
    1373         575 :   return 0;
    1374             : }
    1375             : 
    1376        7514 : VLIB_CONFIG_FUNCTION (tls_config_fn, "tls");
    1377             : 
    1378             : tls_main_t *
    1379         575 : vnet_tls_get_main (void)
    1380             : {
    1381         575 :   return &tls_main;
    1382             : }
    1383             : 
    1384             : /*
    1385             :  * fd.io coding-style-patch-verification: ON
    1386             :  *
    1387             :  * Local Variables:
    1388             :  * eval: (c-set-style "gnu")
    1389             :  * End:
    1390             :  */

Generated by: LCOV version 1.14