1bae1f726f84b634d67f20f9a5c972d02ca78ed9
[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   mbedtls_ssl_context ssl;
32   mbedtls_ssl_config conf;
33   mbedtls_x509_crt srvcert;
34   mbedtls_pk_context pkey;
35 } mbedtls_ctx_t;
36
37 typedef struct mbedtls_main_
38 {
39   mbedtls_ctx_t ***ctx_pool;
40   mbedtls_ctr_drbg_context *ctr_drbgs;
41   mbedtls_entropy_context *entropy_pools;
42   mbedtls_x509_crt cacert;
43 } mbedtls_main_t;
44
45 static mbedtls_main_t mbedtls_main;
46
47 #if TLS_USE_OUR_MEM_FUNCS
48 #include <mbedtls/platform.h>
49
50 void *
51 mbedtls_calloc_fn (size_t n, size_t size)
52 {
53   void *ptr;
54   ptr = clib_mem_alloc (n * size);
55   memset (ptr, 0, sizeof (*ptr));
56   return ptr;
57 }
58
59 void
60 mbedtls_free_fn (void *ptr)
61 {
62   if (ptr)
63     clib_mem_free (ptr);
64 }
65 #endif
66
67 u32
68 mbedtls_ctx_alloc (void)
69 {
70   u8 thread_index = vlib_get_thread_index ();
71   mbedtls_main_t *tm = &mbedtls_main;
72   mbedtls_ctx_t **ctx;
73
74   pool_get (tm->ctx_pool[thread_index], ctx);
75   if (!(*ctx))
76     *ctx = clib_mem_alloc (sizeof (mbedtls_ctx_t));
77
78   memset (*ctx, 0, sizeof (mbedtls_ctx_t));
79   (*ctx)->ctx.c_thread_index = thread_index;
80   return ctx - tm->ctx_pool[thread_index];
81 }
82
83 void
84 mbedtls_ctx_free (tls_ctx_t * ctx)
85 {
86   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
87
88   if (mc->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER && !ctx->is_passive_close)
89     mbedtls_ssl_close_notify (&mc->ssl);
90   if (mc->ssl.conf->endpoint == MBEDTLS_SSL_IS_SERVER)
91     {
92       mbedtls_x509_crt_free (&mc->srvcert);
93       mbedtls_pk_free (&mc->pkey);
94     }
95   mbedtls_ssl_free (&mc->ssl);
96   mbedtls_ssl_config_free (&mc->conf);
97
98   pool_put_index (mbedtls_main.ctx_pool[vlib_get_thread_index ()],
99                   ctx->tls_ctx_idx);
100 }
101
102 tls_ctx_t *
103 mbedtls_ctx_get (u32 ctx_index)
104 {
105   mbedtls_ctx_t **ctx;
106   ctx = pool_elt_at_index (mbedtls_main.ctx_pool[vlib_get_thread_index ()],
107                            ctx_index);
108   return &(*ctx)->ctx;
109 }
110
111 tls_ctx_t *
112 mbedtls_ctx_get_w_thread (u32 ctx_index, u8 thread_index)
113 {
114   mbedtls_ctx_t **ctx;
115   ctx = pool_elt_at_index (mbedtls_main.ctx_pool[thread_index], ctx_index);
116   return &(*ctx)->ctx;
117 }
118
119 static int
120 tls_init_ctr_seed_drbgs (void)
121 {
122   u32 thread_index = vlib_get_thread_index ();
123   mbedtls_main_t *tm = &mbedtls_main;
124   u8 *pers;
125   int rv;
126   pers = format (0, "vpp thread %u", thread_index);
127
128   mbedtls_entropy_init (&tm->entropy_pools[thread_index]);
129   mbedtls_ctr_drbg_init (&mbedtls_main.ctr_drbgs[thread_index]);
130   if ((rv = mbedtls_ctr_drbg_seed (&tm->ctr_drbgs[thread_index],
131                                    mbedtls_entropy_func,
132                                    &tm->entropy_pools[thread_index],
133                                    (const unsigned char *) pers,
134                                    vec_len (pers))) != 0)
135     {
136       vec_free (pers);
137       TLS_DBG (1, " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", rv);
138       return -1;
139     }
140   vec_free (pers);
141   return 0;
142 }
143
144 mbedtls_ctr_drbg_context *
145 tls_get_ctr_drbg ()
146 {
147   u8 thread_index = vlib_get_thread_index ();
148   if (PREDICT_FALSE (!mbedtls_main.ctr_drbgs[thread_index].f_entropy))
149     tls_init_ctr_seed_drbgs ();
150   return &mbedtls_main.ctr_drbgs[thread_index];
151 }
152
153 static int
154 tls_net_send (void *ctx_indexp, const unsigned char *buf, size_t len)
155 {
156   stream_session_t *tls_session;
157   uword ctx_index;
158   tls_ctx_t *ctx;
159   int rv;
160
161   ctx_index = pointer_to_uword (ctx_indexp);
162   ctx = mbedtls_ctx_get (ctx_index);
163   tls_session = session_get_from_handle (ctx->tls_session_handle);
164   rv = svm_fifo_enqueue_nowait (tls_session->server_tx_fifo, len, buf);
165   if (rv < 0)
166     return MBEDTLS_ERR_SSL_WANT_WRITE;
167   tls_add_vpp_q_evt (tls_session->server_tx_fifo, FIFO_EVENT_APP_TX);
168   return rv;
169 }
170
171 static int
172 tls_net_recv (void *ctx_indexp, unsigned char *buf, size_t len)
173 {
174   stream_session_t *tls_session;
175   uword ctx_index;
176   tls_ctx_t *ctx;
177   int rv;
178
179   ctx_index = pointer_to_uword (ctx_indexp);
180   ctx = mbedtls_ctx_get (ctx_index);
181   tls_session = session_get_from_handle (ctx->tls_session_handle);
182   rv = svm_fifo_dequeue_nowait (tls_session->server_rx_fifo, len, buf);
183   return (rv < 0) ? 0 : rv;
184 }
185
186 static void
187 mbedtls_debug (void *ctx, int level, const char *file, int line,
188                const char *str)
189 {
190   ((void) level);
191   fprintf ((FILE *) ctx, "%s:%04d: %s", file, line, str);
192   fflush ((FILE *) ctx);
193 }
194
195 static int
196 mbedtls_ctx_init_client (tls_ctx_t * ctx)
197 {
198   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
199   mbedtls_main_t *mm = &mbedtls_main;
200   void *ctx_ptr;
201   int rv;
202
203   /*
204    * 1. Setup SSL
205    */
206   mbedtls_ssl_init (&mc->ssl);
207   mbedtls_ssl_config_init (&mc->conf);
208   if ((rv = mbedtls_ssl_config_defaults (&mc->conf, MBEDTLS_SSL_IS_CLIENT,
209                                          MBEDTLS_SSL_TRANSPORT_STREAM,
210                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
211     {
212       TLS_DBG (1, "failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n",
213                rv);
214       return -1;
215     }
216
217   mbedtls_ssl_conf_authmode (&mc->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
218   mbedtls_ssl_conf_ca_chain (&mc->conf, &mm->cacert, NULL);
219   mbedtls_ssl_conf_rng (&mc->conf, mbedtls_ctr_drbg_random,
220                         tls_get_ctr_drbg ());
221   mbedtls_ssl_conf_dbg (&mc->conf, mbedtls_debug, stdout);
222
223   if ((rv = mbedtls_ssl_setup (&mc->ssl, &mc->conf)) != 0)
224     {
225       TLS_DBG (1, "failed\n  ! mbedtls_ssl_setup returned %d\n", rv);
226       return -1;
227     }
228
229   if ((rv = mbedtls_ssl_set_hostname (&mc->ssl,
230                                       (const char *) ctx->srv_hostname)) != 0)
231     {
232       TLS_DBG (1, "failed\n  ! mbedtls_ssl_set_hostname returned %d\n", rv);
233       return -1;
234     }
235
236   ctx_ptr = uword_to_pointer (ctx->tls_ctx_idx, void *);
237   mbedtls_ssl_set_bio (&mc->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
238   mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_CLIENT);
239
240   /*
241    * 2. Do the first 2 steps in the handshake.
242    */
243   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
244            ctx->tls_ctx_idx);
245   while (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
246     {
247       rv = mbedtls_ssl_handshake_step (&mc->ssl);
248       if (rv != 0)
249         break;
250     }
251   TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
252            ctx->tls_ctx_idx, mc->ssl.state);
253   return 0;
254 }
255
256 static int
257 mbedtls_ctx_init_server (tls_ctx_t * ctx)
258 {
259   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
260   mbedtls_main_t *mm = &mbedtls_main;
261   application_t *app;
262   void *ctx_ptr;
263   int rv;
264
265   mbedtls_ssl_init (&mc->ssl);
266   mbedtls_ssl_config_init (&mc->conf);
267   mbedtls_x509_crt_init (&mc->srvcert);
268   mbedtls_pk_init (&mc->pkey);
269
270   /*
271    * 1. Cert
272    */
273   app = application_get (ctx->parent_app_index);
274   if (!app->tls_cert || !app->tls_key)
275     {
276       TLS_DBG (1, " failed\n  ! tls cert and/or key not configured %d",
277                ctx->parent_app_index);
278       return -1;
279     }
280
281   rv = mbedtls_x509_crt_parse (&mc->srvcert,
282                                (const unsigned char *) app->tls_cert,
283                                vec_len (app->tls_cert));
284   if (rv != 0)
285     {
286       TLS_DBG (1, " failed\n  !  mbedtls_x509_crt_parse returned %d", rv);
287       goto exit;
288     }
289
290   rv = mbedtls_pk_parse_key (&mc->pkey,
291                              (const unsigned char *) app->tls_key,
292                              vec_len (app->tls_key), NULL, 0);
293   if (rv != 0)
294     {
295       TLS_DBG (1, " failed\n  !  mbedtls_pk_parse_key returned %d", rv);
296       goto exit;
297     }
298
299   /*
300    * 2. SSL context config
301    */
302   if ((rv = mbedtls_ssl_config_defaults (&mc->conf, MBEDTLS_SSL_IS_SERVER,
303                                          MBEDTLS_SSL_TRANSPORT_STREAM,
304                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
305     {
306       TLS_DBG (1, " failed\n  ! mbedtls_ssl_config_defaults returned %d", rv);
307       goto exit;
308     }
309
310   mbedtls_ssl_conf_rng (&mc->conf, mbedtls_ctr_drbg_random,
311                         tls_get_ctr_drbg ());
312   mbedtls_ssl_conf_dbg (&mc->conf, mbedtls_debug, stdout);
313
314   /* TODO CACHE
315      mbedtls_ssl_conf_session_cache( &ctx->conf, &cache,
316      mbedtls_ssl_cache_get,
317      mbedtls_ssl_cache_set );
318    */
319
320   mbedtls_ssl_conf_ca_chain (&mc->conf, &mm->cacert, NULL);
321   if ((rv = mbedtls_ssl_conf_own_cert (&mc->conf, &mc->srvcert, &mc->pkey))
322       != 0)
323     {
324       TLS_DBG (1, " failed\n  ! mbedtls_ssl_conf_own_cert returned %d", rv);
325       goto exit;
326     }
327
328   if ((rv = mbedtls_ssl_setup (&mc->ssl, &mc->conf)) != 0)
329     {
330       TLS_DBG (1, " failed\n  ! mbedtls_ssl_setup returned %d", rv);
331       goto exit;
332     }
333
334   mbedtls_ssl_session_reset (&mc->ssl);
335   ctx_ptr = uword_to_pointer (ctx->tls_ctx_idx, void *);
336   mbedtls_ssl_set_bio (&mc->ssl, ctx_ptr, tls_net_send, tls_net_recv, NULL);
337   mbedtls_debug_set_threshold (TLS_DEBUG_LEVEL_SERVER);
338
339   /*
340    * 3. Start handshake state machine
341    */
342   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
343            ctx->tls_ctx_idx);
344   while (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
345     {
346       rv = mbedtls_ssl_handshake_step (&mc->ssl);
347       if (rv != 0)
348         break;
349     }
350
351   TLS_DBG (2, "tls state for [%u]%u is %u", ctx->c_thread_index,
352            ctx->tls_ctx_idx, mc->ssl.state);
353   return 0;
354
355 exit:
356   return -1;
357 }
358
359 static int
360 mbedtls_handshake_rx (tls_ctx_t * ctx)
361 {
362   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
363   u32 flags;
364   int rv;
365   while (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
366     {
367       rv = mbedtls_ssl_handshake_step (&mc->ssl);
368       if (rv != 0)
369         break;
370     }
371   TLS_DBG (2, "tls state for %u is %u", ctx->tls_ctx_idx, mc->ssl.state);
372
373   if (mc->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
374     return HANDSHAKE_NOT_OVER;
375
376   /*
377    * Handshake complete
378    */
379   if (mc->ssl.conf->endpoint == MBEDTLS_SSL_IS_CLIENT)
380     {
381       /*
382        * Verify server certificate
383        */
384       if ((flags = mbedtls_ssl_get_verify_result (&mc->ssl)) != 0)
385         {
386           char buf[512];
387           TLS_DBG (1, " failed\n");
388           mbedtls_x509_crt_verify_info (buf, sizeof (buf), "  ! ", flags);
389           TLS_DBG (1, "%s\n", buf);
390
391           /*
392            * Presence of hostname enforces strict certificate verification
393            */
394           if (ctx->srv_hostname)
395             return CLIENT_HANDSHAKE_FAIL;
396         }
397       rv = CLIENT_HANDSHAKE_OK;
398     }
399   else
400     {
401       rv = SERVER_HANDSHAKE_OK;
402     }
403
404   TLS_DBG (1, "Handshake for %u complete. TLS cipher is %x",
405            ctx->tls_ctx_idx, mc->ssl.session->ciphersuite);
406   return rv;
407 }
408
409 static int
410 mbedtls_write (tls_ctx_t * ctx, u8 * buf, u32 len)
411 {
412   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
413   return mbedtls_ssl_write (&mc->ssl, buf, len);
414 }
415
416 static int
417 mbedtls_read (tls_ctx_t * ctx, u8 * buf, u32 len)
418 {
419   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
420   return mbedtls_ssl_read (&mc->ssl, buf, len);
421 }
422
423 static u8
424 mbedtls_handshake_is_over (tls_ctx_t * ctx)
425 {
426   mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx;
427   return (mc->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER);
428 }
429
430 const static tls_engine_vft_t mbedtls_engine = {
431   .ctx_alloc = mbedtls_ctx_alloc,
432   .ctx_free = mbedtls_ctx_free,
433   .ctx_get = mbedtls_ctx_get,
434   .ctx_get_w_thread = mbedtls_ctx_get_w_thread,
435   .ctx_init_server = mbedtls_ctx_init_server,
436   .ctx_init_client = mbedtls_ctx_init_client,
437   .ctx_handshake_rx = mbedtls_handshake_rx,
438   .ctx_write = mbedtls_write,
439   .ctx_read = mbedtls_read,
440   .ctx_handshake_is_over = mbedtls_handshake_is_over,
441 };
442
443 int
444 tls_init_mem (void)
445 {
446 #if TLS_USE_OUR_MEM_FUNCS
447   mbedtls_platform_set_calloc_free (mbedtls_calloc_fn, mbedtls_free_fn);
448 #endif
449   return 0;
450 }
451
452 static int
453 tls_init_ctr_drbgs_and_entropy (u32 num_threads)
454 {
455   mbedtls_main_t *mm = &mbedtls_main;
456   int i;
457
458   vec_validate (mm->ctr_drbgs, num_threads - 1);
459   vec_validate (mm->entropy_pools, num_threads - 1);
460   for (i = 0; i < num_threads; i++)
461     mm->ctr_drbgs[i].f_entropy = 0;
462
463   return 0;
464 }
465
466 int
467 tls_init_ca_chain (void)
468 {
469   mbedtls_main_t *mm = &mbedtls_main;
470   tls_main_t *tm = vnet_tls_get_main ();
471   int rv;
472
473   if (access (tm->ca_cert_path, F_OK | R_OK) == -1)
474     {
475       clib_warning ("Could not initialize TLS CA certificates");
476       return -1;
477     }
478
479   mbedtls_x509_crt_init (&mm->cacert);
480   rv = mbedtls_x509_crt_parse_file (&mm->cacert, tm->ca_cert_path);
481   if (rv < 0)
482     {
483       clib_warning ("Couldn't parse system CA certificates: -0x%x", -rv);
484     }
485   if (tm->use_test_cert_in_ca)
486     {
487       rv = mbedtls_x509_crt_parse (&mm->cacert,
488                                    (const unsigned char *) test_srv_crt_rsa,
489                                    test_srv_crt_rsa_len);
490       if (rv < 0)
491         {
492           clib_warning ("Couldn't parse test certificate: -0x%x", -rv);
493           return -1;
494         }
495     }
496   return (rv < 0 ? -1 : 0);
497 }
498
499 static clib_error_t *
500 tls_mbedtls_init (vlib_main_t * vm)
501 {
502   vlib_thread_main_t *vtm = vlib_get_thread_main ();
503   mbedtls_main_t *mm = &mbedtls_main;
504   clib_error_t *error;
505   u32 num_threads;
506
507   num_threads = 1 /* main thread */  + vtm->n_threads;
508
509   if ((error = vlib_call_init_function (vm, tls_init)))
510     return error;
511
512   if (tls_init_ca_chain ())
513     {
514       clib_warning ("failed to initialize TLS CA chain");
515       return 0;
516     }
517   if (tls_init_mem ())
518     {
519       clib_warning ("failed to initialize mem");
520       return 0;
521     }
522   if (tls_init_ctr_drbgs_and_entropy (num_threads))
523     {
524       clib_warning ("failed to initialize entropy and random generators");
525       return 0;
526     }
527
528   vec_validate (mm->ctx_pool, num_threads - 1);
529   tls_register_engine (&mbedtls_engine, TLS_ENGINE_MBEDTLS);
530   return 0;
531 }
532
533 VLIB_INIT_FUNCTION (tls_mbedtls_init);
534
535 /* *INDENT-OFF* */
536 VLIB_PLUGIN_REGISTER () = {
537     .version = VPP_BUILD_VER,
538     .description = "mbedtls based TLS Engine",
539 };
540 /* *INDENT-ON* */
541
542 /*
543  * fd.io coding-style-patch-verification: ON
544  *
545  * Local Variables:
546  * eval: (c-set-style "gnu")
547  * End:
548  */