From 3a305831d1a9d10b2bfd4fa3939ed41275fee7f7 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Wed, 15 Oct 2025 21:01:46 +0200 Subject: [PATCH] mbedtls: add support for 4.0.0 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 --- .github/workflows/linux.yml | 39 +++++++++--- CMakeLists.txt | 2 +- configure.ac | 4 +- lib/curl_ntlm_core.c | 20 ++++--- lib/curl_setup.h | 10 +++- lib/easy.c | 29 +++++++++ lib/md4.c | 12 ++-- lib/md5.c | 30 +++++----- lib/sha256.c | 29 +++++---- lib/vtls/mbedtls.c | 115 ++++++++++++++++++++---------------- m4/curl-mbedtls.m4 | 19 ++++++ tests/libtest/lib1308.c | 15 +++-- 12 files changed, 218 insertions(+), 106 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 2d674dc195..527c9ce607 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -42,7 +42,9 @@ env: # renovate: datasource=github-tags depName=wolfSSL/wolfssl versioning=semver extractVersion=^v?(?.+)-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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 65eaaf670a..b6aff6ce7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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))) diff --git a/configure.ac b/configure.ac index 999ab122a3..97d0310497 100644 --- a/configure.ac +++ b/configure.ac @@ -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" \ diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c index cf0e4dc288..a81e97f0ce 100644 --- a/lib/curl_ntlm_core.c +++ b/lib/curl_ntlm_core.c @@ -38,10 +38,9 @@ 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 @@ -61,6 +60,11 @@ #ifndef NO_DES3 #define USE_OPENSSL_DES #endif +#elif defined(USE_MBEDTLS) + #include + #if MBEDTLS_VERSION_NUMBER < 0x04000000 + #define USE_MBEDTLS_DES + #endif #endif #ifdef USE_OPENSSL_DES @@ -97,7 +101,7 @@ # include -#elif defined(USE_MBEDTLS) +#elif defined(USE_MBEDTLS_DES) # include @@ -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); diff --git a/lib/curl_setup.h b/lib/curl_setup.h index 694d14df4f..4934baa22b 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -737,6 +737,13 @@ # endif #endif +#ifdef USE_MBEDTLS +#include +#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 @@ -756,8 +763,9 @@ /* 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 diff --git a/lib/easy.c b/lib/easy.c index 793a18f33e..f12a8b143f 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -80,6 +80,10 @@ #include "easy_lock.h" +#ifdef USE_MBEDTLS +#include +#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 diff --git a/lib/md4.c b/lib/md4.c index 9db85786e1..5d0908eade 100644 --- a/lib/md4.c +++ b/lib/md4.c @@ -53,11 +53,11 @@ #ifdef USE_MBEDTLS #include -#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 -#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 #elif defined(USE_GNUTLS) #include -#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C)) +#elif defined(USE_MBEDTLS_MD4) #include #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; diff --git a/lib/md5.c b/lib/md5.c index 0919240340..897bd1b1a4 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -34,13 +34,6 @@ #include "curl_hmac.h" #include "curlx/warnless.h" -#ifdef USE_MBEDTLS -#include -#if MBEDTLS_VERSION_NUMBER < 0x03020000 - #error "mbedTLS 3.2.0 or later required" -#endif -#endif /* USE_MBEDTLS */ - #ifdef USE_OPENSSL #include #if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_DEPRECATED_3_0) @@ -55,14 +48,21 @@ #endif #endif +#ifdef USE_MBEDTLS + #include + #if defined(PSA_WANT_ALG_MD5) && PSA_WANT_ALG_MD5 /* mbedTLS 4+ */ + #define USE_MBEDTLS_MD5 + #endif +#endif + #ifdef USE_GNUTLS #include #elif defined(USE_OPENSSL_MD5) #include #elif defined(USE_WOLFSSL_MD5) #include -#elif defined(USE_MBEDTLS) -#include +#elif defined(USE_MBEDTLS_MD5) +#include #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) diff --git a/lib/sha256.c b/lib/sha256.c index 2d0357189a..cf8e98a550 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -32,16 +32,19 @@ #include "curl_sha256.h" #include "curl_hmac.h" +#ifdef USE_MBEDTLS + #include + #if defined(PSA_WANT_ALG_SHA_256) && PSA_WANT_ALG_SHA_256 /* mbedTLS 4+ */ + #define USE_MBEDTLS_SHA256 + #endif +#endif + #ifdef USE_OPENSSL #include #elif defined(USE_GNUTLS) #include -#elif defined(USE_MBEDTLS) -#include -#if MBEDTLS_VERSION_NUMBER < 0x03020000 - #error "mbedTLS 3.2.0 or later required" -#endif -#include +#elif defined(USE_MBEDTLS_SHA256) +#include #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) diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 3ff131b441..ebb8a4abc0 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -37,17 +37,21 @@ /* #define MBEDTLS_DEBUG */ #include -#if MBEDTLS_VERSION_NUMBER < 0x03020000 - #error "mbedTLS 3.2.0 or later required" -#endif +#include #include #include #include +#include + +#if MBEDTLS_VERSION_NUMBER < 0x04000000 +#define CURL_MBEDTLS_DRBG +#endif #include +#ifdef CURL_MBEDTLS_DRBG #include #include -#include +#endif #ifdef MBEDTLS_DEBUG #include #endif @@ -77,8 +81,10 @@ #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, diff --git a/m4/curl-mbedtls.m4 b/m4/curl-mbedtls.m4 index 519c29d79a..55152c5408 100644 --- a/m4/curl-mbedtls.m4 +++ b/m4/curl-mbedtls.m4 @@ -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 + ]],[[ + #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 diff --git a/tests/libtest/lib1308.c b/tests/libtest/lib1308.c index 8e83462a7a..1455b0b0df 100644 --- a/tests/libtest/lib1308.c +++ b/tests/libtest/lib1308.c @@ -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; } -- 2.47.3