]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
mbedtls: add support for 4.0.0
authorViktor Szakats <commit@vsz.me>
Wed, 15 Oct 2025 19:01:46 +0000 (21:01 +0200)
committerViktor Szakats <commit@vsz.me>
Fri, 17 Oct 2025 09:50:48 +0000 (11:50 +0200)
After this patch libcurl requires (as already documented)
the `curl_global_init()` call when using the `curl_formadd()` API with
mbedTLS.

Note: NTLM is not supported with mbedTLS 4+, because it lacks
the necessary crypto primitive: DES.

Also:
- lib: de-dupe mbedTLS minimum version checks into `curl_setup.h`.
- lib: initialize PSA Crypto as part of `curl_global_init()`.
  For MD5, SHA-256, `curl_formadd()`, and MultiSSL builds with mbedTLS
  but where mbedTLS isn't the default backend.
- lib1308: fix to call `curl_global_init()` (for the Form API).
- curl_ntlm_core: disable with mbedTLS 4+.
- md4: disable mbedTLS implementation when building against 4.x.
- md5: use mbedTLS PSA Crypto API when available, otherwise use
  the default local implementation.
- sha256: use mbedTLS PSA Crypto API when available, otherwise use
  the default local implementation.
- vtls/mbedtls: drop PSA Crypto initialization in favor of
  `curl_global_init()`.
- vtls/mbedtls: use PSA Crypto random API with all mbedTLS versions.
- vtls/mbedtls: do the same for the SHA-256 callback.
- autotools: detect mbedTLS 4+, and disable NTLM for 3.x.
- cmake: disable NTLM for mbedTLS 3.x.
- GHA/linux: keep building mbedTLS 3.x manually and use it in
  an existing job, while also enabling pytest in it.
- GHA/linux: bump to mbedTLS 4.0.0.
  Closes #19075
  Closes #19074

Refs:
https://github.com/Mbed-TLS/mbedtls/releases/tag/mbedtls-4.0.0
https://github.com/Mbed-TLS/mbedtls/blob/mbedtls-4.0.0/docs/4.0-migration-guide.md
https://github.com/Mbed-TLS/mbedtls/blob/mbedtls-4.0.0/tf-psa-crypto/docs/1.0-migration-guide.md [404]
https://github.com/Mbed-TLS/TF-PSA-Crypto/blob/tf-psa-crypto-1.0.0/docs/1.0-migration-guide.md
https://github.com/Mbed-TLS/TF-PSA-Crypto/blob/tf-psa-crypto-1.0.0/docs/psa-transition.md
https://github.com/Mbed-TLS/TF-PSA-Crypto/tree/627f727bbed3d9319ed548f1c0839a29c223414e/docs/4.0-migration-guide

Closes #19077

12 files changed:
.github/workflows/linux.yml
CMakeLists.txt
configure.ac
lib/curl_ntlm_core.c
lib/curl_setup.h
lib/easy.c
lib/md4.c
lib/md5.c
lib/sha256.c
lib/vtls/mbedtls.c
m4/curl-mbedtls.m4
tests/libtest/lib1308.c

index 2d674dc195cff6b15c626ce54aa98520b8d0f317..527c9ce6075b93c57d74b2c534ea1a705801484e 100644 (file)
@@ -42,7 +42,9 @@ env:
   # renovate: datasource=github-tags depName=wolfSSL/wolfssl versioning=semver extractVersion=^v?(?<version>.+)-stable$ registryUrl=https://github.com
   WOLFSSL_VERSION: 5.8.2
   # renovate: datasource=github-tags depName=Mbed-TLS/mbedtls versioning=semver registryUrl=https://github.com
-  MBEDTLS_VERSION: 3.6.4
+  MBEDTLS_VERSION: 4.0.0
+  # renovate: datasource=github-tags depName=Mbed-TLS/mbedtls versioning=semver:^3.0.0 registryUrl=https://github.com
+  MBEDTLS_VERSION_PREV: 3.6.4
   # renovate: datasource=github-tags depName=awslabs/aws-lc versioning=semver registryUrl=https://github.com
   AWSLC_VERSION: 1.61.4
   # renovate: datasource=github-tags depName=google/boringssl versioning=semver registryUrl=https://github.com
@@ -109,10 +111,10 @@ jobs:
             install_steps: mbedtls pytest
             configure: CC=clang LDFLAGS=-Wl,-rpath,/home/runner/mbedtls/lib --with-mbedtls=/home/runner/mbedtls --enable-debug --with-fish-functions-dir --with-zsh-functions-dir
 
-          - name: 'mbedtls'
+          - name: 'mbedtls-prev'
             install_packages: libnghttp2-dev libuv1-dev
-            install_steps: mbedtls
-            PKG_CONFIG_PATH: /home/runner/mbedtls/lib/pkgconfig  # Requires v3.6.0
+            install_steps: mbedtls-prev pytest
+            PKG_CONFIG_PATH: /home/runner/mbedtls-prev/lib/pkgconfig  # Requires v3.6.0
             generate: -DCURL_USE_MBEDTLS=ON -DCURL_USE_LIBUV=ON -DENABLE_DEBUG=ON
 
           - name: 'mbedtls-pkg MultiSSL !pc'
@@ -435,7 +437,7 @@ jobs:
       - name: 'cache mbedtls'
         if: ${{ contains(matrix.build.install_steps, 'mbedtls') }}
         uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
-        id: cache-mbedtls
+        id: cache-mbedtls-threadsafe
         env:
           cache-name: cache-mbedtls-threadsafe
         with:
@@ -443,7 +445,7 @@ jobs:
           key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.MBEDTLS_VERSION }}
 
       - name: 'build mbedtls'
-        if: ${{ contains(matrix.build.install_steps, 'mbedtls') && steps.cache-mbedtls.outputs.cache-hit != 'true' }}
+        if: ${{ contains(matrix.build.install_steps, 'mbedtls') && steps.cache-mbedtls-threadsafe.outputs.cache-hit != 'true' }}
         run: |
           curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \
             --location "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MBEDTLS_VERSION}/mbedtls-${MBEDTLS_VERSION}.tar.bz2" | tar -xj
@@ -455,7 +457,30 @@ jobs:
           cmake --build .
           cmake --install .
 
-      - name: 'cache openldap-static'
+      - name: 'cache mbedtls (prev)'
+        if: ${{ contains(matrix.build.install_steps, 'mbedtls-prev') }}
+        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
+        id: cache-mbedtls-threadsafe-prev
+        env:
+          cache-name: cache-mbedtls-threadsafe-prev
+        with:
+          path: ~/mbedtls-prev
+          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.MBEDTLS_VERSION }}
+
+      - name: 'build mbedtls (prev)'
+        if: ${{ contains(matrix.build.install_steps, 'mbedtls-prev') && steps.cache-mbedtls-threadsafe-prev.outputs.cache-hit != 'true' }}
+        run: |
+          curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \
+            --location "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MBEDTLS_VERSION_PREV}/mbedtls-${MBEDTLS_VERSION_PREV}.tar.bz2" | tar -xj
+          cd "mbedtls-${MBEDTLS_VERSION_PREV}"
+          ./scripts/config.py set MBEDTLS_THREADING_C
+          ./scripts/config.py set MBEDTLS_THREADING_PTHREAD
+          cmake -B . -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=/home/runner/mbedtls-prev \
+            -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF
+          cmake --build .
+          cmake --install .
+
+      - name: 'cache openldap (static)'
         if: ${{ contains(matrix.build.install_steps, 'openldap-static') }}
         uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
         id: cache-openldap-static
index 65eaaf670a5e5ad2be966a509b974fd4cc0963b5..b6aff6ce7cc496580196531fa34aab9a4ab4d933 100644 (file)
@@ -2083,7 +2083,7 @@ endmacro()
 # These conditions must match those in lib/curl_setup.h.
 if(NOT CURL_DISABLE_NTLM AND
    (USE_OPENSSL OR
-    USE_MBEDTLS OR
+    (USE_MBEDTLS AND MBEDTLS_VERSION VERSION_LESS 4.0.0) OR
     USE_GNUTLS OR
     USE_WIN32_CRYPTO OR
     (USE_WOLFSSL AND HAVE_WOLFSSL_DES_ECB_ENCRYPT)))
index 999ab122a323b95eb00b08c9355bdfb2c50bdb9e..97d0310497756edc5dd7c31b9c1124aa2cabaec3 100644 (file)
@@ -5252,11 +5252,13 @@ fi
 use_curl_ntlm_core=no
 
 if test "x$CURL_DISABLE_NTLM" != "x1"; then
-  if test "x$OPENSSL_ENABLED" = "x1" -o "x$MBEDTLS_ENABLED" = "x1" \
+  if test "x$OPENSSL_ENABLED" = "x1" \
       -o "x$GNUTLS_ENABLED" = "x1" \
       -o "x$USE_WIN32_CRYPTO" = "x1" \
       -o "x$HAVE_WOLFSSL_DES_ECB_ENCRYPT" = "x1"; then
     use_curl_ntlm_core=yes
+  elif test "x$MBEDTLS_ENABLED" = "x1" && test "$mbedtls_4" = "0"; then
+    use_curl_ntlm_core=yes
   fi
 
   if test "x$use_curl_ntlm_core" = "xyes" \
index cf0e4dc28832c29defc5658ed054847883e5e109..a81e97f0ce725fd2436a4318ae1e35800260ba37 100644 (file)
    1. USE_OPENSSL
    2. USE_WOLFSSL
    3. USE_GNUTLS
-   4. -
-   5. USE_MBEDTLS
-   6. USE_OS400CRYPTO
-   7. USE_WIN32_CRYPTO
+   4. USE_MBEDTLS
+   5. USE_OS400CRYPTO
+   6. USE_WIN32_CRYPTO
 
    This ensures that:
    - the same SSL branch gets activated throughout this source
   #ifndef NO_DES3
     #define USE_OPENSSL_DES
   #endif
+#elif defined(USE_MBEDTLS)
+  #include <mbedtls/version.h>
+  #if MBEDTLS_VERSION_NUMBER < 0x04000000
+    #define USE_MBEDTLS_DES
+  #endif
 #endif
 
 #ifdef USE_OPENSSL_DES
 
 #  include <nettle/des.h>
 
-#elif defined(USE_MBEDTLS)
+#elif defined(USE_MBEDTLS_DES)
 
 #  include <mbedtls/des.h>
 
@@ -178,7 +182,7 @@ static void setup_des_key(const unsigned char *key_56,
   des_set_key(des, (const uint8_t *) key);
 }
 
-#elif defined(USE_MBEDTLS)
+#elif defined(USE_MBEDTLS_DES)
 
 static bool encrypt_des(const unsigned char *in, unsigned char *out,
                         const unsigned char *key_56)
@@ -305,7 +309,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
   des_encrypt(&des, 8, results + 8, plaintext);
   setup_des_key(keys + 14, &des);
   des_encrypt(&des, 8, results + 16, plaintext);
-#elif defined(USE_MBEDTLS) || defined(USE_OS400CRYPTO) ||       \
+#elif defined(USE_MBEDTLS_DES) || defined(USE_OS400CRYPTO) ||   \
   defined(USE_WIN32_CRYPTO)
   encrypt_des(plaintext, results, keys);
   encrypt_des(plaintext, results + 8, keys + 7);
@@ -353,7 +357,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
     des_encrypt(&des, 8, lmbuffer, magic);
     setup_des_key(pw + 7, &des);
     des_encrypt(&des, 8, lmbuffer + 8, magic);
-#elif defined(USE_MBEDTLS) || defined(USE_OS400CRYPTO) ||       \
+#elif defined(USE_MBEDTLS_DES) || defined(USE_OS400CRYPTO) ||   \
   defined(USE_WIN32_CRYPTO)
     encrypt_des(magic, lmbuffer, pw);
     encrypt_des(magic, lmbuffer + 8, pw + 7);
index 694d14df4f09b1b15b2b5884fae27054372c173d..4934baa22b712e8e0539d7b2973e1eeedcc7f842 100644 (file)
 #  endif
 #endif
 
+#ifdef USE_MBEDTLS
+#include <mbedtls/version.h>
+#if MBEDTLS_VERSION_NUMBER < 0x03020000
+  #error "mbedTLS 3.2.0 or later required"
+#endif
+#endif
+
 #if defined(USE_WOLFSSL) && defined(USE_GNUTLS)
 /* Avoid defining unprefixed wolfSSL SHA macros colliding with nettle ones */
 #define NO_OLD_WC_NAMES
 
 /* Single point where USE_NTLM definition might be defined */
 #ifndef CURL_DISABLE_NTLM
-#  if defined(USE_OPENSSL) || defined(USE_MBEDTLS) ||                   \
+#  if defined(USE_OPENSSL) ||                                           \
   defined(USE_GNUTLS) ||                                                \
+  (defined(USE_MBEDTLS) && MBEDTLS_VERSION_NUMBER < 0x04000000) ||      \
   defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) ||              \
   (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
 #    define USE_CURL_NTLM_CORE
index 793a18f33eb88090ca72bcb56479d19ade337ce0..f12a8b143f0cc781c60c50937d13dbc39e43b29e 100644 (file)
 
 #include "easy_lock.h"
 
+#ifdef USE_MBEDTLS
+#include <psa/crypto.h>
+#endif
+
 /* The last 2 #include files should be in this order */
 #include "curl_memory.h"
 #include "memdebug.h"
@@ -137,6 +141,24 @@ curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
 static char *leakpointer;
 #endif
 
+static CURLcode crypto_init(void)
+{
+#ifdef USE_MBEDTLS
+  psa_status_t status;
+  status = psa_crypto_init();
+  if(status != PSA_SUCCESS)
+    return CURLE_FAILED_INIT;
+#endif
+  return CURLE_OK;
+}
+
+static void crypto_cleanup(void)
+{
+#ifdef USE_MBEDTLS
+  mbedtls_psa_crypto_free();
+#endif
+}
+
 /**
  * curl_global_init() globally initializes curl given a bitwise set of the
  * different features of what to initialize.
@@ -160,6 +182,11 @@ static CURLcode global_init(long flags, bool memoryfuncs)
     goto fail;
   }
 
+  if(crypto_init()) {
+    DEBUGF(curl_mfprintf(stderr, "Error: crypto_init failed\n"));
+    goto fail;
+  }
+
   if(!Curl_ssl_init()) {
     DEBUGF(curl_mfprintf(stderr, "Error: Curl_ssl_init failed\n"));
     goto fail;
@@ -298,6 +325,8 @@ void curl_global_cleanup(void)
 
   Curl_ssh_cleanup();
 
+  crypto_cleanup();
+
 #ifdef DEBUGBUILD
   free(leakpointer);
 #endif
index 9db85786e125324a2913a44bfa32a724534096ae..5d0908eadefa94a5f36cc3f0f0646fa6d1b9008e 100644 (file)
--- a/lib/md4.c
+++ b/lib/md4.c
 
 #ifdef USE_MBEDTLS
 #include <mbedtls/version.h>
-#if MBEDTLS_VERSION_NUMBER < 0x03020000
-  #error "mbedTLS 3.2.0 or later required"
-#endif
+#if MBEDTLS_VERSION_NUMBER < 0x04000000 && defined(MBEDTLS_MD4_C)
+#define USE_MBEDTLS_MD4
 #include <mbedtls/mbedtls_config.h>
-#endif /* USE_MBEDTLS */
+#endif
+#endif
 
 /* When OpenSSL or wolfSSL is available, we use their MD4 functions. */
 #if defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4)
@@ -78,7 +78,7 @@
 #include <wincrypt.h>
 #elif defined(USE_GNUTLS)
 #include <nettle/md4.h>
-#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
+#elif defined(USE_MBEDTLS_MD4)
 #include <mbedtls/md4.h>
 #endif
 
@@ -187,7 +187,7 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
   md4_digest(ctx, MD4_DIGEST_SIZE, result);
 }
 
-#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
+#elif defined(USE_MBEDTLS_MD4)
 
 struct md4_ctx {
   void *data;
index 091924034055e448a52954e891eed7371b2ae730..897bd1b1a407ddb6bf8977f577f299fc416d6b53 100644 (file)
--- a/lib/md5.c
+++ b/lib/md5.c
 #include "curl_hmac.h"
 #include "curlx/warnless.h"
 
-#ifdef USE_MBEDTLS
-#include <mbedtls/version.h>
-#if MBEDTLS_VERSION_NUMBER < 0x03020000
-  #error "mbedTLS 3.2.0 or later required"
-#endif
-#endif /* USE_MBEDTLS */
-
 #ifdef USE_OPENSSL
   #include <openssl/opensslconf.h>
   #if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_DEPRECATED_3_0)
   #endif
 #endif
 
+#ifdef USE_MBEDTLS
+  #include <psa/crypto_config.h>
+  #if defined(PSA_WANT_ALG_MD5) && PSA_WANT_ALG_MD5  /* mbedTLS 4+ */
+    #define USE_MBEDTLS_MD5
+  #endif
+#endif
+
 #ifdef USE_GNUTLS
 #include <nettle/md5.h>
 #elif defined(USE_OPENSSL_MD5)
 #include <openssl/md5.h>
 #elif defined(USE_WOLFSSL_MD5)
 #include <wolfssl/openssl/md5.h>
-#elif defined(USE_MBEDTLS)
-#include <mbedtls/md5.h>
+#elif defined(USE_MBEDTLS_MD5)
+#include <psa/crypto.h>
 #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
               (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
        defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
@@ -152,13 +152,14 @@ static void my_md5_final(unsigned char *digest, void *ctx)
   (void)wolfSSL_MD5_Final(digest, ctx);
 }
 
-#elif defined(USE_MBEDTLS)
+#elif defined(USE_MBEDTLS_MD5)
 
-typedef mbedtls_md5_context my_md5_ctx;
+typedef psa_hash_operation_t my_md5_ctx;
 
 static CURLcode my_md5_init(void *ctx)
 {
-  if(mbedtls_md5_starts(ctx))
+  memset(ctx, 0, sizeof(my_md5_ctx));
+  if(psa_hash_setup(ctx, PSA_ALG_MD5) != PSA_SUCCESS)
     return CURLE_OUT_OF_MEMORY;
   return CURLE_OK;
 }
@@ -167,12 +168,13 @@ static void my_md5_update(void *ctx,
                           const unsigned char *data,
                           unsigned int length)
 {
-  (void)mbedtls_md5_update(ctx, data, length);
+  (void)psa_hash_update(ctx, data, length);
 }
 
 static void my_md5_final(unsigned char *digest, void *ctx)
 {
-  (void)mbedtls_md5_finish(ctx, digest);
+  size_t actual_length;
+  (void)psa_hash_finish(ctx, digest, 16, &actual_length);
 }
 
 #elif defined(AN_APPLE_OS)
index 2d0357189a0ecf56fba2944aaca47b6a8c04ba25..cf8e98a550e539126b518b766a948e2fae369372 100644 (file)
 #include "curl_sha256.h"
 #include "curl_hmac.h"
 
+#ifdef USE_MBEDTLS
+  #include <psa/crypto_config.h>
+  #if defined(PSA_WANT_ALG_SHA_256) && PSA_WANT_ALG_SHA_256  /* mbedTLS 4+ */
+    #define USE_MBEDTLS_SHA256
+  #endif
+#endif
+
 #ifdef USE_OPENSSL
 #include <openssl/evp.h>
 #elif defined(USE_GNUTLS)
 #include <nettle/sha.h>
-#elif defined(USE_MBEDTLS)
-#include <mbedtls/version.h>
-#if MBEDTLS_VERSION_NUMBER < 0x03020000
-  #error "mbedTLS 3.2.0 or later required"
-#endif
-#include <mbedtls/sha256.h>
+#elif defined(USE_MBEDTLS_SHA256)
+#include <psa/crypto.h>
 #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
               (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
       (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
@@ -126,13 +129,15 @@ static void my_sha256_final(unsigned char *digest, void *ctx)
   sha256_digest(ctx, SHA256_DIGEST_SIZE, digest);
 }
 
-#elif defined(USE_MBEDTLS)
+#elif defined(USE_MBEDTLS_SHA256)
 
-typedef mbedtls_sha256_context my_sha256_ctx;
+typedef psa_hash_operation_t my_sha256_ctx;
 
 static CURLcode my_sha256_init(void *ctx)
 {
-  (void)mbedtls_sha256_starts(ctx, 0);
+  memset(ctx, 0, sizeof(my_sha256_ctx));
+  if(psa_hash_setup(ctx, PSA_ALG_SHA_256) != PSA_SUCCESS)
+    return CURLE_OUT_OF_MEMORY;
   return CURLE_OK;
 }
 
@@ -140,12 +145,14 @@ static void my_sha256_update(void *ctx,
                              const unsigned char *data,
                              unsigned int length)
 {
-  (void)mbedtls_sha256_update(ctx, data, length);
+  (void)psa_hash_update(ctx, data, length);
 }
 
 static void my_sha256_final(unsigned char *digest, void *ctx)
 {
-  (void)mbedtls_sha256_finish(ctx, digest);
+  size_t actual_length;
+  (void)psa_hash_finish(ctx, digest, CURL_SHA256_DIGEST_LENGTH,
+                        &actual_length);
 }
 
 #elif defined(AN_APPLE_OS)
index 3ff131b441a0c22f70074d73e504a9a5f2394240..ebb8a4abc00955ed6c001be4fa57b122200c6aef 100644 (file)
 /* #define MBEDTLS_DEBUG */
 
 #include <mbedtls/version.h>
-#if MBEDTLS_VERSION_NUMBER < 0x03020000
-  #error "mbedTLS 3.2.0 or later required"
-#endif
+#include <psa/crypto_config.h>
 #include <mbedtls/net_sockets.h>
 #include <mbedtls/ssl.h>
 #include <mbedtls/x509.h>
+#include <mbedtls/psa_util.h>
+
+#if MBEDTLS_VERSION_NUMBER < 0x04000000
+#define CURL_MBEDTLS_DRBG
+#endif
 
 #include <mbedtls/error.h>
+#ifdef CURL_MBEDTLS_DRBG
 #include <mbedtls/entropy.h>
 #include <mbedtls/ctr_drbg.h>
-#include <mbedtls/sha256.h>
+#endif
 #ifdef MBEDTLS_DEBUG
 #include <mbedtls/debug.h>
 #endif
 #endif
 
 struct mbed_ssl_backend_data {
+#ifdef CURL_MBEDTLS_DRBG
   mbedtls_ctr_drbg_context ctr_drbg;
   mbedtls_entropy_context entropy;
+#endif
   mbedtls_ssl_context ssl;
   mbedtls_x509_crt cacert;
   mbedtls_x509_crt clicert;
@@ -106,7 +112,7 @@ struct mbed_ssl_backend_data {
 #define mbedtls_strerror(a,b,c) b[0] = 0
 #endif
 
-#ifdef HAS_THREADING_SUPPORT
+#if defined(CURL_MBEDTLS_DRBG) && defined(HAS_THREADING_SUPPORT)
 static mbedtls_entropy_context ts_entropy;
 
 static int entropy_init_initialized = 0;
@@ -144,7 +150,7 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
   return ret;
 }
 
-#endif /* HAS_THREADING_SUPPORT */
+#endif /* CURL_MBEDTLS_DRBG && HAS_THREADING_SUPPORT */
 
 #ifdef MBEDTLS_DEBUG
 static void mbed_debug(void *context, int level, const char *f_name,
@@ -538,6 +544,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     return CURLE_NOT_BUILT_IN;
   }
 
+#ifdef CURL_MBEDTLS_DRBG
 #ifdef HAS_THREADING_SUPPORT
   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
 
@@ -562,6 +569,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     return CURLE_FAILED_INIT;
   }
 #endif /* HAS_THREADING_SUPPORT */
+#endif /* CURL_MBEDTLS_DRBG */
 
   /* Load the trusted CA */
   mbedtls_x509_crt_init(&backend->cacert);
@@ -665,6 +673,17 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
   if(ssl_config->key || ssl_config->key_blob) {
     if(ssl_config->key) {
 #ifdef MBEDTLS_FS_IO
+#if MBEDTLS_VERSION_NUMBER >= 0x04000000
+      ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
+                                     ssl_config->key_passwd);
+      if(ret == 0 && !(mbedtls_pk_can_do_psa(&backend->pk,
+                                   PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH),
+                                   PSA_KEY_USAGE_SIGN_HASH) ||
+                       mbedtls_pk_can_do_psa(&backend->pk,
+                                   MBEDTLS_PK_ALG_ECDSA(PSA_ALG_ANY_HASH),
+                                   PSA_KEY_USAGE_SIGN_HASH)))
+        ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
+#else
       ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
                                      ssl_config->key_passwd,
                                      mbedtls_ctr_drbg_random,
@@ -672,6 +691,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
       if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
                        mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
         ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
+#endif
 
       if(ret) {
         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -689,6 +709,18 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
       const unsigned char *key_data =
         (const unsigned char *)ssl_key_blob->data;
       const char *passwd = ssl_config->key_passwd;
+#if MBEDTLS_VERSION_NUMBER >= 0x04000000
+      ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
+                                 (const unsigned char *)passwd,
+                                 passwd ? strlen(passwd) : 0);
+      if(ret == 0 && !(mbedtls_pk_can_do_psa(&backend->pk,
+                                   PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH),
+                                   PSA_KEY_USAGE_SIGN_HASH) ||
+                       mbedtls_pk_can_do_psa(&backend->pk,
+                                   MBEDTLS_PK_ALG_ECDSA(PSA_ALG_ANY_HASH),
+                                   PSA_KEY_USAGE_SIGN_HASH)))
+        ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
+#else
       ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
                                  (const unsigned char *)passwd,
                                  passwd ? strlen(passwd) : 0,
@@ -697,6 +729,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
       if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
                        mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
         ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
+#endif
 
       if(ret) {
         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -746,8 +779,9 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-#ifdef MBEDTLS_SSL_SESSION_TICKETS
-  /* New in mbedTLS 3.6.1, need to enable, default is now disabled */
+#if MBEDTLS_VERSION_NUMBER < 0x04000000 && defined(MBEDTLS_SSL_SESSION_TICKETS)
+  /* New in mbedTLS 3.6.1, need to enable, default is now disabled.
+     4.0.0 enabled it by default for TLSv1.3. */
   mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(&backend->config,
     MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED);
 #endif
@@ -769,8 +803,10 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
   if(ret != CURLE_OK)
     return ret;
 
+#ifdef CURL_MBEDTLS_DRBG
   mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
                        &backend->ctr_drbg);
+#endif
 
   ret = mbedtls_ssl_setup(&backend->ssl, &backend->config);
   if(ret) {
@@ -1272,10 +1308,12 @@ static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
     Curl_safefree(backend->ciphersuites);
     mbedtls_ssl_config_free(&backend->config);
     mbedtls_ssl_free(&backend->ssl);
+#ifdef CURL_MBEDTLS_DRBG
     mbedtls_ctr_drbg_free(&backend->ctr_drbg);
 #ifndef HAS_THREADING_SUPPORT
     mbedtls_entropy_free(&backend->entropy);
-#endif /* HAS_THREADING_SUPPORT */
+#endif /* !HAS_THREADING_SUPPORT */
+#endif
     backend->initialized = FALSE;
   }
 }
@@ -1346,33 +1384,12 @@ static size_t mbedtls_version(char *buffer, size_t size)
 static CURLcode mbedtls_random(struct Curl_easy *data,
                                unsigned char *entropy, size_t length)
 {
-#ifdef MBEDTLS_CTR_DRBG_C
-  int ret;
-  mbedtls_entropy_context ctr_entropy;
-  mbedtls_ctr_drbg_context ctr_drbg;
-  mbedtls_entropy_init(&ctr_entropy);
-  mbedtls_ctr_drbg_init(&ctr_drbg);
+  psa_status_t status;
   (void)data;
 
-  ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
-                              &ctr_entropy, NULL, 0);
-
-  if(!ret)
-    ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
+  status = psa_generate_random(entropy, length);
 
-  mbedtls_ctr_drbg_free(&ctr_drbg);
-  mbedtls_entropy_free(&ctr_entropy);
-
-  return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
-#elif defined(MBEDTLS_HAVEGE_C)
-  mbedtls_havege_state hs;
-  mbedtls_havege_init(&hs);
-  mbedtls_havege_random(&hs, entropy, length);
-  mbedtls_havege_free(&hs);
-  return CURLE_OK;
-#else
-  return CURLE_NOT_BUILT_IN;
-#endif
+  return status == PSA_SUCCESS ? CURLE_OK : CURLE_FAILED_INIT;
 }
 
 static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
@@ -1434,29 +1451,15 @@ static int mbedtls_init(void)
 {
   if(!Curl_mbedtlsthreadlock_thread_setup())
     return 0;
-#ifdef HAS_THREADING_SUPPORT
+#if defined(CURL_MBEDTLS_DRBG) && defined(HAS_THREADING_SUPPORT)
   entropy_init_mutex(&ts_entropy);
 #endif
-#ifdef MBEDTLS_USE_PSA_CRYPTO  /* requires mbedTLS 3.6.0+ */
-  {
-    int ret;
-#ifdef HAS_THREADING_SUPPORT
-    Curl_mbedtlsthreadlock_lock_function(0);
-#endif
-    ret = psa_crypto_init();
-#ifdef HAS_THREADING_SUPPORT
-    Curl_mbedtlsthreadlock_unlock_function(0);
-#endif
-    if(ret != PSA_SUCCESS)
-      return 0;
-  }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
   return 1;
 }
 
 static void mbedtls_cleanup(void)
 {
-#ifdef HAS_THREADING_SUPPORT
+#if defined(CURL_MBEDTLS_DRBG) && defined(HAS_THREADING_SUPPORT)
   entropy_cleanup_mutex(&ts_entropy);
 #endif
   (void)Curl_mbedtlsthreadlock_thread_cleanup();
@@ -1479,11 +1482,19 @@ static CURLcode mbedtls_sha256sum(const unsigned char *input,
                                   unsigned char *sha256sum,
                                   size_t sha256len)
 {
-  (void)sha256len;
-  /* returns 0 on success, otherwise failure */
-  if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0)
+#if defined(PSA_WANT_ALG_SHA_256) && PSA_WANT_ALG_SHA_256  /* mbedTLS 4+ */
+  psa_status_t status;
+  size_t sha256len_actual;
+  status = psa_hash_compute(PSA_ALG_SHA_256, input, inputlen,
+                            sha256sum, sha256len,
+                            &sha256len_actual);
+  if(status != PSA_SUCCESS)
     return CURLE_BAD_FUNCTION_ARGUMENT;
   return CURLE_OK;
+#else
+  (void)sha256len;
+  return Curl_sha256it(sha256sum, input, inputlen);
+#endif
 }
 
 static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
index 519c29d79a6911938ef5c72d7c2ca539619581d2..55152c54081be69def809d8b437937b0caa5aa73 100644 (file)
@@ -106,6 +106,25 @@ if test "x$OPT_MBEDTLS" != xno; then
       if false; then
         LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE mbedtls mbedx509 mbedcrypto"
       fi
+
+      mbedtls_4=0
+      AC_MSG_CHECKING([for mbedTLS >= v4])
+      AC_COMPILE_IFELSE([
+        AC_LANG_PROGRAM([[
+          #include <mbedtls/version.h>
+        ]],[[
+          #if (MBEDTLS_VERSION_NUMBER >= 0x04000000)
+          return 0;
+          #else
+          #error older than 4
+          #endif
+        ]])
+      ],[
+        mbedtls_4=1
+        AC_MSG_RESULT([yes])
+      ],[
+        AC_MSG_RESULT([no])
+      ])
     fi
 
   fi dnl mbedTLS not disabled
index 8e83462a7ade4664a6c6788996c3452df59b3100..1455b0b0dfe7c3a8fd695b87905b5ab382eb8e38 100644 (file)
@@ -43,12 +43,15 @@ static CURLcode test_lib1308(const char *URL)
 {
   int errorcount = 0;
   CURLFORMcode rc;
-  int res;
+  CURLcode res = CURLE_OK;
+  int formres = 0;
   struct curl_httppost *post = NULL;
   struct curl_httppost *last = NULL;
   size_t total_size = 0;
   char buffer[] = "test buffer";
 
+  global_init(CURL_GLOBAL_ALL);
+
   rc = curl_formadd(&post, &last, CURLFORM_COPYNAME, "name",
                     CURLFORM_COPYCONTENTS, "content", CURLFORM_END);
   t1308_fail_unless(rc == 0, "curl_formadd returned error");
@@ -66,8 +69,8 @@ static CURLcode test_lib1308(const char *URL)
                     CURLFORM_PTRCONTENTS, buffer, CURLFORM_END);
   t1308_fail_unless(rc == 0, "curl_formadd returned error");
 
-  res = curl_formget(post, &total_size, print_httppost_callback);
-  t1308_fail_unless(res == 0, "curl_formget returned error");
+  formres = curl_formget(post, &total_size, print_httppost_callback);
+  t1308_fail_unless(formres == 0, "curl_formget returned error");
 
   t1308_fail_unless(total_size == 518, "curl_formget got wrong size back");
 
@@ -83,12 +86,14 @@ static CURLcode test_lib1308(const char *URL)
                     CURLFORM_END);
   t1308_fail_unless(rc == 0, "curl_formadd returned error");
 
-  res = curl_formget(post, &total_size, print_httppost_callback);
+  formres = curl_formget(post, &total_size, print_httppost_callback);
 
-  t1308_fail_unless(res == 0, "curl_formget returned error");
+  t1308_fail_unless(formres == 0, "curl_formget returned error");
   t1308_fail_unless(total_size == 899, "curl_formget got wrong size back");
 
   curl_formfree(post);
 
+  curl_global_cleanup();
+
   return errorcount ? TEST_ERR_FAILURE : CURLE_OK;
 }