plugins: clean up plugin descriptions
[vpp.git] / src / plugins / tlsmbedtls / tls_mbedtls.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 <mbedtls/ssl.h>
17 #include <mbedtls/certs.h>
18 #include <mbedtls/entropy.h>
19 #include <mbedtls/ctr_drbg.h>
20 #include <mbedtls/timing.h>
21 #include <mbedtls/debug.h>
22 #include <vnet/plugin/plugin.h>
23 #include <vpp/app/version.h>
24 #include <vnet/tls/tls.h>
25
26 #define TLS_USE_OUR_MEM_FUNCS   0
27
28 typedef struct tls_ctx_mbedtls_
29 {
30   tls_ctx_t ctx;                        /**< First */
31   u32 mbedtls_ctx_index;
32   mbedtls_ssl_context ssl;
33   mbedtls_ssl_config conf;
34   mbedtls_x509_crt srvcert;
35   mbedtls_pk_context pkey;
36 } mbedtls_ctx_t;
37
38 typedef struct mbedtls_main_
39 {
40   mbedtls_ctx_t ***ctx_pool;
41   mbedtls_ctr_drbg_context *ctr_drbgs;
42   mbedtls_entropy_context *entropy_pools;
43   mbedtls_x509_crt cacert;
44   u8 **rx_bufs;
45   u8 **tx_bufs;
46 } mbedtls_main_t;
47
48 static mbedtls_main_t mbedtls_main;
49
50 #if TLS_USE_OUR_MEM_FUNCS
51 #include <mbedtls/platform.h>
52
53 void *
54 mbedtls_calloc_fn (size_t n, size_t size)
55 {
56   void *ptr;
57   ptr = clib_mem_alloc (n * size);
58   clib_memset (ptr, 0, sizeof (*ptr));
59   return ptr;
60 }
61
62 void
63 mbedtls_free_fn (void *ptr)
64 {
65   if (ptr)
66     clib_mem_free (ptr);
67 }
68 #endif
69
70 static u32
71 mbedtls_ctx_alloc (void)
72 {
73   u8 thread_index = vlib_get_thread_index ();
74   mbedtls_main_t *tm = &mbedtls_main;
75   mbedtls_ctx_t **ctx;
76
77   pool_get (tm->ctx_pool[thread_index], ctx);
78   if (!(*ctx))
79     *ctx = clib_mem_alloc (sizeof (mbedtls_ctx_t));
80
81   clib_memset (*ctx, 0, sizeof (mbedtls_ctx_t));
82   (*ctx)->ctx.c_thread_index = thread_index;
83   (*ctx)->ctx.tls_ctx_engine = TLS_ENGINE_MBEDTLS;
84   (*ctx)->mbedtls_ctx_index = ctx - tm->ctx_pool[thread_index];
85   return ((*ctx)->mbedtls_ctx_index);
86 }
87
88 static void
89 mbedtls_ctx_free (tls_ctx_t * ctx)
90 {
91   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
92
93   if (mc->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER && !ctx->is_passive_close)
94     mbedtls_ssl_close_notify (&mc->ssl);
95   if (mc->ssl.conf->endpoint == MBEDTLS_SSL_IS_SERVER)
96     {
97       mbedtls_x509_crt_free (&mc->srvcert);
98       mbedtls_pk_free (&mc->pkey);
99     }
100   mbedtls_ssl_free (&mc->ssl);
101   mbedtls_ssl_config_free (&mc->conf);
102
103   vec_free (ctx->srv_hostname);
104   pool_put_index (mbedtls_main.ctx_pool[ctx->c_thread_index],
105                   mc->mbedtls_ctx_index);
106 }
107
108 static tls_ctx_t *
109 mbedtls_ctx_get (u32 ctx_index)
110 {
111   mbedtls_ctx_t **ctx;
112   ctx = pool_elt_at_index (mbedtls_main.ctx_pool[vlib_get_thread_index ()],
113                            ctx_index);
114   return &(*ctx)->ctx;
115 }
116
117 static tls_ctx_t *
118 mbedtls_ctx_get_w_thread (u32 ctx_index, u8 thread_index)
119 {
120   mbedtls_ctx_t **ctx;
121   ctx = pool_elt_at_index (mbedtls_main.ctx_pool[thread_index], ctx_index);
122   return &(*ctx)->ctx;
123 }
124
125 static int
126 tls_init_ctr_seed_drbgs (void)
127 {
128   u32 thread_index = vlib_get_thread_index ();
129   mbedtls_main_t *tm = &mbedtls_main;
130   u8 *pers;
131   int rv;
132   pers = format (0, "vpp thread %u", thread_index);
133
134   mbedtls_entropy_init (&tm->entropy_pools[thread_index]);
135   mbedtls_ctr_drbg_init (&mbedtls_main.ctr_drbgs[thread_index]);
136   if ((rv = mbedtls_ctr_drbg_seed (&tm->ctr_drbgs[thread_index],
137                                    mbedtls_entropy_func,
138                                    &tm->entropy_pools[thread_index],
139                                    (const unsigned char *) pers,
140                                    vec_len (pers))) != 0)
141     {
142       vec_free (pers);
143       TLS_DBG (1, " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", rv);
144       return -1;
145     }
146   vec_free (pers);
147   return 0;
148 }
149
150 mbedtls_ctr_drbg_context *
151 tls_get_ctr_drbg ()
152 {
153   u8 thread_index = vlib_get_thread_index ();
154   if (PREDICT_FALSE (!mbedtls_main.ctr_drbgs[thread_index].f_entropy))
155     tls_init_ctr_seed_drbgs ();
156   return &mbedtls_main.ctr_drbgs[thread_index];
157 }
158
159 static int
160 tls_net_send (void *ctx_indexp, const unsigned char *buf, size_t len)
161 {
162   session_t *tls_session;
163   uword ctx_index;
164   tls_ctx_t *ctx;
165   int rv;
166
167   ctx_index = pointer_to_uword (ctx_indexp);
168   ctx = mbedtls_ctx_get (ctx_index);
169   tls_session = session_get_from_handle (ctx->tls_session_handle);
170   rv = svm_fifo_enqueue (tls_session->tx_fifo, len, buf);
171   if (rv < 0)
172     return MBEDTLS_ERR_SSL_WANT_WRITE;
173   tls_add_vpp_q_tx_evt (tls_session);
174   return rv;
175 }
176
177 static int
178 tls_net_recv (void *ctx_indexp, unsigned char *buf, size_t len)
179 {
180   session_t *tls_session;
181   uword ctx_index;
182   tls_ctx_t *ctx;
183   int rv;
184
185   ctx_index = pointer_to_uword (ctx_indexp);
186   ctx = mbedtls_ctx_get (ctx_index);
187   tls_session = session_get_from_handle (ctx->tls_session_handle);
188   rv = svm_fifo_dequeue (tls_session->rx_fifo, len, buf);
189   return (rv < 0) ? 0 : rv;
190 }
191
192 static void
193 mbedtls_debug (void *ctx, int level, const char *file, int line,
194                const char *str)
195 {
196   ((void) level);
197   fprintf ((FILE *) ctx, "%s:%04d: %s", file, line, str);
198   fflush ((FILE *) ctx);
199 }
200
201 static int
202 mbedtls_ctx_init_client (tls_ctx_t * ctx)
203 {
204   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
205   mbedtls_main_t *mm = &mbedtls_main;
206   void *ctx_ptr;
207   int rv;
208
209   /*
210    * 1. Setup SSL
211    */
212   mbedtls_ssl_init (&mc->ssl);
213   mbedtls_ssl_config_init (&mc->conf);
214   if ((rv = mbedtls_ssl_config_defaults (&mc->conf, MBEDTLS_SSL_IS_CLIENT,
215                                          MBEDTLS_SSL_TRANSPORT_STREAM,
216                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
217     {
218       TLS_DBG (1, "failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n",
219                rv);
220       return -1;
221     }
222
223   mbedtls_ssl_conf_authmode (&mc->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
224   mbedtls_ssl_conf_ca_chain (&mc->conf, &mm->cacert, NULL);
225   mbedtls_ssl_conf_rng (&mc->conf, mbedtls_ctr_drbg_random,
226                         tls_get_ctr_drbg ());
227   mbedtls_ssl_conf_dbg (&mc->conf, mbedtls_debug, stdout);
228
229   if ((rv = mbedtls_ssl_setup (&mc->ssl, &mc->conf)) != 0)
230     {
231       TLS_DBG (1, "failed\n  ! mbedtls_ssl_setup returned %d\n", rv);
232       return -1;
233     }
234
235   if ((rv = mbedtls_ssl_set_hostname (&mc->ssl,
236                                       (const char *) ctx->srv_hostname)) != 0)
237     {
238       TLS_DBG (1, "failed\n  ! mbedtls_ssl_set_hostname returned %d\n", rv);
239       return -1;
240     }
241
242   ctx_ptr = uword_to_pointer (mc->mbedtls_ctx_index, void *);
243   mbedtls_ssl_set_bio (&mc->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
244   mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_CLIENT);
245
246   /*
247    * 2. Do the first 2 steps in the handshake.
248    */
249   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
250            mc->mbedtls_ctx_index);
251   while (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
252     {
253       rv = mbedtls_ssl_handshake_step (&mc->ssl);
254       if (rv != 0)
255         break;
256     }
257   TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
258            mc->mbedtls_ctx_index, mc->ssl.state);
259   return 0;
260 }
261
262 static int
263 mbedtls_start_listen (tls_ctx_t * lctx)
264 {
265   return 0;
266 }
267
268 static int
269 mbedtls_stop_listen (tls_ctx_t * lctx)
270 {
271   return 0;
272 }
273
274 static int
275 mbedtls_ctx_init_server (tls_ctx_t * ctx)
276 {
277   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
278   mbedtls_main_t *mm = &mbedtls_main;
279   app_worker_t *app_wrk;
280   application_t *app;
281   void *ctx_ptr;
282   int rv;
283
284   mbedtls_ssl_init (&mc->ssl);
285   mbedtls_ssl_config_init (&mc->conf);
286   mbedtls_x509_crt_init (&mc->srvcert);
287   mbedtls_pk_init (&mc->pkey);
288
289   /*
290    * 1. Cert
291    */
292   app_wrk = app_worker_get (ctx->parent_app_wrk_index);
293   if (!app_wrk)
294     return -1;
295
296   app = application_get (app_wrk->app_index);
297   if (!app->tls_cert || !app->tls_key)
298     {
299       TLS_DBG (1, " failed\n  ! tls cert and/or key not configured %d",
300                ctx->parent_app_wrk_index);
301       return -1;
302     }
303
304   rv = mbedtls_x509_crt_parse (&mc->srvcert,
305                                (const unsigned char *) app->tls_cert,
306                                vec_len (app->tls_cert));
307   if (rv != 0)
308     {
309       TLS_DBG (1, " failed\n  !  mbedtls_x509_crt_parse returned %d", rv);
310       goto exit;
311     }
312
313   rv = mbedtls_pk_parse_key (&mc->pkey,
314                              (const unsigned char *) app->tls_key,
315                              vec_len (app->tls_key), NULL, 0);
316   if (rv != 0)
317     {
318       TLS_DBG (1, " failed\n  !  mbedtls_pk_parse_key returned %d", rv);
319       goto exit;
320     }
321
322   /*
323    * 2. SSL context config
324    */
325   if ((rv = mbedtls_ssl_config_defaults (&mc->conf, MBEDTLS_SSL_IS_SERVER,
326                                          MBEDTLS_SSL_TRANSPORT_STREAM,
327                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
328     {
329       TLS_DBG (1, " failed\n  ! mbedtls_ssl_config_defaults returned %d", rv);
330       goto exit;
331     }
332
333   mbedtls_ssl_conf_rng (&mc->conf, mbedtls_ctr_drbg_random,
334                         tls_get_ctr_drbg ());
335   mbedtls_ssl_conf_dbg (&mc->conf, mbedtls_debug, stdout);
336
337   /* TODO CACHE
338      mbedtls_ssl_conf_session_cache( &ctx->conf, &cache,
339      mbedtls_ssl_cache_get,
340      mbedtls_ssl_cache_set );
341    */
342
343   mbedtls_ssl_conf_ca_chain (&mc->conf, &mm->cacert, NULL);
344   if ((rv = mbedtls_ssl_conf_own_cert (&mc->conf, &mc->srvcert, &mc->pkey))
345       != 0)
346     {
347       TLS_DBG (1, " failed\n  ! mbedtls_ssl_conf_own_cert returned %d", rv);
348       goto exit;
349     }
350
351   if ((rv = mbedtls_ssl_setup (&mc->ssl, &mc->conf)) != 0)
352     {
353       TLS_DBG (1, " failed\n  ! mbedtls_ssl_setup returned %d", rv);
354       goto exit;
355     }
356
357   mbedtls_ssl_session_reset (&mc->ssl);
358   ctx_ptr = uword_to_pointer (mc->mbedtls_ctx_index, void *);
359   mbedtls_ssl_set_bio (&mc->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
360   mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_SERVER);
361
362   /*
363    * 3. Start handshake state machine
364    */
365   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
366            mc->mbedtls_ctx_index);
367   while (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
368     {
369       rv = mbedtls_ssl_handshake_step (&mc->ssl);
370       if (rv != 0)
371         break;
372     }
373
374   TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
375            mc->mbedtls_ctx_index, mc->ssl.state);
376   return 0;
377
378 exit:
379   return -1;
380 }
381
382 static int
383 mbedtls_ctx_handshake_rx (tls_ctx_t * ctx)
384 {
385   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
386   u32 flags;
387   int rv;
388   while (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
389     {
390       rv = mbedtls_ssl_handshake_step (&mc->ssl);
391       if (rv != 0)
392         break;
393     }
394   TLS_DBG (2, "tls state for %u is %u", mc->mbedtls_ctx_index, mc->ssl.state);
395
396   if (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
397     return 0;
398
399   /*
400    * Handshake complete
401    */
402   if (mc->ssl.conf->endpoint == MBEDTLS_SSL_IS_CLIENT)
403     {
404       /*
405        * Verify server certificate
406        */
407       if ((flags = mbedtls_ssl_get_verify_result (&mc->ssl)) != 0)
408         {
409           char buf[512];
410           TLS_DBG (1, " failed\n");
411           mbedtls_x509_crt_verify_info (buf, sizeof (buf), "  ! ", flags);
412           TLS_DBG (1, "%s\n", buf);
413
414           /*
415            * Presence of hostname enforces strict certificate verification
416            */
417           if (ctx->srv_hostname)
418             {
419               tls_notify_app_connected (ctx, /* is failed */ 0);
420               return -1;
421             }
422         }
423       tls_notify_app_connected (ctx, /* is failed */ 0);
424     }
425   else
426     {
427       tls_notify_app_accept (ctx);
428     }
429
430   TLS_DBG (1, "Handshake for %u complete. TLS cipher is %x",
431            mc->mbedtls_ctx_index, mc->ssl.session->ciphersuite);
432   return 0;
433 }
434
435 static int
436 mbedtls_ctx_write (tls_ctx_t * ctx, session_t * app_session)
437 {
438   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
439   u8 thread_index = ctx->c_thread_index;
440   mbedtls_main_t *mm = &mbedtls_main;
441   u32 enq_max, deq_max, deq_now;
442   session_t *tls_session;
443   int wrote;
444
445   ASSERT (mc->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
446
447   deq_max = svm_fifo_max_dequeue_cons (app_session->tx_fifo);
448   if (!deq_max)
449     return 0;
450
451   tls_session = session_get_from_handle (ctx->tls_session_handle);
452   enq_max = svm_fifo_max_enqueue_prod (tls_session->tx_fifo);
453   deq_now = clib_min (deq_max, TLS_CHUNK_SIZE);
454
455   if (PREDICT_FALSE (enq_max == 0))
456     {
457       tls_add_vpp_q_builtin_tx_evt (app_session);
458       return 0;
459     }
460
461   vec_validate (mm->tx_bufs[thread_index], deq_now);
462   svm_fifo_peek (app_session->tx_fifo, 0, deq_now, mm->tx_bufs[thread_index]);
463
464   wrote = mbedtls_ssl_write (&mc->ssl, mm->tx_bufs[thread_index], deq_now);
465   if (wrote <= 0)
466     {
467       tls_add_vpp_q_builtin_tx_evt (app_session);
468       return 0;
469     }
470
471   svm_fifo_dequeue_drop (app_session->tx_fifo, wrote);
472   vec_reset_length (mm->tx_bufs[thread_index]);
473   tls_add_vpp_q_tx_evt (tls_session);
474
475   if (deq_now < deq_max)
476     tls_add_vpp_q_builtin_tx_evt (app_session);
477
478   return 0;
479 }
480
481 static int
482 mbedtls_ctx_read (tls_ctx_t * ctx, session_t * tls_session)
483 {
484   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
485   mbedtls_main_t *mm = &mbedtls_main;
486   u8 thread_index = ctx->c_thread_index;
487   u32 deq_max, enq_max, enq_now;
488   session_t *app_session;
489   int read, enq;
490
491   if (PREDICT_FALSE (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER))
492     {
493       mbedtls_ctx_handshake_rx (ctx);
494       return 0;
495     }
496
497   deq_max = svm_fifo_max_dequeue_cons (tls_session->rx_fifo);
498   if (!deq_max)
499     return 0;
500
501   app_session = session_get_from_handle (ctx->app_session_handle);
502   enq_max = svm_fifo_max_enqueue_prod (app_session->rx_fifo);
503   enq_now = clib_min (enq_max, TLS_CHUNK_SIZE);
504
505   if (PREDICT_FALSE (enq_now == 0))
506     {
507       tls_add_vpp_q_builtin_rx_evt (tls_session);
508       return 0;
509     }
510
511   vec_validate (mm->rx_bufs[thread_index], enq_now);
512   read = mbedtls_ssl_read (&mc->ssl, mm->rx_bufs[thread_index], enq_now);
513   if (read <= 0)
514     {
515       tls_add_vpp_q_builtin_rx_evt (tls_session);
516       return 0;
517     }
518
519   enq = svm_fifo_enqueue (app_session->rx_fifo, read,
520                           mm->rx_bufs[thread_index]);
521   ASSERT (enq == read);
522   vec_reset_length (mm->rx_bufs[thread_index]);
523
524   if (svm_fifo_max_dequeue_cons (tls_session->rx_fifo))
525     tls_add_vpp_q_builtin_rx_evt (tls_session);
526
527   if (enq > 0)
528     tls_notify_app_enqueue (ctx, app_session);
529
530   return enq;
531 }
532
533 static u8
534 mbedtls_handshake_is_over (tls_ctx_t * ctx)
535 {
536   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
537   return (mc->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
538 }
539
540 static int
541 mbedtls_transport_close (tls_ctx_t * ctx)
542 {
543   if (!mbedtls_handshake_is_over (ctx))
544     {
545       session_close (session_get_from_handle (ctx->tls_session_handle));
546       return 0;
547     }
548   session_transport_closing_notify (&ctx->connection);
549   return 0;
550 }
551
552 static int
553 mbedtls_app_close (tls_ctx_t * ctx)
554 {
555   tls_disconnect_transport (ctx);
556   session_transport_delete_notify (&ctx->connection);
557   mbedtls_ctx_free (ctx);
558   return 0;
559 }
560
561 const static tls_engine_vft_t mbedtls_engine = {
562   .ctx_alloc = mbedtls_ctx_alloc,
563   .ctx_free = mbedtls_ctx_free,
564   .ctx_get = mbedtls_ctx_get,
565   .ctx_get_w_thread = mbedtls_ctx_get_w_thread,
566   .ctx_init_server = mbedtls_ctx_init_server,
567   .ctx_init_client = mbedtls_ctx_init_client,
568   .ctx_write = mbedtls_ctx_write,
569   .ctx_read = mbedtls_ctx_read,
570   .ctx_handshake_is_over = mbedtls_handshake_is_over,
571   .ctx_start_listen = mbedtls_start_listen,
572   .ctx_stop_listen = mbedtls_stop_listen,
573   .ctx_transport_close = mbedtls_transport_close,
574   .ctx_app_close = mbedtls_app_close,
575 };
576
577 int
578 tls_init_mem (void)
579 {
580 #if TLS_USE_OUR_MEM_FUNCS
581   mbedtls_platform_set_calloc_free (mbedtls_calloc_fn, mbedtls_free_fn);
582 #endif
583   return 0;
584 }
585
586 static int
587 tls_init_ctr_drbgs_and_entropy (u32 num_threads)
588 {
589   mbedtls_main_t *mm = &mbedtls_main;
590   int i;
591
592   vec_validate (mm->ctr_drbgs, num_threads - 1);
593   vec_validate (mm->entropy_pools, num_threads - 1);
594   for (i = 0; i < num_threads; i++)
595     mm->ctr_drbgs[i].f_entropy = 0;
596
597   return 0;
598 }
599
600 int
601 tls_init_ca_chain (void)
602 {
603   mbedtls_main_t *mm = &mbedtls_main;
604   tls_main_t *tm = vnet_tls_get_main ();
605   int rv;
606
607   if (access (tm->ca_cert_path, F_OK | R_OK) == -1)
608     {
609       clib_warning ("Could not initialize TLS CA certificates");
610       return -1;
611     }
612
613   mbedtls_x509_crt_init (&mm->cacert);
614   rv = mbedtls_x509_crt_parse_file (&mm->cacert, tm->ca_cert_path);
615   if (rv < 0)
616     {
617       clib_warning ("Couldn't parse system CA certificates: -0x%x", -rv);
618     }
619   if (tm->use_test_cert_in_ca)
620     {
621       rv = mbedtls_x509_crt_parse (&mm->cacert,
622                                    (const unsigned char *) test_srv_crt_rsa,
623                                    test_srv_crt_rsa_len);
624       if (rv < 0)
625         {
626           clib_warning ("Couldn't parse test certificate: -0x%x", -rv);
627           return -1;
628         }
629     }
630   return (rv < 0 ? -1 : 0);
631 }
632
633 static clib_error_t *
634 tls_mbedtls_init (vlib_main_t * vm)
635 {
636   vlib_thread_main_t *vtm = vlib_get_thread_main ();
637   mbedtls_main_t *mm = &mbedtls_main;
638   clib_error_t *error;
639   u32 num_threads;
640
641   num_threads = 1 /* main thread */  + vtm->n_threads;
642
643   if ((error = vlib_call_init_function (vm, tls_init)))
644     return error;
645
646   if (tls_init_ca_chain ())
647     {
648       clib_warning ("failed to initialize TLS CA chain");
649       return 0;
650     }
651   if (tls_init_mem ())
652     {
653       clib_warning ("failed to initialize mem");
654       return 0;
655     }
656   if (tls_init_ctr_drbgs_and_entropy (num_threads))
657     {
658       clib_warning ("failed to initialize entropy and random generators");
659       return 0;
660     }
661
662   vec_validate (mm->ctx_pool, num_threads - 1);
663   vec_validate (mm->rx_bufs, num_threads - 1);
664   vec_validate (mm->tx_bufs, num_threads - 1);
665
666   tls_register_engine (&mbedtls_engine, TLS_ENGINE_MBEDTLS);
667   return 0;
668 }
669
670 VLIB_INIT_FUNCTION (tls_mbedtls_init);
671
672 /* *INDENT-OFF* */
673 VLIB_PLUGIN_REGISTER () = {
674     .version = VPP_BUILD_VER,
675     .description = "Transport Layer Security (TLS) Engine, Mbedtls Based",
676 };
677 /* *INDENT-ON* */
678
679 /*
680  * fd.io coding-style-patch-verification: ON
681  *
682  * Local Variables:
683  * eval: (c-set-style "gnu")
684  * End:
685  */