From: okhowang(王沛文) Date: Thu, 28 May 2020 09:14:46 +0000 (+0800) Subject: fix build system and add test and cleanup code X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=028385f685585b4b247bdd4acae3cd12de2b4da4;p=libevent fix build system and add test and cleanup code --- diff --git a/CMakeLists.txt b/CMakeLists.txt index f3072aa4..90052916 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -991,7 +991,9 @@ endif() if (NOT EVENT__DISABLE_MBEDTLS) add_event_library(event_mbedtls - LIBRARIES event_core_shared ${MBEDTLS_LIBRARIES} + INNER_LIBRARIES event_core + OUTER_INCLUDES ${MBEDTLS_INCLUDE_DIR} + LIBRARIES ${MBEDTLS_LIBRARIES} SOURCES ${SRC_MBEDTLS}) endif() @@ -1038,8 +1040,8 @@ macro(add_sample_prog ssl name) ${LIB_APPS} ${LIB_PLATFORM}) - if (${ssl}) - target_link_libraries(${name} event_openssl) + if (TARGET ${ssl}) + target_link_libraries(${name} ${ssl}) if(WIN32) target_link_libraries(${name} crypt32) endif() @@ -1062,13 +1064,18 @@ if (NOT EVENT__DISABLE_SAMPLES) endif() if (NOT EVENT__DISABLE_OPENSSL) - add_sample_prog(ON https-client + add_sample_prog(event_openssl https-client sample/https-client.c sample/openssl_hostname_validation.c sample/hostcheck.c) - add_sample_prog(ON le-proxy + add_sample_prog(event_openssl le-proxy sample/le-proxy.c) - add_sample_prog(ON becat sample/becat.c ${WIN32_GETOPT}) + add_sample_prog(event_openssl becat sample/becat.c ${WIN32_GETOPT}) + endif() + + if (NOT EVENT__DISABLE_MBEDTLS) + add_sample_prog(event_mbedtls ssl-client-mbedtls + sample/ssl-client-mbedtls.c) endif() set(SAMPLES_WOPT @@ -1180,7 +1187,11 @@ if (NOT EVENT__DISABLE_TESTS) endif() if (NOT EVENT__DISABLE_OPENSSL) - list(APPEND SRC_REGRESS test/regress_ssl.c) + list(APPEND SRC_REGRESS test/regress_openssl.c) + endif() + + if (NOT EVENT__DISABLE_MBEDTLS) + list(APPEND SRC_REGRESS test/regress_mbedtls.c) endif() add_executable(regress ${SRC_REGRESS}) @@ -1193,6 +1204,9 @@ if (NOT EVENT__DISABLE_TESTS) if (NOT EVENT__DISABLE_OPENSSL) target_link_libraries(regress event_openssl) endif() + if (NOT EVENT__DISABLE_MBEDTLS) + target_link_libraries(regress event_mbedtls) + endif() if (CMAKE_USE_PTHREADS_INIT) target_link_libraries(regress event_pthreads) endif() diff --git a/Makefile.am b/Makefile.am index 61d4ff81..a004e898 100644 --- a/Makefile.am +++ b/Makefile.am @@ -101,7 +101,8 @@ LIBEVENT_PKGCONFIG=libevent.pc libevent_core.pc libevent_extra.pc # included from other files. PLATFORM_DEPENDENT_SRC = \ arc4random.c \ - epoll_sub.c + epoll_sub.c \ + test/regress_ssl.c CMAKE_FILES = \ cmake/AddCompilerFlags.cmake \ @@ -116,6 +117,7 @@ CMAKE_FILES = \ cmake/CodeCoverage.cmake \ cmake/COPYING-CMAKE-SCRIPTS \ cmake/Copyright.txt \ + cmake/FindMbedTLS.cmake \ cmake/LibeventConfig.cmake.in \ cmake/LibeventConfigVersion.cmake.in \ cmake/Macros.cmake \ diff --git a/bufferevent_mbedtls.c b/bufferevent_mbedtls.c index 22f0b7b1..5dc95f47 100644 --- a/bufferevent_mbedtls.c +++ b/bufferevent_mbedtls.c @@ -70,39 +70,13 @@ #define SSL_ERROR_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE #define SSL mbedtls_ssl_context -/* - * Define an OpenSSL bio that targets a bufferevent. - */ - -/* -------------------- - A BIO is an OpenSSL abstraction that handles reading and writing data. The - library will happily speak SSL over anything that implements a BIO - interface. - - Here we define a BIO implementation that directs its output to a - bufferevent. We'll want to use this only when none of OpenSSL's built-in - IO mechanisms work for us. - -------------------- */ - -/* every BIO type needs its own integer type value. */ -#define BIO_TYPE_LIBEVENT 57 -/* ???? Arguably, we should set BIO_TYPE_FILTER or BIO_TYPE_SOURCE_SINK on - * this. */ - #if 0 static void print_err(int val) { - int err; - printf("Error was %d\n", val); - - while ((err = ERR_get_error())) { - const char *msg = (const char*)ERR_reason_error_string(err); - const char *lib = (const char*)ERR_lib_error_string(err); - const char *func = (const char*)ERR_func_error_string(err); - - printf("%s in %s %s\n", msg, lib, func); - } + char buf[1024]; + mbedtls_strerror(val, buf, sizeof(buf)); + printf("Error was %d:%s\n", val, buf); } #else #define print_err(v) ((void)0) @@ -117,10 +91,6 @@ bio_bufferevent_read(void *ctx, unsigned char *out, size_t outlen) int r = 0; struct evbuffer *input; - //BIO_clear_retry_flags(b); - fprintf(stdout, "bio prepare write:\n"); - fwrite(out, 1, outlen, stdout); - if (!out) return 0; if (!bufev) @@ -129,17 +99,15 @@ bio_bufferevent_read(void *ctx, unsigned char *out, size_t outlen) input = bufferevent_get_input(bufev); if (evbuffer_get_length(input) == 0) { /* If there's no data to read, say so. */ - //BIO_set_retry_read(b); return MBEDTLS_ERR_SSL_WANT_READ; } else { r = evbuffer_remove(input, out, outlen); } - fprintf(stderr, "bio read %d bytes\n", r); return r; } -/* Called to write data info the BIO */ +/* Called to write data into the BIO */ static int bio_bufferevent_write(void *ctx, const unsigned char *in, size_t inlen) { @@ -147,8 +115,6 @@ bio_bufferevent_write(void *ctx, const unsigned char *in, size_t inlen) struct evbuffer *output; size_t outlen; - //BIO_clear_retry_flags(b); - if (!bufev) return MBEDTLS_ERR_NET_INVALID_CONTEXT; @@ -160,7 +126,6 @@ bio_bufferevent_write(void *ctx, const unsigned char *in, size_t inlen) if (bufev->wm_write.high && bufev->wm_write.high <= (outlen+inlen)) { if (bufev->wm_write.high <= outlen) { /* If no data can fit, we'll need to retry later. */ - //BIO_set_retry_write(b); return MBEDTLS_ERR_SSL_WANT_WRITE; } inlen = bufev->wm_write.high - outlen; @@ -168,22 +133,15 @@ bio_bufferevent_write(void *ctx, const unsigned char *in, size_t inlen) EVUTIL_ASSERT(inlen > 0); evbuffer_add(output, in, inlen); - fprintf(stderr, "bio write %d bytes\n", inlen); return inlen; } /* -------------------- - Now, here's the OpenSSL-based implementation of bufferevent. - - The implementation comes in two flavors: one that connects its SSL object - to an underlying bufferevent using a BIO_bufferevent, and one that has the - SSL object connect to a socket directly. The latter should generally be - faster, except on Windows, where your best bet is using a - bufferevent_async. + Now, here's the mbedTLS-based implementation of bufferevent. - (OpenSSL supports many other BIO types, too. But we can't use any unless - we have a good way to get notified when they become readable/writable.) + The implementation comes in only one flavors, that has the + SSL object connect to a socket directly. -------------------- */ struct bio_data_counts { @@ -201,8 +159,8 @@ struct bufferevent_mbedtls { /* An underlying bufferevent that we're directing our output to. If it's NULL, then we're connected to an fd, not an evbuffer. */ struct bufferevent *underlying; - /* net fd */ - mbedtls_net_context net_ctx; + /* net fd */ + mbedtls_net_context net_ctx; /* The SSL object doing our encryption. */ SSL *ssl; @@ -248,7 +206,7 @@ static int be_mbedtls_flush(struct bufferevent *bufev, static int be_mbedtls_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); const struct bufferevent_ops bufferevent_ops_mbedtls = { - "ssl", + "mbedtls", evutil_offsetof(struct bufferevent_mbedtls, bev.bev), be_mbedtls_enable, be_mbedtls_disable, @@ -407,10 +365,7 @@ conn_closed(struct bufferevent_mbedtls *bev_ssl, int when, int errcode, int ret) { int event = BEV_EVENT_ERROR; //int dirty_shutdown = 0; - unsigned long err; - char buf[100] = {}; - - fprintf(stderr, "when %d error code %d", when, errcode); + char buf[100]; if (when & BEV_EVENT_READING && ret == 0) { @@ -443,33 +398,6 @@ conn_closed(struct bufferevent_mbedtls *bev_ssl, int when, int errcode, int ret) bufferevent_run_eventcb_(&bev_ssl->bev.bev, when | event, 0); } -/*static void -init_bio_counts(struct bufferevent_mbedtls *bev_ssl) -{ - BIO *rbio, *wbio; - - wbio = SSL_get_wbio(bev_ssl->ssl); - bev_ssl->counts.n_written = wbio ? BIO_number_written(wbio) : 0; - rbio = SSL_get_rbio(bev_ssl->ssl); - bev_ssl->counts.n_read = rbio ? BIO_number_read(rbio) : 0; -} - -static inline void -decrement_buckets(struct bufferevent_mbedtls *bev_ssl) -{ - unsigned long num_w = BIO_number_written(SSL_get_wbio(bev_ssl->ssl)); - unsigned long num_r = BIO_number_read(SSL_get_rbio(bev_ssl->ssl)); - /* These next two subtractions can wrap around. That's okay. * / - unsigned long w = num_w - bev_ssl->counts.n_written; - unsigned long r = num_r - bev_ssl->counts.n_read; - if (w) - bufferevent_decrement_write_buckets_(&bev_ssl->bev, w); - if (r) - bufferevent_decrement_read_buckets_(&bev_ssl->bev, r); - bev_ssl->counts.n_written = num_w; - bev_ssl->counts.n_read = num_r; -}*/ - #define OP_MADE_PROGRESS 1 #define OP_BLOCKED 2 #define OP_ERR 4 @@ -507,7 +435,6 @@ do_read(struct bufferevent_mbedtls *bev_ssl, int n_to_read) { return OP_ERR | result; ++n_used; space[i].iov_len = r; - //decrement_buckets(bev_ssl); } else { int err = r; print_err(err); @@ -584,7 +511,6 @@ do_write(struct bufferevent_mbedtls *bev_ssl, int atmost) return OP_ERR | result; n_written += r; bev_ssl->last_write = -1; - //decrement_buckets(bev_ssl); } else { int err = r; print_err(err); @@ -924,7 +850,6 @@ do_handshake(struct bufferevent_mbedtls *bev_ssl) r = mbedtls_ssl_handshake(bev_ssl->ssl); break; } - //decrement_buckets(bev_ssl); if (r==0) { evutil_socket_t fd = event_get_fd(&bev_ssl->bev.bev.ev_read); @@ -1010,7 +935,7 @@ set_handshake_callbacks(struct bufferevent_mbedtls *bev_ssl, evutil_socket_t fd) } int -bufferevent_ssl_renegotiate(struct bufferevent *bev) +bufferevent_mbedtls_renegotiate(struct bufferevent *bev) { struct bufferevent_mbedtls *bev_ssl = upcast(bev); if (!bev_ssl) @@ -1103,7 +1028,9 @@ be_mbedtls_unlink(struct bufferevent *bev) } else { mbedtls_ssl_set_bio(bev_ssl->ssl, NULL, NULL, NULL, NULL); bufferevent_free(bev_ssl->underlying); - bev_ssl->underlying = NULL; + /* We still have a reference to it, via our + * BIO. So we don't drop this. */ + // bev_ssl->underlying = NULL; } } } else { @@ -1169,14 +1096,12 @@ be_mbedtls_set_fd(struct bufferevent_mbedtls *bev_ssl, case BUFFEREVENT_SSL_ACCEPTING: if (bev_ssl->ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER) return -1; - //SSL_set_accept_state(bev_ssl->ssl); if (set_handshake_callbacks(bev_ssl, fd) < 0) return -1; break; case BUFFEREVENT_SSL_CONNECTING: if (bev_ssl->ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) return -1; - //SSL_set_connect_state(bev_ssl->ssl); if (set_handshake_callbacks(bev_ssl, fd) < 0) return -1; break; @@ -1256,10 +1181,6 @@ bufferevent_mbedtls_new_impl(struct event_base *base, &bufferevent_ops_mbedtls, tmp_options) < 0) goto err; - /* Don't explode if we decide to realloc a chunk we're writing from in - * the output buffer. */ - //SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - bev_ssl->underlying = underlying; bev_ssl->ssl = ssl; @@ -1277,8 +1198,6 @@ bufferevent_mbedtls_new_impl(struct event_base *base, bev_ssl->old_state = state; bev_ssl->last_write = -1; - //init_bio_counts(bev_ssl); - fd = be_mbedtls_auto_fd(bev_ssl, fd); if (be_mbedtls_set_fd(bev_ssl, state, fd)) goto err; @@ -1340,10 +1259,6 @@ bufferevent_mbedtls_socket_new(struct event_base *base, return bufferevent_mbedtls_new_impl( base, NULL, fd, ssl, state, options); -err: - if (options & BEV_OPT_CLOSE_ON_FREE) - mbedtls_ssl_free(ssl); - return NULL; } int diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake index d82baa41..c430269d 100644 --- a/cmake/FindMbedTLS.cmake +++ b/cmake/FindMbedTLS.cmake @@ -124,7 +124,7 @@ endif() include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(mbedTLS +find_package_handle_standard_args(MbedTLS FOUND_VAR MBEDTLS_FOUND REQUIRED_VARS MBEDTLS_INCLUDE_DIR diff --git a/configure.ac b/configure.ac index 7caa85a4..2599c225 100644 --- a/configure.ac +++ b/configure.ac @@ -60,6 +60,9 @@ AC_ARG_ENABLE(malloc-replacement, AC_ARG_ENABLE(openssl, AS_HELP_STRING(--disable-openssl, disable support for openssl encryption), [], [enable_openssl=yes]) +AC_ARG_ENABLE(mbedtls, + AS_HELP_STRING(--disable-mbedtls, disable support for mbedtls encryption), + [], [enable_mbedtls=yes]) AC_ARG_ENABLE(debug-mode, AS_HELP_STRING(--disable-debug-mode, disable support for running in debug mode), [], [enable_debug_mode=yes]) @@ -179,6 +182,7 @@ AC_SUBST(OPENSSL_LIBADD) AC_SYS_LARGEFILE LIBEVENT_OPENSSL +LIBEVENT_MBEDTLS dnl Checks for header files. AC_CHECK_HEADERS([ \ @@ -804,7 +808,7 @@ if test x$enable_debug_mode = xno; then [Define if libevent should build without support for a debug mode]) fi -dnl check if we should enable verbose debugging +dnl check if we should enable verbose debugging if test x$enable_verbose_debug = xyes; then CFLAGS="$CFLAGS -DUSE_DEBUG" fi @@ -812,6 +816,9 @@ fi dnl check if we have and should use OpenSSL AM_CONDITIONAL(OPENSSL, [test "$enable_openssl" != "no" && test "$have_openssl" = "yes"]) +# check if we have and should use mbedtls +AM_CONDITIONAL(MBEDTLS, [test "$enable_mbedtls" != "no" && test "$have_mbedtls" = "yes"]) + dnl enable some warnings by default AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"],[],[-Werror]) @@ -961,5 +968,5 @@ DX_INIT_DOXYGEN([libevent], [${top_srcdir}/Doxyfile], [doxygen]) AM_CONDITIONAL([ENABLE_DOXYGEN], [test "$DX_FLAG_doc" = "1"]) AM_CONDITIONAL([ENABLE_DOXYGEN_MAN], [test "$DX_FLAG_man" = "1"]) -AC_CONFIG_FILES( [libevent.pc libevent_openssl.pc libevent_pthreads.pc libevent_core.pc libevent_extra.pc] ) +AC_CONFIG_FILES( [libevent.pc libevent_mbedtls.pc libevent_openssl.pc libevent_pthreads.pc libevent_core.pc libevent_extra.pc] ) AC_OUTPUT(Makefile) diff --git a/event-config.h.cmake b/event-config.h.cmake index b8f59fef..1e7adb1c 100644 --- a/event-config.h.cmake +++ b/event-config.h.cmake @@ -214,6 +214,9 @@ /* Define if the system has openssl */ #cmakedefine EVENT__HAVE_OPENSSL 1 +/* Define if the system has mbedtls */ +#cmakedefine EVENT__HAVE_MBEDTLS 1 + /* Define to 1 if you have the `pipe' function. */ #cmakedefine EVENT__HAVE_PIPE 1 diff --git a/include/event2/bufferevent_ssl.h b/include/event2/bufferevent_ssl.h index 00e64071..69fb40b7 100644 --- a/include/event2/bufferevent_ssl.h +++ b/include/event2/bufferevent_ssl.h @@ -194,7 +194,7 @@ bufferevent_mbedtls_get_ssl(struct bufferevent *bufev); /** Tells a bufferevent to begin SSL renegotiation. */ EVENT2_EXPORT_SYMBOL -int bufferevent_ssl_renegotiate(struct bufferevent *bev); +int bufferevent_mbedtls_renegotiate(struct bufferevent *bev); /** Return the most recent OpenSSL error reported on an SSL bufferevent. */ EVENT2_EXPORT_SYMBOL diff --git a/include/event2/visibility.h b/include/event2/visibility.h index 006bbf06..2b07994a 100644 --- a/include/event2/visibility.h +++ b/include/event2/visibility.h @@ -33,7 +33,8 @@ defined(event_extra_shared_EXPORTS) || \ defined(event_core_shared_EXPORTS) || \ defined(event_pthreads_shared_EXPORTS) || \ - defined(event_openssl_shared_EXPORTS) + defined(event_openssl_shared_EXPORTS) || \ + defined(event_mbedtls_shared_EXPORTS) # if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550) # define EVENT2_EXPORT_SYMBOL __global diff --git a/m4/libevent_mbedtls.m4 b/m4/libevent_mbedtls.m4 index 946a9fdd..4b903b9b 100644 --- a/m4/libevent_mbedtls.m4 +++ b/m4/libevent_mbedtls.m4 @@ -11,18 +11,15 @@ case "$enable_mbedtls" in save_LIBS="$LIBS" LIBS="" MBEDTLS_LIBS="" - for lib in mbedtls ; do - # clear cache - unset ac_cv_search_mbedtls_ssl_init - AC_SEARCH_LIBS([mbedtls_ssl_init], [mbedtls ], - [have_mbedtls=yes - MBEDTLS_LIBS="$LIBS -l$lib -lmbedcrypto -lmbedx509 $EV_LIB_GDI $EV_LIB_WS32 $MBEDTLS_LIBADD"], - [have_mbedtls=no], - [-l$lib $EV_LIB_GDI $EV_LIB_WS32 $MBEDTLS_LIBADD]) - LIBS="$save_LIBS" - test "$have_mbedtls" = "yes" && break - done - ;; + # clear cache + unset ac_cv_search_mbedtls_ssl_init + AC_SEARCH_LIBS([mbedtls_ssl_init], [mbedtls], + [have_mbedtls=yes + MBEDTLS_LIBS="$LIBS -lmbedtls -lmbedcrypto -lmbedx509 $EV_LIB_GDI $EV_LIB_WS32"], + [have_mbedtls=no], + [-lmbedtls -lmbedcrypto -lmbedx509 $EV_LIB_GDI $EV_LIB_WS32]) + LIBS="$save_LIBS" + test "$have_mbedtls" = "yes" && break esac CPPFLAGS_SAVE=$CPPFLAGS CPPFLAGS="$CPPFLAGS $MBEDTLS_INCS" diff --git a/sample/include.am b/sample/include.am index 301787db..19d6a9a6 100644 --- a/sample/include.am +++ b/sample/include.am @@ -40,6 +40,13 @@ noinst_HEADERS += \ sample/openssl_hostname_validation.h endif +if MBEDTLS +SAMPLES += sample/ssl-client-mbedtls +sample_ssl_client_mbedtls_SOURCES = sample/ssl-client-mbedtls.c +sample_ssl_client_mbedtls_LDADD = libevent.la libevent_mbedtls.la $(MBEDTLS_LIBS) $(MBEDTLS_LIBADD) +sample_ssl_client_mbedtls_CPPFLAGS = $(AM_CPPFLAGS) $(MBEDTLS_INCS) +endif + if BUILD_SAMPLES noinst_PROGRAMS += $(SAMPLES) endif diff --git a/sample/ssl-client-mbedtls.c b/sample/ssl-client-mbedtls.c new file mode 100644 index 00000000..965913b2 --- /dev/null +++ b/sample/ssl-client-mbedtls.c @@ -0,0 +1,264 @@ +/* + * SSL client demonstration program + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#include "mbedtls/config.h" +#include "mbedtls/platform.h" + +#include "mbedtls/net_sockets.h" +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" + +#include + +#include +#include +#include +#include +#include + +#define SERVER_PORT "443" +#define SERVER_NAME "amazon.com" +#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" + +#define DEBUG_LEVEL 1 + +static void +my_debug(void *ctx, int level, const char *file, int line, const char *str) +{ + ((void)level); + + mbedtls_fprintf((FILE *)ctx, "%s:%04d: %s", file, line, str); + fflush((FILE *)ctx); +} + +static void +writecb(struct bufferevent *bev, void *arg) +{ + fprintf(stderr, "writecb\n"); +} + +static void +readcb(struct bufferevent *bev, void *arg) +{ + char buf[1000]; + size_t r = 0; + int i; + for (i = 0; i < 10; ++i) { + r = bufferevent_read(bev, buf, 800); + fprintf(stderr, "readcb %zu\n\n", r); + if (r > 1) { + fwrite(buf, 1, r, stdout); + fwrite("\n", 1, r, stdout); + fflush(stdout); + } + } +} + +static void +eventcb(struct bufferevent *bev, short what, void *arg) +{ + fprintf(stderr, "\n---------------eventcb %d\n", what); + if (what & BEV_EVENT_CONNECTED) { + const char headers[] = "GET / HTTP/1.1\r\n" + "HOST: " SERVER_NAME "\r\n" + "User-Agent: curl/7.65.1\r\n" + "Connection: Keep-Alive\r\n" + "\r\n"; + bufferevent_write( + bev, headers, sizeof(headers) - 1); // without ending '\0' + // bufferevent_disable(bev, EV_WRITE); + fprintf(stderr, "write request completely\n"); + } else if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { + fprintf(stderr, "closed\n"); + bufferevent_free(bev); + } +} + + +int +main(void) +{ + int ret; + mbedtls_net_context server_fd; + const char *pers = "ssl_client1"; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt cacert; + + struct event_base *evbase; + struct evdns_base *evdns; + struct bufferevent *bev; + struct bufferevent *bevf; + +#ifdef WIN32 + WORD wVersionRequested; + WSADATA wsaData; + int err; + + /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); +#endif + + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold(DEBUG_LEVEL); +#endif + + /* + * 0. Initialize the RNG and the session data + */ + mbedtls_net_init(&server_fd); + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + mbedtls_x509_crt_init(&cacert); + mbedtls_ctr_drbg_init(&ctr_drbg); + + mbedtls_printf("\n . Seeding the random number generator..."); + fflush(stdout); + + mbedtls_entropy_init(&entropy); + if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers))) != 0) { + mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret); + goto exit; + } + + mbedtls_printf(" ok\n"); + + /* + * 0. Initialize certificates + */ + mbedtls_printf(" . Loading the CA root certificate ..."); + fflush(stdout); + + ret = mbedtls_x509_crt_parse(&cacert, + (const unsigned char *)mbedtls_test_cas_pem, mbedtls_test_cas_pem_len); + if (ret < 0) { + mbedtls_printf( + " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); + goto exit; + } + + mbedtls_printf(" ok (%d skipped)\n", ret); + + /* + * 1. Start the connection + */ + mbedtls_printf(" . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT); + fflush(stdout); + + if ((ret = mbedtls_net_connect(&server_fd, SERVER_NAME, SERVER_PORT, + MBEDTLS_NET_PROTO_TCP)) != 0) { + mbedtls_printf(" failed\n ! mbedtls_net_connect returned %d\n\n", ret); + goto exit; + } + + mbedtls_printf(" ok\n"); + + /* + * 2. Setup stuff + */ + mbedtls_printf(" . Setting up the SSL/TLS structure..."); + fflush(stdout); + + if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + mbedtls_printf( + " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret); + goto exit; + } + + mbedtls_printf(" ok\n"); + + /* OPTIONAL is not optimal for security, + * but makes interop easier in this simplified example */ + mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); + mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); + mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); + mbedtls_ssl_conf_dbg(&conf, my_debug, stdout); + + if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { + mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret); + goto exit; + } + + if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) { + mbedtls_printf( + " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); + goto exit; + } + fflush(stdout); + + event_enable_debug_mode(); + evbase = event_base_new(); + evdns = evdns_base_new(evbase, 1); + evdns_base_set_option(evdns, "randomize-case:", "0"); + + evutil_make_socket_nonblocking(server_fd.fd); + + bev = bufferevent_socket_new(evbase, server_fd.fd, BEV_OPT_CLOSE_ON_FREE); + bevf = bufferevent_mbedtls_filter_new( + evbase, bev, &ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE); + bev = bevf; + bufferevent_setcb(bev, readcb, writecb, eventcb, NULL); + + bufferevent_enable(bev, EV_READ); + + + event_base_loop(evbase, 0); + event_base_free(evbase); + + +exit: + +#ifdef MBEDTLS_ERROR_C + if (ret != 0) { + char error_buf[100]; + mbedtls_strerror(ret, error_buf, 100); + mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf); + } +#endif + + mbedtls_net_free(&server_fd); + + mbedtls_x509_crt_free(&cacert); + mbedtls_ssl_free(&ssl); + mbedtls_ssl_config_free(&conf); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + +#if defined(_WIN32) + mbedtls_printf(" + Press Enter to exit this program.\n"); + fflush(stdout); + getchar(); +#endif + + return (ret); +} diff --git a/sample/ssl_client1.c b/sample/ssl_client1.c deleted file mode 100644 index af8019c9..00000000 --- a/sample/ssl_client1.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * SSL client demonstration program - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_time time -#define mbedtls_time_t time_t -#define mbedtls_fprintf fprintf -#define mbedtls_printf printf -#endif - -#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \ - !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \ - !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \ - !defined(MBEDTLS_CERTS_C) || !defined(MBEDTLS_PEM_PARSE_C) || \ - !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) -int main( void ) -{ - mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or " - "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or " - "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " - "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C " - "not defined.\n"); - return( 0 ); -} -#else - -#include "mbedtls/net_sockets.h" -#include "mbedtls/debug.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/error.h" -#include "mbedtls/certs.h" - -#include - -#include -#include -#include -#include - -#define SERVER_PORT "443" -#define SERVER_NAME "amazon.com" -#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" - -#define DEBUG_LEVEL 1 - -static void my_debug( void *ctx, int level, - const char *file, int line, - const char *str ) -{ - ((void) level); - - mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str ); - fflush( (FILE *) ctx ); -} - -void writecb(struct bufferevent *bev, void *arg) -{ - fprintf(stderr, "writecb\n"); -} - -void readcb(struct bufferevent *bev, void *arg) -{ - char buf[1000] = {}; - size_t r = 0; - int i; - for (i=0; i<10; ++i) -{ - r = bufferevent_read(bev, buf, 800); - fprintf(stderr, "readcb %d\n\n", r); - if (r > 1) { - fwrite(buf, 1, r, stdout); - fwrite("\n", 1, r, stdout); - fflush(stdout); - } - } -} - -void eventcb(struct bufferevent *bev, short what, void *arg) -{ - fprintf(stderr, "\n---------------eventcb %d\n", what); - if (what & BEV_EVENT_CONNECTED) { - const char headers[] = - "GET / HTTP/1.1\r\n" - "HOST: " SERVER_NAME "\r\n" - "User-Agent: curl/7.65.1\r\n" - "Connection: Keep-Alive\r\n" - "\r\n"; - bufferevent_write(bev, headers, sizeof(headers) - 1); // without ending '\0' - //bufferevent_disable(bev, EV_WRITE); - fprintf(stderr, "write request completely\n"); - } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) { - fprintf(stderr, "closed\n"); - bufferevent_free(bev); - } -} - - - -int main( void ) -{ - int ret, len; - mbedtls_net_context server_fd; - uint32_t flags; - unsigned char buf[1024]; - const char *pers = "ssl_client1"; - - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_context ssl; - mbedtls_ssl_config conf; - mbedtls_x509_crt cacert; - - struct event *ev_sigterm; - struct event_base *evbase; - struct evdns_base *evdns; - -#ifdef WIN32 - WORD wVersionRequested; - WSADATA wsaData; - int err; - - /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ - wVersionRequested = MAKEWORD(2, 2); - - err = WSAStartup(wVersionRequested, &wsaData); -#endif - - -#if defined(MBEDTLS_DEBUG_C) - mbedtls_debug_set_threshold( DEBUG_LEVEL ); -#endif - - /* - * 0. Initialize the RNG and the session data - */ - mbedtls_net_init( &server_fd ); - mbedtls_ssl_init( &ssl ); - mbedtls_ssl_config_init( &conf ); - mbedtls_x509_crt_init( &cacert ); - mbedtls_ctr_drbg_init( &ctr_drbg ); - - mbedtls_printf( "\n . Seeding the random number generator..." ); - fflush( stdout ); - - mbedtls_entropy_init( &entropy ); - if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, - (const unsigned char *) pers, - strlen( pers ) ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); - goto exit; - } - - mbedtls_printf( " ok\n" ); - - /* - * 0. Initialize certificates - */ - mbedtls_printf( " . Loading the CA root certificate ..." ); - fflush( stdout ); - - ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, - mbedtls_test_cas_pem_len ); - if( ret < 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); - goto exit; - } - - mbedtls_printf( " ok (%d skipped)\n", ret ); - - /* - * 1. Start the connection - */ - mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT ); - fflush( stdout ); - - if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME, - SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); - goto exit; - } - - mbedtls_printf( " ok\n" ); - - /* - * 2. Setup stuff - */ - mbedtls_printf( " . Setting up the SSL/TLS structure..." ); - fflush( stdout ); - - if( ( ret = mbedtls_ssl_config_defaults( &conf, - MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); - goto exit; - } - - mbedtls_printf( " ok\n" ); - - /* OPTIONAL is not optimal for security, - * but makes interop easier in this simplified example */ - mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE ); - mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); - mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); - mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); - - if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); - goto exit; - } - - if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); - goto exit; - } - fflush( stdout ); - - //mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); - - event_enable_debug_mode(); - evbase = event_base_new(); - evdns = evdns_base_new(evbase, 1); - evdns_base_set_option(evdns, "randomize-case:", "0"); - - evutil_make_socket_nonblocking(server_fd.fd); - - -#if 1 -struct bufferevent *bev = bufferevent_socket_new(evbase, server_fd.fd, BEV_OPT_CLOSE_ON_FREE); -struct bufferevent *bevf = bufferevent_mbedtls_filter_new( - evbase, bev, &ssl, - BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE); - bev = bevf; -#else - -struct bufferevent *bev = bufferevent_mbedtls_socket_new( - evbase, server_fd.fd, &ssl, - BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE); -#endif - bufferevent_setcb(bev, readcb, NULL, eventcb, NULL); - - bufferevent_enable(bev, EV_READ); - - - event_base_loop(evbase, 0); - event_base_free(evbase); - - - -exit: - -#ifdef MBEDTLS_ERROR_C - if( ret != 0 ) - { - char error_buf[100]; - mbedtls_strerror( ret, error_buf, 100 ); - mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); - } -#endif - - mbedtls_net_free( &server_fd ); - - mbedtls_x509_crt_free( &cacert ); - mbedtls_ssl_free( &ssl ); - mbedtls_ssl_config_free( &conf ); - mbedtls_ctr_drbg_free( &ctr_drbg ); - mbedtls_entropy_free( &entropy ); - -#if defined(_WIN32) - mbedtls_printf( " + Press Enter to exit this program.\n" ); - fflush( stdout ); getchar(); -#endif - - return( ret ); -} -#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && - MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C && - MBEDTLS_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C && - MBEDTLS_X509_CRT_PARSE_C */ diff --git a/test-export/test-export.c b/test-export/test-export.c index 90917775..3dbeadb5 100644 --- a/test-export/test-export.c +++ b/test-export/test-export.c @@ -9,6 +9,9 @@ #include #include #include +#elif defined(EVENT_EXPORT_TEST_COMPONENT_MBEDTLS) +#include +#include #endif #if defined(EVENT_EXPORT_TEST_COMPONENT_EXTRA) @@ -90,6 +93,54 @@ error: SSL_free(ssl); return r; } +#elif defined(EVENT_EXPORT_TEST_COMPONENT_MBEDTLS) +static int +test() +{ + struct event_base *base = NULL; + mbedtls_ssl_config *conf = NULL; + mbedtls_ssl_context *ssl = NULL; + struct bufferevent *bev; + int r = 1; + + base = event_base_new(); + if (!base) { + goto error; + } + + conf = malloc(sizeof(*conf)); + if (!conf) { + goto error; + } + mbedtls_ssl_config_init(conf); + + ssl = malloc(sizeof(*ssl)); + if (!ssl) { + goto error; + } + mbedtls_ssl_init(ssl); + mbedtls_ssl_setup(ssl, conf); + + bev = bufferevent_mbedtls_socket_new(base, -1, ssl, + BUFFEREVENT_SSL_CONNECTING, + BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); + if (bev == NULL) { + goto error; + } + r = 0; +error: + if (base) + event_base_free(base); + if (ssl) { + mbedtls_ssl_free(ssl); + free(ssl); + } + if (conf) { + mbedtls_ssl_config_free(conf); + free(conf); + } + return r; +} #else static int test() diff --git a/test-export/test-export.py b/test-export/test-export.py index d71e5dba..a6def1ca 100644 --- a/test-export/test-export.py +++ b/test-export/test-export.py @@ -88,13 +88,18 @@ def test_group(): testcase("core", "core", 0) testcase("extra", "extra", 0) testcase("openssl", "openssl", 0) + testcase("mbedtls", "mbedtls", 0) testcase("", "", 0) testcase("extra", "core", 0) testcase("openssl", "core", 0) + testcase("mbedtls", "core", 0) testcase("core", "extra", 1) testcase("core", "openssl", 1) testcase("extra", "openssl", 1) testcase("openssl", "extra", 1) + testcase("core", "mbedtls", 1) + testcase("extra", "mbedtls", 1) + testcase("mbedtls", "extra", 1) if platform.system() != "Windows": testcase("pthreads", "pthreads", 0) testcase("pthreads", "core", 0) @@ -103,6 +108,8 @@ def test_group(): testcase("pthreads", "extra", 1) testcase("pthreads", "openssl", 1) testcase("openssl", "pthreads", 1) + testcase("pthreads", "mbedtls", 1) + testcase("mbedtls", "pthreads", 1) def config_restore(): diff --git a/test/include.am b/test/include.am index 50e9cdbd..8ec8d534 100644 --- a/test/include.am +++ b/test/include.am @@ -149,11 +149,17 @@ test_regress_CPPFLAGS = $(AM_CPPFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS) -Itest test_regress_LDFLAGS = $(PTHREAD_CFLAGS) if OPENSSL -test_regress_SOURCES += test/regress_ssl.c +test_regress_SOURCES += test/regress_openssl.c test_regress_CPPFLAGS += $(OPENSSL_INCS) test_regress_LDADD += libevent_openssl.la $(OPENSSL_LIBS) ${OPENSSL_LIBADD} endif +if MBEDTLS +test_regress_SOURCES += test/regress_mbedtls.c +test_regress_CPPFLAGS += $(MBEDTLS_INCS) +test_regress_LDADD += libevent_mbedtls.la $(MBEDTLS_LIBS) +endif + test_bench_SOURCES = test/bench.c test_bench_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la test_bench_cascade_SOURCES = test/bench_cascade.c diff --git a/test/regress.h b/test/regress.h index 55a2fddb..35965715 100644 --- a/test/regress.h +++ b/test/regress.h @@ -50,6 +50,7 @@ extern struct testcase_t edgetriggered_testcases[]; extern struct testcase_t minheap_testcases[]; extern struct testcase_t iocp_testcases[]; extern struct testcase_t ssl_testcases[]; +extern struct testcase_t mbedtls_testcases[]; extern struct testcase_t listener_testcases[]; extern struct testcase_t listener_iocp_testcases[]; extern struct testcase_t thread_testcases[]; diff --git a/test/regress_main.c b/test/regress_main.c index 2951e3d4..35945938 100644 --- a/test/regress_main.c +++ b/test/regress_main.c @@ -452,6 +452,9 @@ struct testgroup_t testgroups[] = { #endif #ifdef EVENT__HAVE_OPENSSL { "ssl/", ssl_testcases }, +#endif +#ifdef EVENT__HAVE_MBEDTLS + { "mbedtls/", mbedtls_testcases }, #endif END_OF_GROUPS }; diff --git a/test/regress_mbedtls.c b/test/regress_mbedtls.c new file mode 100644 index 00000000..44434fe4 --- /dev/null +++ b/test/regress_mbedtls.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** For event_debug() usage/coverage */ +#define EVENT_VISIBILITY_WANT_DLLIMPORT + +#include "event2/util.h" +#include +#include +#include +#include +#include "regress.h" +#include "tinytest.h" + +#define TESTCASES_NAME mbedtls_testcases + +#ifdef OPENSSL_VERSION_NUMBER +#undef OPENSSL_VERSION_NUMBER +#endif +#define OPENSSL_VERSION_NUMBER 0 +#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT +#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER + +#define get_ssl_ctx get_mbedtls_config + +#define SSL_renegotiate mbedtls_ssl_renegotiate +#define SSL_get_peer_certificate mbedtls_ssl_get_peer_cert +#define SSL_new mbedtls_ssl_new +#define SSL_use_certificate(a, b) \ + do { \ + } while (0); +#define SSL_use_PrivateKey(a, b) \ + do { \ + } while (0); +#define X509_free(x) \ + do { \ + } while (0); + +#define X509 const mbedtls_x509_crt +#define SSL mbedtls_ssl_context + +#define bufferevent_ssl_get_ssl bufferevent_mbedtls_get_ssl +#define bufferevent_ssl_set_allow_dirty_shutdown \ + bufferevent_mbedtls_set_allow_dirty_shutdown +#define bufferevent_ssl_socket_new bufferevent_mbedtls_socket_new +#define bufferevent_ssl_filter_new bufferevent_mbedtls_filter_new + +struct rwcount; +static void BIO_setup(SSL *ssl, struct rwcount *rw); +static mbedtls_ssl_config *get_mbedtls_config(int endpoint); +static mbedtls_ssl_context *mbedtls_ssl_new(mbedtls_ssl_config *config); +static void *mbedtls_test_setup(const struct testcase_t *testcase); +static int mbedtls_test_cleanup(const struct testcase_t *testcase, void *ptr); +static const struct testcase_setup_t ssl_setup = { + mbedtls_test_setup, mbedtls_test_cleanup}; +#include "regress_ssl.c" +static mbedtls_ssl_config *the_mbedtls_conf[2] = {NULL, NULL}; +static mbedtls_ssl_context *the_mbedtls_ctx[1024] = {NULL}; +static int the_mbedtls_ctx_count = 0; +static mbedtls_entropy_context entropy; +static mbedtls_ctr_drbg_context ctr_drbg; +static mbedtls_x509_crt *the_cert; +static mbedtls_pk_context *the_key; + +static void +mbedtls_debug( + void *userdata, int level, const char *file, int line, const char *str) +{ + int loglen = strlen(str); + if (str[loglen - 1] == '\n') + loglen--; + event_debug(("[mbedtls][%s][%d][%s][%d]%.*s", (char *)userdata, level, file, + line, loglen, str)); +} + +static mbedtls_pk_context * +mbedtls_getkey(void) +{ + int ret = 0; + mbedtls_pk_context *pk = malloc(sizeof(mbedtls_pk_context)); + tt_assert(pk); + mbedtls_pk_init(pk); + ret = mbedtls_pk_parse_key( + pk, (const unsigned char *)KEY, sizeof(KEY), NULL, 0); + tt_assert(ret == 0); + return pk; +end: + if (pk) { + mbedtls_pk_free(pk); + free(pk); + } + return NULL; +} + +static void +create_tm_from_unix_epoch(struct tm *cur_p, const time_t t) +{ +#ifdef _WIN32 + struct tm *tmp = gmtime(&t); + if (!tmp) { + fprintf(stderr, "gmtime: %s (%i)", strerror(errno), (int)t); + exit(1); + } + *cur_p = *tmp; +#else + gmtime_r(&t, cur_p); +#endif +} + +static mbedtls_x509_crt * +mbedtls_getcert(mbedtls_pk_context *pk) +{ + const char *name = "commonName=example.com"; + time_t now = time(NULL); + char now_string[32] = ""; + char not_before[32] = ""; + char not_after[32] = ""; + unsigned char certbuf[8192]; + struct tm tm; + mbedtls_x509_crt *crt = NULL; + int ret = 0; + + mbedtls_mpi serial; + mbedtls_x509write_cert write_cert; + + snprintf(now_string, sizeof(now_string), "%lld", (long long)now); + + create_tm_from_unix_epoch(&tm, now); + strftime(not_before, sizeof(not_before), "%Y%m%d%H%M%S", &tm); + now += 3600; + create_tm_from_unix_epoch(&tm, now); + strftime(not_after, sizeof(not_after), "%Y%m%d%H%M%S", &tm); + + mbedtls_x509write_crt_init(&write_cert); + mbedtls_x509write_crt_set_version(&write_cert, 2); + + mbedtls_mpi_init(&serial); + ret = mbedtls_mpi_read_string(&serial, 10, now_string); + tt_assert(ret == 0); + ret = mbedtls_x509write_crt_set_serial(&write_cert, &serial); + tt_assert(ret == 0); + mbedtls_mpi_free(&serial); + + ret = mbedtls_x509write_crt_set_subject_name(&write_cert, name); + tt_assert(ret == 0); + ret = mbedtls_x509write_crt_set_issuer_name(&write_cert, name); + tt_assert(ret == 0); + + mbedtls_x509write_crt_set_md_alg(&write_cert, MBEDTLS_MD_SHA256); + + ret = + mbedtls_x509write_crt_set_validity(&write_cert, not_before, not_after); + tt_assert(ret == 0); + mbedtls_x509write_crt_set_issuer_key(&write_cert, pk); + mbedtls_x509write_crt_set_subject_key(&write_cert, pk); + + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)name, strlen(name)); + tt_assert(ret == 0); + ret = mbedtls_x509write_crt_pem(&write_cert, certbuf, sizeof(certbuf), + mbedtls_ctr_drbg_random, &ctr_drbg); + tt_assert(ret == 0); + mbedtls_x509write_crt_free(&write_cert); + + crt = malloc(sizeof(mbedtls_x509_crt)); + tt_assert(crt); + mbedtls_x509_crt_init(crt); + ret = mbedtls_x509_crt_parse(crt, certbuf, strlen((char *)certbuf) + 1); + tt_assert(ret == 0); + return crt; +end: + if (crt) { + mbedtls_x509_crt_free(crt); + free(crt); + } + return NULL; +} + +static mbedtls_ssl_config * +get_mbedtls_config(int endpoint) +{ + if (the_mbedtls_conf[endpoint]) + return the_mbedtls_conf[endpoint]; + the_mbedtls_conf[endpoint] = malloc(sizeof(mbedtls_ssl_config)); + if (!the_mbedtls_conf[endpoint]) + return NULL; + mbedtls_ssl_config_init(the_mbedtls_conf[endpoint]); + mbedtls_ssl_conf_renegotiation( + the_mbedtls_conf[endpoint], MBEDTLS_SSL_RENEGOTIATION_ENABLED); + mbedtls_ssl_conf_dbg(the_mbedtls_conf[endpoint], mbedtls_debug, + (void *)(endpoint == MBEDTLS_SSL_IS_SERVER ? "server" : "client")); + mbedtls_ssl_config_defaults(the_mbedtls_conf[endpoint], endpoint, + MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); + mbedtls_ssl_conf_rng( + the_mbedtls_conf[endpoint], mbedtls_ctr_drbg_random, &ctr_drbg); + if (disable_tls_11_and_12) { + mbedtls_ssl_conf_max_version(the_mbedtls_conf[endpoint], + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); + } + if (endpoint == MBEDTLS_SSL_IS_SERVER) { + mbedtls_ssl_conf_own_cert( + the_mbedtls_conf[endpoint], the_cert, the_key); + } else { /* MBEDTLS_SSL_IS_CLIENT */ + mbedtls_ssl_conf_ca_chain(the_mbedtls_conf[endpoint], the_cert, NULL); + } + return the_mbedtls_conf[endpoint]; +} + +static void +init_mbedtls(void) +{ + mbedtls_debug_set_threshold(5); +} + +static void * +mbedtls_test_setup(const struct testcase_t *testcase) +{ + init_mbedtls(); + + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)"libevent", sizeof("libevent")); + + the_key = mbedtls_getkey(); + EVUTIL_ASSERT(the_key); + + the_cert = mbedtls_getcert(the_key); + EVUTIL_ASSERT(the_cert); + + disable_tls_11_and_12 = 0; + + return basic_test_setup(testcase); +} +static int +mbedtls_test_cleanup(const struct testcase_t *testcase, void *ptr) +{ + int i; + int ret = basic_test_cleanup(testcase, ptr); + if (!ret) { + return ret; + } + + test_is_done = 0; + n_connected = 0; + got_close = 0; + got_error = 0; + got_timeout = 0; + renegotiate_at = -1; + stop_when_connected = 0; + pending_connect_events = 0; + exit_base = NULL; + + mbedtls_x509_crt_free(the_cert); + free(the_cert); + mbedtls_pk_free(the_key); + free(the_key); + + for (i = 0; i < the_mbedtls_ctx_count; i++) { + mbedtls_ssl_free(the_mbedtls_ctx[i]); + } + if (the_mbedtls_conf[0]) { + mbedtls_ssl_config_free(the_mbedtls_conf[0]); + free(the_mbedtls_conf[0]); + the_mbedtls_conf[0] = NULL; + } + if (the_mbedtls_conf[1]) { + mbedtls_ssl_config_free(the_mbedtls_conf[1]); + free(the_mbedtls_conf[1]); + the_mbedtls_conf[1] = NULL; + } + + return 1; +} + +static mbedtls_ssl_context * +mbedtls_ssl_new(mbedtls_ssl_config *config) +{ + mbedtls_ssl_context *ssl = malloc(sizeof(*ssl)); + mbedtls_ssl_init(ssl); + mbedtls_ssl_setup(ssl, config); + the_mbedtls_ctx[the_mbedtls_ctx_count++] = ssl; + return ssl; +} + +static int +bio_rwcount_read(void *ctx, unsigned char *out, size_t outlen) +{ + struct rwcount *rw = ctx; + ev_ssize_t ret = recv(rw->fd, out, outlen, 0); + ++rw->read; + if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + return ret; +} +static int +bio_rwcount_write(void *ctx, const unsigned char *in, size_t inlen) +{ + struct rwcount *rw = ctx; + ev_ssize_t ret = send(rw->fd, in, inlen, 0); + ++rw->write; + if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) { + return MBEDTLS_ERR_SSL_WANT_WRITE; + } + return ret; +} +static void +BIO_setup(SSL *ssl, struct rwcount *rw) +{ + mbedtls_ssl_set_bio(ssl, rw, bio_rwcount_write, bio_rwcount_read, + NULL); +} diff --git a/test/regress_openssl.c b/test/regress_openssl.c new file mode 100644 index 00000000..1a0ddd0e --- /dev/null +++ b/test/regress_openssl.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "event2/util.h" +#include +#include +#include "openssl-compat.h" +#include "regress.h" +#include "tinytest.h" +#define TESTCASES_NAME ssl_testcases +static void *ssl_test_setup(const struct testcase_t *testcase); +static int ssl_test_cleanup(const struct testcase_t *testcase, void *ptr); +static const struct testcase_setup_t ssl_setup = { + ssl_test_setup, ssl_test_cleanup}; + +static X509 *the_cert; +EVP_PKEY *the_key; + +#define SSL_IS_CLIENT +#define SSL_IS_SERVER + +#define bufferevent_ssl_get_ssl bufferevent_openssl_get_ssl +#define bufferevent_ssl_set_allow_dirty_shutdown \ + bufferevent_openssl_set_allow_dirty_shutdown +#define bufferevent_ssl_socket_new bufferevent_openssl_socket_new +#define bufferevent_ssl_filter_new bufferevent_openssl_filter_new + +struct rwcount; +static void BIO_setup(SSL *ssl, struct rwcount *rw); +#include "regress_ssl.c" + +EVP_PKEY * +ssl_getkey(void) +{ + EVP_PKEY *key; + BIO *bio; + + /* new read-only BIO backed by KEY. */ + bio = BIO_new_mem_buf((char *)KEY, -1); + tt_assert(bio); + + key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + BIO_free(bio); + tt_assert(key); + + return key; +end: + return NULL; +} + +X509 * +ssl_getcert(EVP_PKEY *key) +{ + /* Dummy code to make a quick-and-dirty valid certificate with + OpenSSL. Don't copy this code into your own program! It does a + number of things in a stupid and insecure way. */ + X509 *x509 = NULL; + X509_NAME *name = NULL; + int nid; + time_t now = time(NULL); + + tt_assert(key); + + x509 = X509_new(); + tt_assert(x509); + tt_assert(0 != X509_set_version(x509, 2)); + tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)now)); + + name = X509_NAME_new(); + tt_assert(name); + nid = OBJ_txt2nid("commonName"); + tt_assert(NID_undef != nid); + tt_assert(0 != X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC, + (unsigned char *)"example.com", -1, -1, 0)); + + X509_set_subject_name(x509, name); + X509_set_issuer_name(x509, name); + X509_NAME_free(name); + + X509_time_adj(X509_getm_notBefore(x509), 0, &now); + now += 3600; + X509_time_adj(X509_getm_notAfter(x509), 0, &now); + X509_set_pubkey(x509, key); + tt_assert(0 != X509_sign(x509, key, EVP_sha1())); + + return x509; +end: + X509_free(x509); + X509_NAME_free(name); + return NULL; +} + +static SSL_CTX *the_ssl_ctx = NULL; + +SSL_CTX * +get_ssl_ctx(void) +{ + if (the_ssl_ctx) + return the_ssl_ctx; + the_ssl_ctx = SSL_CTX_new(SSLv23_method()); + if (!the_ssl_ctx) + return NULL; + if (disable_tls_11_and_12) { +#ifdef SSL_OP_NO_TLSv1_2 + SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_2); +#endif +#ifdef SSL_OP_NO_TLSv1_1 + SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_1); +#endif + } + return the_ssl_ctx; +} + +void +init_ssl(void) +{ +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) + SSL_library_init(); + ERR_load_crypto_strings(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); + if (SSLeay() != OPENSSL_VERSION_NUMBER) { + TT_DECLARE("WARN", ("Version mismatch for openssl: compiled with %lx " + "but running with %lx", + (unsigned long)OPENSSL_VERSION_NUMBER, + (unsigned long)SSLeay())); + } +#endif +} + +static void * +ssl_test_setup(const struct testcase_t *testcase) +{ + init_ssl(); + + the_key = ssl_getkey(); + EVUTIL_ASSERT(the_key); + + the_cert = ssl_getcert(the_key); + EVUTIL_ASSERT(the_cert); + + disable_tls_11_and_12 = 0; + + return basic_test_setup(testcase); +} +static int +ssl_test_cleanup(const struct testcase_t *testcase, void *ptr) +{ + int ret = basic_test_cleanup(testcase, ptr); + if (!ret) { + return ret; + } + + test_is_done = 0; + n_connected = 0; + got_close = 0; + got_error = 0; + got_timeout = 0; + renegotiate_at = -1; + stop_when_connected = 0; + pending_connect_events = 0; + exit_base = NULL; + + X509_free(the_cert); + EVP_PKEY_free(the_key); + + SSL_CTX_free(the_ssl_ctx); + the_ssl_ctx = NULL; + + return 1; +} + +static int +bio_rwcount_new(BIO *b) +{ + BIO_set_init(b, 0); + BIO_set_data(b, NULL); + return 1; +} +static int +bio_rwcount_free(BIO *b) +{ + TT_BLATHER(("bio_rwcount_free: %p", b)); + if (!b) + return 0; + if (BIO_get_shutdown(b)) { + BIO_set_init(b, 0); + BIO_set_data(b, NULL); + } + return 1; +} +static int +bio_rwcount_read(BIO *b, char *out, int outlen) +{ + struct rwcount *rw = BIO_get_data(b); + ev_ssize_t ret = recv(rw->fd, out, outlen, 0); + ++rw->read; + if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) { + BIO_set_retry_read(b); + } + return ret; +} +static int +bio_rwcount_write(BIO *b, const char *in, int inlen) +{ + struct rwcount *rw = BIO_get_data(b); + ev_ssize_t ret = send(rw->fd, in, inlen, 0); + ++rw->write; + if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) { + BIO_set_retry_write(b); + } + return ret; +} +static long +bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + struct rwcount *rw = BIO_get_data(b); + long ret = 0; + switch (cmd) { + case BIO_C_GET_FD: + ret = rw->fd; + break; + case BIO_CTRL_GET_CLOSE: + ret = BIO_get_shutdown(b); + break; + case BIO_CTRL_SET_CLOSE: + BIO_set_shutdown(b, (int)num); + break; + case BIO_CTRL_PENDING: + ret = 0; + break; + case BIO_CTRL_WPENDING: + ret = 0; + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret = 1; + break; + } + return ret; +} +static int +bio_rwcount_puts(BIO *b, const char *s) +{ + return bio_rwcount_write(b, s, strlen(s)); +} +#define BIO_TYPE_LIBEVENT_RWCOUNT 0xff1 +static BIO_METHOD *methods_rwcount; + +static BIO_METHOD * +BIO_s_rwcount(void) +{ + if (methods_rwcount == NULL) { + methods_rwcount = BIO_meth_new(BIO_TYPE_LIBEVENT_RWCOUNT, "rwcount"); + if (methods_rwcount == NULL) + return NULL; + BIO_meth_set_write(methods_rwcount, bio_rwcount_write); + BIO_meth_set_read(methods_rwcount, bio_rwcount_read); + BIO_meth_set_puts(methods_rwcount, bio_rwcount_puts); + BIO_meth_set_ctrl(methods_rwcount, bio_rwcount_ctrl); + BIO_meth_set_create(methods_rwcount, bio_rwcount_new); + BIO_meth_set_destroy(methods_rwcount, bio_rwcount_free); + } + return methods_rwcount; +} +static BIO * +BIO_new_rwcount(int close_flag) +{ + BIO *result; + if (!(result = BIO_new(BIO_s_rwcount()))) + return NULL; + BIO_set_init(result, 1); + BIO_set_data(result, NULL); + BIO_set_shutdown(result, !!close_flag); + return result; +} +static void +BIO_setup(SSL *ssl, struct rwcount *rw) +{ + BIO *bio; + bio = BIO_new_rwcount(0); + tt_assert(bio); + BIO_set_data(bio, rw); + SSL_set_bio(ssl, bio, bio); +end: + return; +} diff --git a/test/regress_ssl.c b/test/regress_ssl.c index 37dc334d..b5c37b80 100644 --- a/test/regress_ssl.c +++ b/test/regress_ssl.c @@ -42,21 +42,15 @@ #include #endif -#include "event2/util.h" #include "event2/event.h" #include "event2/bufferevent_ssl.h" #include "event2/bufferevent_struct.h" #include "event2/buffer.h" #include "event2/listener.h" -#include "regress.h" #include "tinytest.h" #include "tinytest_macros.h" -#include -#include -#include "openssl-compat.h" - #include #ifdef _WIN32 #include @@ -98,91 +92,7 @@ static const char KEY[] = "lhdEOj7mAgHwGwwVZWOgs9Lq6vfztnSuhqjha1daESY6kDscPIQ=\n" "-----END RSA PRIVATE KEY-----\n"; -EVP_PKEY * -ssl_getkey(void) -{ - EVP_PKEY *key; - BIO *bio; - - /* new read-only BIO backed by KEY. */ - bio = BIO_new_mem_buf((char*)KEY, -1); - tt_assert(bio); - - key = PEM_read_bio_PrivateKey(bio,NULL,NULL,NULL); - BIO_free(bio); - tt_assert(key); - - return key; -end: - return NULL; -} - -X509 * -ssl_getcert(EVP_PKEY *key) -{ - /* Dummy code to make a quick-and-dirty valid certificate with - OpenSSL. Don't copy this code into your own program! It does a - number of things in a stupid and insecure way. */ - X509 *x509 = NULL; - X509_NAME *name = NULL; - int nid; - time_t now = time(NULL); - - tt_assert(key); - - x509 = X509_new(); - tt_assert(x509); - tt_assert(0 != X509_set_version(x509, 2)); - tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509), - (long)now)); - - name = X509_NAME_new(); - tt_assert(name); - nid = OBJ_txt2nid("commonName"); - tt_assert(NID_undef != nid); - tt_assert(0 != X509_NAME_add_entry_by_NID( - name, nid, MBSTRING_ASC, (unsigned char*)"example.com", - -1, -1, 0)); - - X509_set_subject_name(x509, name); - X509_set_issuer_name(x509, name); - X509_NAME_free(name); - - X509_time_adj(X509_getm_notBefore(x509), 0, &now); - now += 3600; - X509_time_adj(X509_getm_notAfter(x509), 0, &now); - X509_set_pubkey(x509, key); - tt_assert(0 != X509_sign(x509, key, EVP_sha1())); - - return x509; -end: - X509_free(x509); - X509_NAME_free(name); - return NULL; -} - static int disable_tls_11_and_12 = 0; -static SSL_CTX *the_ssl_ctx = NULL; - -SSL_CTX * -get_ssl_ctx(void) -{ - if (the_ssl_ctx) - return the_ssl_ctx; - the_ssl_ctx = SSL_CTX_new(SSLv23_method()); - if (!the_ssl_ctx) - return NULL; - if (disable_tls_11_and_12) { -#ifdef SSL_OP_NO_TLSv1_2 - SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_2); -#endif -#ifdef SSL_OP_NO_TLSv1_1 - SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_1); -#endif - } - return the_ssl_ctx; -} - static int test_is_done; static int n_connected; static int got_close; @@ -192,70 +102,6 @@ static int renegotiate_at = -1; static int stop_when_connected; static int pending_connect_events; static struct event_base *exit_base; -static X509 *the_cert; -EVP_PKEY *the_key; - -void -init_ssl(void) -{ -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \ - (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) - SSL_library_init(); - ERR_load_crypto_strings(); - SSL_load_error_strings(); - OpenSSL_add_all_algorithms(); - if (SSLeay() != OPENSSL_VERSION_NUMBER) { - TT_DECLARE("WARN", - ("Version mismatch for openssl: compiled with %lx but running with %lx", - (unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long)SSLeay())); - } -#endif -} - -static void * -ssl_test_setup(const struct testcase_t *testcase) -{ - init_ssl(); - - the_key = ssl_getkey(); - EVUTIL_ASSERT(the_key); - - the_cert = ssl_getcert(the_key); - EVUTIL_ASSERT(the_cert); - - disable_tls_11_and_12 = 0; - - return basic_test_setup(testcase); -} -static int -ssl_test_cleanup(const struct testcase_t *testcase, void *ptr) -{ - int ret = basic_test_cleanup(testcase, ptr); - if (!ret) { - return ret; - } - - test_is_done = 0; - n_connected = 0; - got_close = 0; - got_error = 0; - got_timeout = 0; - renegotiate_at = -1; - stop_when_connected = 0; - pending_connect_events = 0; - exit_base = NULL; - - X509_free(the_cert); - EVP_PKEY_free(the_key); - - SSL_CTX_free(the_ssl_ctx); - the_ssl_ctx = NULL; - - return 1; -} -const struct testcase_setup_t ssl_setup = { - ssl_test_setup, ssl_test_cleanup -}; /* ==================== @@ -285,7 +131,7 @@ enum regress_openssl_type }; static void -bufferevent_openssl_check_fd(struct bufferevent *bev, int filter) +bufferevent_ssl_check_fd(struct bufferevent *bev, int filter) { tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET); tt_fd_op(bufferevent_setfd(bev, EVUTIL_INVALID_SOCKET), ==, 0); @@ -299,7 +145,7 @@ end: ; } static void -bufferevent_openssl_check_freed(struct bufferevent *bev) +bufferevent_ssl_check_freed(struct bufferevent *bev) { tt_int_op(event_pending(&bev->ev_read, EVLIST_ALL, NULL), ==, 0); tt_int_op(event_pending(&bev->ev_write, EVLIST_ALL, NULL), ==, 0); @@ -339,14 +185,15 @@ respond_to_number(struct bufferevent *bev, void *ctx) return; } if ((type & REGRESS_OPENSSL_CLIENT) && n == renegotiate_at) { - SSL_renegotiate(bufferevent_openssl_get_ssl(bev)); + SSL_renegotiate(bufferevent_ssl_get_ssl(bev)); } ++n; evbuffer_add_printf(bufferevent_get_output(bev), "%d\n", n); TT_BLATHER(("Done reading; now writing.")); bufferevent_enable(bev, EV_WRITE); - bufferevent_disable(bev, EV_READ); + // we shouldn't disable EV_READ here, otherwise we wouldn't got close cb + // bufferevent_disable(bev, EV_READ); } static void @@ -372,7 +219,7 @@ eventcb(struct bufferevent *bev, short what, void *ctx) if (what & BEV_EVENT_CONNECTED) { SSL *ssl; ++n_connected; - ssl = bufferevent_openssl_get_ssl(bev); + ssl = bufferevent_ssl_get_ssl(bev); tt_assert(ssl); peer_cert = SSL_get_peer_certificate(ssl); if (type & REGRESS_OPENSSL_SERVER) { @@ -391,30 +238,30 @@ eventcb(struct bufferevent *bev, short what, void *ctx) TT_BLATHER(("Got a good EOF")); ++got_close; if (type & REGRESS_OPENSSL_FD) { - bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER); + bufferevent_ssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER); } if (type & REGRESS_OPENSSL_FREED) { - bufferevent_openssl_check_freed(bev); + bufferevent_ssl_check_freed(bev); } bufferevent_free(bev); } else if (what & BEV_EVENT_ERROR) { TT_BLATHER(("Got an error.")); ++got_error; if (type & REGRESS_OPENSSL_FD) { - bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER); + bufferevent_ssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER); } if (type & REGRESS_OPENSSL_FREED) { - bufferevent_openssl_check_freed(bev); + bufferevent_ssl_check_freed(bev); } bufferevent_free(bev); } else if (what & BEV_EVENT_TIMEOUT) { TT_BLATHER(("Got timeout.")); ++got_timeout; if (type & REGRESS_OPENSSL_FD) { - bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER); + bufferevent_ssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER); } if (type & REGRESS_OPENSSL_FREED) { - bufferevent_openssl_check_freed(bev); + bufferevent_ssl_check_freed(bev); } bufferevent_free(bev); } @@ -434,14 +281,14 @@ open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out, int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING; int dirty_shutdown = type & REGRESS_OPENSSL_DIRTY_SHUTDOWN; if (fd_pair) { - *bev1_out = bufferevent_openssl_socket_new( + *bev1_out = bufferevent_ssl_socket_new( base, fd_pair[0], ssl1, state1, flags); - *bev2_out = bufferevent_openssl_socket_new( + *bev2_out = bufferevent_ssl_socket_new( base, fd_pair[1], ssl2, state2, flags); } else { - *bev1_out = bufferevent_openssl_filter_new( + *bev1_out = bufferevent_ssl_filter_new( base, underlying_pair[0], ssl1, state1, flags); - *bev2_out = bufferevent_openssl_filter_new( + *bev2_out = bufferevent_ssl_filter_new( base, underlying_pair[1], ssl2, state2, flags); } @@ -450,8 +297,8 @@ open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out, bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb, eventcb, (void*)(REGRESS_OPENSSL_SERVER | (long)type)); - bufferevent_openssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown); - bufferevent_openssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown); + bufferevent_ssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown); + bufferevent_ssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown); } static void @@ -478,8 +325,8 @@ regress_bufferevent_openssl(void *arg) renegotiate_at = 600; } - ssl1 = SSL_new(get_ssl_ctx()); - ssl2 = SSL_new(get_ssl_ctx()); + ssl1 = SSL_new(get_ssl_ctx(SSL_IS_CLIENT)); + ssl2 = SSL_new(get_ssl_ctx(SSL_IS_SERVER)); SSL_use_certificate(ssl2, the_cert); SSL_use_PrivateKey(ssl2, the_key); @@ -581,14 +428,14 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd, struct basic_test_data *data = arg; struct bufferevent *bev; enum regress_openssl_type type; - SSL *ssl = SSL_new(get_ssl_ctx()); + SSL *ssl = SSL_new(get_ssl_ctx(SSL_IS_SERVER)); type = (enum regress_openssl_type)data->setup_data; SSL_use_certificate(ssl, the_cert); SSL_use_PrivateKey(ssl, the_key); - bev = bufferevent_openssl_socket_new( + bev = bufferevent_ssl_socket_new( data->base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); tt_assert(bev); @@ -618,110 +465,6 @@ struct rwcount size_t read; size_t write; }; -static int -bio_rwcount_new(BIO *b) -{ - BIO_set_init(b, 0); - BIO_set_data(b, NULL); - return 1; -} -static int -bio_rwcount_free(BIO *b) -{ - TT_BLATHER(("bio_rwcount_free: %p", b)); - if (!b) - return 0; - if (BIO_get_shutdown(b)) { - BIO_set_init(b, 0); - BIO_set_data(b, NULL); - } - return 1; -} -static int -bio_rwcount_read(BIO *b, char *out, int outlen) -{ - struct rwcount *rw = BIO_get_data(b); - ev_ssize_t ret = recv(rw->fd, out, outlen, 0); - ++rw->read; - if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) { - BIO_set_retry_read(b); - } - return ret; -} -static int -bio_rwcount_write(BIO *b, const char *in, int inlen) -{ - struct rwcount *rw = BIO_get_data(b); - ev_ssize_t ret = send(rw->fd, in, inlen, 0); - ++rw->write; - if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) { - BIO_set_retry_write(b); - } - return ret; -} -static long -bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr) -{ - struct rwcount *rw = BIO_get_data(b); - long ret = 0; - switch (cmd) { - case BIO_C_GET_FD: - ret = rw->fd; - break; - case BIO_CTRL_GET_CLOSE: - ret = BIO_get_shutdown(b); - break; - case BIO_CTRL_SET_CLOSE: - BIO_set_shutdown(b, (int)num); - break; - case BIO_CTRL_PENDING: - ret = 0; - break; - case BIO_CTRL_WPENDING: - ret = 0; - break; - case BIO_CTRL_DUP: - case BIO_CTRL_FLUSH: - ret = 1; - break; - } - return ret; -} -static int -bio_rwcount_puts(BIO *b, const char *s) -{ - return bio_rwcount_write(b, s, strlen(s)); -} -#define BIO_TYPE_LIBEVENT_RWCOUNT 0xff1 -static BIO_METHOD *methods_rwcount; - -static BIO_METHOD * -BIO_s_rwcount(void) -{ - if (methods_rwcount == NULL) { - methods_rwcount = BIO_meth_new(BIO_TYPE_LIBEVENT_RWCOUNT, "rwcount"); - if (methods_rwcount == NULL) - return NULL; - BIO_meth_set_write(methods_rwcount, bio_rwcount_write); - BIO_meth_set_read(methods_rwcount, bio_rwcount_read); - BIO_meth_set_puts(methods_rwcount, bio_rwcount_puts); - BIO_meth_set_ctrl(methods_rwcount, bio_rwcount_ctrl); - BIO_meth_set_create(methods_rwcount, bio_rwcount_new); - BIO_meth_set_destroy(methods_rwcount, bio_rwcount_free); - } - return methods_rwcount; -} -static BIO * -BIO_new_rwcount(int close_flag) -{ - BIO *result; - if (!(result = BIO_new(BIO_s_rwcount()))) - return NULL; - BIO_set_init(result, 1); - BIO_set_data(result, NULL); - BIO_set_shutdown(result, !!close_flag); - return result; -} static void regress_bufferevent_openssl_connect(void *arg) @@ -755,10 +498,10 @@ regress_bufferevent_openssl_connect(void *arg) tt_assert(listener); tt_assert(evconnlistener_get_fd(listener) >= 0); - ssl = SSL_new(get_ssl_ctx()); + ssl = SSL_new(get_ssl_ctx(SSL_IS_CLIENT)); tt_assert(ssl); - bev = bufferevent_openssl_socket_new( + bev = bufferevent_ssl_socket_new( data->base, -1, ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); @@ -777,13 +520,8 @@ regress_bufferevent_openssl_connect(void *arg) /* Possible only when we have fd, since be_openssl can and will overwrite * bio otherwise before */ if (type & REGRESS_OPENSSL_SLEEP) { - BIO *bio; - rw.fd = bufferevent_getfd(bev); - bio = BIO_new_rwcount(0); - tt_assert(bio); - BIO_set_data(bio, &rw); - SSL_set_bio(ssl, bio, bio); + BIO_setup(ssl, &rw); } evbuffer_add_printf(bufferevent_get_output(bev), "1\n"); bufferevent_enable(bev, EV_READ|EV_WRITE); @@ -859,12 +597,12 @@ wm_acceptcb(struct evconnlistener *listener, evutil_socket_t fd, struct wm_context *ctx = arg; struct bufferevent *bev; struct event_base *base = evconnlistener_get_base(listener); - SSL *ssl = SSL_new(get_ssl_ctx()); + SSL *ssl = SSL_new(get_ssl_ctx(SSL_IS_SERVER)); SSL_use_certificate(ssl, the_cert); SSL_use_PrivateKey(ssl, the_key); - bev = bufferevent_openssl_socket_new( + bev = bufferevent_ssl_socket_new( base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, ctx->flags); TT_BLATHER(("wm_transfer-%s(%p): accept", @@ -940,16 +678,16 @@ regress_bufferevent_openssl_wm(void *arg) tt_assert(listener); tt_assert(evconnlistener_get_fd(listener) >= 0); - ssl = SSL_new(get_ssl_ctx()); + ssl = SSL_new(get_ssl_ctx(SSL_IS_CLIENT)); tt_assert(ssl); if (type & REGRESS_OPENSSL_FILTER) { bev = bufferevent_socket_new(data->base, -1, client.flags); tt_assert(bev); - bev = bufferevent_openssl_filter_new( + bev = bufferevent_ssl_filter_new( base, bev, ssl, BUFFEREVENT_SSL_CONNECTING, client.flags); } else { - bev = bufferevent_openssl_socket_new( + bev = bufferevent_ssl_socket_new( data->base, -1, ssl, BUFFEREVENT_SSL_CONNECTING, client.flags); @@ -988,7 +726,7 @@ end: event_base_loop(base, EVLOOP_ONCE); } -struct testcase_t ssl_testcases[] = { +struct testcase_t TESTCASES_NAME[] = { #define T(a) ((void *)(a)) { "bufferevent_socketpair", regress_bufferevent_openssl, TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR) }, @@ -1057,12 +795,10 @@ struct testcase_t ssl_testcases[] = { { "bufferevent_socketpair_timeout_freed_fd", regress_bufferevent_openssl, TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) }, - { "bufferevent_connect", regress_bufferevent_openssl_connect, TT_FORK|TT_NEED_BASE, &ssl_setup, NULL }, { "bufferevent_connect_sleep", regress_bufferevent_openssl_connect, TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_SLEEP) }, - { "bufferevent_wm", regress_bufferevent_openssl_wm, TT_FORK|TT_NEED_BASE, &ssl_setup, NULL }, { "bufferevent_wm_filter", regress_bufferevent_openssl_wm,