From: Viktor Szakats Date: Fri, 31 Jul 2026 22:45:57 +0000 (+0200) Subject: curl_ed25519: add GnuTLS support (via nettle, hogweed) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a368fbe968f6aa4ef88c7d3469eb4f90124e5dbc;p=thirdparty%2Fcurl.git curl_ed25519: add GnuTLS support (via nettle, hogweed) The necessary cryptography API is provided by nettle 3.1+, via its 'hogweed' library. The minimum GnuTLS version required by curl is 3.6.5, which requires nettle 3.4.1+, so the API is always available. Also: - autotools: detect and use nettle's hogweed library. - cmake/FindNettle: add support for the hogweed library. - GHA/http3-linux: enable in the autotools/cmake GnuTLS jobs. Ref: https://github.com/gnutls/gnutls/commit/4353ea025ae032887f3e8cf5aadace25662c6b35 Closes #22456 --- diff --git a/.github/workflows/http3-linux.yml b/.github/workflows/http3-linux.yml index 6d107895c1..d880b16885 100644 --- a/.github/workflows/http3-linux.yml +++ b/.github/workflows/http3-linux.yml @@ -473,7 +473,7 @@ jobs: LDFLAGS: -Wl,-rpath,/home/runner/gnutls/build/lib -Wl,-rpath,/home/runner/nettle/build/lib64 -Wl,-rpath,/home/runner/ngtcp2/build/lib PKG_CONFIG_PATH: /home/runner/nettle/build/lib64/pkgconfig:/home/runner/gnutls/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig configure: >- - --with-gnutls=/home/runner/gnutls/build --with-ngtcp2=/home/runner/ngtcp2/build --with-libssh --enable-ssls-export + --with-gnutls=/home/runner/gnutls/build --with-ngtcp2=/home/runner/ngtcp2/build --with-libssh --enable-ssls-export --enable-httpsig - name: 'gnutls' install_packages: libp11-kit-dev libssh-dev @@ -486,7 +486,7 @@ jobs: /home/runner/nghttp2/build/lib/pkgconfig" generate: >- -DCURL_USE_GNUTLS=ON -DUSE_NGTCP2=ON -DCURL_USE_LIBSSH=ON - -DCMAKE_UNITY_BUILD=ON + -DCMAKE_UNITY_BUILD=ON -DCURL_DISABLE_HTTPSIG=OFF - name: 'libressl' install_steps: skipall diff --git a/CMake/FindNettle.cmake b/CMake/FindNettle.cmake index c963180cba..f14cf23886 100644 --- a/CMake/FindNettle.cmake +++ b/CMake/FindNettle.cmake @@ -25,19 +25,21 @@ # # Input variables: # -# - `NETTLE_INCLUDE_DIR`: Absolute path to nettle include directory. -# - `NETTLE_LIBRARY`: Absolute path to `nettle` library. +# - `NETTLE_INCLUDE_DIR`: Absolute path to nettle include directory. +# - `NETTLE_HOGWEED_LIBRARY`: Absolute path to `hogweed` library. +# - `NETTLE_LIBRARY`: Absolute path to `nettle` library. # # Defines: # -# - `NETTLE_FOUND`: System has nettle. -# - `NETTLE_VERSION`: Version of nettle. -# - `CURL::nettle`: nettle library target. +# - `NETTLE_FOUND`: System has nettle. +# - `NETTLE_VERSION`: Version of nettle. +# - `CURL::nettle`: nettle library target. -set(_nettle_pc_requires "nettle") +set(_nettle_pc_requires "hogweed" "nettle") if(CURL_USE_PKGCONFIG AND NOT DEFINED NETTLE_INCLUDE_DIR AND + NOT DEFINED NETTLE_HOGWEED_LIBRARY AND NOT DEFINED NETTLE_LIBRARY) find_package(PkgConfig QUIET) pkg_check_modules(_nettle ${_nettle_pc_requires}) @@ -46,10 +48,11 @@ endif() if(_nettle_FOUND) set(Nettle_FOUND TRUE) set(NETTLE_FOUND TRUE) - set(NETTLE_VERSION ${_nettle_VERSION}) + set(NETTLE_VERSION ${_nettle_nettle_VERSION}) message(STATUS "Found Nettle (via pkg-config): ${_nettle_INCLUDE_DIRS} (found version \"${NETTLE_VERSION}\")") else() find_path(NETTLE_INCLUDE_DIR NAMES "nettle/sha2.h") + find_library(NETTLE_HOGWEED_LIBRARY NAMES "hogweed") find_library(NETTLE_LIBRARY NAMES "nettle") unset(NETTLE_VERSION CACHE) @@ -71,6 +74,7 @@ else() find_package_handle_standard_args(Nettle REQUIRED_VARS NETTLE_INCLUDE_DIR + NETTLE_HOGWEED_LIBRARY NETTLE_LIBRARY VERSION_VAR NETTLE_VERSION @@ -78,10 +82,10 @@ else() if(NETTLE_FOUND) set(_nettle_INCLUDE_DIRS ${NETTLE_INCLUDE_DIR}) - set(_nettle_LIBRARIES ${NETTLE_LIBRARY}) + set(_nettle_LIBRARIES ${NETTLE_HOGWEED_LIBRARY} ${NETTLE_LIBRARY}) endif() - mark_as_advanced(NETTLE_INCLUDE_DIR NETTLE_LIBRARY) + mark_as_advanced(NETTLE_INCLUDE_DIR NETTLE_HOGWEED_LIBRARY NETTLE_LIBRARY) endif() if(NETTLE_FOUND) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae1152c9b3..8682349265 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1106,8 +1106,8 @@ if(USE_ECH) endif() endif() -if(NOT CURL_DISABLE_HTTPSIG AND (NOT USE_OPENSSL AND NOT USE_WOLFSSL)) - message(WARNING "HTTPSIG requires OpenSSL or wolfSSL. HTTPSIG support disabled.") +if(NOT CURL_DISABLE_HTTPSIG AND NOT USE_GNUTLS AND NOT USE_OPENSSL AND NOT USE_WOLFSSL) + message(WARNING "HTTPSIG requires GnuTLS, OpenSSL or wolfSSL. HTTPSIG support disabled.") set(CURL_DISABLE_HTTPSIG ON) endif() diff --git a/configure.ac b/configure.ac index a00a2f8aa6..6ae2e7b57e 100644 --- a/configure.ac +++ b/configure.ac @@ -4608,8 +4608,8 @@ AS_HELP_STRING([--disable-httpsig],[Disable HTTP Message Signatures support (exp want_httpsig="no" ) -if test "$want_httpsig" = "yes" && test "$OPENSSL_ENABLED" != "1" && test "$WOLFSSL_ENABLED" != "1"; then - AC_MSG_WARN([HTTPSIG requires OpenSSL or wolfSSL. HTTPSIG support disabled.]) +if test "$want_httpsig" = "yes" && test "$GNUTLS_ENABLED" != "1" && test "$OPENSSL_ENABLED" != "1" && test "$WOLFSSL_ENABLED" != "1"; then + AC_MSG_WARN([HTTPSIG requires GnuTLS, OpenSSL or wolfSSL. HTTPSIG support disabled.]) want_httpsig="no" fi if test "$want_httpsig" != "yes"; then diff --git a/docs/INSTALL-CMAKE.md b/docs/INSTALL-CMAKE.md index 1e7b1639e9..f240d9c52e 100644 --- a/docs/INSTALL-CMAKE.md +++ b/docs/INSTALL-CMAKE.md @@ -456,6 +456,7 @@ Details via CMake - `NGTCP2_CRYPTO_WOLFSSL_LIBRARY`: Absolute path to `ngtcp2_crypto_wolfssl` library. - `NGTCP2_USE_STATIC_LIBS`: Configure for static ngtcp2 libraries. (experimental) - `NETTLE_INCLUDE_DIR`: Absolute path to nettle include directory. +- `NETTLE_HOGWEED_LIBRARY`: Absolute path to `hogweed` library. - `NETTLE_LIBRARY`: Absolute path to `nettle` library. - `PTHREAD_LIBRARY`: Absolute path to `pthread` library. (for Rustls) - `QUICHE_INCLUDE_DIR`: Absolute path to quiche include directory. diff --git a/lib/curl_ed25519.c b/lib/curl_ed25519.c index cc95a7d526..44311ec54e 100644 --- a/lib/curl_ed25519.c +++ b/lib/curl_ed25519.c @@ -135,6 +135,26 @@ fail: return CURLE_AUTH_ERROR; } +#elif defined(USE_GNUTLS) +#include + +CURLcode Curl_ed25519_sign(const unsigned char *key, size_t keylen, + const unsigned char *msg, size_t msglen, + unsigned char *sig, size_t *siglen) +{ + uint8_t pubkey[ED25519_KEY_SIZE]; + + if(keylen != ED25519_KEY_SIZE) + return CURLE_BAD_FUNCTION_ARGUMENT; + + nettle_ed25519_sha512_public_key(pubkey, key); + + nettle_ed25519_sha512_sign(pubkey, key, msglen, msg, sig); + *siglen = CURL_ED25519_SIGLEN; + + return CURLE_OK; +} + #else /* no Ed25519-capable backend */ CURLcode Curl_ed25519_sign(const unsigned char *key, size_t keylen, diff --git a/m4/curl-gnutls.m4 b/m4/curl-gnutls.m4 index 9da5cf6bd5..59012a1ab5 100644 --- a/m4/curl-gnutls.m4 +++ b/m4/curl-gnutls.m4 @@ -199,5 +199,66 @@ if test "$GNUTLS_ENABLED" = "1"; then if test "$USE_GNUTLS_NETTLE" = "1"; then LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE nettle" fi + + USE_GNUTLS_HOGWEED= + dnl First check if we can detect either crypto library via transitive linking + AC_CHECK_LIB(gnutls, nettle_ed25519_sha512_sign, [ USE_GNUTLS_HOGWEED=1 ]) + + dnl If not, try linking directly to both of them to see if they are available + if test -z "$USE_GNUTLS_HOGWEED"; then + + dnl this is with no particular path given + CURL_CHECK_PKGCONFIG(hogweed) + + if test "$PKGCONFIG" != "no"; then + addlib=`$PKGCONFIG --libs-only-l hogweed` + addld=`$PKGCONFIG --libs-only-L hogweed` + addcflags=`$PKGCONFIG --cflags-only-I hogweed` + version=`$PKGCONFIG --modversion hogweed` + gtlslib=`echo $addld | $SED -e 's/^-L//'` + + if test -n "$addlib"; then + + CLEANLIBS="$LIBS" + CLEANCPPFLAGS="$CPPFLAGS" + CLEANLDFLAGS="$LDFLAGS" + CLEANLDFLAGSPC="$LDFLAGSPC" + + LIBS="$addlib $LIBS" + LDFLAGS="$LDFLAGS $addld" + LDFLAGSPC="$LDFLAGSPC $addld" + if test "$addcflags" != "-I/usr/include"; then + CPPFLAGS="$CPPFLAGS $addcflags" + fi + + AC_CHECK_LIB(hogweed, nettle_ed25519_sha512_sign, + [ + USE_GNUTLS_HOGWEED=1 + ], + [ + LIBS="$CLEANLIBS" + CPPFLAGS="$CLEANCPPFLAGS" + LDFLAGS="$CLEANLDFLAGS" + LDFLAGSPC="$CLEANLDFLAGSPC" + ]) + + if test "$USE_GNUTLS_HOGWEED" = "1"; then + if test -z "$version"; then + version="unknown" + fi + AC_MSG_NOTICE([detected hogweed version $version]) + fi + fi + fi + if test -z "$USE_GNUTLS_HOGWEED"; then + AC_MSG_ERROR([GnuTLS found, but hogweed was not found]) + fi + else + LIBS="-lhogweed $LIBS" + fi + + if test "$USE_GNUTLS_HOGWEED" = "1"; then + LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE hogweed" + fi fi ])