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