tls: use fifo segments instead of chunks
[vpp.git] / src / plugins / tlsopenssl / tls_openssl.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 <openssl/ssl.h>
17 #include <openssl/conf.h>
18 #include <openssl/err.h>
19
20 #ifdef HAVE_OPENSSL_ASYNC
21 #include <openssl/async.h>
22 #endif
23 #include <dlfcn.h>
24 #include <vnet/plugin/plugin.h>
25 #include <vpp/app/version.h>
26 #include <vnet/tls/tls.h>
27 #include <ctype.h>
28 #include <tlsopenssl/tls_openssl.h>
29 #include <tlsopenssl/tls_bio.h>
30
31 #define MAX_CRYPTO_LEN 64
32
33 openssl_main_t openssl_main;
34 static u32
35 openssl_ctx_alloc (void)
36 {
37   u8 thread_index = vlib_get_thread_index ();
38   openssl_main_t *tm = &openssl_main;
39   openssl_ctx_t **ctx;
40
41   pool_get (tm->ctx_pool[thread_index], ctx);
42   if (!(*ctx))
43     *ctx = clib_mem_alloc (sizeof (openssl_ctx_t));
44
45   clib_memset (*ctx, 0, sizeof (openssl_ctx_t));
46   (*ctx)->ctx.c_thread_index = thread_index;
47   (*ctx)->ctx.tls_ctx_engine = CRYPTO_ENGINE_OPENSSL;
48   (*ctx)->ctx.app_session_handle = SESSION_INVALID_HANDLE;
49   (*ctx)->openssl_ctx_index = ctx - tm->ctx_pool[thread_index];
50   return ((*ctx)->openssl_ctx_index);
51 }
52
53 static void
54 openssl_ctx_free (tls_ctx_t * ctx)
55 {
56   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
57
58   if (SSL_is_init_finished (oc->ssl) && !ctx->is_passive_close)
59     SSL_shutdown (oc->ssl);
60
61   SSL_free (oc->ssl);
62
63 #ifdef HAVE_OPENSSL_ASYNC
64   openssl_evt_free (ctx->evt_index, ctx->c_thread_index);
65 #endif
66   vec_free (ctx->srv_hostname);
67   pool_put_index (openssl_main.ctx_pool[ctx->c_thread_index],
68                   oc->openssl_ctx_index);
69 }
70
71 tls_ctx_t *
72 openssl_ctx_get (u32 ctx_index)
73 {
74   openssl_ctx_t **ctx;
75   ctx = pool_elt_at_index (openssl_main.ctx_pool[vlib_get_thread_index ()],
76                            ctx_index);
77   return &(*ctx)->ctx;
78 }
79
80 tls_ctx_t *
81 openssl_ctx_get_w_thread (u32 ctx_index, u8 thread_index)
82 {
83   openssl_ctx_t **ctx;
84   ctx = pool_elt_at_index (openssl_main.ctx_pool[thread_index], ctx_index);
85   return &(*ctx)->ctx;
86 }
87
88 static u32
89 openssl_listen_ctx_alloc (void)
90 {
91   openssl_main_t *om = &openssl_main;
92   openssl_listen_ctx_t *lctx;
93
94   pool_get (om->lctx_pool, lctx);
95
96   clib_memset (lctx, 0, sizeof (openssl_listen_ctx_t));
97   lctx->openssl_lctx_index = lctx - om->lctx_pool;
98   return lctx->openssl_lctx_index;
99 }
100
101 static void
102 openssl_listen_ctx_free (openssl_listen_ctx_t * lctx)
103 {
104   pool_put_index (openssl_main.lctx_pool, lctx->openssl_lctx_index);
105 }
106
107 openssl_listen_ctx_t *
108 openssl_lctx_get (u32 lctx_index)
109 {
110   return pool_elt_at_index (openssl_main.lctx_pool, lctx_index);
111 }
112
113 static int
114 openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl)
115 {
116   int read, rv, n_fs, i;
117   const int n_segs = 2;
118   svm_fifo_seg_t fs[n_segs];
119   u32 max_enq;
120
121   max_enq = svm_fifo_max_enqueue_prod (f);
122   n_fs = svm_fifo_provision_chunks (f, fs, n_segs, max_enq);
123   if (n_fs < 0)
124     return 0;
125
126   /* Return early if we can't read anything */
127   read = SSL_read (ssl, fs[0].data, fs[0].len);
128   if (read <= 0)
129     return 0;
130
131   for (i = 1; i < n_fs; i++)
132     {
133       rv = SSL_read (ssl, fs[i].data, fs[i].len);
134       read += rv > 0 ? rv : 0;
135
136       if (rv < fs[i].len)
137         break;
138     }
139
140   svm_fifo_enqueue_nocopy (f, read);
141
142   return read;
143 }
144
145 static int
146 openssl_write_from_fifo_into_ssl (svm_fifo_t *f, SSL *ssl, u32 max_len)
147 {
148   int wrote = 0, rv, i = 0, len;
149   const int n_segs = 2;
150   svm_fifo_seg_t fs[n_segs];
151
152   len = svm_fifo_segments (f, 0, fs, n_segs, max_len);
153   if (len <= 0)
154     return 0;
155
156   while (wrote < len && i < n_segs)
157     {
158       rv = SSL_write (ssl, fs[i].data, fs[i].len);
159       wrote += (rv > 0) ? rv : 0;
160       if (rv < fs[i].len)
161         break;
162       i++;
163     }
164
165   if (wrote)
166     svm_fifo_dequeue_drop (f, wrote);
167
168   return wrote;
169 }
170
171 #ifdef HAVE_OPENSSL_ASYNC
172 static int
173 openssl_check_async_status (tls_ctx_t * ctx, openssl_resume_handler * handler,
174                             session_t * session)
175 {
176   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
177   int estatus;
178
179   SSL_get_async_status (oc->ssl, &estatus);
180   if (estatus == ASYNC_STATUS_EAGAIN)
181     {
182       vpp_tls_async_update_event (ctx, 1);
183     }
184   else
185     {
186       vpp_tls_async_update_event (ctx, 0);
187     }
188
189   return 1;
190
191 }
192
193 #endif
194
195 static void
196 openssl_handle_handshake_failure (tls_ctx_t * ctx)
197 {
198   session_t *app_session;
199
200   if (SSL_is_server (((openssl_ctx_t *) ctx)->ssl))
201     {
202       /*
203        * Cleanup pre-allocated app session and close transport
204        */
205       app_session =
206         session_get_if_valid (ctx->c_s_index, ctx->c_thread_index);
207       if (app_session)
208         {
209           session_free (app_session);
210           ctx->no_app_session = 1;
211           ctx->c_s_index = SESSION_INVALID_INDEX;
212           tls_disconnect_transport (ctx);
213         }
214     }
215   else
216     {
217       /*
218        * Also handles cleanup of the pre-allocated session
219        */
220       tls_notify_app_connected (ctx, SESSION_E_TLS_HANDSHAKE);
221     }
222 }
223
224 int
225 openssl_ctx_handshake_rx (tls_ctx_t * ctx, session_t * tls_session)
226 {
227   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
228   int rv = 0, err;
229
230   while (SSL_in_init (oc->ssl))
231     {
232       if (ctx->resume)
233         {
234           ctx->resume = 0;
235         }
236       else if (!svm_fifo_max_dequeue_cons (tls_session->rx_fifo))
237         break;
238
239       rv = SSL_do_handshake (oc->ssl);
240       err = SSL_get_error (oc->ssl, rv);
241
242 #ifdef HAVE_OPENSSL_ASYNC
243       if (err == SSL_ERROR_WANT_ASYNC)
244         {
245           openssl_check_async_status (ctx, openssl_ctx_handshake_rx,
246                                       tls_session);
247         }
248 #endif
249       if (err == SSL_ERROR_SSL)
250         {
251           char buf[512];
252           ERR_error_string (ERR_get_error (), buf);
253           clib_warning ("Err: %s", buf);
254
255           openssl_handle_handshake_failure (ctx);
256           return -1;
257         }
258
259       if (err != SSL_ERROR_WANT_WRITE && err != SSL_ERROR_WANT_READ)
260         break;
261     }
262   TLS_DBG (2, "tls state for %u is %s", oc->openssl_ctx_index,
263            SSL_state_string_long (oc->ssl));
264
265   if (SSL_in_init (oc->ssl))
266     return -1;
267
268   /*
269    * Handshake complete
270    */
271   if (!SSL_is_server (oc->ssl))
272     {
273       /*
274        * Verify server certificate
275        */
276       if ((rv = SSL_get_verify_result (oc->ssl)) != X509_V_OK)
277         {
278           TLS_DBG (1, " failed verify: %s\n",
279                    X509_verify_cert_error_string (rv));
280
281           /*
282            * Presence of hostname enforces strict certificate verification
283            */
284           if (ctx->srv_hostname)
285             {
286               tls_notify_app_connected (ctx, SESSION_E_TLS_HANDSHAKE);
287               return -1;
288             }
289         }
290       tls_notify_app_connected (ctx, SESSION_E_NONE);
291     }
292   else
293     {
294       /* Need to check transport status */
295       if (ctx->is_passive_close)
296         openssl_handle_handshake_failure (ctx);
297       else
298         tls_notify_app_accept (ctx);
299     }
300
301   TLS_DBG (1, "Handshake for %u complete. TLS cipher is %s",
302            oc->openssl_ctx_index, SSL_get_cipher (oc->ssl));
303   return rv;
304 }
305
306 static void
307 openssl_confirm_app_close (tls_ctx_t * ctx)
308 {
309   tls_disconnect_transport (ctx);
310   session_transport_closed_notify (&ctx->connection);
311 }
312
313 static inline int
314 openssl_ctx_write (tls_ctx_t * ctx, session_t * app_session,
315                    transport_send_params_t * sp)
316 {
317   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
318   u32 deq_max, space, enq_buf;
319   session_t *ts;
320   int wrote = 0;
321   svm_fifo_t *f;
322
323   ts = session_get_from_handle (ctx->tls_session_handle);
324   space = svm_fifo_max_enqueue_prod (ts->tx_fifo);
325   /* Leave a bit of extra space for tls ctrl data, if any needed */
326   space = clib_max ((int) space - TLSO_CTRL_BYTES, 0);
327
328   f = app_session->tx_fifo;
329
330   deq_max = svm_fifo_max_dequeue_cons (f);
331   deq_max = clib_min (deq_max, space);
332   if (!deq_max)
333     goto check_tls_fifo;
334
335   deq_max = clib_min (deq_max, sp->max_burst_size);
336
337   wrote = openssl_write_from_fifo_into_ssl (f, oc->ssl, deq_max);
338   if (!wrote)
339     goto check_tls_fifo;
340
341   if (svm_fifo_needs_deq_ntf (f, wrote))
342     session_dequeue_notify (app_session);
343
344 check_tls_fifo:
345
346   /* Deschedule and wait for deq notification if fifo is almost full */
347   enq_buf = clib_min (svm_fifo_size (ts->tx_fifo) / 2, TLSO_MIN_ENQ_SPACE);
348   if (space < wrote + enq_buf)
349     {
350       svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
351       transport_connection_deschedule (&ctx->connection);
352       sp->flags |= TRANSPORT_SND_F_DESCHED;
353     }
354   else
355     /* Request tx reschedule of the app session */
356     app_session->flags |= SESSION_F_CUSTOM_TX;
357
358   return wrote;
359 }
360
361 static inline int
362 openssl_ctx_read (tls_ctx_t * ctx, session_t * tls_session)
363 {
364   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
365   session_t *app_session;
366   int read, wrote = 0;
367   svm_fifo_t *f;
368
369   if (PREDICT_FALSE (SSL_in_init (oc->ssl)))
370     {
371       if (openssl_ctx_handshake_rx (ctx, tls_session) < 0)
372         return 0;
373     }
374
375   app_session = session_get_from_handle (ctx->app_session_handle);
376   f = app_session->rx_fifo;
377
378   read = openssl_read_from_ssl_into_fifo (f, oc->ssl);
379
380   /* If handshake just completed, session may still be in accepting state */
381   if (read && app_session->session_state >= SESSION_STATE_READY)
382     tls_notify_app_enqueue (ctx, app_session);
383
384   if (SSL_pending (oc->ssl) > 0)
385     tls_add_vpp_q_builtin_rx_evt (tls_session);
386
387   return wrote;
388 }
389
390 static int
391 openssl_ctx_init_client (tls_ctx_t * ctx)
392 {
393   long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
394   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
395   openssl_main_t *om = &openssl_main;
396   const SSL_METHOD *method;
397   int rv, err;
398
399   method = SSLv23_client_method ();
400   if (method == NULL)
401     {
402       TLS_DBG (1, "SSLv23_method returned null");
403       return -1;
404     }
405
406   oc->ssl_ctx = SSL_CTX_new (method);
407   if (oc->ssl_ctx == NULL)
408     {
409       TLS_DBG (1, "SSL_CTX_new returned null");
410       return -1;
411     }
412
413   SSL_CTX_set_ecdh_auto (oc->ssl_ctx, 1);
414   SSL_CTX_set_mode (oc->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
415 #ifdef HAVE_OPENSSL_ASYNC
416   if (om->async)
417     SSL_CTX_set_mode (oc->ssl_ctx, SSL_MODE_ASYNC);
418 #endif
419   rv = SSL_CTX_set_cipher_list (oc->ssl_ctx, (const char *) om->ciphers);
420   if (rv != 1)
421     {
422       TLS_DBG (1, "Couldn't set cipher");
423       return -1;
424     }
425
426   SSL_CTX_set_options (oc->ssl_ctx, flags);
427   SSL_CTX_set_cert_store (oc->ssl_ctx, om->cert_store);
428
429   oc->ssl = SSL_new (oc->ssl_ctx);
430   if (oc->ssl == NULL)
431     {
432       TLS_DBG (1, "Couldn't initialize ssl struct");
433       return -1;
434     }
435
436   oc->rbio = BIO_new_tls (ctx->tls_session_handle);
437   oc->wbio = BIO_new_tls (ctx->tls_session_handle);
438
439   SSL_set_bio (oc->ssl, oc->wbio, oc->rbio);
440   SSL_set_connect_state (oc->ssl);
441
442   rv = SSL_set_tlsext_host_name (oc->ssl, ctx->srv_hostname);
443   if (rv != 1)
444     {
445       TLS_DBG (1, "Couldn't set hostname");
446       return -1;
447     }
448
449   /*
450    * 2. Do the first steps in the handshake.
451    */
452   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
453            oc->openssl_ctx_index);
454
455 #ifdef HAVE_OPENSSL_ASYNC
456   session_t *tls_session = session_get_from_handle (ctx->tls_session_handle);
457   vpp_tls_async_init_event (ctx, openssl_ctx_handshake_rx, tls_session);
458 #endif
459   while (1)
460     {
461       rv = SSL_do_handshake (oc->ssl);
462       err = SSL_get_error (oc->ssl, rv);
463 #ifdef HAVE_OPENSSL_ASYNC
464       if (err == SSL_ERROR_WANT_ASYNC)
465         {
466           openssl_check_async_status (ctx, openssl_ctx_handshake_rx,
467                                       tls_session);
468           break;
469         }
470 #endif
471       if (err != SSL_ERROR_WANT_WRITE)
472         break;
473     }
474
475   TLS_DBG (2, "tls state for [%u]%u is su", ctx->c_thread_index,
476            oc->openssl_ctx_index, SSL_state_string_long (oc->ssl));
477   return 0;
478 }
479
480 static int
481 openssl_start_listen (tls_ctx_t * lctx)
482 {
483   const SSL_METHOD *method;
484   SSL_CTX *ssl_ctx;
485   int rv;
486   BIO *cert_bio;
487   X509 *srvcert;
488   EVP_PKEY *pkey;
489   u32 olc_index;
490   openssl_listen_ctx_t *olc;
491   app_cert_key_pair_t *ckpair;
492
493   long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
494   openssl_main_t *om = &openssl_main;
495
496   ckpair = app_cert_key_pair_get_if_valid (lctx->ckpair_index);
497   if (!ckpair)
498     return -1;
499
500   if (!ckpair->cert || !ckpair->key)
501     {
502       TLS_DBG (1, "tls cert and/or key not configured %d",
503                lctx->parent_app_wrk_index);
504       return -1;
505     }
506
507   method = SSLv23_method ();
508   ssl_ctx = SSL_CTX_new (method);
509   if (!ssl_ctx)
510     {
511       clib_warning ("Unable to create SSL context");
512       return -1;
513     }
514
515   SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
516 #ifdef HAVE_OPENSSL_ASYNC
517   if (om->async)
518     {
519       SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ASYNC);
520       SSL_CTX_set_async_callback (ssl_ctx, tls_async_openssl_callback);
521     }
522 #endif
523   SSL_CTX_set_options (ssl_ctx, flags);
524   SSL_CTX_set_ecdh_auto (ssl_ctx, 1);
525
526   rv = SSL_CTX_set_cipher_list (ssl_ctx, (const char *) om->ciphers);
527   if (rv != 1)
528     {
529       TLS_DBG (1, "Couldn't set cipher");
530       return -1;
531     }
532
533   /*
534    * Set the key and cert
535    */
536   cert_bio = BIO_new (BIO_s_mem ());
537   BIO_write (cert_bio, ckpair->cert, vec_len (ckpair->cert));
538   srvcert = PEM_read_bio_X509 (cert_bio, NULL, NULL, NULL);
539   if (!srvcert)
540     {
541       clib_warning ("unable to parse certificate");
542       return -1;
543     }
544   SSL_CTX_use_certificate (ssl_ctx, srvcert);
545   BIO_free (cert_bio);
546
547   cert_bio = BIO_new (BIO_s_mem ());
548   BIO_write (cert_bio, ckpair->key, vec_len (ckpair->key));
549   pkey = PEM_read_bio_PrivateKey (cert_bio, NULL, NULL, NULL);
550   if (!pkey)
551     {
552       clib_warning ("unable to parse pkey");
553       return -1;
554     }
555   SSL_CTX_use_PrivateKey (ssl_ctx, pkey);
556   BIO_free (cert_bio);
557
558   olc_index = openssl_listen_ctx_alloc ();
559   olc = openssl_lctx_get (olc_index);
560   olc->ssl_ctx = ssl_ctx;
561   olc->srvcert = srvcert;
562   olc->pkey = pkey;
563
564   /* store SSL_CTX into TLS level structure */
565   lctx->tls_ssl_ctx = olc_index;
566
567   return 0;
568
569 }
570
571 static int
572 openssl_stop_listen (tls_ctx_t * lctx)
573 {
574   u32 olc_index;
575   openssl_listen_ctx_t *olc;
576
577   olc_index = lctx->tls_ssl_ctx;
578   olc = openssl_lctx_get (olc_index);
579
580   X509_free (olc->srvcert);
581   EVP_PKEY_free (olc->pkey);
582
583   SSL_CTX_free (olc->ssl_ctx);
584   openssl_listen_ctx_free (olc);
585
586   return 0;
587 }
588
589 static int
590 openssl_ctx_init_server (tls_ctx_t * ctx)
591 {
592   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
593   u32 olc_index = ctx->tls_ssl_ctx;
594   openssl_listen_ctx_t *olc;
595   int rv, err;
596
597   /* Start a new connection */
598
599   olc = openssl_lctx_get (olc_index);
600   oc->ssl = SSL_new (olc->ssl_ctx);
601   if (oc->ssl == NULL)
602     {
603       TLS_DBG (1, "Couldn't initialize ssl struct");
604       return -1;
605     }
606
607   oc->rbio = BIO_new_tls (ctx->tls_session_handle);
608   oc->wbio = BIO_new_tls (ctx->tls_session_handle);
609
610   SSL_set_bio (oc->ssl, oc->wbio, oc->rbio);
611   SSL_set_accept_state (oc->ssl);
612
613   TLS_DBG (1, "Initiating handshake for [%u]%u", ctx->c_thread_index,
614            oc->openssl_ctx_index);
615
616 #ifdef HAVE_OPENSSL_ASYNC
617   session_t *tls_session = session_get_from_handle (ctx->tls_session_handle);
618   vpp_tls_async_init_event (ctx, openssl_ctx_handshake_rx, tls_session);
619 #endif
620   while (1)
621     {
622       rv = SSL_do_handshake (oc->ssl);
623       err = SSL_get_error (oc->ssl, rv);
624 #ifdef HAVE_OPENSSL_ASYNC
625       if (err == SSL_ERROR_WANT_ASYNC)
626         {
627           openssl_check_async_status (ctx, openssl_ctx_handshake_rx,
628                                       tls_session);
629           break;
630         }
631 #endif
632       if (err != SSL_ERROR_WANT_WRITE)
633         break;
634     }
635
636   TLS_DBG (2, "tls state for [%u]%u is su", ctx->c_thread_index,
637            oc->openssl_ctx_index, SSL_state_string_long (oc->ssl));
638   return 0;
639 }
640
641 static u8
642 openssl_handshake_is_over (tls_ctx_t * ctx)
643 {
644   openssl_ctx_t *mc = (openssl_ctx_t *) ctx;
645   if (!mc->ssl)
646     return 0;
647   return SSL_is_init_finished (mc->ssl);
648 }
649
650 static int
651 openssl_transport_close (tls_ctx_t * ctx)
652 {
653 #ifdef HAVE_OPENSSL_ASYNC
654   if (vpp_openssl_is_inflight (ctx))
655     return 0;
656 #endif
657
658   if (!openssl_handshake_is_over (ctx))
659     {
660       openssl_handle_handshake_failure (ctx);
661       return 0;
662     }
663   session_transport_closing_notify (&ctx->connection);
664   return 0;
665 }
666
667 static int
668 openssl_app_close (tls_ctx_t * ctx)
669 {
670   openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
671   session_t *app_session;
672
673   /* Wait for all data to be written to tcp */
674   app_session = session_get_from_handle (ctx->app_session_handle);
675   if (BIO_ctrl_pending (oc->rbio) <= 0
676       && !svm_fifo_max_dequeue_cons (app_session->tx_fifo))
677     openssl_confirm_app_close (ctx);
678   else
679     ctx->app_closed = 1;
680   return 0;
681 }
682
683 const static tls_engine_vft_t openssl_engine = {
684   .ctx_alloc = openssl_ctx_alloc,
685   .ctx_free = openssl_ctx_free,
686   .ctx_get = openssl_ctx_get,
687   .ctx_get_w_thread = openssl_ctx_get_w_thread,
688   .ctx_init_server = openssl_ctx_init_server,
689   .ctx_init_client = openssl_ctx_init_client,
690   .ctx_write = openssl_ctx_write,
691   .ctx_read = openssl_ctx_read,
692   .ctx_handshake_is_over = openssl_handshake_is_over,
693   .ctx_start_listen = openssl_start_listen,
694   .ctx_stop_listen = openssl_stop_listen,
695   .ctx_transport_close = openssl_transport_close,
696   .ctx_app_close = openssl_app_close,
697 };
698
699 int
700 tls_init_ca_chain (void)
701 {
702   openssl_main_t *om = &openssl_main;
703   tls_main_t *tm = vnet_tls_get_main ();
704   BIO *cert_bio;
705   X509 *testcert;
706   int rv;
707
708   if (access (tm->ca_cert_path, F_OK | R_OK) == -1)
709     {
710       clib_warning ("Could not initialize TLS CA certificates");
711       return -1;
712     }
713
714   if (!(om->cert_store = X509_STORE_new ()))
715     {
716       clib_warning ("failed to create cert store");
717       return -1;
718     }
719
720 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
721   rv = X509_STORE_load_file (om->cert_store, tm->ca_cert_path);
722 #else
723   rv = X509_STORE_load_locations (om->cert_store, tm->ca_cert_path, 0);
724 #endif
725
726   if (rv < 0)
727     {
728       clib_warning ("failed to load ca certificate");
729     }
730
731   if (tm->use_test_cert_in_ca)
732     {
733       cert_bio = BIO_new (BIO_s_mem ());
734       BIO_write (cert_bio, test_srv_crt_rsa, test_srv_crt_rsa_len);
735       testcert = PEM_read_bio_X509 (cert_bio, NULL, NULL, NULL);
736       if (!testcert)
737         {
738           clib_warning ("unable to parse certificate");
739           return -1;
740         }
741       X509_STORE_add_cert (om->cert_store, testcert);
742       rv = 0;
743     }
744   return (rv < 0 ? -1 : 0);
745 }
746
747 int
748 tls_openssl_set_ciphers (char *ciphers)
749 {
750   openssl_main_t *om = &openssl_main;
751   int i;
752
753   if (!ciphers)
754     {
755       return -1;
756     }
757
758   vec_validate (om->ciphers, strlen (ciphers) - 1);
759   for (i = 0; i < vec_len (om->ciphers); i++)
760     {
761       om->ciphers[i] = toupper (ciphers[i]);
762     }
763
764   return 0;
765
766 }
767
768 static clib_error_t *
769 tls_openssl_init (vlib_main_t * vm)
770 {
771   vlib_thread_main_t *vtm = vlib_get_thread_main ();
772   openssl_main_t *om = &openssl_main;
773   clib_error_t *error = 0;
774   u32 num_threads;
775
776   error = tls_openssl_api_init (vm);
777   num_threads = 1 /* main thread */  + vtm->n_threads;
778
779   SSL_library_init ();
780   SSL_load_error_strings ();
781
782   if (tls_init_ca_chain ())
783     {
784       clib_warning ("failed to initialize TLS CA chain");
785       return 0;
786     }
787
788   vec_validate (om->ctx_pool, num_threads - 1);
789
790   tls_register_engine (&openssl_engine, CRYPTO_ENGINE_OPENSSL);
791
792   om->engine_init = 0;
793
794   /* default ciphers */
795   tls_openssl_set_ciphers
796     ("ALL:!ADH:!LOW:!EXP:!MD5:!RC4-SHA:!DES-CBC3-SHA:@STRENGTH");
797
798   return error;
799 }
800 /* *INDENT-OFF* */
801 VLIB_INIT_FUNCTION (tls_openssl_init) =
802 {
803   .runs_after = VLIB_INITS("tls_init"),
804 };
805 /* *INDENT-ON* */
806
807 #ifdef HAVE_OPENSSL_ASYNC
808 static clib_error_t *
809 tls_openssl_set_command_fn (vlib_main_t * vm, unformat_input_t * input,
810                             vlib_cli_command_t * cmd)
811 {
812   openssl_main_t *om = &openssl_main;
813   char *engine_name = NULL;
814   char *engine_alg = NULL;
815   char *ciphers = NULL;
816   u8 engine_name_set = 0;
817   int i, async = 0;
818
819   /* By present, it is not allowed to configure engine again after running */
820   if (om->engine_init)
821     {
822       clib_warning ("engine has started!\n");
823       return clib_error_return
824         (0, "engine has started, and no config is accepted");
825     }
826
827   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
828     {
829       if (unformat (input, "engine %s", &engine_name))
830         {
831           engine_name_set = 1;
832         }
833       else if (unformat (input, "async"))
834         {
835           async = 1;
836         }
837       else if (unformat (input, "alg %s", &engine_alg))
838         {
839           for (i = 0; i < strnlen (engine_alg, MAX_CRYPTO_LEN); i++)
840             engine_alg[i] = toupper (engine_alg[i]);
841         }
842       else if (unformat (input, "ciphers %s", &ciphers))
843         {
844           tls_openssl_set_ciphers (ciphers);
845         }
846       else
847         return clib_error_return (0, "failed: unknown input `%U'",
848                                   format_unformat_error, input);
849     }
850
851   /* reset parameters if engine is not configured */
852   if (!engine_name_set)
853     {
854       clib_warning ("No engine provided! \n");
855       async = 0;
856     }
857   else
858     {
859       vnet_session_enable_disable (vm, 1);
860       if (openssl_engine_register (engine_name, engine_alg, async) < 0)
861         {
862           return clib_error_return (0, "Failed to register %s polling",
863                                     engine_name);
864         }
865       else
866         {
867           vlib_cli_output (vm, "Successfully register engine %s\n",
868                            engine_name);
869         }
870     }
871   om->async = async;
872
873   return 0;
874 }
875
876 /* *INDENT-OFF* */
877 VLIB_CLI_COMMAND (tls_openssl_set_command, static) =
878 {
879   .path = "tls openssl set",
880   .short_help = "tls openssl set [engine <engine name>] [alg [algorithm] [async]",
881   .function = tls_openssl_set_command_fn,
882 };
883 /* *INDENT-ON* */
884 #endif
885
886 /* *INDENT-OFF* */
887 VLIB_PLUGIN_REGISTER () = {
888     .version = VPP_BUILD_VER,
889     .description = "Transport Layer Security (TLS) Engine, OpenSSL Based",
890 };
891 /* *INDENT-ON* */
892
893 /*
894  * fd.io coding-style-patch-verification: ON
895  *
896  * Local Variables:
897  * eval: (c-set-style "gnu")
898  * End:
899  */