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
This commit is contained in:
Stefan Eissing 2024-11-04 12:26:47 +01:00 committed by Daniel Stenberg
parent f81abcbfeb
commit 3a35901a11
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
10 changed files with 87 additions and 30 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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 */

View File

@ -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,

View File

@ -26,13 +26,16 @@
#include "curl_setup.h"
#ifdef USE_WOLFSSL
#include <wolfssl/version.h>
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include <wolfssl/error-ssl.h>
#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 {

View File

@ -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,

View File

@ -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