]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
mbedtls: v3.6.0 workarounds
authorStefan Eissing <stefan@eissing.org>
Fri, 31 May 2024 11:01:17 +0000 (13:01 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 4 Jun 2024 07:02:37 +0000 (09:02 +0200)
- add special sauce to disable unwanted peer verification by mbedtls
  when negotiating TLS v1.3
- add special sauce for MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET
  return code on *writing* TLS data. We assume the data had not been
  written and EAGAIN.
- return correct Curl error code when peer verification failed.
- disable test_08_05 with 50 HTTP/1.1 connections, as mbedtls reports a
  memory allocation failed during handshake.
- bump CI mbedtls version to 3.6.0

Fixes #13653
Closes #13838

.github/workflows/linux.yml
lib/vtls/mbedtls.c
tests/http/test_08_caddy.py
tests/http/test_17_ssl_use.py

index 608666c6bff55e86bc074e37de97d4589418582e..65a3fd72506be4c8e89c02c399c3ef39e2669748 100644 (file)
@@ -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
index c714cc1b0aca54b5a8e8e8229d9dd699ea7384ac..8393b02d2f7a13f38e92a32ef81d6aef0d1758f4 100644 (file)
@@ -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 <https://github.com/Mbed-TLS/mbedtls/issues/9210> */
+  *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;
   }
 
index 6b8fce8fef24fe6edaef7a2e46cbb5844923ab0e..4a75ef552367832b665b799ff55121d72d5f6569 100644 (file)
@@ -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}]'
index d741514bbe0610f2c123c9b10732bebb8628195f..b9c3dcf5564638f31af166a25e8292f391b4a80e 100644 (file)
@@ -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