blob: 4e4453cb0d37e8ac70812d79466f0125184d195d [file] [log] [blame]
Florin Coras371ca502018-02-21 12:07:41 -08001/*
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
42void *
43mbedtls_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
51void
52mbedtls_free_fn (void *ptr)
53{
54 if (ptr)
55 clib_mem_free (ptr);
56}
57#endif
58
59/* *INDENT-OFF* */
60typedef 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
70typedef 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
Florin Corasdcde9272018-03-02 09:23:42 -080082#define tls_ctx_idx c_c_index
Florin Coras371ca502018-02-21 12:07:41 -080083 /* 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
94typedef struct tls_main_
95{
96 u32 app_index;
Florin Corasdcde9272018-03-02 09:23:42 -080097 tls_ctx_t ***ctx_pool;
Florin Coras371ca502018-02-21 12:07:41 -080098 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
106static tls_main_t tls_main;
107
108void tls_disconnect (u32 ctx_index, u32 thread_index);
109
110static inline int
111tls_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
135static inline int
136tls_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
172u32
173tls_ctx_alloc (void)
174{
175 u8 thread_index = vlib_get_thread_index ();
176 tls_main_t *tm = &tls_main;
Florin Corasdcde9272018-03-02 09:23:42 -0800177 tls_ctx_t **ctx;
Florin Coras371ca502018-02-21 12:07:41 -0800178
179 pool_get (tm->ctx_pool[thread_index], ctx);
Florin Corasdcde9272018-03-02 09:23:42 -0800180 if (!(*ctx))
181 *ctx = clib_mem_alloc (sizeof (tls_ctx_t));
182
183 memset (*ctx, 0, sizeof (tls_ctx_t));
184 (*ctx)->c_thread_index = thread_index;
Florin Coras371ca502018-02-21 12:07:41 -0800185 return ctx - tm->ctx_pool[thread_index];
186}
187
188void
189tls_ctx_free (tls_ctx_t * ctx)
190{
Florin Corasdcde9272018-03-02 09:23:42 -0800191 pool_put_index (tls_main.ctx_pool[vlib_get_thread_index ()],
192 ctx->tls_ctx_idx);
Florin Coras371ca502018-02-21 12:07:41 -0800193}
194
195tls_ctx_t *
196tls_ctx_get (u32 ctx_index)
197{
Florin Corasdcde9272018-03-02 09:23:42 -0800198 tls_ctx_t **ctx;
199 ctx = pool_elt_at_index (tls_main.ctx_pool[vlib_get_thread_index ()],
200 ctx_index);
201 return (*ctx);
Florin Coras371ca502018-02-21 12:07:41 -0800202}
203
204tls_ctx_t *
205tls_ctx_get_w_thread (u32 ctx_index, u8 thread_index)
206{
Florin Corasdcde9272018-03-02 09:23:42 -0800207 tls_ctx_t **ctx;
208 ctx = pool_elt_at_index (tls_main.ctx_pool[thread_index], ctx_index);
209 return (*ctx);
Florin Coras371ca502018-02-21 12:07:41 -0800210}
211
212u32
213tls_listener_ctx_alloc (void)
214{
215 tls_main_t *tm = &tls_main;
216 tls_ctx_t *ctx;
217
218 pool_get (tm->listener_ctx_pool, ctx);
219 memset (ctx, 0, sizeof (*ctx));
220 return ctx - tm->listener_ctx_pool;
221}
222
223void
224tls_ctx_listener_free (tls_ctx_t * ctx)
225{
226 pool_put (tls_main.half_open_ctx_pool, ctx);
227}
228
229tls_ctx_t *
230tls_listener_ctx_get (u32 ctx_index)
231{
232 return pool_elt_at_index (tls_main.listener_ctx_pool, ctx_index);
233}
234
235u32
236tls_listener_ctx_index (tls_ctx_t * ctx)
237{
238 return (ctx - tls_main.listener_ctx_pool);
239}
240
241u32
242tls_ctx_half_open_alloc (void)
243{
244 tls_main_t *tm = &tls_main;
245 u8 will_expand = 0;
246 tls_ctx_t *ctx;
247 u32 ctx_index;
248
249 pool_get_aligned_will_expand (tm->half_open_ctx_pool, will_expand, 0);
250 if (PREDICT_FALSE (will_expand && vlib_num_workers ()))
251 {
252 clib_rwlock_writer_lock (&tm->half_open_rwlock);
253 pool_get (tm->half_open_ctx_pool, ctx);
254 memset (ctx, 0, sizeof (*ctx));
255 ctx_index = ctx - tm->half_open_ctx_pool;
256 clib_rwlock_writer_unlock (&tm->half_open_rwlock);
257 }
258 else
259 {
260 pool_get (tm->half_open_ctx_pool, ctx);
261 memset (ctx, 0, sizeof (*ctx));
262 ctx_index = ctx - tm->half_open_ctx_pool;
263 }
264 return ctx_index;
265}
266
267void
268tls_ctx_half_open_free (u32 ho_index)
269{
270 tls_main_t *tm = &tls_main;
271 clib_rwlock_writer_lock (&tm->half_open_rwlock);
272 pool_put_index (tls_main.half_open_ctx_pool, ho_index);
273 clib_rwlock_writer_unlock (&tm->half_open_rwlock);
274}
275
276tls_ctx_t *
277tls_ctx_half_open_get (u32 ctx_index)
278{
279 tls_main_t *tm = &tls_main;
280 clib_rwlock_reader_lock (&tm->half_open_rwlock);
281 return pool_elt_at_index (tm->half_open_ctx_pool, ctx_index);
282}
283
284void
285tls_ctx_half_open_reader_unlock ()
286{
287 clib_rwlock_reader_unlock (&tls_main.half_open_rwlock);
288}
289
290u32
291tls_ctx_half_open_index (tls_ctx_t * ctx)
292{
293 return (ctx - tls_main.half_open_ctx_pool);
294}
295
296static int
297tls_init_ctr_drbgs_and_entropy (u32 num_threads)
298{
299 tls_main_t *tm = &tls_main;
300 int i;
301
302 vec_validate (tm->ctr_drbgs, num_threads - 1);
303 vec_validate (tm->entropy_pools, num_threads - 1);
304 for (i = 0; i < num_threads; i++)
305 tls_main.ctr_drbgs[i].f_entropy = 0;
306
307 return 0;
308}
309
310static int
311tls_init_ctr_seed_drbgs (void)
312{
313 u32 thread_index = vlib_get_thread_index ();
314 tls_main_t *tm = &tls_main;
315 u8 *pers;
316 int rv;
317 pers = format (0, "vpp thread %u", thread_index);
318
319 mbedtls_entropy_init (&tm->entropy_pools[thread_index]);
320 mbedtls_ctr_drbg_init (&tls_main.ctr_drbgs[thread_index]);
321 if ((rv = mbedtls_ctr_drbg_seed (&tm->ctr_drbgs[thread_index],
322 mbedtls_entropy_func,
323 &tm->entropy_pools[thread_index],
324 (const unsigned char *) pers,
325 vec_len (pers))) != 0)
326 {
327 vec_free (pers);
328 TLS_DBG (1, " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", rv);
329 return -1;
330 }
331 vec_free (pers);
332 return 0;
333}
334
335mbedtls_ctr_drbg_context *
336tls_get_ctr_drbg ()
337{
338 u8 thread_index = vlib_get_thread_index ();
339 if (PREDICT_FALSE (!tls_main.ctr_drbgs[thread_index].f_entropy))
340 tls_init_ctr_seed_drbgs ();
341 return &tls_main.ctr_drbgs[thread_index];
342}
343
344static int
345tls_net_send (void *ctx_indexp, const unsigned char *buf, size_t len)
346{
347 stream_session_t *tls_session;
348 uword ctx_index;
349 tls_ctx_t *ctx;
350 int rv;
351
352 ctx_index = pointer_to_uword (ctx_indexp);
353 ctx = tls_ctx_get (ctx_index);
354 tls_session = session_get_from_handle (ctx->tls_session_handle);
355 rv = svm_fifo_enqueue_nowait (tls_session->server_tx_fifo, len, buf);
356 if (rv < 0)
357 return MBEDTLS_ERR_SSL_WANT_WRITE;
358 tls_add_vpp_q_evt (tls_session->server_tx_fifo, FIFO_EVENT_APP_TX);
359 return rv;
360}
361
362static int
363tls_net_recv (void *ctx_indexp, unsigned char *buf, size_t len)
364{
365 stream_session_t *tls_session;
366 uword ctx_index;
367 tls_ctx_t *ctx;
368 int rv;
369
370 ctx_index = pointer_to_uword (ctx_indexp);
371 ctx = tls_ctx_get (ctx_index);
372 tls_session = session_get_from_handle (ctx->tls_session_handle);
373 rv = svm_fifo_dequeue_nowait (tls_session->server_rx_fifo, len, buf);
374 return (rv < 0) ? 0 : rv;
375}
376
377static void
378mbedtls_debug (void *ctx, int level, const char *file, int line,
379 const char *str)
380{
381 ((void) level);
382 fprintf ((FILE *) ctx, "%s:%04d: %s", file, line, str);
383 fflush ((FILE *) ctx);
384}
385
386static int
387tls_ctx_init_client (tls_ctx_t * ctx)
388{
389 tls_main_t *tm = &tls_main;
390 void *ctx_ptr;
391 int rv;
392
393 /*
394 * 1. Setup SSL
395 */
396 mbedtls_ssl_init (&ctx->ssl);
397 mbedtls_ssl_config_init (&ctx->conf);
398 if ((rv = mbedtls_ssl_config_defaults (&ctx->conf, MBEDTLS_SSL_IS_CLIENT,
399 MBEDTLS_SSL_TRANSPORT_STREAM,
400 MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
401 {
402 TLS_DBG (1, "failed\n ! mbedtls_ssl_config_defaults returned %d\n\n",
403 rv);
404 return -1;
405 }
406
407 mbedtls_ssl_conf_authmode (&ctx->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
408 mbedtls_ssl_conf_ca_chain (&ctx->conf, &tm->cacert, NULL);
409 mbedtls_ssl_conf_rng (&ctx->conf, mbedtls_ctr_drbg_random,
410 tls_get_ctr_drbg ());
411 mbedtls_ssl_conf_dbg (&ctx->conf, mbedtls_debug, stdout);
412
413 if ((rv = mbedtls_ssl_setup (&ctx->ssl, &ctx->conf)) != 0)
414 {
415 TLS_DBG (1, "failed\n ! mbedtls_ssl_setup returned %d\n", rv);
416 return -1;
417 }
418
419 if ((rv = mbedtls_ssl_set_hostname (&ctx->ssl, "SERVER NAME")) != 0)
420 {
421 TLS_DBG (1, "failed\n ! mbedtls_ssl_set_hostname returned %d\n", rv);
422 return -1;
423 }
424
Florin Corasdcde9272018-03-02 09:23:42 -0800425 ctx_ptr = uword_to_pointer (ctx->tls_ctx_idx, void *);
Florin Coras371ca502018-02-21 12:07:41 -0800426 mbedtls_ssl_set_bio (&ctx->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
427
428 mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_CLIENT);
429
430 /*
431 * 2. Do the first 2 steps in the handshake.
432 */
433 TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
434 tls_ctx_index (ctx));
435 while (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
436 {
437 rv = mbedtls_ssl_handshake_step (&ctx->ssl);
438 if (rv != 0)
439 break;
440 }
441 TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
442 tls_ctx_index (ctx), ctx->ssl.state);
443 return 0;
444}
445
446static int
447tls_ctx_init_server (tls_ctx_t * ctx)
448{
449 application_t *app;
450 void *ctx_ptr;
451 int rv;
452
453 mbedtls_ssl_init (&ctx->ssl);
454 mbedtls_ssl_config_init (&ctx->conf);
455 mbedtls_x509_crt_init (&ctx->srvcert);
456 mbedtls_pk_init (&ctx->pkey);
457
458 /*
459 * 1. Cert
460 */
461 app = application_get (ctx->parent_app_index);
462 if (!app->tls_cert || !app->tls_key)
463 {
464 TLS_DBG (1, " failed\n ! tls cert and/or key not configured %d",
465 ctx->parent_app_index);
466 return -1;
467 }
468
469 rv = mbedtls_x509_crt_parse (&ctx->srvcert,
470 (const unsigned char *) app->tls_cert,
471 mbedtls_test_srv_crt_len);
472 if (rv != 0)
473 {
474 TLS_DBG (1, " failed\n ! mbedtls_x509_crt_parse returned %d", rv);
475 goto exit;
476 }
477
478 /* TODO clone CA */
479 rv = mbedtls_x509_crt_parse (&ctx->srvcert,
480 (const unsigned char *) mbedtls_test_cas_pem,
481 mbedtls_test_cas_pem_len);
482 if (rv != 0)
483 {
484 TLS_DBG (1, " failed\n ! mbedtls_x509_crt_parse returned %d", rv);
485 goto exit;
486 }
487
488 rv = mbedtls_pk_parse_key (&ctx->pkey,
489 (const unsigned char *) app->tls_key,
490 mbedtls_test_srv_key_len, NULL, 0);
491 if (rv != 0)
492 {
493 TLS_DBG (1, " failed\n ! mbedtls_pk_parse_key returned %d", rv);
494 goto exit;
495 }
496
497 /*
498 * 2. SSL context config
499 */
500 if ((rv = mbedtls_ssl_config_defaults (&ctx->conf, MBEDTLS_SSL_IS_SERVER,
501 MBEDTLS_SSL_TRANSPORT_STREAM,
502 MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
503 {
504 TLS_DBG (1, " failed\n ! mbedtls_ssl_config_defaults returned %d", rv);
505 goto exit;
506 }
507
508 mbedtls_ssl_conf_rng (&ctx->conf, mbedtls_ctr_drbg_random,
509 tls_get_ctr_drbg ());
510 mbedtls_ssl_conf_dbg (&ctx->conf, mbedtls_debug, stdout);
511
512 /* TODO CACHE
513 mbedtls_ssl_conf_session_cache( &ctx->conf, &cache,
514 mbedtls_ssl_cache_get,
515 mbedtls_ssl_cache_set );
516 */
517
518 mbedtls_ssl_conf_ca_chain (&ctx->conf, ctx->srvcert.next, NULL);
519 if ((rv = mbedtls_ssl_conf_own_cert (&ctx->conf, &ctx->srvcert, &ctx->pkey))
520 != 0)
521 {
522 TLS_DBG (1, " failed\n ! mbedtls_ssl_conf_own_cert returned %d", rv);
523 goto exit;
524 }
525
526 if ((rv = mbedtls_ssl_setup (&ctx->ssl, &ctx->conf)) != 0)
527 {
528 TLS_DBG (1, " failed\n ! mbedtls_ssl_setup returned %d", rv);
529 goto exit;
530 }
531
532 mbedtls_ssl_session_reset (&ctx->ssl);
Florin Corasdcde9272018-03-02 09:23:42 -0800533 ctx_ptr = uword_to_pointer (ctx->tls_ctx_idx, void *);
Florin Coras371ca502018-02-21 12:07:41 -0800534 mbedtls_ssl_set_bio (&ctx->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
535
536 mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_SERVER);
537
538 /*
539 * 3. Start handshake state machine
540 */
541 TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
542 tls_ctx_index (ctx));
543 while (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
544 {
545 rv = mbedtls_ssl_handshake_step (&ctx->ssl);
546 if (rv != 0)
547 break;
548 }
549
550 TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
551 tls_ctx_index (ctx), ctx->ssl.state);
552 return 0;
553
554exit:
555 return -1;
556}
557
558static int
559tls_notify_app_accept (tls_ctx_t * ctx)
560{
561 stream_session_t *app_listener, *app_session;
562 segment_manager_t *sm;
563 application_t *app;
564 tls_ctx_t *lctx;
565 int rv;
566
567 app = application_get (ctx->parent_app_index);
568 lctx = tls_listener_ctx_get (ctx->listener_ctx_index);
569 app_listener = listen_session_get_from_handle (lctx->app_session_handle);
570 sm = application_get_listen_segment_manager (app, app_listener);
571
572 app_session = session_alloc (vlib_get_thread_index ());
573 app_session->app_index = ctx->parent_app_index;
Florin Corasdcde9272018-03-02 09:23:42 -0800574 app_session->connection_index = ctx->tls_ctx_idx;
Florin Coras371ca502018-02-21 12:07:41 -0800575 app_session->session_type = app_listener->session_type;
576 app_session->listener_index = app_listener->session_index;
577 if ((rv = session_alloc_fifos (sm, app_session)))
578 {
579 TLS_DBG (1, "failed to allocate fifos");
580 return rv;
581 }
582 ctx->c_s_index = app_session->session_index;
Florin Coras371ca502018-02-21 12:07:41 -0800583 ctx->app_session_handle = session_handle (app_session);
584 return app->cb_fns.session_accept_callback (app_session);
585}
586
587static int
588tls_notify_app_connected (tls_ctx_t * ctx)
589{
590 int (*cb_fn) (u32, u32, stream_session_t *, u8);
591 stream_session_t *app_session;
592 segment_manager_t *sm;
593 application_t *app;
594
595 app = application_get (ctx->parent_app_index);
596 cb_fn = app->cb_fns.session_connected_callback;
597
598 sm = application_get_connect_segment_manager (app);
599 app_session = session_alloc (vlib_get_thread_index ());
600 app_session->app_index = ctx->parent_app_index;
Florin Corasdcde9272018-03-02 09:23:42 -0800601 app_session->connection_index = ctx->tls_ctx_idx;
Florin Coras371ca502018-02-21 12:07:41 -0800602 app_session->session_type =
603 session_type_from_proto_and_ip (TRANSPORT_PROTO_TLS, ctx->tcp_is_ip4);
604 if (session_alloc_fifos (sm, app_session))
605 goto failed;
606
607 ctx->app_session_handle = session_handle (app_session);
608 ctx->c_s_index = app_session->session_index;
Florin Coras371ca502018-02-21 12:07:41 -0800609 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");
Florin Corasdcde9272018-03-02 09:23:42 -0800614 tls_disconnect (ctx->tls_ctx_idx, vlib_get_thread_index ());
Florin Coras371ca502018-02-21 12:07:41 -0800615 }
616
617 return 0;
618
619failed:
620 return cb_fn (ctx->parent_app_index, ctx->parent_app_api_context, 0,
621 1 /* failed */ );
622}
623
624static int
625tls_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
672void
673tls_session_reset_callback (stream_session_t * s)
674{
675 clib_warning ("called...");
676}
677
678int
679tls_add_segment_callback (u32 client_index, const ssvm_private_t * fs)
680{
681 /* No-op for builtin */
682 return 0;
683}
684
685int
686tls_del_segment_callback (u32 client_index, const ssvm_private_t * fs)
687{
688 return 0;
689}
690
691void
692tls_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
710int
711tls_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 ();
Florin Corasdcde9272018-03-02 09:23:42 -0800724 ctx->tls_ctx_idx = ctx_index;
Florin Coras371ca502018-02-21 12:07:41 -0800725 tls_session->session_state = SESSION_STATE_READY;
726 tls_session->opaque = ctx_index;
727 ctx->tls_session_handle = session_handle (tls_session);
728 ctx->listener_ctx_index = tls_listener->opaque;
729
730 TLS_DBG (1, "Accept on listener %u new connection [%u]%u",
731 tls_listener->opaque, vlib_get_thread_index (), ctx_index);
732
733 return tls_ctx_init_server (ctx);
734}
735
736int
737tls_app_tx_callback (stream_session_t * app_session)
738{
739 stream_session_t *tls_session;
740 tls_ctx_t *ctx;
741 static u8 *tmp_buf;
742 u32 enq_max, deq_max, deq_now;
743 int wrote;
744
745 ctx = tls_ctx_get (app_session->connection_index);
746 if (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
747 tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
748
749 deq_max = svm_fifo_max_dequeue (app_session->server_tx_fifo);
750 if (!deq_max)
751 return 0;
752
753 tls_session = session_get_from_handle (ctx->tls_session_handle);
754 enq_max = svm_fifo_max_enqueue (tls_session->server_tx_fifo);
755 deq_now = clib_min (deq_max, TLS_CHUNK_SIZE);
756
757 if (PREDICT_FALSE (enq_max == 0))
758 {
759 tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
760 return 0;
761 }
762
763 vec_validate (tmp_buf, deq_now);
764 svm_fifo_peek (app_session->server_tx_fifo, 0, deq_now, tmp_buf);
765 wrote = mbedtls_ssl_write (&ctx->ssl, tmp_buf, deq_now);
766 if (wrote <= 0)
767 {
768 tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
769 return 0;
770 }
771
772 svm_fifo_dequeue_drop (app_session->server_tx_fifo, wrote);
773 vec_reset_length (tmp_buf);
774
775 tls_add_vpp_q_evt (tls_session->server_tx_fifo, FIFO_EVENT_APP_TX);
776
777 if (deq_now < deq_max)
778 tls_add_vpp_q_evt (app_session->server_tx_fifo, FIFO_EVENT_APP_TX);
779
780 return 0;
781}
782
783int
784tls_app_rx_callback (stream_session_t * tls_session)
785{
786 stream_session_t *app_session;
787 u32 deq_max, enq_max, enq_now;
788 application_t *app;
789 static u8 *tmp_buf;
790 tls_ctx_t *ctx;
791 int read, enq;
792
793 ctx = tls_ctx_get (tls_session->opaque);
794 if (ctx->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
795 return tls_handshake_rx (ctx);
796
797 deq_max = svm_fifo_max_dequeue (tls_session->server_rx_fifo);
798 if (!deq_max)
799 return 0;
800
801 app_session = session_get_from_handle (ctx->app_session_handle);
802 enq_max = svm_fifo_max_enqueue (app_session->server_rx_fifo);
803 enq_now = clib_min (enq_max, TLS_CHUNK_SIZE);
804
805 if (PREDICT_FALSE (enq_now == 0))
806 {
807 tls_add_vpp_q_evt (tls_session->server_rx_fifo, FIFO_EVENT_BUILTIN_RX);
808 return 0;
809 }
810
811 vec_validate (tmp_buf, enq_now);
812 read = mbedtls_ssl_read (&ctx->ssl, tmp_buf, enq_now);
813 if (read <= 0)
814 {
815 tls_add_vpp_q_evt (tls_session->server_rx_fifo, FIFO_EVENT_BUILTIN_RX);
816 return 0;
817 }
818
819 enq = svm_fifo_enqueue_nowait (app_session->server_rx_fifo, read, tmp_buf);
820 ASSERT (enq == read);
821 vec_reset_length (tmp_buf);
822
823 if (svm_fifo_max_dequeue (tls_session->server_rx_fifo))
824 tls_add_vpp_q_evt (tls_session->server_rx_fifo, FIFO_EVENT_BUILTIN_RX);
825
826 app = application_get_if_valid (app_session->app_index);
827 return tls_add_app_q_evt (app, app_session);
828}
829
830int
831tls_session_connected_callback (u32 tls_app_index, u32 ho_ctx_index,
832 stream_session_t * tls_session, u8 is_fail)
833{
834 int (*cb_fn) (u32, u32, stream_session_t *, u8);
835 application_t *app;
836 tls_ctx_t *ho_ctx, *ctx;
837 u32 ctx_index;
838
839 ho_ctx = tls_ctx_half_open_get (ho_ctx_index);
840 app = application_get (ho_ctx->parent_app_index);
841 cb_fn = app->cb_fns.session_connected_callback;
842
843 if (is_fail)
Florin Corasdcde9272018-03-02 09:23:42 -0800844 {
845 tls_ctx_half_open_reader_unlock ();
846 tls_ctx_half_open_free (ho_ctx_index);
847 return cb_fn (ho_ctx->parent_app_index, ho_ctx->c_s_index, 0,
848 1 /* failed */ );
849 }
Florin Coras371ca502018-02-21 12:07:41 -0800850
851 ctx_index = tls_ctx_alloc ();
852 ctx = tls_ctx_get (ctx_index);
853 clib_memcpy (ctx, ho_ctx, sizeof (*ctx));
Florin Coras371ca502018-02-21 12:07:41 -0800854 tls_ctx_half_open_reader_unlock ();
855 tls_ctx_half_open_free (ho_ctx_index);
856
Florin Corasdcde9272018-03-02 09:23:42 -0800857 ctx->c_thread_index = vlib_get_thread_index ();
858 ctx->tls_ctx_idx = ctx_index;
859
Florin Coras371ca502018-02-21 12:07:41 -0800860 TLS_DBG (1, "TCP connect for %u returned %u. New connection [%u]%u",
861 ho_ctx_index, is_fail, vlib_get_thread_index (),
862 (ctx) ? ctx_index : ~0);
863
864 ctx->tls_session_handle = session_handle (tls_session);
865 tls_session->opaque = ctx_index;
866 tls_session->session_state = SESSION_STATE_READY;
867
868 return tls_ctx_init_client (ctx);
Florin Coras371ca502018-02-21 12:07:41 -0800869}
870
871/* *INDENT-OFF* */
872static session_cb_vft_t tls_app_cb_vft = {
873 .session_accept_callback = tls_session_accept_callback,
874 .session_disconnect_callback = tls_session_disconnect_callback,
875 .session_connected_callback = tls_session_connected_callback,
876 .session_reset_callback = tls_session_reset_callback,
877 .add_segment_callback = tls_add_segment_callback,
878 .del_segment_callback = tls_del_segment_callback,
879 .builtin_app_rx_callback = tls_app_rx_callback,
880 .builtin_app_tx_callback = tls_app_tx_callback,
881};
882/* *INDENT-ON* */
883
884int
885tls_connect (transport_endpoint_t * tep)
886{
887 session_endpoint_extended_t *sep;
888 session_endpoint_t tls_sep;
889 tls_main_t *tm = &tls_main;
890 application_t *app;
891 tls_ctx_t *ctx;
892 u32 ctx_index;
893 int rv;
894
895 sep = (session_endpoint_extended_t *) tep;
896
897 ctx_index = tls_ctx_half_open_alloc ();
898 ctx = tls_ctx_half_open_get (ctx_index);
899 ctx->parent_app_index = sep->app_index;
900 ctx->parent_app_api_context = sep->opaque;
901 ctx->tcp_is_ip4 = sep->is_ip4;
902 tls_ctx_half_open_reader_unlock ();
903
904 app = application_get (sep->app_index);
905 application_alloc_connects_segment_manager (app);
906
907 clib_memcpy (&tls_sep, sep, sizeof (tls_sep));
908 tls_sep.transport_proto = TRANSPORT_PROTO_TCP;
909 if ((rv = application_connect (tm->app_index, ctx_index, &tls_sep)))
910 return rv;
911
912 TLS_DBG (1, "New connect request %u", ctx_index);
913 return 0;
914}
915
916void
917tls_disconnect (u32 ctx_index, u32 thread_index)
918{
919 stream_session_t *tls_session, *app_session;
920 tls_ctx_t *ctx;
921
922 TLS_DBG (1, "Disconnecting %u", ctx_index);
923
924 ctx = tls_ctx_get (ctx_index);
925 if (ctx->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER && !ctx->is_passive_close)
926 mbedtls_ssl_close_notify (&ctx->ssl);
927
928 tls_session = session_get_from_handle (ctx->tls_session_handle);
929 stream_session_disconnect (tls_session);
930
931 app_session = session_get_from_handle_if_valid (ctx->app_session_handle);
932 if (app_session)
933 {
934 segment_manager_dealloc_fifos (app_session->svm_segment_index,
935 app_session->server_rx_fifo,
936 app_session->server_tx_fifo);
937 session_free (app_session);
938 }
939 tls_ctx_free (ctx);
940}
941
942u32
943tls_start_listen (u32 app_listener_index, transport_endpoint_t * tep)
944{
945 tls_main_t *tm = &tls_main;
946 application_t *tls_app;
947 session_handle_t tls_handle;
948 session_endpoint_extended_t *sep;
949 stream_session_t *tls_listener;
950 tls_ctx_t *lctx;
951 u32 lctx_index;
952 session_type_t st;
953 stream_session_t *app_listener;
954
955 sep = (session_endpoint_extended_t *) tep;
956 lctx_index = tls_listener_ctx_alloc ();
957 lctx = tls_listener_ctx_get (lctx_index);
958 st = session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4);
959 app_listener = listen_session_get (st, app_listener_index);
960
961 tls_app = application_get (tm->app_index);
962 sep->transport_proto = TRANSPORT_PROTO_TCP;
963 if (application_start_listen (tls_app, (session_endpoint_t *) sep,
964 &tls_handle))
965 return ~0;
966
967 tls_listener = listen_session_get_from_handle (tls_handle);
968 tls_listener->opaque = lctx_index;
969 lctx->parent_app_index = sep->app_index;
970 lctx->tls_session_handle = tls_handle;
971 lctx->app_session_handle = listen_session_get_handle (app_listener);
972 lctx->tcp_is_ip4 = sep->is_ip4;
973 return lctx_index;
974}
975
976u32
977tls_stop_listen (u32 listener_index)
978{
979 clib_warning ("TBD");
980 return 0;
981}
982
983transport_connection_t *
984tls_listener_get (u32 listener_index)
985{
986 tls_ctx_t *ctx;
987 ctx = tls_listener_ctx_get (listener_index);
988 return &ctx->connection;
989}
990
991u8 *
992format_tls_ctx (u8 * s, va_list * args)
993{
994 tls_ctx_t *ctx = va_arg (*args, tls_ctx_t *);
995 u32 thread_index = va_arg (*args, u32);
996 u32 child_si, child_ti;
997
998 session_parse_handle (ctx->tls_session_handle, &child_si, &child_ti);
999 if (thread_index != child_ti)
1000 clib_warning ("app and tls sessions are on different threads!");
1001
1002 s =
1003 format (s, "[#%d][TLS] app %u child %u", child_ti, ctx->parent_app_index,
1004 child_si);
1005 return s;
1006}
1007
1008u8 *
1009format_tls_connection (u8 * s, va_list * args)
1010{
1011 u32 ctx_index = va_arg (*args, u32);
1012 u32 thread_index = va_arg (*args, u32);
1013 u32 verbose = va_arg (*args, u32);
1014 tls_ctx_t *ctx;
1015
1016 ctx = tls_ctx_get_w_thread (ctx_index, thread_index);
1017 if (!ctx)
1018 return s;
1019
1020 s = format (s, "%-50U", format_tls_ctx, ctx, thread_index);
1021 if (verbose)
1022 {
1023 s = format (s, "%-15s", "state");
1024 if (verbose > 1)
1025 s = format (s, "\n");
1026 }
1027 return s;
1028}
1029
1030u8 *
1031format_tls_listener (u8 * s, va_list * args)
1032{
1033 u32 tc_index = va_arg (*args, u32);
1034 tls_ctx_t *ctx = tls_listener_ctx_get (tc_index);
1035 u32 listener_index, type;
1036
1037 listen_session_parse_handle (ctx->tls_session_handle, &type,
1038 &listener_index);
1039 return format (s, "[TLS] listener app %u child %u", ctx->parent_app_index,
1040 listener_index);
1041}
1042
1043u8 *
1044format_tls_half_open (u8 * s, va_list * args)
1045{
1046 u32 tc_index = va_arg (*args, u32);
1047 tls_ctx_t *ctx = tls_ctx_half_open_get (tc_index);
1048 s = format (s, "[TLS] half-open app %u", ctx->parent_app_index);
1049 tls_ctx_half_open_reader_unlock ();
1050 return s;
1051}
1052
1053/* *INDENT-OFF* */
1054const static transport_proto_vft_t tls_proto = {
1055 .open = tls_connect,
1056 .close = tls_disconnect,
1057 .bind = tls_start_listen,
1058 .get_listener = tls_listener_get,
1059 .unbind = tls_stop_listen,
1060 .tx_type = TRANSPORT_TX_INTERNAL,
1061 .service_type = TRANSPORT_SERVICE_APP,
1062 .format_connection = format_tls_connection,
1063 .format_half_open = format_tls_half_open,
1064 .format_listener = format_tls_listener,
1065};
1066/* *INDENT-ON* */
1067
1068int
1069tls_init_mem (void)
1070{
1071#if TLS_USE_OUR_MEM_FUNCS
1072 mbedtls_platform_set_calloc_free (mbedtls_calloc_fn, mbedtls_free_fn);
1073#endif
1074 return 0;
1075}
1076
1077int
1078tls_init_ca_chain (void)
1079{
1080 tls_main_t *tm = &tls_main;
1081 int rv;
1082
1083 /* TODO config */
1084 mbedtls_x509_crt_init (&tm->cacert);
1085 rv = mbedtls_x509_crt_parse (&tm->cacert,
1086 (const unsigned char *) mbedtls_test_cas_pem,
1087 mbedtls_test_cas_pem_len);
1088 if (rv < 0)
1089 {
1090 clib_warning ("mbedtls_x509_crt_parse returned -0x%x", -rv);
1091 return -1;
1092 }
1093 return 0;
1094}
1095
1096clib_error_t *
1097tls_init (vlib_main_t * vm)
1098{
1099 vlib_thread_main_t *vtm = vlib_get_thread_main ();
1100 u32 fifo_size = 64 << 10, num_threads;
1101 vnet_app_attach_args_t _a, *a = &_a;
1102 u64 options[APP_OPTIONS_N_OPTIONS];
1103 u32 segment_size = 512 << 20;
1104 tls_main_t *tm = &tls_main;
1105
1106 num_threads = 1 /* main thread */ + vtm->n_threads;
1107
1108 if (tls_init_mem ())
1109 {
1110 clib_warning ("failed to initialize mem");
1111 return clib_error_return (0, "failed to initalize mem");
1112 }
1113 if (tls_init_ca_chain ())
1114 {
1115 clib_warning ("failed to initialize TLS CA chain");
1116 return clib_error_return (0, "failed to initalize TLS CA chain");
1117 }
1118 if (tls_init_ctr_drbgs_and_entropy (num_threads))
1119 {
1120 clib_warning ("failed to initialize entropy and random generators");
1121 return clib_error_return (0, "failed to initialize entropy and random "
1122 "generators");
1123 }
1124
1125 memset (a, 0, sizeof (*a));
1126 memset (options, 0, sizeof (options));
1127
1128 a->session_cb_vft = &tls_app_cb_vft;
1129 a->api_client_index = (1 << 24) + 1;
1130 a->options = options;
1131 a->options[APP_OPTIONS_SEGMENT_SIZE] = segment_size;
1132 a->options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
1133 a->options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
1134 a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1135 a->options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1136
1137 if (vnet_application_attach (a))
1138 {
1139 clib_warning ("failed to attach tls app");
1140 return clib_error_return (0, "failed to attach tls app");
1141 }
1142
1143 tm->app_index = a->app_index;
1144 vec_validate (tm->ctx_pool, num_threads - 1);
1145 clib_rwlock_init (&tm->half_open_rwlock);
1146
1147 transport_register_protocol (TRANSPORT_PROTO_TLS, &tls_proto,
1148 FIB_PROTOCOL_IP4, ~0);
1149 transport_register_protocol (TRANSPORT_PROTO_TLS, &tls_proto,
1150 FIB_PROTOCOL_IP6, ~0);
1151
1152 return 0;
1153}
1154
1155VLIB_INIT_FUNCTION (tls_init);
1156
1157/*
1158 * fd.io coding-style-patch-verification: ON
1159 *
1160 * Local Variables:
1161 * eval: (c-set-style "gnu")
1162 * End:
1163 */