udp: fix csum computation when offload disabled
[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 &&
95       !(ctx->flags & TLS_CONN_F_PASSIVE_CLOSE))
96     mbedtls_ssl_close_notify (&mc->ssl);
97   if (mc->ssl.conf->endpoint == MBEDTLS_SSL_IS_SERVER)
98     {
99       mbedtls_x509_crt_free (&mc->srvcert);
100       mbedtls_pk_free (&mc->pkey);
101     }
102   mbedtls_ssl_free (&mc->ssl);
103   mbedtls_ssl_config_free (&mc->conf);
104
105   vec_free (ctx->srv_hostname);
106   pool_put_index (mbedtls_main.ctx_pool[ctx->c_thread_index],
107                   mc->mbedtls_ctx_index);
108 }
109
110 static tls_ctx_t *
111 mbedtls_ctx_get (u32 ctx_index)
112 {
113   mbedtls_ctx_t **ctx;
114   ctx = pool_elt_at_index (mbedtls_main.ctx_pool[vlib_get_thread_index ()],
115                            ctx_index);
116   return &(*ctx)->ctx;
117 }
118
119 static tls_ctx_t *
120 mbedtls_ctx_get_w_thread (u32 ctx_index, u8 thread_index)
121 {
122   mbedtls_ctx_t **ctx;
123   ctx = pool_elt_at_index (mbedtls_main.ctx_pool[thread_index], ctx_index);
124   return &(*ctx)->ctx;
125 }
126
127 static int
128 tls_init_ctr_seed_drbgs (void)
129 {
130   u32 thread_index = vlib_get_thread_index ();
131   mbedtls_main_t *tm = &mbedtls_main;
132   u8 *pers;
133   int rv;
134   pers = format (0, "vpp thread %u", thread_index);
135
136   mbedtls_entropy_init (&tm->entropy_pools[thread_index]);
137   mbedtls_ctr_drbg_init (&mbedtls_main.ctr_drbgs[thread_index]);
138   if ((rv = mbedtls_ctr_drbg_seed (&tm->ctr_drbgs[thread_index],
139                                    mbedtls_entropy_func,
140                                    &tm->entropy_pools[thread_index],
141                                    (const unsigned char *) pers,
142                                    vec_len (pers))) != 0)
143     {
144       vec_free (pers);
145       TLS_DBG (1, " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", rv);
146       return -1;
147     }
148   vec_free (pers);
149   return 0;
150 }
151
152 mbedtls_ctr_drbg_context *
153 tls_get_ctr_drbg ()
154 {
155   u8 thread_index = vlib_get_thread_index ();
156   if (PREDICT_FALSE (!mbedtls_main.ctr_drbgs[thread_index].f_entropy))
157     tls_init_ctr_seed_drbgs ();
158   return &mbedtls_main.ctr_drbgs[thread_index];
159 }
160
161 static int
162 tls_net_send (void *ctx_indexp, const unsigned char *buf, size_t len)
163 {
164   session_t *tls_session;
165   uword ctx_index;
166   tls_ctx_t *ctx;
167   int rv;
168
169   ctx_index = pointer_to_uword (ctx_indexp);
170   ctx = mbedtls_ctx_get (ctx_index);
171   tls_session = session_get_from_handle (ctx->tls_session_handle);
172   rv = svm_fifo_enqueue (tls_session->tx_fifo, len, buf);
173   if (rv < 0)
174     return MBEDTLS_ERR_SSL_WANT_WRITE;
175   tls_add_vpp_q_tx_evt (tls_session);
176   return rv;
177 }
178
179 static int
180 tls_net_recv (void *ctx_indexp, unsigned char *buf, size_t len)
181 {
182   session_t *tls_session;
183   uword ctx_index;
184   tls_ctx_t *ctx;
185   int rv;
186
187   ctx_index = pointer_to_uword (ctx_indexp);
188   ctx = mbedtls_ctx_get (ctx_index);
189   tls_session = session_get_from_handle (ctx->tls_session_handle);
190   rv = svm_fifo_dequeue (tls_session->rx_fifo, len, buf);
191   return (rv < 0) ? 0 : rv;
192 }
193
194 static void
195 mbedtls_debug (void *ctx, int level, const char *file, int line,
196                const char *str)
197 {
198   ((void) level);
199   fprintf ((FILE *) ctx, "%s:%04d: %s", file, line, str);
200   fflush ((FILE *) ctx);
201 }
202
203 static int
204 mbedtls_ctx_init_client (tls_ctx_t * ctx)
205 {
206   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
207   mbedtls_main_t *mm = &mbedtls_main;
208   void *ctx_ptr;
209   int rv;
210
211   /*
212    * 1. Setup SSL
213    */
214   mbedtls_ssl_init (&mc->ssl);
215   mbedtls_ssl_config_init (&mc->conf);
216   if ((rv = mbedtls_ssl_config_defaults (&mc->conf, MBEDTLS_SSL_IS_CLIENT,
217                                          MBEDTLS_SSL_TRANSPORT_STREAM,
218                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
219     {
220       TLS_DBG (1, "failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n",
221                rv);
222       return -1;
223     }
224
225   mbedtls_ssl_conf_authmode (&mc->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
226   mbedtls_ssl_conf_ca_chain (&mc->conf, &mm->cacert, NULL);
227   mbedtls_ssl_conf_rng (&mc->conf, mbedtls_ctr_drbg_random,
228                         tls_get_ctr_drbg ());
229   mbedtls_ssl_conf_dbg (&mc->conf, mbedtls_debug, stdout);
230
231   if ((rv = mbedtls_ssl_setup (&mc->ssl, &mc->conf)) != 0)
232     {
233       TLS_DBG (1, "failed\n  ! mbedtls_ssl_setup returned %d\n", rv);
234       return -1;
235     }
236
237   if ((rv = mbedtls_ssl_set_hostname (&mc->ssl,
238                                       (const char *) ctx->srv_hostname)) != 0)
239     {
240       TLS_DBG (1, "failed\n  ! mbedtls_ssl_set_hostname returned %d\n", rv);
241       return -1;
242     }
243
244   ctx_ptr = uword_to_pointer (mc->mbedtls_ctx_index, void *);
245   mbedtls_ssl_set_bio (&mc->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
246   mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_CLIENT);
247
248   /*
249    * 2. Do the first 2 steps in the handshake.
250    */
251   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
252            mc->mbedtls_ctx_index);
253   while (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
254     {
255       rv = mbedtls_ssl_handshake_step (&mc->ssl);
256       if (rv != 0)
257         break;
258     }
259   TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
260            mc->mbedtls_ctx_index, mc->ssl.state);
261   return 0;
262 }
263
264 static int
265 mbedtls_start_listen (tls_ctx_t * lctx)
266 {
267   return 0;
268 }
269
270 static int
271 mbedtls_stop_listen (tls_ctx_t * lctx)
272 {
273   return 0;
274 }
275
276 static int
277 mbedtls_ctx_init_server (tls_ctx_t * ctx)
278 {
279   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
280   mbedtls_main_t *mm = &mbedtls_main;
281   app_cert_key_pair_t *ckpair;
282   void *ctx_ptr;
283   int rv;
284
285   mbedtls_ssl_init (&mc->ssl);
286   mbedtls_ssl_config_init (&mc->conf);
287   mbedtls_x509_crt_init (&mc->srvcert);
288   mbedtls_pk_init (&mc->pkey);
289
290   /*
291    * 1. Cert
292    */
293   ckpair = app_cert_key_pair_get_if_valid (ctx->ckpair_index);
294   if (!ckpair)
295     return -1;
296
297   if (!ckpair->cert || !ckpair->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 *) ckpair->cert,
306                                vec_len (ckpair->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 *) ckpair->key,
315                              vec_len (ckpair->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, SESSION_E_TLS_HANDSHAKE);
420               return -1;
421             }
422         }
423       tls_notify_app_connected (ctx, SESSION_E_NONE);
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                    transport_send_params_t * sp)
438 {
439   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
440   u8 thread_index = ctx->c_thread_index;
441   mbedtls_main_t *mm = &mbedtls_main;
442   u32 enq_max, deq_max, deq_now;
443   session_t *tls_session;
444   int wrote;
445
446   ASSERT (mc->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
447
448   deq_max = svm_fifo_max_dequeue_cons (app_session->tx_fifo);
449   if (!deq_max)
450     return 0;
451
452   deq_max = clib_min (deq_max, sp->max_burst_size);
453   tls_session = session_get_from_handle (ctx->tls_session_handle);
454   enq_max = svm_fifo_max_enqueue_prod (tls_session->tx_fifo);
455   deq_now = clib_min (deq_max, TLS_CHUNK_SIZE);
456
457   if (PREDICT_FALSE (enq_max == 0))
458     {
459       app_session->flags |= SESSION_F_CUSTOM_TX;
460       return 0;
461     }
462
463   vec_validate (mm->tx_bufs[thread_index], deq_now);
464   svm_fifo_peek (app_session->tx_fifo, 0, deq_now, mm->tx_bufs[thread_index]);
465
466   wrote = mbedtls_ssl_write (&mc->ssl, mm->tx_bufs[thread_index], deq_now);
467   if (wrote <= 0)
468     {
469       app_session->flags |= SESSION_F_CUSTOM_TX;
470       return 0;
471     }
472
473   svm_fifo_dequeue_drop (app_session->tx_fifo, wrote);
474   vec_reset_length (mm->tx_bufs[thread_index]);
475   tls_add_vpp_q_tx_evt (tls_session);
476
477   if (deq_now < deq_max)
478     app_session->flags |= SESSION_F_CUSTOM_TX;
479
480   return 0;
481 }
482
483 static int
484 mbedtls_ctx_read (tls_ctx_t * ctx, session_t * tls_session)
485 {
486   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
487   mbedtls_main_t *mm = &mbedtls_main;
488   u8 thread_index = ctx->c_thread_index;
489   u32 deq_max, enq_max, enq_now;
490   session_t *app_session;
491   int read, enq;
492
493   if (PREDICT_FALSE (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER))
494     {
495       mbedtls_ctx_handshake_rx (ctx);
496       return 0;
497     }
498
499   deq_max = svm_fifo_max_dequeue_cons (tls_session->rx_fifo);
500   if (!deq_max)
501     return 0;
502
503   app_session = session_get_from_handle (ctx->app_session_handle);
504   enq_max = svm_fifo_max_enqueue_prod (app_session->rx_fifo);
505   enq_now = clib_min (enq_max, TLS_CHUNK_SIZE);
506
507   if (PREDICT_FALSE (enq_now == 0))
508     {
509       tls_add_vpp_q_builtin_rx_evt (tls_session);
510       return 0;
511     }
512
513   vec_validate (mm->rx_bufs[thread_index], enq_now);
514   read = mbedtls_ssl_read (&mc->ssl, mm->rx_bufs[thread_index], enq_now);
515   if (read <= 0)
516     {
517       tls_add_vpp_q_builtin_rx_evt (tls_session);
518       return 0;
519     }
520
521   enq = svm_fifo_enqueue (app_session->rx_fifo, read,
522                           mm->rx_bufs[thread_index]);
523   ASSERT (enq == read);
524   vec_reset_length (mm->rx_bufs[thread_index]);
525
526   if (svm_fifo_max_dequeue_cons (tls_session->rx_fifo))
527     tls_add_vpp_q_builtin_rx_evt (tls_session);
528
529   if (enq > 0)
530     tls_notify_app_enqueue (ctx, app_session);
531
532   return enq;
533 }
534
535 static u8
536 mbedtls_handshake_is_over (tls_ctx_t * ctx)
537 {
538   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
539   return (mc->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
540 }
541
542 static int
543 mbedtls_transport_close (tls_ctx_t * ctx)
544 {
545   if (!mbedtls_handshake_is_over (ctx))
546     {
547       session_close (session_get_from_handle (ctx->tls_session_handle));
548       return 0;
549     }
550   session_transport_closing_notify (&ctx->connection);
551   return 0;
552 }
553
554 static int
555 mbedtls_transport_reset (tls_ctx_t *ctx)
556 {
557   if (!mbedtls_handshake_is_over (ctx))
558     {
559       session_close (session_get_from_handle (ctx->tls_session_handle));
560       return 0;
561     }
562
563   session_transport_reset_notify (&ctx->connection);
564   session_transport_closed_notify (&ctx->connection);
565   tls_disconnect_transport (ctx);
566   return 0;
567 }
568
569 static int
570 mbedtls_app_close (tls_ctx_t * ctx)
571 {
572   tls_disconnect_transport (ctx);
573   session_transport_delete_notify (&ctx->connection);
574   return 0;
575 }
576
577 static int
578 mbedtls_reinit_ca_chain (void)
579 {
580   /* Not supported Yet */
581   return 0;
582 }
583
584 const static tls_engine_vft_t mbedtls_engine = {
585   .ctx_alloc = mbedtls_ctx_alloc,
586   .ctx_free = mbedtls_ctx_free,
587   .ctx_get = mbedtls_ctx_get,
588   .ctx_get_w_thread = mbedtls_ctx_get_w_thread,
589   .ctx_init_server = mbedtls_ctx_init_server,
590   .ctx_init_client = mbedtls_ctx_init_client,
591   .ctx_write = mbedtls_ctx_write,
592   .ctx_read = mbedtls_ctx_read,
593   .ctx_handshake_is_over = mbedtls_handshake_is_over,
594   .ctx_start_listen = mbedtls_start_listen,
595   .ctx_stop_listen = mbedtls_stop_listen,
596   .ctx_transport_close = mbedtls_transport_close,
597   .ctx_transport_reset = mbedtls_transport_reset,
598   .ctx_app_close = mbedtls_app_close,
599   .ctx_reinit_cachain = mbedtls_reinit_ca_chain,
600 };
601
602 int
603 tls_init_mem (void)
604 {
605 #if TLS_USE_OUR_MEM_FUNCS
606   mbedtls_platform_set_calloc_free (mbedtls_calloc_fn, mbedtls_free_fn);
607 #endif
608   return 0;
609 }
610
611 static int
612 tls_init_ctr_drbgs_and_entropy (u32 num_threads)
613 {
614   mbedtls_main_t *mm = &mbedtls_main;
615   int i;
616
617   vec_validate (mm->ctr_drbgs, num_threads - 1);
618   vec_validate (mm->entropy_pools, num_threads - 1);
619   for (i = 0; i < num_threads; i++)
620     mm->ctr_drbgs[i].f_entropy = 0;
621
622   return 0;
623 }
624
625 int
626 tls_init_ca_chain (void)
627 {
628   mbedtls_main_t *mm = &mbedtls_main;
629   tls_main_t *tm = vnet_tls_get_main ();
630   int rv;
631
632   if (access (tm->ca_cert_path, F_OK | R_OK) == -1)
633     {
634       clib_warning ("Could not initialize TLS CA certificates");
635       return -1;
636     }
637
638   mbedtls_x509_crt_init (&mm->cacert);
639   rv = mbedtls_x509_crt_parse_file (&mm->cacert, tm->ca_cert_path);
640   if (rv < 0)
641     {
642       clib_warning ("Couldn't parse system CA certificates: -0x%x", -rv);
643     }
644   if (tm->use_test_cert_in_ca)
645     {
646       rv = mbedtls_x509_crt_parse (&mm->cacert,
647                                    (const unsigned char *) test_srv_crt_rsa,
648                                    test_srv_crt_rsa_len);
649       if (rv < 0)
650         {
651           clib_warning ("Couldn't parse test certificate: -0x%x", -rv);
652           return -1;
653         }
654     }
655   return (rv < 0 ? -1 : 0);
656 }
657
658 static clib_error_t *
659 tls_mbedtls_init (vlib_main_t * vm)
660 {
661   vlib_thread_main_t *vtm = vlib_get_thread_main ();
662   mbedtls_main_t *mm = &mbedtls_main;
663   u32 num_threads;
664
665   num_threads = 1 /* main thread */  + vtm->n_threads;
666
667   if (tls_init_ca_chain ())
668     {
669       clib_warning ("failed to initialize TLS CA chain");
670       return 0;
671     }
672   if (tls_init_mem ())
673     {
674       clib_warning ("failed to initialize mem");
675       return 0;
676     }
677   if (tls_init_ctr_drbgs_and_entropy (num_threads))
678     {
679       clib_warning ("failed to initialize entropy and random generators");
680       return 0;
681     }
682
683   vec_validate (mm->ctx_pool, num_threads - 1);
684   vec_validate (mm->rx_bufs, num_threads - 1);
685   vec_validate (mm->tx_bufs, num_threads - 1);
686
687   tls_register_engine (&mbedtls_engine, CRYPTO_ENGINE_MBEDTLS);
688   return 0;
689 }
690
691 VLIB_INIT_FUNCTION (tls_mbedtls_init) =
692 {
693   .runs_after = VLIB_INITS("tls_init"),
694 };
695
696 VLIB_PLUGIN_REGISTER () = {
697     .version = VPP_BUILD_VER,
698     .description = "Transport Layer Security (TLS) Engine, Mbedtls Based",
699 };
700
701 /*
702  * fd.io coding-style-patch-verification: ON
703  *
704  * Local Variables:
705  * eval: (c-set-style "gnu")
706  * End:
707  */