diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 608666c6bf..65a3fd7250 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -46,7 +46,7 @@ env: # renovate: datasource=github-tags depName=libressl-portable/portable versioning=semver registryUrl=https://github.com libressl-version: 3.9.2 # renovate: datasource=github-tags depName=ARMmbed/mbedtls versioning=semver registryUrl=https://github.com - mbedtls-version: 3.5.0 + mbedtls-version: 3.6.0 # renovate: datasource=github-tags depName=icing/mod_h2 versioning=semver registryUrl=https://github.com mod_h2-version: 2.0.27 # renovate: datasource=github-tags depName=nibanks/msh3 versioning=semver registryUrl=https://github.com diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index c714cc1b0a..8393b02d2f 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -483,6 +483,20 @@ mbed_set_selected_ciphers(struct Curl_easy *data, return CURLE_OK; } +#ifdef TLS13_SUPPORT +static int mbed_no_verify(void *udata, mbedtls_x509_crt *crt, + int depth, uint32_t *flags) +{ + (void)udata; + (void)crt; + (void)depth; + /* we clear any faults the mbedtls' own verification found. + * See */ + *flags = 0; + return 0; +} +#endif + static CURLcode mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) { @@ -739,6 +753,16 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) failf(data, "mbedTLS: ssl_config failed"); return CURLE_SSL_CONNECT_ERROR; } +#ifdef TLS13_SUPPORT + if(!verifypeer) { + /* Default verify behaviour changed in mbedtls v3.6.0 with TLS v1.3. + * On 1.3 connections, the handshake fails by default without trust + * anchors. We override this questionable change by installing our + * own verify callback that clears all errors. */ + mbedtls_ssl_conf_verify(&backend->config, mbed_no_verify, cf); + } +#endif + mbedtls_ssl_init(&backend->ssl); backend->initialized = TRUE; @@ -926,10 +950,16 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) connssl->connecting_state = ssl_connect_2_writing; return CURLE_OK; } + else if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { + failf(data, "peer certificate could not be verified"); + return CURLE_PEER_FAILED_VERIFICATION; + } else if(ret) { char errorbuf[128]; + CURL_TRC_CF(data, cf, "TLS version %04X", + mbedtls_ssl_get_version_number(&backend->ssl)); mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s", + failf(data, "ssl_handshake returned: (-0x%04X) %s", -ret, errorbuf); return CURLE_SSL_CONNECT_ERROR; } @@ -1150,8 +1180,13 @@ static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data, ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len); if(ret < 0) { - *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ? - CURLE_AGAIN : CURLE_SEND_ERROR; + CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X", + len, -ret); + *curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_WRITE) +#ifdef TLS13_SUPPORT + || (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET) +#endif + )? CURLE_AGAIN : CURLE_SEND_ERROR; ret = -1; } @@ -1179,7 +1214,7 @@ static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data) Read it to avoid an RST on the TCP connection. */ (void)mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, sizeof(buf)); ret = mbedtls_ssl_close_notify(&backend->ssl); - CURL_TRC_CF(data, cf, "close_notify() -> %x", ret); + CURL_TRC_CF(data, cf, "close_notify() -> %04x", -ret); mbedtls_pk_free(&backend->pk); mbedtls_x509_crt_free(&backend->clicert); @@ -1213,16 +1248,21 @@ static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data, ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, buffersize); - if(ret <= 0) { + CURL_TRC_CF(data, cf, "mbedtls_ssl_read(len=%zu) -> -0x%04X", + buffersize, -ret); if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) return 0; - *curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_READ) #ifdef TLS13_SUPPORT || (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET) #endif ) ? CURLE_AGAIN : CURLE_RECV_ERROR; + if(*curlcode != CURLE_AGAIN) { + char errorbuf[128]; + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "ssl_read returned: (-0x%04X) %s", -ret, errorbuf); + } return -1; } diff --git a/tests/http/test_08_caddy.py b/tests/http/test_08_caddy.py index 6b8fce8fef..4a75ef5523 100644 --- a/tests/http/test_08_caddy.py +++ b/tests/http/test_08_caddy.py @@ -151,6 +151,9 @@ class TestCaddy: pytest.skip("h3 not supported in curl") if proto == 'h3' and env.curl_uses_lib('msh3'): pytest.skip("msh3 itself crashes") + if proto == 'http/1.1' and env.curl_uses_lib('mbedtls'): + pytest.skip("mbedtls 3.6.0 fails on 50 connections with: "\ + "ssl_handshake returned: (-0x7F00) SSL - Memory allocation failed") count = 50 curl = CurlClient(env=env) urln = f'https://{env.domain1}:{caddy.port}/data10.data?[0-{count-1}]' diff --git a/tests/http/test_17_ssl_use.py b/tests/http/test_17_ssl_use.py index d741514bbe..b9c3dcf556 100644 --- a/tests/http/test_17_ssl_use.py +++ b/tests/http/test_17_ssl_use.py @@ -77,9 +77,8 @@ class TestSSLUse: exp_resumed = 'Initial' # rustls does not support sessions, TODO if env.curl_uses_lib('bearssl') and tls_max == '1.3': pytest.skip('BearSSL does not support TLSv1.3') - if env.curl_uses_lib('mbedtls') and tls_max == '1.3' and \ - not env.curl_lib_version_at_least('mbedtls', '3.6.0'): - pytest.skip('mbedtls TLSv1.3 support requires at least 3.6.0') + if env.curl_uses_lib('mbedtls') and tls_max == '1.3': + pytest.skip('mbedtls TLSv1.3 session resume not working in 3.6.0') curl = CurlClient(env=env) # tell the server to close the connection after each request