mirror of
https://github.com/curl/curl.git
synced 2025-02-05 14:30:10 +08:00
wolfssl: fix CURLOPT_SSLVERSION
Before, setting CURLOPT_SSLVERSION with wolfSSL restricted the the tls proto to just the specified version. Now it properly supports a range. So it can set the min and max tls proto (max requires wolfSSL 4.2.0). Bump the absolute minimum required version of wolfSSL to 3.4.6 (released 2015) because it is needed for the wolfSSL_CTX_SetMinVersion() function. Closes #14480
This commit is contained in:
parent
3e64569a9e
commit
902d9a1d4e
@ -77,7 +77,6 @@ TLS v1.3 or later (Added in 7.52.0)
|
||||
The maximum TLS version can be set by using *one* of the
|
||||
CURL_SSLVERSION_MAX_ macros below. It is also possible to OR *one* of the
|
||||
CURL_SSLVERSION_ macros with *one* of the CURL_SSLVERSION_MAX_ macros.
|
||||
The MAX macros are not supported for wolfSSL.
|
||||
|
||||
## CURL_SSLVERSION_MAX_DEFAULT
|
||||
|
||||
@ -138,13 +137,17 @@ int main(void)
|
||||
|
||||
# HISTORY
|
||||
|
||||
SSLv2 and SSLv3 are refused completely since curl 7.77.0
|
||||
|
||||
SSLv2 is disabled by default since 7.18.1. Other SSL versions availability may
|
||||
vary depending on which backend libcurl has been built to use.
|
||||
|
||||
SSLv3 is disabled by default since 7.39.0.
|
||||
|
||||
SSLv2 and SSLv3 are refused completely since curl 7.77.0
|
||||
|
||||
Since 8.10.0 wolfSSL is fully supported. Before 8.10.0 the MAX macros were not
|
||||
supported with wolfSSL and the other macros did not set a minimum, but
|
||||
restricted the TLS version to only the specified one.
|
||||
|
||||
# %AVAILABILITY%
|
||||
|
||||
# RETURN VALUE
|
||||
|
@ -36,6 +36,10 @@
|
||||
#include <wolfssl/version.h>
|
||||
#include <wolfssl/options.h>
|
||||
|
||||
#if LIBWOLFSSL_VERSION_HEX < 0x03004006 /* wolfSSL 3.4.6 (2015) */
|
||||
#error "wolfSSL version should be at least 3.4.6"
|
||||
#endif
|
||||
|
||||
/* To determine what functions are available we rely on one or both of:
|
||||
- the user's options.h generated by wolfSSL
|
||||
- the symbols detected by curl's configure
|
||||
@ -656,6 +660,45 @@ wssl_get_default_ciphers(bool tls13, char *buf, size_t size)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LIBWOLFSSL_VERSION_HEX < 0x04002000 /* 4.2.0 (2019) */
|
||||
static int
|
||||
wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version)
|
||||
{
|
||||
int res;
|
||||
switch(version) {
|
||||
default:
|
||||
case TLS1_VERSION:
|
||||
res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1);
|
||||
if(res == WOLFSSL_SUCCESS)
|
||||
return res;
|
||||
FALLTHROUGH();
|
||||
case TLS1_1_VERSION:
|
||||
res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_1);
|
||||
if(res == WOLFSSL_SUCCESS)
|
||||
return res;
|
||||
FALLTHROUGH();
|
||||
case TLS1_2_VERSION:
|
||||
res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_2);
|
||||
#ifdef WOLFSSL_TLS13
|
||||
if(res == WOLFSSL_SUCCESS)
|
||||
return res;
|
||||
FALLTHROUGH();
|
||||
case TLS1_3_VERSION:
|
||||
res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_3);
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
static int
|
||||
wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int version)
|
||||
{
|
||||
(void) ctx, (void) version;
|
||||
return WOLFSSL_NOT_IMPLEMENTED;
|
||||
}
|
||||
#define wolfSSL_CTX_set_min_proto_version wssl_legacy_CTX_set_min_proto_version
|
||||
#define wolfSSL_CTX_set_max_proto_version wssl_legacy_CTX_set_max_proto_version
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function loads all the client/CA certificates and CRLs. Setup the TLS
|
||||
* layer and do all necessary magic.
|
||||
@ -663,6 +706,7 @@ wssl_get_default_ciphers(bool tls13, char *buf, size_t size)
|
||||
static CURLcode
|
||||
wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
int res;
|
||||
char *ciphers, *curves;
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
struct wolfssl_ctx *backend =
|
||||
@ -673,12 +717,6 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
#ifdef WOLFSSL_HAVE_KYBER
|
||||
word16 pqkem = 0;
|
||||
size_t idx = 0;
|
||||
#endif
|
||||
#ifdef HAVE_SNI
|
||||
bool sni = FALSE;
|
||||
#define use_sni(x) sni = (x)
|
||||
#else
|
||||
#define use_sni(x) Curl_nop_stmt
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(backend);
|
||||
@ -686,104 +724,76 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
if(connssl->state == ssl_connection_complete)
|
||||
return CURLE_OK;
|
||||
|
||||
if(conn_config->version_max != CURL_SSLVERSION_MAX_NONE) {
|
||||
failf(data, "wolfSSL does not support to set maximum SSL/TLS version");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
/* check to see if we have been told to use an explicit SSL/TLS version */
|
||||
switch(conn_config->version) {
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
#if LIBWOLFSSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
|
||||
/* minimum protocol version is set later after the CTX object is created */
|
||||
req_method = SSLv23_client_method();
|
||||
#if LIBWOLFSSL_VERSION_HEX < 0x04002000 /* 4.2.0 (2019) */
|
||||
req_method = wolfSSLv23_client_method();
|
||||
#else
|
||||
infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
|
||||
"TLS 1.0 is used exclusively");
|
||||
req_method = TLSv1_client_method();
|
||||
req_method = wolfTLS_client_method();
|
||||
#endif
|
||||
use_sni(TRUE);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_0:
|
||||
#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
|
||||
req_method = TLSv1_client_method();
|
||||
use_sni(TRUE);
|
||||
break;
|
||||
#else
|
||||
failf(data, "wolfSSL does not support TLS 1.0");
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
case CURL_SSLVERSION_TLSv1_1:
|
||||
#ifndef NO_OLD_TLS
|
||||
req_method = TLSv1_1_client_method();
|
||||
use_sni(TRUE);
|
||||
break;
|
||||
#else
|
||||
failf(data, "wolfSSL does not support TLS 1.1");
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
case CURL_SSLVERSION_TLSv1_2:
|
||||
#ifndef WOLFSSL_NO_TLS12
|
||||
req_method = TLSv1_2_client_method();
|
||||
use_sni(TRUE);
|
||||
#else
|
||||
failf(data, "wolfSSL does not support TLS 1.2");
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_3:
|
||||
#ifdef WOLFSSL_TLS13
|
||||
req_method = wolfTLSv1_3_client_method();
|
||||
use_sni(TRUE);
|
||||
break;
|
||||
#else
|
||||
failf(data, "wolfSSL: TLS 1.3 is not yet supported");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
#endif
|
||||
default:
|
||||
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
if(!req_method) {
|
||||
failf(data, "SSL: could not create a method");
|
||||
failf(data, "wolfSSL: could not create a client method");
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(backend->ctx)
|
||||
wolfSSL_CTX_free(backend->ctx);
|
||||
backend->ctx = wolfSSL_CTX_new(req_method);
|
||||
|
||||
backend->ctx = wolfSSL_CTX_new(req_method);
|
||||
if(!backend->ctx) {
|
||||
failf(data, "SSL: could not create a context");
|
||||
failf(data, "wolfSSL: could not create a context");
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
switch(conn_config->version) {
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
#if LIBWOLFSSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
|
||||
/* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is
|
||||
* whatever minimum version of TLS was built in and at least TLS 1.0. For
|
||||
* later library versions that could change (eg TLS 1.0 built in but
|
||||
* defaults to TLS 1.1) so we have this short circuit evaluation to find
|
||||
* the minimum supported TLS version.
|
||||
*/
|
||||
if((wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1) != 1) &&
|
||||
(wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_1) != 1) &&
|
||||
(wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_2) != 1)
|
||||
#ifdef WOLFSSL_TLS13
|
||||
&& (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_3) != 1)
|
||||
#endif
|
||||
) {
|
||||
failf(data, "SSL: could not set the minimum protocol version");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
#endif
|
||||
FALLTHROUGH();
|
||||
default:
|
||||
res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_VERSION);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_1:
|
||||
res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_1_VERSION);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_2:
|
||||
res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_2_VERSION);
|
||||
break;
|
||||
#ifdef WOLFSSL_TLS13
|
||||
case CURL_SSLVERSION_TLSv1_3:
|
||||
res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_3_VERSION);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
failf(data, "wolfSSL: unrecognized minimum TLS version value");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
if(res != WOLFSSL_SUCCESS) {
|
||||
failf(data, "wolfSSL: failed set the minimum TLS version");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
switch(conn_config->version_max) {
|
||||
#ifdef WOLFSSL_TLS13
|
||||
case CURL_SSLVERSION_MAX_TLSv1_3:
|
||||
res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);
|
||||
break;
|
||||
#endif
|
||||
case CURL_SSLVERSION_MAX_TLSv1_2:
|
||||
res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_2_VERSION);
|
||||
break;
|
||||
case CURL_SSLVERSION_MAX_TLSv1_1:
|
||||
res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_1_VERSION);
|
||||
break;
|
||||
case CURL_SSLVERSION_MAX_TLSv1_0:
|
||||
res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_VERSION);
|
||||
break;
|
||||
case CURL_SSLVERSION_MAX_DEFAULT:
|
||||
case CURL_SSLVERSION_MAX_NONE:
|
||||
res = WOLFSSL_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
failf(data, "wolfSSL: unrecognized maximum TLS version value");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
if(res != WOLFSSL_SUCCESS) {
|
||||
failf(data, "wolfSSL: failed set the maximum TLS version");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
#ifndef WOLFSSL_TLS13
|
||||
@ -953,7 +963,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
SSL_VERIFY_NONE, NULL);
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
if(sni && connssl->peer.sni) {
|
||||
if(connssl->peer.sni) {
|
||||
size_t sni_len = strlen(connssl->peer.sni);
|
||||
if((sni_len < USHRT_MAX)) {
|
||||
if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME,
|
||||
@ -1284,7 +1294,6 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
|
||||
else if(ASN_NO_SIGNER_E == detail) {
|
||||
if(conn_config->verifypeer) {
|
||||
failf(data, " CA signer not available for verification");
|
||||
@ -1297,7 +1306,6 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
"continuing anyway");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ECH
|
||||
else if(-1 == detail) {
|
||||
/* try access a retry_config ECHConfigList for tracing */
|
||||
|
@ -70,7 +70,6 @@ class TestSSLUse:
|
||||
if tls_max == '1.3':
|
||||
exp_resumed = 'Initial' # 1.2 works in LibreSSL, but 1.3 does not, TODO
|
||||
if env.curl_uses_lib('wolfssl'):
|
||||
xargs = ['--sessionid', f'--tlsv{tls_max}']
|
||||
if tls_max == '1.3':
|
||||
exp_resumed = 'Initial' # 1.2 works in wolfSSL, but 1.3 does not, TODO
|
||||
if env.curl_uses_lib('rustls-ffi'):
|
||||
@ -221,10 +220,6 @@ class TestSSLUse:
|
||||
# test setting TLSv1.2 ciphers
|
||||
if env.curl_uses_lib('schannel'):
|
||||
pytest.skip('Schannel does not support setting TLSv1.2 ciphers by name')
|
||||
elif env.curl_uses_lib('wolfssl'):
|
||||
# setting tls version is botched with wolfssl: setting max (--tls-max)
|
||||
# is not supported, setting min (--tlsv1.*) actually also sets max
|
||||
extra_args = ['--tlsv1.2', '--ciphers', ':'.join(cipher_names)]
|
||||
else:
|
||||
# the server supports TLSv1.3, so to test TLSv1.2 ciphers we set tls-max
|
||||
extra_args = ['--tls-max', '1.2', '--ciphers', ':'.join(cipher_names)]
|
||||
|
Loading…
Reference in New Issue
Block a user