From be4d1aa2c58efa8287bca8795bc4a83cb448993a Mon Sep 17 00:00:00 2001 From: Ping Yu Date: Mon, 19 Aug 2019 07:01:17 -0400 Subject: [PATCH] tls: Add C API for TLS openssl to set engine Type: feature Parameters of the engine can be set by C API. After this patch, it is easier to integrate TLS into CSIT test. Change-Id: I063cabf613aabbfad831727551579328705afb41 Signed-off-by: Ping Yu --- src/plugins/tlsopenssl/CMakeLists.txt | 11 ++ src/plugins/tlsopenssl/tls_async.c | 10 +- src/plugins/tlsopenssl/tls_openssl.api | 31 ++++ src/plugins/tlsopenssl/tls_openssl.c | 13 +- src/plugins/tlsopenssl/tls_openssl.h | 5 + src/plugins/tlsopenssl/tls_openssl_all_api_h.h | 18 +++ src/plugins/tlsopenssl/tls_openssl_api.c | 128 ++++++++++++++++ src/plugins/tlsopenssl/tls_openssl_msg_enum.h | 30 ++++ src/plugins/tlsopenssl/tls_openssl_test.c | 200 +++++++++++++++++++++++++ 9 files changed, 436 insertions(+), 10 deletions(-) create mode 100644 src/plugins/tlsopenssl/tls_openssl.api create mode 100644 src/plugins/tlsopenssl/tls_openssl_all_api_h.h create mode 100644 src/plugins/tlsopenssl/tls_openssl_api.c create mode 100644 src/plugins/tlsopenssl/tls_openssl_msg_enum.h create mode 100644 src/plugins/tlsopenssl/tls_openssl_test.c diff --git a/src/plugins/tlsopenssl/CMakeLists.txt b/src/plugins/tlsopenssl/CMakeLists.txt index ad34cfaa90d..07b587b4ca3 100644 --- a/src/plugins/tlsopenssl/CMakeLists.txt +++ b/src/plugins/tlsopenssl/CMakeLists.txt @@ -17,8 +17,19 @@ if(OPENSSL_FOUND) add_vpp_plugin(tlsopenssl SOURCES tls_openssl.c + tls_openssl_api.c tls_async.c + API_FILES + tls_openssl.api + + INSTALL_HEADERS + tls_openssl_all_api_h.h + tls_openssl_msg_enum.h + + API_TEST_SOURCES + tls_openssl_test.c + LINK_LIBRARIES ${OPENSSL_LIBRARIES} ) diff --git a/src/plugins/tlsopenssl/tls_async.c b/src/plugins/tlsopenssl/tls_async.c index ade073c66bc..e577f34eacf 100644 --- a/src/plugins/tlsopenssl/tls_async.c +++ b/src/plugins/tlsopenssl/tls_async.c @@ -143,7 +143,7 @@ openssl_engine_register (char *engine_name, char *algorithm) if (registered < 0) { clib_error ("engine %s is not regisered in VPP", engine_name); - return 0; + return -1; } ENGINE_load_builtin_engines (); @@ -153,7 +153,7 @@ openssl_engine_register (char *engine_name, char *algorithm) if (engine == NULL) { clib_warning ("Failed to find engine ENGINE_by_id %s", engine_name); - return 0; + return -1; } om->engine = engine; @@ -168,7 +168,7 @@ openssl_engine_register (char *engine_name, char *algorithm) { clib_warning ("Failed to set engine %s algorithm %s\n", engine_name, algorithm); - return 0; + return -1; } } else @@ -177,13 +177,13 @@ openssl_engine_register (char *engine_name, char *algorithm) { clib_warning ("Failed to set engine %s to all algorithm", engine_name); - return 0; + return -1; } } om->start_polling = 1; - return 1; + return 0; } diff --git a/src/plugins/tlsopenssl/tls_openssl.api b/src/plugins/tlsopenssl/tls_openssl.api new file mode 100644 index 00000000000..7de77522c9c --- /dev/null +++ b/src/plugins/tlsopenssl/tls_openssl.api @@ -0,0 +1,31 @@ +/* Define TLS OpenSSL binary API to control the feature */ + +option version = "2.0.0"; + +define tls_openssl_set_engine { + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* if async is enabled */ + u32 async; + + /* engine name */ + u8 engine[64]; + + /* algorithm */ + u8 algorithm[64]; + + /* cipher */ + u8 ciphers[64]; +}; + +define tls_openssl_set_engine_reply { + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; +}; diff --git a/src/plugins/tlsopenssl/tls_openssl.c b/src/plugins/tlsopenssl/tls_openssl.c index 8d0fd36a04f..589d76de860 100644 --- a/src/plugins/tlsopenssl/tls_openssl.c +++ b/src/plugins/tlsopenssl/tls_openssl.c @@ -16,6 +16,7 @@ #include #include #include + #ifdef HAVE_OPENSSL_ASYNC #include #endif @@ -26,9 +27,9 @@ #include #include -#define MAX_CRYPTO_LEN 16 +#define MAX_CRYPTO_LEN 64 -static openssl_main_t openssl_main; +openssl_main_t openssl_main; static u32 openssl_ctx_alloc (void) { @@ -850,7 +851,7 @@ tls_init_ca_chain (void) return (rv < 0 ? -1 : 0); } -static int +int tls_openssl_set_ciphers (char *ciphers) { openssl_main_t *om = &openssl_main; @@ -876,8 +877,10 @@ tls_openssl_init (vlib_main_t * vm) { vlib_thread_main_t *vtm = vlib_get_thread_main (); openssl_main_t *om = &openssl_main; + clib_error_t *error = 0; u32 num_threads; + error = tls_openssl_api_init (vm); num_threads = 1 /* main thread */ + vtm->n_threads; SSL_library_init (); @@ -899,7 +902,7 @@ tls_openssl_init (vlib_main_t * vm) tls_openssl_set_ciphers ("ALL:!ADH:!LOW:!EXP:!MD5:!RC4-SHA:!DES-CBC3-SHA:@STRENGTH"); - return 0; + return error; } /* *INDENT-OFF* */ VLIB_INIT_FUNCTION (tls_openssl_init) = @@ -961,7 +964,7 @@ tls_openssl_set_command_fn (vlib_main_t * vm, unformat_input_t * input, } else { - if (!openssl_engine_register (engine_name, engine_alg)) + if (openssl_engine_register (engine_name, engine_alg) < 0) { return clib_error_return (0, "failed to register %s polling", engine_name); diff --git a/src/plugins/tlsopenssl/tls_openssl.h b/src/plugins/tlsopenssl/tls_openssl.h index 66e0b364cba..e392b9ae4f2 100644 --- a/src/plugins/tlsopenssl/tls_openssl.h +++ b/src/plugins/tlsopenssl/tls_openssl.h @@ -45,6 +45,9 @@ typedef struct openssl_main_ openssl_ctx_t ***ctx_pool; openssl_listen_ctx_t *lctx_pool; + /* API message ID base */ + u16 msg_id_base; + X509_STORE *cert_store; u8 *ciphers; int engine_init; @@ -69,6 +72,8 @@ int tls_async_openssl_callback (SSL * s, void *evt); void openssl_polling_start (ENGINE * engine); int openssl_engine_register (char *engine, char *alg); void openssl_async_node_enable_disable (u8 is_en); +clib_error_t *tls_openssl_api_init (vlib_main_t * vm); +int tls_openssl_set_ciphers (char *ciphers); /* * fd.io coding-style-patch-verification: ON diff --git a/src/plugins/tlsopenssl/tls_openssl_all_api_h.h b/src/plugins/tlsopenssl/tls_openssl_all_api_h.h new file mode 100644 index 00000000000..96b63f2e1a4 --- /dev/null +++ b/src/plugins/tlsopenssl/tls_openssl_all_api_h.h @@ -0,0 +1,18 @@ +/* + * tls_openssl_all_api_h.h - skeleton vpp engine plug-in api #include file + * + * Copyright (c) 2019 Intel Corporation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Include the generated file, see BUILT_SOURCES in Makefile.am */ +#include diff --git a/src/plugins/tlsopenssl/tls_openssl_api.c b/src/plugins/tlsopenssl/tls_openssl_api.c new file mode 100644 index 00000000000..9474aae2faf --- /dev/null +++ b/src/plugins/tlsopenssl/tls_openssl_api.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +/* define message IDs */ +#include + +/* define message structures */ +#define vl_typedefs +#include +#undef vl_typedefs + +/* define generated endian-swappers */ +#define vl_endianfun +#include +#undef vl_endianfun + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) +#define vl_printfun +#include +#undef vl_printfun + +/* Get the API version number */ +#define vl_api_version(n, v) static u32 api_version = (v); +#include +#undef vl_api_version + +#define REPLY_MSG_ID_BASE om->msg_id_base +#include + +/* List of message types that this plugin understands */ + +#define foreach_tls_openssl_plugin_api_msg \ + _ (TLS_OPENSSL_SET_ENGINE, tls_openssl_set_engine) + +extern openssl_main_t openssl_main; + +/* API message handler */ +static void +vl_api_tls_openssl_set_engine_t_handler (vl_api_tls_openssl_set_engine_t *mp) +{ + vl_api_tls_openssl_set_engine_reply_t *rmp; + openssl_main_t *om = &openssl_main; + char *engine, *alg, *ciphers; + int rv; + + engine = (char *)&mp->engine; + alg = (char *)&mp->algorithm; + ciphers = (char *)&mp->ciphers; + + if (mp->async) + { + om->async = 1; + openssl_async_node_enable_disable (1); + } + + if (ciphers[0]) + tls_openssl_set_ciphers (ciphers); + rv = openssl_engine_register (engine, alg); + + REPLY_MACRO (VL_API_TLS_OPENSSL_SET_ENGINE_REPLY); +} + +/* Set up the API message handling tables */ +static clib_error_t *tls_openssl_plugin_api_hookup (vlib_main_t *vm) +{ + openssl_main_t *om = &openssl_main; +#define _(N, n) \ + vl_msg_api_set_handlers ((VL_API_##N + om->msg_id_base), #n, \ + vl_api_##n##_t_handler, vl_noop_handler, \ + vl_api_##n##_t_endian, vl_api_##n##_t_print, \ + sizeof (vl_api_##n##_t), 1); + foreach_tls_openssl_plugin_api_msg; +#undef _ + + return 0; +} + +#define vl_msg_name_crc_list +#include +#undef vl_msg_name_crc_list + +static void setup_message_id_table (openssl_main_t *om, api_main_t *am) +{ +#define _(id, n, crc) \ + vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + om->msg_id_base); + foreach_vl_msg_name_crc_tls_openssl; +#undef _ +} + +clib_error_t *tls_openssl_api_init (vlib_main_t *vm) +{ + openssl_main_t *om = &openssl_main; + clib_error_t *error = 0; + u8 *name; + + name = format (0, "tls_openssl_%08x%c", api_version, 0); + + /* Ask for a correctly-sized block of API message decode slots */ + om->msg_id_base = + vl_msg_api_get_msg_ids ((char *)name, VL_MSG_FIRST_AVAILABLE); + + error = tls_openssl_plugin_api_hookup (vm); + + /* Add our API messages to the global name_crc hash table */ + setup_message_id_table (om, &api_main); + vec_free (name); + + return error; +} diff --git a/src/plugins/tlsopenssl/tls_openssl_msg_enum.h b/src/plugins/tlsopenssl/tls_openssl_msg_enum.h new file mode 100644 index 00000000000..d1f74d0b4dd --- /dev/null +++ b/src/plugins/tlsopenssl/tls_openssl_msg_enum.h @@ -0,0 +1,30 @@ +/* + * tlsopenssl_msg_enum.h - skeleton vpp engine plug-in message enumeration + * + * Copyright (c) 2019 Intel Corportation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef included_tlsopenssl_msg_enum_h +#define included_tlsopenssl_msg_enum_h + +#include + +#define vl_msg_id(n,h) n, +typedef enum { +#include + /* We'll want to know how many messages IDs we need... */ + VL_MSG_FIRST_AVAILABLE, +} vl_msg_id_t; +#undef vl_msg_id + +#endif /* included_tlsopenssl_msg_enum_h*/ diff --git a/src/plugins/tlsopenssl/tls_openssl_test.c b/src/plugins/tlsopenssl/tls_openssl_test.c new file mode 100644 index 00000000000..1c810c9a7f8 --- /dev/null +++ b/src/plugins/tlsopenssl/tls_openssl_test.c @@ -0,0 +1,200 @@ +/* + * tls_openssl_test.c - skeleton vpp-api-test plug-in + * + * Copyright (c) 2019 Intel Corporation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include + +uword unformat_sw_if_index (unformat_input_t * input, va_list * args); + +/* Declare message IDs */ +#include + +/* define message structures */ +#define vl_typedefs +#include +#undef vl_typedefs + +/* declare message handlers for each api */ + +#define vl_endianfun /* define message structures */ +#include +#undef vl_endianfun + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) +#define vl_printfun +#include +#undef vl_printfun + +/* Get the API version number. */ +#define vl_api_version(n,v) static u32 api_version=(v); +#include +#undef vl_api_version + +typedef struct +{ + /* API message ID base */ + u16 msg_id_base; + vat_main_t *vat_main; +} tls_openssl_test_main_t; + +tls_openssl_test_main_t tls_openssl_test_main; + +#define __plugin_msg_base tls_openssl_test_main.msg_id_base +#include + +#define foreach_standard_reply_retval_handler \ +_(tls_openssl_set_engine_reply) + +#define _(n) \ + static void vl_api_##n##_t_handler \ + (vl_api_##n##_t * mp) \ + { \ + vat_main_t * vam = tls_openssl_test_main.vat_main; \ + i32 retval = ntohl(mp->retval); \ + if (vam->async_mode) { \ + vam->async_errors += (retval < 0); \ + } else { \ + vam->retval = retval; \ + vam->result_ready = 1; \ + } \ + } +foreach_standard_reply_retval_handler; +#undef _ + +/* + * Table of message reply handlers, must include boilerplate handlers + * we just generated + */ +#define foreach_vpe_api_reply_msg \ +_(TLS_OPENSSL_SET_ENGINE_REPLY, tls_openssl_set_engine_reply) + + +static int +api_tls_openssl_set_engine (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_tls_openssl_set_engine_t *mp; + u8 *engine_name = 0; + u8 *engine_alg = 0; + u8 *ciphers = 0; + u32 async = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "engine %s", &engine_name)) + ; + else if (unformat (line_input, "async")) + { + async = 1; + } + else if (unformat (line_input, "alg %s", &engine_alg)) + ; + else if (unformat (line_input, "ciphers %s", &ciphers)) + ; + else + { + errmsg ("unknown input `%U'", format_unformat_error, line_input); + return -99; + } + } + + if (engine_name == 0) + { + errmsg ("Must specify engine name"); + return -99; + } + + if (engine_alg == 0) + engine_alg = format (0, "ALL"); + else + { + for (int i = 0; i < strnlen ((char *) engine_alg, 64); i++) + engine_alg[i] = toupper (engine_alg[i]); + } + + + /* Construct the API message */ + M (TLS_OPENSSL_SET_ENGINE, mp); + mp->async = async; + + clib_memcpy_fast (mp->engine, engine_name, + strnlen ((const char *) engine_name, 64)); + + clib_memcpy_fast (mp->algorithm, engine_alg, + strnlen ((const char *) engine_alg, 64)); + + if (ciphers) + clib_memcpy_fast (mp->ciphers, ciphers, + strnlen ((const char *) ciphers, 64)); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +/* + * List of messages that the api test plugin sends, + * and that the data plane plugin processes + */ +#define foreach_vpe_api_msg \ +_(tls_openssl_set_engine, "tls openssl set [engine ]" \ +"[alg [algorithm] [async]\n") + +static void +tls_openssl_api_hookup (vat_main_t * vam) +{ + tls_openssl_test_main_t *htmp = &tls_openssl_test_main; + /* Hook up handlers for replies from the data plane plug-in */ +#define _(N,n) \ + vl_msg_api_set_handlers((VL_API_##N + htmp->msg_id_base), \ + #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_api_##n##_t_endian, \ + vl_api_##n##_t_print, \ + sizeof(vl_api_##n##_t), 1); + foreach_vpe_api_reply_msg; +#undef _ + + /* API messages we can send */ +#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n); + foreach_vpe_api_msg; +#undef _ + + /* Help strings */ +#define _(n,h) hash_set_mem (vam->help_by_name, #n, h); + foreach_vpe_api_msg; +#undef _ +} + +VAT_PLUGIN_REGISTER (tls_openssl); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- 2.16.6