From: Stefan Eissing Date: Mon, 4 Nov 2024 11:26:47 +0000 (+0100) Subject: wolfssl: coexist with openssl, further work X-Git-Tag: curl-8_11_0~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3a35901a115e8587a8c45688af2e36cd746b65aa;p=thirdparty%2Fcurl.git wolfssl: coexist with openssl, further work Build wolfSSL master with ./configure --prefix=/path --enable-ip-alt-name --enable-quic --enable-earlydata --enable-psk --enable-opensslcoexist and configure curl with openssl + wolfssl. Normal tests run. pytest session resumption fails, as wolfssl does not handle the new_session callback without opensslextra right now. Closes #15481 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 796ce8ad62..c4ba74d9fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -832,6 +832,7 @@ endmacro() if(USE_WOLFSSL) openssl_check_symbol_exists("wolfSSL_DES_ecb_encrypt" "wolfssl/openssl/des.h" HAVE_WOLFSSL_DES_ECB_ENCRYPT "") + openssl_check_symbol_exists("wolfSSL_BIO_new" "wolfssl/ssl.h" HAVE_WOLFSSL_BIO "") openssl_check_symbol_exists("wolfSSL_BIO_set_shutdown" "wolfssl/ssl.h" HAVE_WOLFSSL_FULL_BIO "") endif() @@ -1985,7 +1986,7 @@ _add_if("MultiSSL" CURL_WITH_MULTI_SSL) _add_if("HTTPS-proxy" _ssl_enabled AND (USE_OPENSSL OR USE_GNUTLS OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR USE_MBEDTLS OR USE_SECTRANSP OR - (USE_WOLFSSL AND HAVE_WOLFSSL_FULL_BIO))) + (USE_WOLFSSL AND HAVE_WOLFSSL_BIO))) _add_if("Unicode" ENABLE_UNICODE) _add_if("threadsafe" HAVE_ATOMIC OR (USE_THREADS_POSIX AND HAVE_PTHREAD_H) OR diff --git a/configure.ac b/configure.ac index 47c8353494..a8bd87e736 100644 --- a/configure.ac +++ b/configure.ac @@ -5171,7 +5171,7 @@ if test "x$CURL_DISABLE_HTTP" != "x1"; then -o "x$MBEDTLS_ENABLED" = "x1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy" AC_MSG_RESULT([yes]) - elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$WOLFSSL_FULL_BIO" = "x1"; then + elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$WOLFSSL_BIO" = "x1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy" AC_MSG_RESULT([yes]) else diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake index 32a8208b68..7ee0a400f7 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config.h.cmake @@ -721,6 +721,9 @@ ${SIZEOF_TIME_T_CODE} /* if wolfSSL has the wolfSSL_DES_ecb_encrypt function. */ #cmakedefine HAVE_WOLFSSL_DES_ECB_ENCRYPT 1 +/* if wolfSSL has the wolfSSL_BIO_new function. */ +#cmakedefine HAVE_WOLFSSL_BIO 1 + /* if wolfSSL has the wolfSSL_BIO_set_shutdown function. */ #cmakedefine HAVE_WOLFSSL_FULL_BIO 1 diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index f0ef267039..5d143486d6 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -37,6 +37,7 @@ #include "sendf.h" #include "vtls.h" #include "vtls_int.h" +#include "rustls.h" #include "select.h" #include "strerror.h" #include "multiif.h" diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 6d12dfd73e..61b407ab22 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -55,6 +55,16 @@ #include "vtls.h" /* generic SSL protos etc */ #include "vtls_int.h" + +#include "openssl.h" /* OpenSSL versions */ +#include "gtls.h" /* GnuTLS versions */ +#include "wolfssl.h" /* wolfSSL versions */ +#include "schannel.h" /* Schannel SSPI version */ +#include "sectransp.h" /* Secure Transport (Darwin) version */ +#include "mbedtls.h" /* mbedTLS versions */ +#include "bearssl.h" /* BearSSL versions */ +#include "rustls.h" /* Rustls versions */ + #include "slist.h" #include "sendf.h" #include "strcase.h" diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h index 660c3379b1..13bd3fbb5e 100644 --- a/lib/vtls/vtls_int.h +++ b/lib/vtls/vtls_int.h @@ -250,15 +250,6 @@ CURLcode Curl_ssl_set_sessionid(struct Curl_cfilter *cf, size_t sessionid_size, Curl_ssl_sessionid_dtor *sessionid_free_cb); -#include "openssl.h" /* OpenSSL versions */ -#include "gtls.h" /* GnuTLS versions */ -#include "wolfssl.h" /* wolfSSL versions */ -#include "schannel.h" /* Schannel SSPI version */ -#include "sectransp.h" /* Secure Transport (Darwin) version */ -#include "mbedtls.h" /* mbedTLS versions */ -#include "bearssl.h" /* BearSSL versions */ -#include "rustls.h" /* Rustls versions */ - #endif /* USE_SSL */ #endif /* HEADER_CURL_VTLS_INT_H */ diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index 1769a1367a..0d74b3e763 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -97,9 +97,25 @@ #endif #endif -#if defined(HAVE_WOLFSSL_FULL_BIO) && HAVE_WOLFSSL_FULL_BIO +#ifdef HAVE_WOLFSSL_BIO #define USE_BIO_CHAIN -#else +#ifdef HAVE_WOLFSSL_FULL_BIO +#define USE_FULL_BIO +#else /* HAVE_WOLFSSL_FULL_BIO */ +#undef USE_FULL_BIO +#endif +/* wolfSSL 5.7.4 and older do not have these symbols, but only the + * OpenSSL ones. */ +#ifndef WOLFSSL_BIO_CTRL_GET_CLOSE +#define WOLFSSL_BIO_CTRL_GET_CLOSE BIO_CTRL_GET_CLOSE +#define WOLFSSL_BIO_CTRL_SET_CLOSE BIO_CTRL_SET_CLOSE +#define WOLFSSL_BIO_CTRL_FLUSH BIO_CTRL_FLUSH +#define WOLFSSL_BIO_CTRL_DUP BIO_CTRL_DUP +#define wolfSSL_BIO_set_retry_write BIO_set_retry_write +#define wolfSSL_BIO_set_retry_read BIO_set_retry_read +#endif /* !WOLFSSL_BIO_CTRL_GET_CLOSE */ + +#else /* HAVE_WOLFSSL_BIO */ #undef USE_BIO_CHAIN #endif @@ -237,7 +253,9 @@ static const struct group_name_map gnm[] = { static int wolfssl_bio_cf_create(WOLFSSL_BIO *bio) { +#ifdef USE_FULL_BIO wolfSSL_BIO_set_shutdown(bio, 1); +#endif wolfSSL_BIO_set_data(bio, NULL); return 1; } @@ -251,28 +269,35 @@ static int wolfssl_bio_cf_destroy(WOLFSSL_BIO *bio) static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr) { - struct Curl_cfilter *cf = BIO_get_data(bio); + struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); long ret = 1; (void)cf; (void)ptr; + (void)num; switch(cmd) { - case BIO_CTRL_GET_CLOSE: + case WOLFSSL_BIO_CTRL_GET_CLOSE: +#ifdef USE_FULL_BIO ret = (long)wolfSSL_BIO_get_shutdown(bio); +#else + ret = 0; +#endif break; - case BIO_CTRL_SET_CLOSE: + case WOLFSSL_BIO_CTRL_SET_CLOSE: +#ifdef USE_FULL_BIO wolfSSL_BIO_set_shutdown(bio, (int)num); +#endif break; - case BIO_CTRL_FLUSH: + case WOLFSSL_BIO_CTRL_FLUSH: /* we do no delayed writes, but if we ever would, this * needs to trigger it. */ ret = 1; break; - case BIO_CTRL_DUP: + case WOLFSSL_BIO_CTRL_DUP: ret = 1; break; -#ifdef BIO_CTRL_EOF - case BIO_CTRL_EOF: +#ifdef WOLFSSL_BIO_CTRL_EOF + case WOLFSSL_BIO_CTRL_EOF: /* EOF has been reached on input? */ return (!cf->next || !cf->next->connected); #endif @@ -309,9 +334,11 @@ static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio, backend->io_result = result; CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d", blen, nwritten, result); +#ifdef USE_FULL_BIO wolfSSL_BIO_clear_retry_flags(bio); +#endif if(nwritten < 0 && CURLE_AGAIN == result) { - BIO_set_retry_write(bio); + wolfSSL_BIO_set_retry_write(bio); if(backend->shutting_down && !backend->io_send_blocked_len) backend->io_send_blocked_len = blen; } @@ -338,9 +365,11 @@ static int wolfssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen) nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result); backend->io_result = result; CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %zd, %d", blen, nread, result); +#ifdef USE_FULL_BIO wolfSSL_BIO_clear_retry_flags(bio); +#endif if(nread < 0 && CURLE_AGAIN == result) - BIO_set_retry_read(bio); + wolfSSL_BIO_set_retry_read(bio); else if(nread == 0) connssl->peer_closed = TRUE; return (int)nread; @@ -350,7 +379,8 @@ static WOLFSSL_BIO_METHOD *wolfssl_bio_cf_method = NULL; static void wolfssl_bio_cf_init_methods(void) { - wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO"); + wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(WOLFSSL_BIO_MEMORY, + "wolfSSL CF BIO"); wolfSSL_BIO_meth_set_write(wolfssl_bio_cf_method, &wolfssl_bio_cf_out_write); wolfSSL_BIO_meth_set_read(wolfssl_bio_cf_method, &wolfssl_bio_cf_in_read); wolfSSL_BIO_meth_set_ctrl(wolfssl_bio_cf_method, &wolfssl_bio_cf_ctrl); @@ -1248,7 +1278,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) { WOLFSSL_BIO *bio; - bio = BIO_new(wolfssl_bio_cf_method); + bio = wolfSSL_BIO_new(wolfssl_bio_cf_method); if(!bio) return CURLE_OUT_OF_MEMORY; @@ -1730,6 +1760,11 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf, case WOLFSSL_ERROR_NONE: case WOLFSSL_ERROR_WANT_READ: case WOLFSSL_ERROR_WANT_WRITE: + if(!backend->io_result && connssl->peer_closed) { + CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen); + *curlcode = CURLE_OK; + return 0; + } /* there is data pending, re-invoke wolfSSL_read() */ CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen); *curlcode = CURLE_AGAIN; @@ -1740,7 +1775,12 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf, *curlcode = CURLE_AGAIN; return -1; } - { + else if(!backend->io_result && connssl->peer_closed) { + CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen); + *curlcode = CURLE_OK; + return 0; + } + else { char error_buffer[256]; failf(data, "SSL read: %s, errno %d", wolfssl_strerror((unsigned long)err, error_buffer, diff --git a/lib/vtls/wolfssl.h b/lib/vtls/wolfssl.h index e39fa88adc..dc2967d69c 100644 --- a/lib/vtls/wolfssl.h +++ b/lib/vtls/wolfssl.h @@ -26,13 +26,16 @@ #include "curl_setup.h" #ifdef USE_WOLFSSL -#include -#include -#include -#include #include "urldata.h" +struct WOLFSSL; +typedef struct WOLFSSL WOLFSSL; +struct WOLFSSL_CTX; +typedef struct WOLFSSL_CTX WOLFSSL_CTX; +struct WOLFSSL_SESSION; +typedef struct WOLFSSL_SESSION WOLFSSL_SESSION; + extern const struct Curl_ssl Curl_ssl_wolfssl; struct wolfssl_ctx { diff --git a/m4/curl-wolfssl.m4 b/m4/curl-wolfssl.m4 index ca60d3b488..cd5a2b14b5 100644 --- a/m4/curl-wolfssl.m4 +++ b/m4/curl-wolfssl.m4 @@ -145,6 +145,14 @@ if test "x$OPT_WOLFSSL" != xno; then ) dnl if this symbol is present, we can make use of BIO filter chains + AC_CHECK_FUNC(wolfSSL_BIO_new, + [ + AC_DEFINE(HAVE_WOLFSSL_BIO, 1, + [if you have wolfSSL_BIO_new]) + WOLFSSL_BIO=1 + ] + ) + dnl if this symbol is present, we have the full BIO feature set AC_CHECK_FUNC(wolfSSL_BIO_set_shutdown, [ AC_DEFINE(HAVE_WOLFSSL_FULL_BIO, 1, diff --git a/tests/http/test_05_errors.py b/tests/http/test_05_errors.py index e00edcfab6..a496d6d8b5 100644 --- a/tests/http/test_05_errors.py +++ b/tests/http/test_05_errors.py @@ -127,7 +127,7 @@ class TestErrors: r = curl.http_download(urls=[url], alpn_proto=proto, extra_args=[ '--parallel', ]) - if proto == 'http/1.0' and \ + if proto == 'http/1.0' and not env.curl_uses_lib('wolfssl') and \ (env.curl_is_debug() or not env.curl_uses_lib('openssl')): # we are inconsistent if we fail or not in missing TLS shutdown # openssl code ignore such errors intentionally in non-debug builds