From: Ping Yu Date: Sat, 1 Dec 2018 00:16:17 +0000 (-0500) Subject: Add TLS support for VCL X-Git-Tag: v19.04-rc0~50 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=34a3a08d993cbbb3846b83b69b5338d452463e15 Add TLS support for VCL Ater this patch, vcl_test_client and vcl_test_server can work happily with TLS connection. "-S" is to indicate TLS connection. Change-Id: I761894b0b5929912691625f0fe63604725b55978 Signed-off-by: Ping Yu --- diff --git a/src/vcl/vcl_bapi.c b/src/vcl/vcl_bapi.c index b513bd7a6b3..de5e80a55b3 100644 --- a/src/vcl/vcl_bapi.c +++ b/src/vcl/vcl_bapi.c @@ -367,6 +367,31 @@ vl_api_connect_session_reply_t_handler (vl_api_connect_sock_reply_t * mp) ntohl (mp->retval)); } +static void + vl_api_application_tls_cert_add_reply_t_handler + (vl_api_application_tls_cert_add_reply_t * mp) +{ + if (mp->retval) + { + clib_warning ("VCL<%d>: add cert failed: %U", getpid (), + format_api_error, ntohl (mp->retval)); + return; + } +} + +static void + vl_api_application_tls_key_add_reply_t_handler + (vl_api_application_tls_key_add_reply_t * mp) +{ + if (mp->retval) + { + clib_warning ("VCL<%d>: add key failed: %U", getpid (), + format_api_error, ntohl (mp->retval)); + return; + } + +} + #define foreach_sock_msg \ _(SESSION_ENABLE_DISABLE_REPLY, session_enable_disable_reply) \ _(BIND_SOCK_REPLY, bind_sock_reply) \ @@ -375,6 +400,8 @@ _(CONNECT_SESSION_REPLY, connect_session_reply) \ _(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \ _(APPLICATION_ATTACH_REPLY, application_attach_reply) \ _(APPLICATION_DETACH_REPLY, application_detach_reply) \ +_(APPLICATION_TLS_CERT_ADD_REPLY, application_tls_cert_add_reply) \ +_(APPLICATION_TLS_KEY_ADD_REPLY, application_tls_key_add_reply) \ _(MAP_ANOTHER_SEGMENT, map_another_segment) \ _(UNMAP_SEGMENT, unmap_segment) \ _(APP_CUT_THROUGH_REGISTRATION_ADD, app_cut_through_registration_add) \ @@ -444,6 +471,7 @@ vppcom_app_send_attach (void) bmp->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = vcm->cfg.preallocated_fifo_pairs; bmp->options[APP_OPTIONS_EVT_QUEUE_SIZE] = vcm->cfg.event_queue_size; + bmp->options[APP_OPTIONS_TLS_ENGINE] = TLS_ENGINE_OPENSSL; if (nsid_len) { bmp->namespace_id_len = nsid_len; @@ -596,6 +624,42 @@ vppcom_send_accept_session_reply (u64 handle, u32 context, int retval) vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & rmp); } +void +vppcom_send_application_tls_cert_add (vcl_session_t * session, char *cert, + u32 cert_len) +{ + vcl_worker_t *wrk = vcl_worker_get_current (); + vl_api_application_tls_cert_add_t *cert_mp; + + cert_mp = vl_msg_api_alloc (sizeof (*cert_mp) + cert_len); + clib_memset (cert_mp, 0, sizeof (*cert_mp)); + cert_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_CERT_ADD); + cert_mp->client_index = wrk->my_client_index; + cert_mp->context = session->session_index; + cert_mp->cert_len = clib_host_to_net_u16 (cert_len); + clib_memcpy_fast (cert_mp->cert, cert, cert_len); + vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & cert_mp); + +} + +void +vppcom_send_application_tls_key_add (vcl_session_t * session, char *key, + u32 key_len) +{ + vcl_worker_t *wrk = vcl_worker_get_current (); + vl_api_application_tls_key_add_t *key_mp; + + key_mp = vl_msg_api_alloc (sizeof (*key_mp) + key_len); + clib_memset (key_mp, 0, sizeof (*key_mp)); + key_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_KEY_ADD); + key_mp->client_index = wrk->my_client_index; + key_mp->context = session->session_index; + key_mp->key_len = clib_host_to_net_u16 (key_len); + clib_memcpy_fast (key_mp->key, key, key_len); + vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & key_mp); + +} + u32 vcl_max_nsid_len (void) { diff --git a/src/vcl/vcl_private.h b/src/vcl/vcl_private.h index 34098ac44f1..9dce5182193 100644 --- a/src/vcl/vcl_private.h +++ b/src/vcl/vcl_private.h @@ -557,6 +557,11 @@ void vppcom_send_bind_sock (vcl_session_t * session); void vppcom_send_unbind_sock (u64 vpp_handle); void vppcom_api_hookup (void); void vppcom_send_accept_session_reply (u64 vpp_handle, u32 context, int rv); +void vppcom_send_application_tls_cert_add (vcl_session_t * session, + char *cert, u32 cert_len); +void +vppcom_send_application_tls_key_add (vcl_session_t * session, char *key, + u32 key_len); void vcl_send_app_worker_add_del (u8 is_add); void vcl_send_child_worker_del (vcl_worker_t * wrk); diff --git a/src/vcl/vcl_test.h b/src/vcl/vcl_test.h index 9d28b262e3a..638d519d95c 100644 --- a/src/vcl/vcl_test.h +++ b/src/vcl/vcl_test.h @@ -89,6 +89,7 @@ typedef struct __attribute__ ((packed)) uint32_t verbose; uint32_t address_ip6; uint32_t transport_udp; + uint32_t transport_tls; uint64_t rxbuf_size; uint64_t txbuf_size; uint64_t num_writes; @@ -120,6 +121,66 @@ typedef struct vcl_test_stats_t stats; } vcl_test_session_t; + +/* + * TLS server cert and keys to be used for testing only + */ +char vcl_test_crt_rsa[] = + "-----BEGIN CERTIFICATE-----\r\n" + "MIID5zCCAs+gAwIBAgIJALeMYCEHrTtJMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD\r\n" + "VQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQK\r\n" + "DAVDaXNjbzEOMAwGA1UECwwFZmQuaW8xFjAUBgNVBAMMDXRlc3R0bHMuZmQuaW8x\r\n" + "IjAgBgkqhkiG9w0BCQEWE3ZwcC1kZXZAbGlzdHMuZmQuaW8wHhcNMTgwMzA1MjEx\r\n" + "NTEyWhcNMjgwMzAyMjExNTEyWjCBiTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNB\r\n" + "MREwDwYDVQQHDAhTYW4gSm9zZTEOMAwGA1UECgwFQ2lzY28xDjAMBgNVBAsMBWZk\r\n" + "LmlvMRYwFAYDVQQDDA10ZXN0dGxzLmZkLmlvMSIwIAYJKoZIhvcNAQkBFhN2cHAt\r\n" + "ZGV2QGxpc3RzLmZkLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\r\n" + "4C1k8a1DuStgggqT4o09fP9sJ2dC54bxhS/Xk2VEfaIZ222WSo4X/syRVfVy9Yah\r\n" + "cpI1zJ/RDxaZSFhgA+nPZBrFMsrULkrdAOpOVj8eDEp9JuWdO2ODSoFnCvLxcYWB\r\n" + "Yc5kHryJpEaGJl1sFQSesnzMFty/59ta0stk0Fp8r5NhIjWvSovGzPo6Bhz+VS2c\r\n" + "ebIZh4x1t2hHaFcgm0qJoJ6DceReWCW8w+yOVovTolGGq+bpb2Hn7MnRSZ2K2NdL\r\n" + "+aLXpkZbS/AODP1FF2vTO1mYL290LO7/51vJmPXNKSDYMy5EvILr5/VqtjsFCwRL\r\n" + "Q4jcM/+GeHSAFWx4qIv0BwIDAQABo1AwTjAdBgNVHQ4EFgQUWa1SOB37xmT53tZQ\r\n" + "aXuLLhRI7U8wHwYDVR0jBBgwFoAUWa1SOB37xmT53tZQaXuLLhRI7U8wDAYDVR0T\r\n" + "BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoUht13W4ya27NVzQuCMvqPWL3VM4\r\n" + "3xbPFk02FaGz/WupPu276zGlzJAZrbuDcQowwwU1Ni1Yygxl96s1c2M5rHDTrOKG\r\n" + "rK0hbkSFBo+i6I8u4HiiQ4rYmG0Hv6+sXn3of0HsbtDPGgWZoipPWDljPYEURu3e\r\n" + "3HRe/Dtsj9CakBoSDzs8ndWaBR+f4sM9Tk1cjD46Gq2T/qpSPXqKxEUXlzhdCAn4\r\n" + "twub17Bq2kykHpppCwPg5M+v30tHG/R2Go15MeFWbEJthFk3TZMjKL7UFs7fH+x2\r\n" + "wSonXb++jY+KmCb93C+soABBizE57g/KmiR2IxQ/LMjDik01RSUIaM0lLA==\r\n" + "-----END CERTIFICATE-----\r\n"; +uint32_t vcl_test_crt_rsa_len = sizeof (vcl_test_crt_rsa); + +char vcl_test_key_rsa[] = + "-----BEGIN PRIVATE KEY-----\r\n" + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgLWTxrUO5K2CC\r\n" + "CpPijT18/2wnZ0LnhvGFL9eTZUR9ohnbbZZKjhf+zJFV9XL1hqFykjXMn9EPFplI\r\n" + "WGAD6c9kGsUyytQuSt0A6k5WPx4MSn0m5Z07Y4NKgWcK8vFxhYFhzmQevImkRoYm\r\n" + "XWwVBJ6yfMwW3L/n21rSy2TQWnyvk2EiNa9Ki8bM+joGHP5VLZx5shmHjHW3aEdo\r\n" + "VyCbSomgnoNx5F5YJbzD7I5Wi9OiUYar5ulvYefsydFJnYrY10v5otemRltL8A4M\r\n" + "/UUXa9M7WZgvb3Qs7v/nW8mY9c0pINgzLkS8guvn9Wq2OwULBEtDiNwz/4Z4dIAV\r\n" + "bHioi/QHAgMBAAECggEBAMzGipP8+oT166U+NlJXRFifFVN1DvdhG9PWnOxGL+c3\r\n" + "ILmBBC08WQzmHshPemBvR6DZkA1H23cV5JTiLWrFtC00CvhXsLRMrE5+uWotI6yE\r\n" + "iofybMroHvD6/X5R510UX9hQ6MHu5ShLR5VZ9zXHz5MpTmB/60jG5dLx+jgcwBK8\r\n" + "LuGv2YB/WCUwT9QJ3YU2eaingnXtz/MrFbkbltrqlnBdlD+kTtw6Yac9y1XuuQXc\r\n" + "BPeulLNDuPolJVWbUvDBZrpt2dXTgz8ws1sv+wCNE0xwQJsqW4Nx3QkpibUL9RUr\r\n" + "CVbKlNfa9lopT6nGKlgX69R/uH35yh9AOsfasro6w0ECgYEA82UJ8u/+ORah+0sF\r\n" + "Q0FfW5MTdi7OAUHOz16pUsGlaEv0ERrjZxmAkHA/VRwpvDBpx4alCv0Hc39PFLIk\r\n" + "nhSsM2BEuBkTAs6/GaoNAiBtQVE/hN7awNRWVmlieS0go3Y3dzaE9IUMyj8sPOFT\r\n" + "5JdJ6BM69PHKCkY3dKdnnfpFEuECgYEA68mRpteunF1mdZgXs+WrN+uLlRrQR20F\r\n" + "ZyMYiUCH2Dtn26EzA2moy7FipIIrQcX/j+KhYNGM3e7MU4LymIO29E18mn8JODnH\r\n" + "sQOXzBTsf8A4yIVMkcuQD3bfb0JiUGYUPOidTp2N7IJA7+6Yc3vQOyb74lnKnJoO\r\n" + "gougPT2wS+cCgYAn7muzb6xFsXDhyW0Tm6YJYBfRS9yAWEuVufINobeBZPSl2cN1\r\n" + "Jrnw+HlrfTNbrJWuJmjtZJXUXQ6cVp2rUbjutNyRV4vG6iRwEXYQ40EJdkr1gZpi\r\n" + "CHQhuShuuPih2MNAy7EEbM+sXrDjTBR3bFqzuHPzu7dp+BshCFX3lRfAAQKBgGQt\r\n" + "K5i7IhCFDjb/+3IPLgOAK7mZvsvZ4eXD33TQ2eZgtut1PXtBtNl17/b85uv293Fm\r\n" + "VDISVcsk3eLNS8zIiT6afUoWlxAwXEs0v5WRfjl4radkGvgGiJpJYvyeM67877RB\r\n" + "EDSKc/X8ESLfOB44iGvZUEMG6zJFscx9DgN25iQZAoGAbyd+JEWwdVH9/K3IH1t2\r\n" + "PBkZX17kNWv+iVM1WyFjbe++vfKZCrOJiyiqhDeEqgrP3AuNMlaaduC3VRC3G5oV\r\n" + "Mj1tlhDWQ/qhvKdCKNdIVQYDE75nw+FRWV8yYkHAnXYW3tNoweDIwixE0hkPR1bc\r\n" + "oEjPLVNtx8SOj/M4rhaPT3I=\r\n" "-----END PRIVATE KEY-----\r\n"; +uint32_t vcl_test_key_rsa_len = sizeof (vcl_test_key_rsa); + static inline void vcl_test_stats_accumulate (vcl_test_stats_t * accum, vcl_test_stats_t * incr) { diff --git a/src/vcl/vcl_test_client.c b/src/vcl/vcl_test_client.c index e1d7b3b3a81..70fe75d9acd 100644 --- a/src/vcl/vcl_test_client.c +++ b/src/vcl/vcl_test_client.c @@ -711,10 +711,11 @@ print_usage_and_exit (void) " OPTIONS\n" " -h Print this message and exit.\n" " -6 Use IPv6\n" - " -u Use UDP transport layer\n" " -c Print test config before test.\n" " -w Write test results to .\n" " -X Exit after running test.\n" + " -D Use UDP transport layer\n" + " -S Use TLS transport layer\n" " -E Run Echo test.\n" " -N Test Cfg: number of writes.\n" " -R Test Cfg: rx buffer size.\n" @@ -732,7 +733,7 @@ vtc_process_opts (vcl_test_client_main_t * vcm, int argc, char **argv) int c, v; opterr = 0; - while ((c = getopt (argc, argv, "chn:w:XE:I:N:R:T:UBV6D")) != -1) + while ((c = getopt (argc, argv, "chn:w:XE:I:N:R:T:UBV6DS")) != -1) switch (c) { case 'c': @@ -873,6 +874,10 @@ vtc_process_opts (vcl_test_client_main_t * vcm, int argc, char **argv) ctrl->cfg.transport_udp = 1; break; + case 'S': + ctrl->cfg.transport_tls = 1; + break; + case '?': switch (optopt) { @@ -902,7 +907,19 @@ vtc_process_opts (vcl_test_client_main_t * vcm, int argc, char **argv) vtwrn ("Insufficient number of arguments!"); print_usage_and_exit (); } - vcm->proto = ctrl->cfg.transport_udp ? VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP; + + if (ctrl->cfg.transport_udp) + { + vcm->proto = VPPCOM_PROTO_UDP; + } + else if (ctrl->cfg.transport_tls) + { + vcm->proto = VPPCOM_PROTO_TLS; + } + else + { + vcm->proto = VPPCOM_PROTO_TCP; + } memset (&vcm->server_addr, 0, sizeof (vcm->server_addr)); if (ctrl->cfg.address_ip6) @@ -988,6 +1005,15 @@ main (int argc, char **argv) if (ctrl->fd < 0) vtfail ("vppcom_session_create()", ctrl->fd); + if (vcm->proto == VPPCOM_PROTO_TLS) + { + vppcom_session_tls_add_cert (ctrl->fd, vcl_test_crt_rsa, + vcl_test_crt_rsa_len); + vppcom_session_tls_add_key (ctrl->fd, vcl_test_key_rsa, + vcl_test_key_rsa_len); + } + + vtinf ("Connecting to server..."); rv = vppcom_session_connect (ctrl->fd, &vcm->server_endpt); if (rv) diff --git a/src/vcl/vcl_test_server.c b/src/vcl/vcl_test_server.c index 54f164e43c1..280944156c8 100644 --- a/src/vcl/vcl_test_server.c +++ b/src/vcl/vcl_test_server.c @@ -320,7 +320,8 @@ print_usage_and_exit (void) " -h Print this message and exit.\n" " -6 Use IPv6\n" " -w Number of workers\n" - " -u Use UDP transport layer\n"); + " -D Use UDP transport layer\n" + " -S Use TLS transport layer\n"); exit (1); } @@ -370,7 +371,7 @@ vcl_test_server_process_opts (vcl_test_server_main_t * vsm, int argc, vsm->cfg.proto = VPPCOM_PROTO_TCP; opterr = 0; - while ((c = getopt (argc, argv, "6Dsw:")) != -1) + while ((c = getopt (argc, argv, "6DSsw:")) != -1) switch (c) { case '6': @@ -381,6 +382,10 @@ vcl_test_server_process_opts (vcl_test_server_main_t * vsm, int argc, vsm->cfg.proto = VPPCOM_PROTO_UDP; break; + case 'S': + vsm->cfg.proto = VPPCOM_PROTO_TLS; + break; + case 'w': v = atoi (optarg); if (v > 1) @@ -499,6 +504,15 @@ vts_worker_init (vcl_test_server_worker_t * wrk) if (wrk->listen_fd < 0) vtfail ("vppcom_session_create()", wrk->listen_fd); + + if (vsm->cfg.proto == VPPCOM_PROTO_TLS) + { + vppcom_session_tls_add_cert (wrk->listen_fd, vcl_test_crt_rsa, + vcl_test_crt_rsa_len); + vppcom_session_tls_add_key (wrk->listen_fd, vcl_test_key_rsa, + vcl_test_key_rsa_len); + } + rv = vppcom_session_bind (wrk->listen_fd, &vsm->cfg.endpt); if (rv < 0) vtfail ("vppcom_session_bind()", rv); diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index be7293679f8..70afdce7832 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -1191,7 +1191,7 @@ vppcom_session_bind (uint32_t session_handle, vppcom_endpt_t * ep) format_ip46_address, &session->transport.lcl_ip, session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6, clib_net_to_host_u16 (session->transport.lcl_port), - session->session_type ? "UDP" : "TCP"); + vppcom_proto_str (session->session_type)); vcl_evt (VCL_EVT_BIND, session); if (session->session_type == VPPCOM_PROTO_UDP) @@ -1246,6 +1246,55 @@ vppcom_session_listen (uint32_t listen_sh, uint32_t q_len) return VPPCOM_OK; } +int +vppcom_session_tls_add_cert (uint32_t session_handle, char *cert, + uint32_t cert_len) +{ + + vcl_worker_t *wrk = vcl_worker_get_current (); + vcl_session_t *session = 0; + + session = vcl_session_get_w_handle (wrk, session_handle); + if (!session) + return VPPCOM_EBADFD; + + if (cert_len == 0 || cert_len == ~0) + return VPPCOM_EBADFD; + + /* + * Send listen request to vpp and wait for reply + */ + vppcom_send_application_tls_cert_add (session, cert, cert_len); + + return VPPCOM_OK; + +} + +int +vppcom_session_tls_add_key (uint32_t session_handle, char *key, + uint32_t key_len) +{ + + vcl_worker_t *wrk = vcl_worker_get_current (); + vcl_session_t *session = 0; + + session = vcl_session_get_w_handle (wrk, session_handle); + if (!session) + return VPPCOM_EBADFD; + + if (key_len == 0 || key_len == ~0) + return VPPCOM_EBADFD; + + /* + * Send listen request to vpp and wait for reply + */ + vppcom_send_application_tls_key_add (session, key, key_len); + + return VPPCOM_OK; + + +} + static int validate_args_session_accept_ (vcl_worker_t * wrk, vcl_session_t * listen_session) @@ -1420,7 +1469,7 @@ vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep) &session->transport.rmt_ip, session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6, clib_net_to_host_u16 (session->transport.rmt_port), - session->session_type ? "UDP" : "TCP", session->session_state, + vppcom_proto_str (session->session_type), session->session_state, vppcom_session_state_str (session->session_state)); return VPPCOM_OK; } @@ -1442,7 +1491,7 @@ vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep) &session->transport.rmt_ip, session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6, clib_net_to_host_u16 (session->transport.rmt_port), - session->session_type ? "UDP" : "TCP"); + vppcom_proto_str (session->session_type)); /* * Send connect request and wait for reply from vpp diff --git a/src/vcl/vppcom.h b/src/vcl/vppcom.h index 00527f4ecfb..641946be55a 100644 --- a/src/vcl/vppcom.h +++ b/src/vcl/vppcom.h @@ -48,6 +48,10 @@ typedef enum { VPPCOM_PROTO_TCP = 0, VPPCOM_PROTO_UDP, + VPPCOM_PROTO_SCTP, + VPPCOM_PROTO_NONE, + VPPCOM_PROTO_TLS, + VPPCOM_PROTO_UDPC } vppcom_proto_t; static inline char * @@ -58,10 +62,19 @@ vppcom_proto_str (vppcom_proto_t proto) switch (proto) { case VPPCOM_PROTO_TCP: - proto_str = "VPPCOM_PROTO_TCP"; + proto_str = "TCP"; break; case VPPCOM_PROTO_UDP: - proto_str = "VPPCOM_PROTO_UDP"; + proto_str = "UDP"; + break; + case VPPCOM_PROTO_SCTP: + proto_str = "SCTP"; + break; + case VPPCOM_PROTO_TLS: + proto_str = "TLS"; + break; + case VPPCOM_PROTO_UDPC: + proto_str = "UDPC"; break; default: proto_str = "UNKNOWN"; @@ -271,6 +284,10 @@ extern int vppcom_session_read_segments (uint32_t session_handle, vppcom_data_segments_t ds); extern void vppcom_session_free_segments (uint32_t session_handle, vppcom_data_segments_t ds); +extern int vppcom_session_tls_add_cert (uint32_t session_handle, char *cert, + uint32_t cert_len); +extern int vppcom_session_tls_add_key (uint32_t session_handle, char *key, + uint32_t key_len); extern int vppcom_data_segment_copy (void *buf, vppcom_data_segments_t ds, uint32_t max_bytes);