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

Generated by: LCOV version 1.14