session: first approximation implementation of tls
[vpp.git] / src / vnet / session-apps / tls.c
1 /*
2  * Copyright (c) 2018 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <vnet/session/application_interface.h>
17 #include <vppinfra/lock.h>
18 #include <mbedtls/ssl.h>
19 #include <mbedtls/certs.h>
20 #include <mbedtls/entropy.h>
21 #include <mbedtls/ctr_drbg.h>
22 #include <mbedtls/timing.h>
23 #include <mbedtls/debug.h>
24
25 #define TLS_DEBUG (0)
26 #define TLS_DEBUG_LEVEL_CLIENT (0)
27 #define TLS_DEBUG_LEVEL_SERVER (0)
28 #define TLS_CHUNK_SIZE (1 << 14)
29 #define TLS_USE_OUR_MEM_FUNCS (0)
30
31 #if TLS_DEBUG
32 #define TLS_DBG(_lvl, _fmt, _args...)                   \
33   if (_lvl <= TLS_DEBUG)                                \
34     clib_warning (_fmt, ##_args)
35 #else
36 #define TLS_DBG(_fmt, _args...)
37 #endif
38
39 #if TLS_USE_OUR_MEM_FUNCS
40 #include <mbedtls/platform.h>
41
42 void *
43 mbedtls_calloc_fn (size_t n, size_t size)
44 {
45   void *ptr;
46   ptr = clib_mem_alloc (n * size);
47   memset (ptr, 0, sizeof (*ptr));
48   return ptr;
49 }
50
51 void
52 mbedtls_free_fn (void *ptr)
53 {
54   if (ptr)
55     clib_mem_free (ptr);
56 }
57 #endif
58
59 /* *INDENT-OFF* */
60 typedef CLIB_PACKED (struct tls_cxt_id_
61 {
62   u32 parent_app_index;
63   session_handle_t app_session_handle;
64   session_handle_t tls_session_handle;
65   u32 listener_ctx_index;
66   u8 tcp_is_ip4;
67 }) tls_ctx_id_t;
68 /* *INDENT-ON* */
69
70 typedef struct tls_ctx_
71 {
72   union
73   {
74     transport_connection_t connection;
75     tls_ctx_id_t c_tls_ctx_id;
76   };
77 #define parent_app_index c_tls_ctx_id.parent_app_index
78 #define app_session_handle c_tls_ctx_id.app_session_handle
79 #define tls_session_handle c_tls_ctx_id.tls_session_handle
80 #define listener_ctx_index c_tls_ctx_id.listener_ctx_index
81 #define tcp_is_ip4 c_tls_ctx_id.tcp_is_ip4
82
83   /* Temporary storage for session open opaque. Overwritten once
84    * underlying tcp connection is established */
85 #define parent_app_api_context c_s_index
86
87   u8 is_passive_close;
88   mbedtls_ssl_context ssl;
89   mbedtls_ssl_config conf;
90   mbedtls_x509_crt srvcert;
91   mbedtls_pk_context pkey;
92 } tls_ctx_t;
93
94 typedef struct tls_main_
95 {
96   u32 app_index;
97   tls_ctx_t **ctx_pool;
98   mbedtls_ctr_drbg_context *ctr_drbgs;
99   mbedtls_entropy_context *entropy_pools;
100   tls_ctx_t *listener_ctx_pool;
101   tls_ctx_t *half_open_ctx_pool;
102   clib_rwlock_t half_open_rwlock;
103   mbedtls_x509_crt cacert;
104 } tls_main_t;
105
106 static tls_main_t tls_main;
107
108 void tls_disconnect (u32 ctx_index, u32 thread_index);
109
110 static inline int
111 tls_add_vpp_q_evt (svm_fifo_t * f, u8 evt_type)
112 {
113   session_fifo_event_t evt;
114   svm_queue_t *q;
115
116   if (svm_fifo_set_event (f))
117     {
118       evt.fifo = f;
119       evt.event_type = evt_type;
120
121       q = session_manager_get_vpp_event_queue (f->master_thread_index);
122       if (PREDICT_TRUE (q->cursize < q->maxsize))
123         {
124           svm_queue_add (q, (u8 *) & evt, 0 /* do wait for mutex */ );
125         }
126       else
127         {
128           clib_warning ("vpp's evt q full");
129           return -1;
130         }
131     }
132   return 0;
133 }
134
135 static inline int
136 tls_add_app_q_evt (application_t * app, stream_session_t * app_session)
137 {
138   session_fifo_event_t evt;
139   svm_queue_t *q;
140
141   if (PREDICT_FALSE (app_session->session_state == SESSION_STATE_CLOSED))
142     {
143       /* Session is closed so app will never clean up. Flush rx fifo */
144       u32 to_dequeue = svm_fifo_max_dequeue (app_session->server_rx_fifo);
145       if (to_dequeue)
146         svm_fifo_dequeue_drop (app_session->server_rx_fifo, to_dequeue);
147       return 0;
148     }
149
150   if (app->cb_fns.builtin_app_rx_callback)
151     return app->cb_fns.builtin_app_rx_callback (app_session);
152
153   if (svm_fifo_set_event (app_session->server_rx_fifo))
154     {
155       evt.fifo = app_session->server_rx_fifo;
156       evt.event_type = FIFO_EVENT_APP_RX;
157       q = app->event_queue;
158
159       if (PREDICT_TRUE (q->cursize < q->maxsize))
160         {
161           svm_queue_add (q, (u8 *) & evt, 0 /* do wait for mutex */ );
162         }
163       else
164         {
165           clib_warning ("app evt q full");
166           return -1;
167         }
168     }
169   return 0;
170 }
171
172 u32
173 tls_ctx_alloc (void)
174 {
175   u8 thread_index = vlib_get_thread_index ();
176   tls_main_t *tm = &tls_main;
177   tls_ctx_t *ctx;
178
179   pool_get (tm->ctx_pool[thread_index], ctx);
180   memset (ctx, 0, sizeof (*ctx));
181   ctx->c_thread_index = thread_index;
182   return ctx - tm->ctx_pool[thread_index];
183 }
184
185 void
186 tls_ctx_free (tls_ctx_t * ctx)
187 {
188   pool_put (tls_main.ctx_pool[vlib_get_thread_index ()], ctx);
189 }
190
191 tls_ctx_t *
192 tls_ctx_get (u32 ctx_index)
193 {
194   return pool_elt_at_index (tls_main.ctx_pool[vlib_get_thread_index ()],
195                             ctx_index);
196 }
197
198 tls_ctx_t *
199 tls_ctx_get_w_thread (u32 ctx_index, u8 thread_index)
200 {
201   return pool_elt_at_index (tls_main.ctx_pool[thread_index], ctx_index);
202 }
203
204 u32
205 tls_ctx_index (tls_ctx_t * ctx)
206 {
207   return (ctx - tls_main.ctx_pool[vlib_get_thread_index ()]);
208 }
209
210 u32
211 tls_listener_ctx_alloc (void)
212 {
213   tls_main_t *tm = &tls_main;
214   tls_ctx_t *ctx;
215
216   pool_get (tm->listener_ctx_pool, ctx);
217   memset (ctx, 0, sizeof (*ctx));
218   return ctx - tm->listener_ctx_pool;
219 }
220
221 void
222 tls_ctx_listener_free (tls_ctx_t * ctx)
223 {
224   pool_put (tls_main.half_open_ctx_pool, ctx);
225 }
226
227 tls_ctx_t *
228 tls_listener_ctx_get (u32 ctx_index)
229 {
230   return pool_elt_at_index (tls_main.listener_ctx_pool, ctx_index);
231 }
232
233 u32
234 tls_listener_ctx_index (tls_ctx_t * ctx)
235 {
236   return (ctx - tls_main.listener_ctx_pool);
237 }
238
239 u32
240 tls_ctx_half_open_alloc (void)
241 {
242   tls_main_t *tm = &tls_main;
243   u8 will_expand = 0;
244   tls_ctx_t *ctx;
245   u32 ctx_index;
246
247   pool_get_aligned_will_expand (tm->half_open_ctx_pool, will_expand, 0);
248   if (PREDICT_FALSE (will_expand && vlib_num_workers ()))
249     {
250       clib_rwlock_writer_lock (&tm->half_open_rwlock);
251       pool_get (tm->half_open_ctx_pool, ctx);
252       memset (ctx, 0, sizeof (*ctx));
253       ctx_index = ctx - tm->half_open_ctx_pool;
254       clib_rwlock_writer_unlock (&tm->half_open_rwlock);
255     }
256   else
257     {
258       pool_get (tm->half_open_ctx_pool, ctx);
259       memset (ctx, 0, sizeof (*ctx));
260       ctx_index = ctx - tm->half_open_ctx_pool;
261     }
262   return ctx_index;
263 }
264
265 void
266 tls_ctx_half_open_free (u32 ho_index)
267 {
268   tls_main_t *tm = &tls_main;
269   clib_rwlock_writer_lock (&tm->half_open_rwlock);
270   pool_put_index (tls_main.half_open_ctx_pool, ho_index);
271   clib_rwlock_writer_unlock (&tm->half_open_rwlock);
272 }
273
274 tls_ctx_t *
275 tls_ctx_half_open_get (u32 ctx_index)
276 {
277   tls_main_t *tm = &tls_main;
278   clib_rwlock_reader_lock (&tm->half_open_rwlock);
279   return pool_elt_at_index (tm->half_open_ctx_pool, ctx_index);
280 }
281
282 void
283 tls_ctx_half_open_reader_unlock ()
284 {
285   clib_rwlock_reader_unlock (&tls_main.half_open_rwlock);
286 }
287
288 u32
289 tls_ctx_half_open_index (tls_ctx_t * ctx)
290 {
291   return (ctx - tls_main.half_open_ctx_pool);
292 }
293
294 static int
295 tls_init_ctr_drbgs_and_entropy (u32 num_threads)
296 {
297   tls_main_t *tm = &tls_main;
298   int i;
299
300   vec_validate (tm->ctr_drbgs, num_threads - 1);
301   vec_validate (tm->entropy_pools, num_threads - 1);
302   for (i = 0; i < num_threads; i++)
303     tls_main.ctr_drbgs[i].f_entropy = 0;
304
305   return 0;
306 }
307
308 static int
309 tls_init_ctr_seed_drbgs (void)
310 {
311   u32 thread_index = vlib_get_thread_index ();
312   tls_main_t *tm = &tls_main;
313   u8 *pers;
314   int rv;
315   pers = format (0, "vpp thread %u", thread_index);
316
317   mbedtls_entropy_init (&tm->entropy_pools[thread_index]);
318   mbedtls_ctr_drbg_init (&tls_main.ctr_drbgs[thread_index]);
319   if ((rv = mbedtls_ctr_drbg_seed (&tm->ctr_drbgs[thread_index],
320                                    mbedtls_entropy_func,
321                                    &tm->entropy_pools[thread_index],
322                                    (const unsigned char *) pers,
323                                    vec_len (pers))) != 0)
324     {
325       vec_free (pers);
326       TLS_DBG (1, " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", rv);
327       return -1;
328     }
329   vec_free (pers);
330   return 0;
331 }
332
333 mbedtls_ctr_drbg_context *
334 tls_get_ctr_drbg ()
335 {
336   u8 thread_index = vlib_get_thread_index ();
337   if (PREDICT_FALSE (!tls_main.ctr_drbgs[thread_index].f_entropy))
338     tls_init_ctr_seed_drbgs ();
339   return &tls_main.ctr_drbgs[thread_index];
340 }
341
342 static int
343 tls_net_send (void *ctx_indexp, const unsigned char *buf, size_t len)
344 {
345   stream_session_t *tls_session;
346   uword ctx_index;
347   tls_ctx_t *ctx;
348   int rv;
349
350   ctx_index = pointer_to_uword (ctx_indexp);
351   ctx = tls_ctx_get (ctx_index);
352   tls_session = session_get_from_handle (ctx->tls_session_handle);
353   rv = svm_fifo_enqueue_nowait (tls_session->server_tx_fifo, len, buf);
354   if (rv < 0)
355     return MBEDTLS_ERR_SSL_WANT_WRITE;
356   tls_add_vpp_q_evt (tls_session->server_tx_fifo, FIFO_EVENT_APP_TX);
357   return rv;
358 }
359
360 static int
361 tls_net_recv (void *ctx_indexp, unsigned char *buf, size_t len)
362 {
363   stream_session_t *tls_session;
364   uword ctx_index;
365   tls_ctx_t *ctx;
366   int rv;
367
368   ctx_index = pointer_to_uword (ctx_indexp);
369   ctx = tls_ctx_get (ctx_index);
370   tls_session = session_get_from_handle (ctx->tls_session_handle);
371   rv = svm_fifo_dequeue_nowait (tls_session->server_rx_fifo, len, buf);
372   return (rv < 0) ? 0 : rv;
373 }
374
375 static void
376 mbedtls_debug (void *ctx, int level, const char *file, int line,
377                const char *str)
378 {
379   ((void) level);
380   fprintf ((FILE *) ctx, "%s:%04d: %s", file, line, str);
381   fflush ((FILE *) ctx);
382 }
383
384 static int
385 tls_ctx_init_client (tls_ctx_t * ctx)
386 {
387   tls_main_t *tm = &tls_main;
388   void *ctx_ptr;
389   int rv;
390
391   /*
392    * 1. Setup SSL
393    */
394   mbedtls_ssl_init (&ctx->ssl);
395   mbedtls_ssl_config_init (&ctx->conf);
396   if ((rv = mbedtls_ssl_config_defaults (&ctx->conf, MBEDTLS_SSL_IS_CLIENT,
397                                          MBEDTLS_SSL_TRANSPORT_STREAM,
398                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
399     {
400       TLS_DBG (1, "failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n",
401                rv);
402       return -1;
403     }
404
405   mbedtls_ssl_conf_authmode (&ctx->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
406   mbedtls_ssl_conf_ca_chain (&ctx->conf, &tm->cacert, NULL);
407   mbedtls_ssl_conf_rng (&ctx->conf, mbedtls_ctr_drbg_random,
408                         tls_get_ctr_drbg ());
409   mbedtls_ssl_conf_dbg (&ctx->conf, mbedtls_debug, stdout);
410
411   if ((rv = mbedtls_ssl_setup (&ctx->ssl, &ctx->conf)) != 0)
412     {
413       TLS_DBG (1, "failed\n  ! mbedtls_ssl_setup returned %d\n", rv);
414       return -1;
415     }
416
417   if ((rv = mbedtls_ssl_set_hostname (&ctx->ssl, "SERVER NAME")) != 0)
418     {
419       TLS_DBG (1, "failed\n  ! mbedtls_ssl_set_hostname returned %d\n", rv);
420       return -1;
421     }
422
423   ctx_ptr = uword_to_pointer (tls_ctx_index (ctx), void *);
424   mbedtls_ssl_set_bio (&ctx->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
425
426   mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_CLIENT);
427
428   /*
429    * 2. Do the first 2 steps in the handshake.
430    */
431   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
432            tls_ctx_index (ctx));
433   while (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
434     {
435       rv = mbedtls_ssl_handshake_step (&ctx->ssl);
436       if (rv != 0)
437         break;
438     }
439   TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
440            tls_ctx_index (ctx), ctx->ssl.state);
441   return 0;
442 }
443
444 static int
445 tls_ctx_init_server (tls_ctx_t * ctx)
446 {
447   application_t *app;
448   void *ctx_ptr;
449   int rv;
450
451   mbedtls_ssl_init (&ctx->ssl);
452   mbedtls_ssl_config_init (&ctx->conf);
453   mbedtls_x509_crt_init (&ctx->srvcert);
454   mbedtls_pk_init (&ctx->pkey);
455
456   /*
457    * 1. Cert
458    */
459   app = application_get (ctx->parent_app_index);
460   if (!app->tls_cert || !app->tls_key)
461     {
462       TLS_DBG (1, " failed\n  ! tls cert and/or key not configured %d",
463                ctx->parent_app_index);
464       return -1;
465     }
466
467   rv = mbedtls_x509_crt_parse (&ctx->srvcert,
468                                (const unsigned char *) app->tls_cert,
469                                mbedtls_test_srv_crt_len);
470   if (rv != 0)
471     {
472       TLS_DBG (1, " failed\n  !  mbedtls_x509_crt_parse returned %d", rv);
473       goto exit;
474     }
475
476   /* TODO clone CA */
477   rv = mbedtls_x509_crt_parse (&ctx->srvcert,
478                                (const unsigned char *) mbedtls_test_cas_pem,
479                                mbedtls_test_cas_pem_len);
480   if (rv != 0)
481     {
482       TLS_DBG (1, " failed\n  !  mbedtls_x509_crt_parse returned %d", rv);
483       goto exit;
484     }
485
486   rv = mbedtls_pk_parse_key (&ctx->pkey,
487                              (const unsigned char *) app->tls_key,
488                              mbedtls_test_srv_key_len, NULL, 0);
489   if (rv != 0)
490     {
491       TLS_DBG (1, " failed\n  !  mbedtls_pk_parse_key returned %d", rv);
492       goto exit;
493     }
494
495   /*
496    * 2. SSL context config
497    */
498   if ((rv = mbedtls_ssl_config_defaults (&ctx->conf, MBEDTLS_SSL_IS_SERVER,
499                                          MBEDTLS_SSL_TRANSPORT_STREAM,
500                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
501     {
502       TLS_DBG (1, " failed\n  ! mbedtls_ssl_config_defaults returned %d", rv);
503       goto exit;
504     }
505
506   mbedtls_ssl_conf_rng (&ctx->conf, mbedtls_ctr_drbg_random,
507                         tls_get_ctr_drbg ());
508   mbedtls_ssl_conf_dbg (&ctx->conf, mbedtls_debug, stdout);
509
510   /* TODO CACHE
511      mbedtls_ssl_conf_session_cache( &ctx->conf, &cache,
512      mbedtls_ssl_cache_get,
513      mbedtls_ssl_cache_set );
514    */
515
516   mbedtls_ssl_conf_ca_chain (&ctx->conf, ctx->srvcert.next, NULL);
517   if ((rv = mbedtls_ssl_conf_own_cert (&ctx->conf, &ctx->srvcert, &ctx->pkey))
518       != 0)
519     {
520       TLS_DBG (1, " failed\n  ! mbedtls_ssl_conf_own_cert returned %d", rv);
521       goto exit;
522     }
523
524   if ((rv = mbedtls_ssl_setup (&ctx->ssl, &ctx->conf)) != 0)
525     {
526       TLS_DBG (1, " failed\n  ! mbedtls_ssl_setup returned %d", rv);
527       goto exit;
528     }
529
530   mbedtls_ssl_session_reset (&ctx->ssl);
531   ctx_ptr = uword_to_pointer (tls_ctx_index (ctx), void *);
532   mbedtls_ssl_set_bio (&ctx->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
533
534   mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_SERVER);
535
536   /*
537    * 3. Start handshake state machine
538    */
539   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
540            tls_ctx_index (ctx));
541   while (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
542     {
543       rv = mbedtls_ssl_handshake_step (&ctx->ssl);
544       if (rv != 0)
545         break;
546     }
547
548   TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
549            tls_ctx_index (ctx), ctx->ssl.state);
550   return 0;
551
552 exit:
553   return -1;
554 }
555
556 static int
557 tls_notify_app_accept (tls_ctx_t * ctx)
558 {
559   stream_session_t *app_listener, *app_session;
560   segment_manager_t *sm;
561   application_t *app;
562   tls_ctx_t *lctx;
563   int rv;
564
565   app = application_get (ctx->parent_app_index);
566   lctx = tls_listener_ctx_get (ctx->listener_ctx_index);
567   app_listener = listen_session_get_from_handle (lctx->app_session_handle);
568   sm = application_get_listen_segment_manager (app, app_listener);
569
570   app_session = session_alloc (vlib_get_thread_index ());
571   app_session->app_index = ctx->parent_app_index;
572   app_session->connection_index = tls_ctx_index (ctx);
573   app_session->session_type = app_listener->session_type;
574   app_session->listener_index = app_listener->session_index;
575   if ((rv = session_alloc_fifos (sm, app_session)))
576     {
577       TLS_DBG (1, "failed to allocate fifos");
578       return rv;
579     }
580   ctx->c_s_index = app_session->session_index;
581   ctx->c_c_index = tls_ctx_index (ctx);
582   ctx->app_session_handle = session_handle (app_session);
583   return app->cb_fns.session_accept_callback (app_session);
584 }
585
586 static int
587 tls_notify_app_connected (tls_ctx_t * ctx)
588 {
589   int (*cb_fn) (u32, u32, stream_session_t *, u8);
590   stream_session_t *app_session;
591   segment_manager_t *sm;
592   application_t *app;
593
594   app = application_get (ctx->parent_app_index);
595   cb_fn = app->cb_fns.session_connected_callback;
596
597   sm = application_get_connect_segment_manager (app);
598   app_session = session_alloc (vlib_get_thread_index ());
599   app_session->app_index = ctx->parent_app_index;
600   app_session->connection_index = tls_ctx_index (ctx);
601   app_session->session_type =
602     session_type_from_proto_and_ip (TRANSPORT_PROTO_TLS, ctx->tcp_is_ip4);
603   if (session_alloc_fifos (sm, app_session))
604     goto failed;
605
606   ctx->app_session_handle = session_handle (app_session);
607   ctx->c_s_index = app_session->session_index;
608   ctx->c_c_index = tls_ctx_index (ctx);
609   app_session->session_state = SESSION_STATE_READY;
610   if (cb_fn (ctx->parent_app_index, ctx->parent_app_api_context,
611              app_session, 0 /* not failed */ ))
612     {
613       TLS_DBG (1, "failed to notify app");
614       tls_disconnect (tls_ctx_index (ctx), vlib_get_thread_index ());
615     }
616
617   return 0;
618
619 failed:
620   return cb_fn (ctx->parent_app_index, ctx->parent_app_api_context, 0,
621                 1 /* failed */ );
622 }
623
624 static int
625 tls_handshake_rx (tls_ctx_t * ctx)
626 {
627   u32 flags;
628   int rv;
629   while (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
630     {
631       rv = mbedtls_ssl_handshake_step (&ctx->ssl);
632       if (rv != 0)
633         break;
634     }
635   TLS_DBG (2, "tls state for %u is %u", tls_ctx_index (ctx), ctx->ssl.state);
636
637   if (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
638     return 0;
639
640   /*
641    * Handshake complete
642    */
643   if (ctx->ssl.conf->endpoint == MBEDTLS_SSL_IS_CLIENT)
644     {
645       /*
646        * Verify server certificate
647        */
648       if ((flags = mbedtls_ssl_get_verify_result (&ctx->ssl)) != 0)
649         {
650           char buf[512];
651           TLS_DBG (1, " failed\n");
652           mbedtls_x509_crt_verify_info (buf, sizeof (buf), "  ! ", flags);
653           TLS_DBG (1, "%s\n", buf);
654
655           /* For testing purposes not enforcing this */
656           /* tls_disconnect (tls_ctx_index (ctx), vlib_get_thread_index ());
657              return -1;
658            */
659         }
660       tls_notify_app_connected (ctx);
661     }
662   else
663     {
664       tls_notify_app_accept (ctx);
665     }
666
667   TLS_DBG (1, "Handshake for %u complete. TLS cipher is %x",
668            tls_ctx_index (ctx), ctx->ssl.session->ciphersuite);
669   return 0;
670 }
671
672 void
673 tls_session_reset_callback (stream_session_t * s)
674 {
675   clib_warning ("called...");
676 }
677
678 int
679 tls_add_segment_callback (u32 client_index, const ssvm_private_t * fs)
680 {
681   /* No-op for builtin */
682   return 0;
683 }
684
685 int
686 tls_del_segment_callback (u32 client_index, const ssvm_private_t * fs)
687 {
688   return 0;
689 }
690
691 void
692 tls_session_disconnect_callback (stream_session_t * tls_session)
693 {
694   stream_session_t *app_session;
695   tls_ctx_t *ctx;
696   application_t *app;
697
698   ctx = tls_ctx_get (tls_session->opaque);
699   if (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
700     {
701       stream_session_disconnect (tls_session);
702       return;
703     }
704   ctx->is_passive_close = 1;
705   app = application_get (ctx->parent_app_index);
706   app_session = session_get_from_handle (ctx->app_session_handle);
707   app->cb_fns.session_disconnect_callback (app_session);
708 }
709
710 int
711 tls_session_accept_callback (stream_session_t * tls_session)
712 {
713   stream_session_t *tls_listener;
714   tls_ctx_t *lctx, *ctx;
715   u32 ctx_index;
716
717   tls_listener = listen_session_get (tls_session->session_type,
718                                      tls_session->listener_index);
719   lctx = tls_listener_ctx_get (tls_listener->opaque);
720   ctx_index = tls_ctx_alloc ();
721   ctx = tls_ctx_get (ctx_index);
722   memcpy (ctx, lctx, sizeof (*lctx));
723   ctx->c_thread_index = vlib_get_thread_index ();
724   tls_session->session_state = SESSION_STATE_READY;
725   tls_session->opaque = ctx_index;
726   ctx->tls_session_handle = session_handle (tls_session);
727   ctx->listener_ctx_index = tls_listener->opaque;
728
729   TLS_DBG (1, "Accept on listener %u new connection [%u]%u",
730            tls_listener->opaque, vlib_get_thread_index (), ctx_index);
731
732   return tls_ctx_init_server (ctx);
733 }
734
735 int
736 tls_app_tx_callback (stream_session_t * app_session)
737 {
738   stream_session_t *tls_session;
739   tls_ctx_t *ctx;
740   static u8 *tmp_buf;
741   u32 enq_max, deq_max, deq_now;
742   int wrote;
743
744   ctx = tls_ctx_get (app_session->connection_index);
745   if (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
746     tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
747
748   deq_max = svm_fifo_max_dequeue (app_session->server_tx_fifo);
749   if (!deq_max)
750     return 0;
751
752   tls_session = session_get_from_handle (ctx->tls_session_handle);
753   enq_max = svm_fifo_max_enqueue (tls_session->server_tx_fifo);
754   deq_now = clib_min (deq_max, TLS_CHUNK_SIZE);
755
756   if (PREDICT_FALSE (enq_max == 0))
757     {
758       tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
759       return 0;
760     }
761
762   vec_validate (tmp_buf, deq_now);
763   svm_fifo_peek (app_session->server_tx_fifo, 0, deq_now, tmp_buf);
764   wrote = mbedtls_ssl_write (&ctx->ssl, tmp_buf, deq_now);
765   if (wrote <= 0)
766     {
767       tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
768       return 0;
769     }
770
771   svm_fifo_dequeue_drop (app_session->server_tx_fifo, wrote);
772   vec_reset_length (tmp_buf);
773
774   tls_add_vpp_q_evt (tls_session->server_tx_fifo, FIFO_EVENT_APP_TX);
775
776   if (deq_now < deq_max)
777     tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
778
779   return 0;
780 }
781
782 int
783 tls_app_rx_callback (stream_session_t * tls_session)
784 {
785   stream_session_t *app_session;
786   u32 deq_max, enq_max, enq_now;
787   application_t *app;
788   static u8 *tmp_buf;
789   tls_ctx_t *ctx;
790   int read, enq;
791
792   ctx = tls_ctx_get (tls_session->opaque);
793   if (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
794     return tls_handshake_rx (ctx);
795
796   deq_max = svm_fifo_max_dequeue (tls_session->server_rx_fifo);
797   if (!deq_max)
798     return 0;
799
800   app_session = session_get_from_handle (ctx->app_session_handle);
801   enq_max = svm_fifo_max_enqueue (app_session->server_rx_fifo);
802   enq_now = clib_min (enq_max, TLS_CHUNK_SIZE);
803
804   if (PREDICT_FALSE (enq_now == 0))
805     {
806       tls_add_vpp_q_evt (tls_session->server_rx_fifo, FIFO_EVENT_BUILTIN_RX);
807       return 0;
808     }
809
810   vec_validate (tmp_buf, enq_now);
811   read = mbedtls_ssl_read (&ctx->ssl, tmp_buf, enq_now);
812   if (read <= 0)
813     {
814       tls_add_vpp_q_evt (tls_session->server_rx_fifo, FIFO_EVENT_BUILTIN_RX);
815       return 0;
816     }
817
818   enq = svm_fifo_enqueue_nowait (app_session->server_rx_fifo, read, tmp_buf);
819   ASSERT (enq == read);
820   vec_reset_length (tmp_buf);
821
822   if (svm_fifo_max_dequeue (tls_session->server_rx_fifo))
823     tls_add_vpp_q_evt (tls_session->server_rx_fifo, FIFO_EVENT_BUILTIN_RX);
824
825   app = application_get_if_valid (app_session->app_index);
826   return tls_add_app_q_evt (app, app_session);
827 }
828
829 int
830 tls_session_connected_callback (u32 tls_app_index, u32 ho_ctx_index,
831                                 stream_session_t * tls_session, u8 is_fail)
832 {
833   int (*cb_fn) (u32, u32, stream_session_t *, u8);
834   application_t *app;
835   tls_ctx_t *ho_ctx, *ctx;
836   u32 ctx_index;
837
838   ho_ctx = tls_ctx_half_open_get (ho_ctx_index);
839   app = application_get (ho_ctx->parent_app_index);
840   cb_fn = app->cb_fns.session_connected_callback;
841
842   if (is_fail)
843     goto failed;
844
845   ctx_index = tls_ctx_alloc ();
846   ctx = tls_ctx_get (ctx_index);
847   clib_memcpy (ctx, ho_ctx, sizeof (*ctx));
848   ctx->c_thread_index = vlib_get_thread_index ();
849   tls_ctx_half_open_reader_unlock ();
850   tls_ctx_half_open_free (ho_ctx_index);
851
852   TLS_DBG (1, "TCP connect for %u returned %u. New connection [%u]%u",
853            ho_ctx_index, is_fail, vlib_get_thread_index (),
854            (ctx) ? ctx_index : ~0);
855
856   ctx->tls_session_handle = session_handle (tls_session);
857   tls_session->opaque = ctx_index;
858   tls_session->session_state = SESSION_STATE_READY;
859
860   return tls_ctx_init_client (ctx);
861
862 failed:
863   tls_ctx_half_open_reader_unlock ();
864   tls_ctx_half_open_free (ho_ctx_index);
865   return cb_fn (ho_ctx->parent_app_index, ho_ctx->c_s_index, 0,
866                 1 /* failed */ );
867 }
868
869 /* *INDENT-OFF* */
870 static session_cb_vft_t tls_app_cb_vft = {
871   .session_accept_callback = tls_session_accept_callback,
872   .session_disconnect_callback = tls_session_disconnect_callback,
873   .session_connected_callback = tls_session_connected_callback,
874   .session_reset_callback = tls_session_reset_callback,
875   .add_segment_callback = tls_add_segment_callback,
876   .del_segment_callback = tls_del_segment_callback,
877   .builtin_app_rx_callback = tls_app_rx_callback,
878   .builtin_app_tx_callback = tls_app_tx_callback,
879 };
880 /* *INDENT-ON* */
881
882 int
883 tls_connect (transport_endpoint_t * tep)
884 {
885   session_endpoint_extended_t *sep;
886   session_endpoint_t tls_sep;
887   tls_main_t *tm = &tls_main;
888   application_t *app;
889   tls_ctx_t *ctx;
890   u32 ctx_index;
891   int rv;
892
893   sep = (session_endpoint_extended_t *) tep;
894
895   ctx_index = tls_ctx_half_open_alloc ();
896   ctx = tls_ctx_half_open_get (ctx_index);
897   ctx->parent_app_index = sep->app_index;
898   ctx->parent_app_api_context = sep->opaque;
899   ctx->tcp_is_ip4 = sep->is_ip4;
900   tls_ctx_half_open_reader_unlock ();
901
902   app = application_get (sep->app_index);
903   application_alloc_connects_segment_manager (app);
904
905   clib_memcpy (&tls_sep, sep, sizeof (tls_sep));
906   tls_sep.transport_proto = TRANSPORT_PROTO_TCP;
907   if ((rv = application_connect (tm->app_index, ctx_index, &tls_sep)))
908     return rv;
909
910   TLS_DBG (1, "New connect request %u", ctx_index);
911   return 0;
912 }
913
914 void
915 tls_disconnect (u32 ctx_index, u32 thread_index)
916 {
917   stream_session_t *tls_session, *app_session;
918   tls_ctx_t *ctx;
919
920   TLS_DBG (1, "Disconnecting %u", ctx_index);
921
922   ctx = tls_ctx_get (ctx_index);
923   if (ctx->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER && !ctx->is_passive_close)
924     mbedtls_ssl_close_notify (&ctx->ssl);
925
926   tls_session = session_get_from_handle (ctx->tls_session_handle);
927   stream_session_disconnect (tls_session);
928
929   app_session = session_get_from_handle_if_valid (ctx->app_session_handle);
930   if (app_session)
931     {
932       segment_manager_dealloc_fifos (app_session->svm_segment_index,
933                                      app_session->server_rx_fifo,
934                                      app_session->server_tx_fifo);
935       session_free (app_session);
936     }
937   tls_ctx_free (ctx);
938 }
939
940 u32
941 tls_start_listen (u32 app_listener_index, transport_endpoint_t * tep)
942 {
943   tls_main_t *tm = &tls_main;
944   application_t *tls_app;
945   session_handle_t tls_handle;
946   session_endpoint_extended_t *sep;
947   stream_session_t *tls_listener;
948   tls_ctx_t *lctx;
949   u32 lctx_index;
950   session_type_t st;
951   stream_session_t *app_listener;
952
953   sep = (session_endpoint_extended_t *) tep;
954   lctx_index = tls_listener_ctx_alloc ();
955   lctx = tls_listener_ctx_get (lctx_index);
956   st = session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4);
957   app_listener = listen_session_get (st, app_listener_index);
958
959   tls_app = application_get (tm->app_index);
960   sep->transport_proto = TRANSPORT_PROTO_TCP;
961   if (application_start_listen (tls_app, (session_endpoint_t *) sep,
962                                 &tls_handle))
963     return ~0;
964
965   tls_listener = listen_session_get_from_handle (tls_handle);
966   tls_listener->opaque = lctx_index;
967   lctx->parent_app_index = sep->app_index;
968   lctx->tls_session_handle = tls_handle;
969   lctx->app_session_handle = listen_session_get_handle (app_listener);
970   lctx->tcp_is_ip4 = sep->is_ip4;
971   return lctx_index;
972 }
973
974 u32
975 tls_stop_listen (u32 listener_index)
976 {
977   clib_warning ("TBD");
978   return 0;
979 }
980
981 transport_connection_t *
982 tls_listener_get (u32 listener_index)
983 {
984   tls_ctx_t *ctx;
985   ctx = tls_listener_ctx_get (listener_index);
986   return &ctx->connection;
987 }
988
989 u8 *
990 format_tls_ctx (u8 * s, va_list * args)
991 {
992   tls_ctx_t *ctx = va_arg (*args, tls_ctx_t *);
993   u32 thread_index = va_arg (*args, u32);
994   u32 child_si, child_ti;
995
996   session_parse_handle (ctx->tls_session_handle, &child_si, &child_ti);
997   if (thread_index != child_ti)
998     clib_warning ("app and tls sessions are on different threads!");
999
1000   s =
1001     format (s, "[#%d][TLS] app %u child %u", child_ti, ctx->parent_app_index,
1002             child_si);
1003   return s;
1004 }
1005
1006 u8 *
1007 format_tls_connection (u8 * s, va_list * args)
1008 {
1009   u32 ctx_index = va_arg (*args, u32);
1010   u32 thread_index = va_arg (*args, u32);
1011   u32 verbose = va_arg (*args, u32);
1012   tls_ctx_t *ctx;
1013
1014   ctx = tls_ctx_get_w_thread (ctx_index, thread_index);
1015   if (!ctx)
1016     return s;
1017
1018   s = format (s, "%-50U", format_tls_ctx, ctx, thread_index);
1019   if (verbose)
1020     {
1021       s = format (s, "%-15s", "state");
1022       if (verbose > 1)
1023         s = format (s, "\n");
1024     }
1025   return s;
1026 }
1027
1028 u8 *
1029 format_tls_listener (u8 * s, va_list * args)
1030 {
1031   u32 tc_index = va_arg (*args, u32);
1032   tls_ctx_t *ctx = tls_listener_ctx_get (tc_index);
1033   u32 listener_index, type;
1034
1035   listen_session_parse_handle (ctx->tls_session_handle, &type,
1036                                &listener_index);
1037   return format (s, "[TLS] listener app %u child %u", ctx->parent_app_index,
1038                  listener_index);
1039 }
1040
1041 u8 *
1042 format_tls_half_open (u8 * s, va_list * args)
1043 {
1044   u32 tc_index = va_arg (*args, u32);
1045   tls_ctx_t *ctx = tls_ctx_half_open_get (tc_index);
1046   s = format (s, "[TLS] half-open app %u", ctx->parent_app_index);
1047   tls_ctx_half_open_reader_unlock ();
1048   return s;
1049 }
1050
1051 /* *INDENT-OFF* */
1052 const static transport_proto_vft_t tls_proto = {
1053   .open = tls_connect,
1054   .close = tls_disconnect,
1055   .bind = tls_start_listen,
1056   .get_listener = tls_listener_get,
1057   .unbind = tls_stop_listen,
1058   .tx_type = TRANSPORT_TX_INTERNAL,
1059   .service_type = TRANSPORT_SERVICE_APP,
1060   .format_connection = format_tls_connection,
1061   .format_half_open = format_tls_half_open,
1062   .format_listener = format_tls_listener,
1063 };
1064 /* *INDENT-ON* */
1065
1066 int
1067 tls_init_mem (void)
1068 {
1069 #if TLS_USE_OUR_MEM_FUNCS
1070   mbedtls_platform_set_calloc_free (mbedtls_calloc_fn, mbedtls_free_fn);
1071 #endif
1072   return 0;
1073 }
1074
1075 int
1076 tls_init_ca_chain (void)
1077 {
1078   tls_main_t *tm = &tls_main;
1079   int rv;
1080
1081   /* TODO config */
1082   mbedtls_x509_crt_init (&tm->cacert);
1083   rv = mbedtls_x509_crt_parse (&tm->cacert,
1084                                (const unsigned char *) mbedtls_test_cas_pem,
1085                                mbedtls_test_cas_pem_len);
1086   if (rv < 0)
1087     {
1088       clib_warning ("mbedtls_x509_crt_parse returned -0x%x", -rv);
1089       return -1;
1090     }
1091   return 0;
1092 }
1093
1094 clib_error_t *
1095 tls_init (vlib_main_t * vm)
1096 {
1097   vlib_thread_main_t *vtm = vlib_get_thread_main ();
1098   u32 fifo_size = 64 << 10, num_threads;
1099   vnet_app_attach_args_t _a, *a = &_a;
1100   u64 options[APP_OPTIONS_N_OPTIONS];
1101   u32 segment_size = 512 << 20;
1102   tls_main_t *tm = &tls_main;
1103
1104   num_threads = 1 /* main thread */  + vtm->n_threads;
1105
1106   if (tls_init_mem ())
1107     {
1108       clib_warning ("failed to initialize mem");
1109       return clib_error_return (0, "failed to initalize mem");
1110     }
1111   if (tls_init_ca_chain ())
1112     {
1113       clib_warning ("failed to initialize TLS CA chain");
1114       return clib_error_return (0, "failed to initalize TLS CA chain");
1115     }
1116   if (tls_init_ctr_drbgs_and_entropy (num_threads))
1117     {
1118       clib_warning ("failed to initialize entropy and random generators");
1119       return clib_error_return (0, "failed to initialize entropy and random "
1120                                 "generators");
1121     }
1122
1123   memset (a, 0, sizeof (*a));
1124   memset (options, 0, sizeof (options));
1125
1126   a->session_cb_vft = &tls_app_cb_vft;
1127   a->api_client_index = (1 << 24) + 1;
1128   a->options = options;
1129   a->options[APP_OPTIONS_SEGMENT_SIZE] = segment_size;
1130   a->options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
1131   a->options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
1132   a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1133   a->options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1134
1135   if (vnet_application_attach (a))
1136     {
1137       clib_warning ("failed to attach tls app");
1138       return clib_error_return (0, "failed to attach tls app");
1139     }
1140
1141   tm->app_index = a->app_index;
1142   vec_validate (tm->ctx_pool, num_threads - 1);
1143   clib_rwlock_init (&tm->half_open_rwlock);
1144
1145   transport_register_protocol (TRANSPORT_PROTO_TLS, &tls_proto,
1146                                FIB_PROTOCOL_IP4, ~0);
1147   transport_register_protocol (TRANSPORT_PROTO_TLS, &tls_proto,
1148                                FIB_PROTOCOL_IP6, ~0);
1149
1150   return 0;
1151 }
1152
1153 VLIB_INIT_FUNCTION (tls_init);
1154
1155 /*
1156  * fd.io coding-style-patch-verification: ON
1157  *
1158  * Local Variables:
1159  * eval: (c-set-style "gnu")
1160  * End:
1161  */