- any-glob-to-all-files: "{\
.github/workflows/macos.yml,\
lib/config-mac.h,\
- lib/macos*,\
- lib/vtls/sectransp*,\
- m4/curl-sectransp.m4\
+ lib/macos*\
}"
authentication:
- all:
- changed-files:
- any-glob-to-all-files: "{\
- CMake/FindBearSSL.cmake,\
CMake/FindMbedTLS.cmake,\
CMake/FindWolfSSL.cmake,\
CMake/FindRustls.cmake,\
docs/libcurl/opts/CURLOPT_TLS*,\
docs/libcurl/opts/CURLOPT_USE_SSL*,\
lib/vtls/**,\
- m4/curl-bearssl.m4,\
m4/curl-gnutls.m4,\
m4/curl-mbedtls.m4,\
m4/curl-openssl.m4,\
m4/curl-rustls.m4,\
m4/curl-schannel.m4,\
- m4/curl-sectransp.m4,\
m4/curl-wolfssl.m4\
}"
MAKEFLAGS: -j 5
CURL_CI: github
CURL_CLANG_TIDYFLAGS: '-checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-valist.Uninitialized'
- # unhandled
- BEARSSL_VERSION: 0.6
# renovate: datasource=github-tags depName=libressl-portable/portable versioning=semver registryUrl=https://github.com
LIBRESSL_VERSION: 4.1.0
# renovate: datasource=github-tags depName=wolfSSL/wolfssl versioning=semver extractVersion=^v?(?<version>.+)-stable$ registryUrl=https://github.com
fail-fast: false
matrix:
build:
- - name: bearssl
- install_packages: zlib1g-dev
- install_steps: bearssl pytest
- configure: LDFLAGS=-Wl,-rpath,/home/runner/bearssl/lib --with-bearssl=/home/runner/bearssl --enable-debug
-
- - name: bearssl clang
- install_packages: zlib1g-dev clang
- install_steps: bearssl
- configure: CC=clang LDFLAGS=-Wl,-rpath,/home/runner/bearssl/lib --with-bearssl=/home/runner/bearssl --enable-debug
-
- name: libressl heimdal
install_packages: zlib1g-dev libnghttp2-dev libldap-dev heimdal-dev
install_steps: libressl pytest
py3-impacket py3-asn1 py3-six py3-pycryptodomex \
perl-time-hires openssh stunnel sudo git openssl
- - name: 'cache bearssl'
- if: ${{ contains(matrix.build.install_steps, 'bearssl') }}
- uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4
- id: cache-bearssl
- env:
- cache-name: cache-bearssl
- with:
- path: ~/bearssl
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.BEARSSL_VERSION }}
-
- - name: 'build bearssl'
- if: ${{ contains(matrix.build.install_steps, 'bearssl') && steps.cache-bearssl.outputs.cache-hit != 'true' }}
- run: |
- curl -LOsSf --retry 6 --retry-connrefused --max-time 999 \
- "https://bearssl.org/bearssl-${BEARSSL_VERSION}.tar.gz" | tar -xz
- cd "bearssl-${BEARSSL_VERSION}"
- make
- mkdir -p ~/bearssl/lib ~/bearssl/include
- cp inc/*.h ~/bearssl/include
- cp build/libbearssl.* ~/bearssl/lib
-
- name: 'cache libressl'
if: ${{ contains(matrix.build.install_steps, 'libressl') }}
uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4
# - 10.9 Mavericks (2013) - LDAP
# - 10.14 Mojave (2018) - Secure Transport
#
-# For Secure Transport, curl implements features that require a target
-# newer than the 10.8 required by `CFURLCreateDataAndPropertiesFromResource`.
env:
CURL_CI: github
--without-nghttp2 --disable-ntlm --without-ssl --without-zlib --without-zstd
macos-version-min: '10.15' # Catalina (2019)
- - name: 'SecureTransport libssh2'
- compiler: clang
- configure: --enable-debug --with-secure-transport --with-libssh2=/opt/homebrew/opt/libssh2
- macos-version-min: '10.8'
- - name: 'SecureTransport libssh2 10.12'
- compiler: clang
- configure: --enable-debug --with-secure-transport --with-libssh2=/opt/homebrew/opt/libssh2
- macos-version-min: '10.12' # for monotonic timers
- - name: 'SecureTransport libssh2'
- compiler: gcc-12
- configure: --enable-debug --with-secure-transport --with-libssh2=/opt/homebrew/opt/libssh2
- macos-version-min: '10.8'
- name: 'LibreSSL +examples'
compiler: clang
install: libressl
chkprefill: _chkprefill
- name: 'quictls +static libssh +examples'
install: quictls libssh
- generate: -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/quictls -DBUILD_STATIC_LIBS=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON
- - name: 'SecureTransport debug'
- generate: -DCURL_USE_SECTRANSP=ON -DENABLE_DEBUG=ON
- macos-version-min: '10.8'
+ generate: -DOPENSSL_ROOT_DIR=$(brew --prefix quictls) -DBUILD_STATIC_LIBS=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON
- name: 'LibreSSL !ldap heimdal c-ares +examples'
install: libressl heimdal
generate: -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/libressl -DENABLE_ARES=ON -DCURL_USE_GSSAPI=ON -DGSS_ROOT_DIR=/opt/homebrew/opt/heimdal -DCURL_DISABLE_LDAP=ON
make -C bld examples V=1
fi
- combinations: # Test buildability with host OS, Xcode / SDK, compiler, target-OS, Secure Transport/not, built tool, combinations
+ combinations: # Test buildability with host OS, Xcode / SDK, compiler, target-OS, built tool, combinations
name: "${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.compiler }} ${{ matrix.image }} ${{ matrix.xcode }} ${{ matrix.config }}"
runs-on: ${{ matrix.image }}
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
- config: [SecureTransport] # also: OpenSSL
+ config: [OpenSSL]
compiler: [gcc-12, gcc-13, gcc-14, llvm@15, llvm@18, clang]
# Xcode support matrix as of 2024-07, with default macOS SDK versions and OS names, years:
# * = default Xcode on the runner.
- { image: macos-14, compiler: 'llvm@18' }
- { image: macos-15, compiler: 'llvm@15' }
# Reduce build combinations, by dropping less interesting ones
- - { compiler: gcc-12, config: SecureTransport }
- { compiler: gcc-13, build: cmake }
- { compiler: gcc-14, build: autotools }
steps:
if [ "${MATRIX_BUILD}" = 'cmake' ]; then
[ "${MATRIX_CONFIG}" = 'OpenSSL' ] && options+=' -DCURL_USE_OPENSSL=ON'
- [ "${MATRIX_CONFIG}" = 'SecureTransport' ] && options+=' -DCURL_USE_SECTRANSP=ON'
[ -n "${MATRIX_MACOS_VERSION_MIN}" ] && options+=" -DCMAKE_OSX_DEPLOYMENT_TARGET=${MATRIX_MACOS_VERSION_MIN}"
# would pick up nghttp2, libidn2, and libssh2
cmake -B bld -G Ninja -D_CURL_PREFILL=ON \
CFLAGS+=" --sysroot=${sysroot}"
fi
[ "${MATRIX_CONFIG}" = 'OpenSSL' ] && options+=" --with-openssl=$(brew --prefix openssl)"
- [ "${MATRIX_CONFIG}" = 'SecureTransport' ] && options+=' --with-secure-transport'
[ -n "${MATRIX_MACOS_VERSION_MIN}" ] && CFLAGS+=" -mmacosx-version-min=${MATRIX_MACOS_VERSION_MIN}"
# would pick up nghttp2, libidn2, but libssh2 is disabled by default
mkdir bld && cd bld && ../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
+++ /dev/null
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-# Find the BearSSL library
-#
-# Input variables:
-#
-# - `BEARSSL_INCLUDE_DIR`: The BearSSL include directory.
-# - `BEARSSL_LIBRARY`: Path to `bearssl` library.
-#
-# Result variables:
-#
-# - `BEARSSL_FOUND`: System has BearSSL.
-# - `BEARSSL_INCLUDE_DIRS`: The BearSSL include directories.
-# - `BEARSSL_LIBRARIES`: The BearSSL library names.
-
-if(DEFINED BEARSSL_INCLUDE_DIRS AND NOT DEFINED BEARSSL_INCLUDE_DIR)
- message(WARNING "BEARSSL_INCLUDE_DIRS is deprecated, use BEARSSL_INCLUDE_DIR instead.")
- set(BEARSSL_INCLUDE_DIR "${BEARSSL_INCLUDE_DIRS}")
- unset(BEARSSL_INCLUDE_DIRS)
-endif()
-
-find_path(BEARSSL_INCLUDE_DIR NAMES "bearssl.h")
-find_library(BEARSSL_LIBRARY NAMES "bearssl")
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(BearSSL
- REQUIRED_VARS
- BEARSSL_INCLUDE_DIR
- BEARSSL_LIBRARY
-)
-
-if(BEARSSL_FOUND)
- set(BEARSSL_INCLUDE_DIRS ${BEARSSL_INCLUDE_DIR})
- set(BEARSSL_LIBRARIES ${BEARSSL_LIBRARY})
-endif()
-
-mark_as_advanced(BEARSSL_INCLUDE_DIR BEARSSL_LIBRARY)
set(_valid_default_ssl_backend FALSE)
endif()
-if(APPLE)
- cmake_dependent_option(CURL_USE_SECTRANSP "Enable Apple OS native SSL/TLS (Secure Transport)" OFF CURL_ENABLE_SSL OFF)
-endif()
if(WIN32)
cmake_dependent_option(CURL_USE_SCHANNEL "Enable Windows native SSL/TLS (Schannel)" OFF CURL_ENABLE_SSL OFF)
option(CURL_WINDOWS_SSPI "Enable SSPI on Windows" ${CURL_USE_SCHANNEL})
endif()
cmake_dependent_option(CURL_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
-cmake_dependent_option(CURL_USE_BEARSSL "Enable BearSSL for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
cmake_dependent_option(CURL_USE_WOLFSSL "Enable wolfSSL for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
cmake_dependent_option(CURL_USE_GNUTLS "Enable GnuTLS for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
cmake_dependent_option(CURL_USE_RUSTLS "Enable Rustls for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
if(WIN32 OR
- CURL_USE_SECTRANSP OR
CURL_USE_SCHANNEL OR
CURL_USE_MBEDTLS OR
- CURL_USE_BEARSSL OR
CURL_USE_WOLFSSL OR
CURL_USE_GNUTLS OR
CURL_USE_RUSTLS)
curl_count_true(_enabled_ssl_options_count
CURL_USE_SCHANNEL
- CURL_USE_SECTRANSP
CURL_USE_OPENSSL
CURL_USE_MBEDTLS
- CURL_USE_BEARSSL
CURL_USE_WOLFSSL
CURL_USE_GNUTLS
CURL_USE_RUSTLS
set(USE_WINDOWS_SSPI ON)
endif()
-if(CURL_USE_SECTRANSP)
- set(_use_core_foundation_and_core_services ON)
-
- find_library(SECURITY_FRAMEWORK NAMES "Security")
- mark_as_advanced(SECURITY_FRAMEWORK)
- if(NOT SECURITY_FRAMEWORK)
- message(FATAL_ERROR "Security framework not found")
- endif()
- list(APPEND CURL_LIBS "-framework Security")
-
- set(_ssl_enabled ON)
- set(USE_SECTRANSP ON)
-
- if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "secure-transport")
- set(_valid_default_ssl_backend TRUE)
- endif()
-
- message(WARNING "Secure Transport does not support TLS 1.3.")
-endif()
-
if(_use_core_foundation_and_core_services)
find_library(COREFOUNDATION_FRAMEWORK NAMES "CoreFoundation")
mark_as_advanced(COREFOUNDATION_FRAMEWORK)
set(_curl_ca_bundle_supported TRUE)
endif()
-if(CURL_USE_BEARSSL)
- find_package(BearSSL REQUIRED)
- set(_ssl_enabled ON)
- set(USE_BEARSSL ON)
- list(APPEND CURL_LIBS ${BEARSSL_LIBRARIES})
- include_directories(SYSTEM ${BEARSSL_INCLUDE_DIRS})
-
- if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "bearssl")
- set(_valid_default_ssl_backend TRUE)
- endif()
- set(_curl_ca_bundle_supported TRUE)
-
- message(WARNING "BearSSL does not support TLS 1.3.")
-endif()
-
if(CURL_USE_WOLFSSL)
find_package(WolfSSL REQUIRED)
set(_ssl_enabled ON)
(USE_OPENSSL OR
USE_MBEDTLS OR
USE_GNUTLS OR
- USE_SECTRANSP OR
USE_WIN32_CRYPTO OR
(USE_WOLFSSL AND HAVE_WOLFSSL_DES_ECB_ENCRYPT)))
set(_use_curl_ntlm_core ON)
curl_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE OR USE_MSH3 OR USE_OPENSSL_QUIC)
curl_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
curl_add_if("HTTPS-proxy" NOT CURL_DISABLE_PROXY AND _ssl_enabled AND (USE_OPENSSL OR USE_GNUTLS
- OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
- USE_MBEDTLS OR USE_SECTRANSP OR
+ OR USE_SCHANNEL OR USE_RUSTLS OR USE_MBEDTLS OR
(USE_WOLFSSL AND HAVE_WOLFSSL_BIO_NEW)))
curl_add_if("Unicode" ENABLE_UNICODE)
curl_add_if("threadsafe" HAVE_ATOMIC OR
curl_add_if("Schannel" _ssl_enabled AND USE_SCHANNEL)
curl_add_if("${_openssl}" _ssl_enabled AND USE_OPENSSL AND OPENSSL_VERSION VERSION_LESS 3.0.0)
curl_add_if("${_openssl} v3+" _ssl_enabled AND USE_OPENSSL AND OPENSSL_VERSION VERSION_GREATER_EQUAL 3.0.0)
-curl_add_if("Secure Transport" _ssl_enabled AND USE_SECTRANSP)
curl_add_if("mbedTLS" _ssl_enabled AND USE_MBEDTLS)
-curl_add_if("BearSSL" _ssl_enabled AND USE_BEARSSL)
curl_add_if("wolfSSL" _ssl_enabled AND USE_WOLFSSL)
curl_add_if("GnuTLS" _ssl_enabled AND USE_GNUTLS)
curl_add_if("rustls" _ssl_enabled AND USE_RUSTLS)
CMake/curl-config.cmake.in \
CMake/CurlSymbolHiding.cmake \
CMake/CurlTests.c \
- CMake/FindBearSSL.cmake \
CMake/FindBrotli.cmake \
CMake/FindCares.cmake \
CMake/FindGSS.cmake \
dnl
dnl initialize all the info variables
- curl_ssl_msg="no (--with-{openssl,gnutls,mbedtls,wolfssl,schannel,secure-transport,amissl,bearssl,rustls} )"
+ curl_ssl_msg="no (--with-{openssl,gnutls,mbedtls,wolfssl,schannel,amissl,rustls} )"
curl_ssh_msg="no (--with-{libssh,libssh2})"
curl_zlib_msg="no (--with-zlib)"
curl_brotli_msg="no (--with-brotli)"
OPT_SCHANNEL=$withval
TLSCHOICE="schannel")
-OPT_SECURETRANSPORT=no
-AC_ARG_WITH(secure-transport,dnl
-AS_HELP_STRING([--with-secure-transport],[enable Apple OS native SSL/TLS]),[
- OPT_SECURETRANSPORT=$withval
- TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }Secure-Transport"
-])
-
OPT_AMISSL=no
AC_ARG_WITH(amissl,dnl
AS_HELP_STRING([--with-amissl],[enable Amiga native SSL/TLS (AmiSSL)]),[
fi
])
-OPT_BEARSSL=no
-AC_ARG_WITH(bearssl,dnl
-AS_HELP_STRING([--with-bearssl=PATH],[where to look for BearSSL, PATH points to the installation root]),[
- OPT_BEARSSL=$withval
- if test X"$withval" != Xno; then
- TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }BearSSL"
- fi
-])
-
OPT_RUSTLS=no
AC_ARG_WITH(rustls,dnl
AS_HELP_STRING([--with-rustls=PATH],[where to look for Rustls, PATH points to the installation root]),[
Select from these:
--with-amissl
- --with-bearssl
--with-gnutls
--with-mbedtls
--with-openssl (also works for BoringSSL and LibreSSL)
--with-rustls
--with-schannel
- --with-secure-transport
--with-wolfssl
])
fi
esac
CURL_WITH_SCHANNEL
-CURL_WITH_SECURETRANSPORT
CURL_WITH_AMISSL
CURL_WITH_OPENSSL
CURL_WITH_GNUTLS
CURL_WITH_MBEDTLS
CURL_WITH_WOLFSSL
-CURL_WITH_BEARSSL
CURL_WITH_RUSTLS
dnl link required libraries for USE_WIN32_CRYPTO or SCHANNEL_ENABLED
LIBS="-lbcrypt $LIBS"
fi
-case "x$SSL_DISABLED$OPENSSL_ENABLED$GNUTLS_ENABLED$MBEDTLS_ENABLED$WOLFSSL_ENABLED$SCHANNEL_ENABLED$SECURETRANSPORT_ENABLED$BEARSSL_ENABLED$RUSTLS_ENABLED" in
+case "x$SSL_DISABLED$OPENSSL_ENABLED$GNUTLS_ENABLED$MBEDTLS_ENABLED$WOLFSSL_ENABLED$SCHANNEL_ENABLED$RUSTLS_ENABLED" in
x)
AC_MSG_ERROR([TLS not detected, you will not be able to use HTTPS, FTPS, NTLM and more.
-Use --with-openssl, --with-gnutls, --with-wolfssl, --with-mbedtls, --with-schannel, --with-secure-transport, --with-amissl, --with-bearssl or --with-rustls to address this.])
+Use --with-openssl, --with-gnutls, --with-wolfssl, --with-mbedtls, --with-schannel, --with-amissl or --with-rustls to address this.])
;;
x1)
# one SSL backend is enabled
;;
xD*)
AC_MSG_ERROR([--without-ssl has been set together with an explicit option to use an ssl library
-(e.g. --with-openssl, --with-gnutls, --with-wolfssl, --with-mbedtls, --with-schannel, --with-secure-transport, --with-amissl, --with-bearssl, --with-rustls).
+(e.g. --with-openssl, --with-gnutls, --with-wolfssl, --with-mbedtls, --with-schannel, --with-amissl, --with-rustls).
Since these are conflicting parameters, verify which is the desired one and drop the other.])
;;
*)
versioned_symbols_flavour="OPENSSL_"
elif test "x$MBEDTLS_ENABLED" = "x1"; then
versioned_symbols_flavour="MBEDTLS_"
- elif test "x$BEARSSL_ENABLED" = "x1"; then
- versioned_symbols_flavour="BEARSSL_"
elif test "x$WOLFSSL_ENABLED" = "x1"; then
versioned_symbols_flavour="WOLFSSL_"
elif test "x$GNUTLS_ENABLED" = "x1"; then
if test "x$CURL_DISABLE_NTLM" != "x1"; then
if test "x$OPENSSL_ENABLED" = "x1" -o "x$MBEDTLS_ENABLED" = "x1" \
-o "x$GNUTLS_ENABLED" = "x1" \
- -o "x$SECURETRANSPORT_ENABLED" = "x1" \
-o "x$USE_WIN32_CRYPTO" = "x1" \
-o "x$HAVE_WOLFSSL_DES_ECB_ENCRYPT" = "x1"; then
use_curl_ntlm_core=yes
if test "x$https_proxy" != "xno"; then
if test "x$OPENSSL_ENABLED" = "x1" \
-o "x$GNUTLS_ENABLED" = "x1" \
- -o "x$SECURETRANSPORT_ENABLED" = "x1" \
-o "x$RUSTLS_ENABLED" = "x1" \
- -o "x$BEARSSL_ENABLED" = "x1" \
-o "x$SCHANNEL_ENABLED" = "x1" \
-o "x$GNUTLS_ENABLED" = "x1" \
-o "x$MBEDTLS_ENABLED" = "x1"; then
Features: ${SUPPORT_FEATURES}
])
-# grep -o would simplify this, but is nonportable
-[non13=`echo "$TLSCHOICE" | $AWK '{split("bearssl secure-transport", a); for (i in a) if(match(tolower($0), a[i])) print a[i];}'`]
-if test -n "$non13"; then
- for a in $non13; do
- AC_MSG_WARN([$a is enabled for TLS but it does not support TLS 1.3])
- done
-fi
-
if test -n "$experimental"; then
for a in $experimental; do
AC_MSG_WARN([$a is enabled but marked EXPERIMENTAL. Use with caution!])
### TLS 1.2 (1.1, 1.0) cipher suites
Setting TLS 1.2 cipher suites is supported by curl with OpenSSL, LibreSSL,
-BoringSSL, mbedTLS (curl 8.8.0+), wolfSSL (curl 7.53.0+),
-Secure Transport (curl 7.77.0+) and BearSSL (curl 7.83.0+). Schannel does not
+BoringSSL, mbedTLS (curl 8.8.0+), wolfSSL (curl 7.53.0+). Schannel does not
support setting cipher suites directly, but does support setting algorithms
(curl 7.61.0+), see Schannel notes below.
```
Restrict TLS 1.2 ciphers to `aes128-gcm` and `chacha20`, use default TLS 1.3
ciphers (if TLS 1.3 is available). Works with OpenSSL, LibreSSL, BoringSSL,
-mbedTLS, wolfSSL, Secure Transport and BearSSL.
+mbedTLS and wolfSSL.
## ciphers, the GnuTLS way
- [wolfSSL cipher support documentation](https://www.wolfssl.com/documentation/manuals/wolfssl/chapter04.html#cipher-support)
- [mbedTLS cipher suites reference](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/ssl__ciphersuites_8h/)
- [Schannel cipher suites documentation](https://learn.microsoft.com/en-us/windows/win32/secauthn/cipher-suites-in-schannel)
-- [BearSSL supported crypto](https://www.bearssl.org/support.html)
-- [Secure Transport cipher suite values](https://developer.apple.com/documentation/security/1550981-ssl_cipher_suite_values)
- [IANA cipher suites list](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4)
- [Wikipedia cipher suite article](https://en.wikipedia.org/wiki/Cipher_suite)
- [GnuTLS Priority Strings](https://gnutls.org/manual/html_node/Priority-Strings.html)
list, specifying `All` or a list of what TLS backends that work with this
option. The available TLS backends are:
-- `BearSSL`
- `GnuTLS`
- `mbedTLS`
- `OpenSSL` (also covers BoringSSL, LibreSSL, quictls, AWS-LC and AmiSSL)
- `rustls`
- `Schannel`
-- `Secure Transport`
- `wolfSSL`
- `All`: all TLS backends
as soon as possible and explain to us why this is a problem for you and
how your use case cannot be satisfied properly using a workaround.
-## TLS libraries without 1.3 support
+## Nothing
-curl drops support for TLS libraries without TLS 1.3 capability after May
-2025.
-
-It requires that a curl build using the library should be able to negotiate
-and use TLS 1.3, or else it is not good enough.
-
-As of May 2024, the libraries that need to get fixed to remain supported after
-May 2025 are: BearSSL and Secure Transport.
+Nothing is currently scheduled to be removed.
## msh3 support
- NTLM_WB (removed in 8.8.0)
- space-separated `NOPROXY` patterns (removed in 8.9.0)
- hyper (removed in 8.12.0)
+ - Secure Transport (8.15.0)
+ - BearSSL (8.15.0)
backends.
curl can be built to use one of the following SSL alternatives: OpenSSL,
- LibreSSL, BoringSSL, AWS-LC, GnuTLS, wolfSSL, mbedTLS, Secure Transport
- (native iOS/macOS), Schannel (native Windows), BearSSL or Rustls. They all
- have their pros and cons, and we try to maintain a comparison of them here:
- https://curl.se/docs/ssl-compared.html
+ LibreSSL, BoringSSL, AWS-LC, GnuTLS, wolfSSL, mbedTLS, Schannel (native
+ Windows) or Rustls. They all have their pros and cons, and we try to
+ maintain a comparison of them here: https://curl.se/docs/ssl-compared.html
2.3 How do I upgrade curl.exe in Windows?
4.9 curl cannot authenticate to a server that requires NTLM?
- NTLM support requires OpenSSL, GnuTLS, mbedTLS, Secure Transport, or
- Microsoft Windows libraries at build-time to provide this functionality.
+ NTLM support requires OpenSSL, GnuTLS, mbedTLS or Microsoft Windows
+ libraries at build-time to provide this functionality.
4.10 My HTTP request using HEAD, PUT or DELETE does not work
- `CURL_COMPLETION_ZSH_DIR`: Custom zsh completion install directory.
- `CURL_DEFAULT_SSL_BACKEND`: Override default TLS backend in MultiSSL builds.
Accepted values in order of default priority:
- `wolfssl`, `gnutls`, `mbedtls`, `openssl`, `secure-transport`, `schannel`, `bearssl`, `rustls`
+ `wolfssl`, `gnutls`, `mbedtls`, `openssl`, `schannel`, `rustls`
- `CURL_ENABLE_EXPORT_TARGET`: Enable CMake export target. Default: `ON`
- `CURL_HIDDEN_SYMBOLS`: Hide libcurl internal symbols (=hide all symbols that are not officially external). Default: `ON`
- `CURL_LIBCURL_SOVERSION`: Enable libcurl SOVERSION. Default: `ON` for supported platforms
## Dependencies
- `CURL_BROTLI`: Use brotli (`ON`, `OFF` or `AUTO`). Default: `AUTO`
-- `CURL_USE_BEARSSL`: Enable BearSSL for SSL/TLS. Default: `OFF`
- `CURL_USE_GNUTLS`: Enable GnuTLS for SSL/TLS. Default: `OFF`
- `CURL_USE_GSASL`: Use libgsasl. Default: `OFF`
- `CURL_USE_GSSAPI`: Use GSSAPI implementation. Default: `OFF`
- `CURL_USE_PKGCONFIG`: Enable `pkg-config` to detect dependencies. Default: `ON` for Unix (except Android, Apple devices), vcpkg, MinGW if not cross-compiling.
- `CURL_USE_RUSTLS`: Enable Rustls for SSL/TLS. Default: `OFF`
- `CURL_USE_SCHANNEL`: Enable Windows native SSL/TLS (Schannel). Default: `OFF`
-- `CURL_USE_SECTRANSP`: Enable Apple OS native SSL/TLS (Secure Transport). Default: `OFF`
- `CURL_USE_WOLFSSH`: Use wolfSSH. Default: `OFF`
- `CURL_USE_WOLFSSL`: Enable wolfSSL for SSL/TLS. Default: `OFF`
- `CURL_ZLIB`: Use zlib (`ON`, `OFF` or `AUTO`). Default: `AUTO`
- `AMISSL_INCLUDE_DIR`: The AmiSSL include directory.
- `AMISSL_STUBS_LIBRARY`: Path to `amisslstubs` library.
- `AMISSL_AUTO_LIBRARY`: Path to `amisslauto` library.
-- `BEARSSL_INCLUDE_DIR`: The BearSSL include directory.
-- `BEARSSL_LIBRARY`: Path to `bearssl` library.
- `BROTLI_INCLUDE_DIR`: The brotli include directory.
- `BROTLICOMMON_LIBRARY`: Path to `brotlicommon` library.
- `BROTLIDEC_LIBRARY`: Path to `brotlidec` library.
These options are provided to select the TLS backend to use.
- AmiSSL: `--with-amissl`
- - BearSSL: `--with-bearssl`
- GnuTLS: `--with-gnutls`.
- mbedTLS: `--with-mbedtls`
- OpenSSL: `--with-openssl` (also for BoringSSL, AWS-LC, LibreSSL, and quictls)
- rustls: `--with-rustls`
- Schannel: `--with-schannel`
- - Secure Transport: `--with-secure-transport`
- wolfSSL: `--with-wolfssl`
You can build curl with *multiple* TLS backends at your choice, but some TLS
are using curl in one of those earlier versions of Windows you should choose
another SSL backend such as OpenSSL.
-# Apple Platforms (macOS, iOS, tvOS, watchOS, and their simulator counterparts)
-
-On modern Apple operating systems, curl can be built to use Apple's SSL/TLS
-implementation, Secure Transport, instead of OpenSSL. To build with Secure
-Transport for SSL/TLS, use the configure option `--with-secure-transport`.
-
-When Secure Transport is in use, the curl options `--cacert` and `--capath`
-and their libcurl equivalents, are ignored, because Secure Transport uses the
-certificates stored in the Keychain to evaluate whether or not to trust the
-server. This, of course, includes the root certificates that ship with the OS.
-The `--cert` and `--engine` options, and their libcurl equivalents, are
-currently unimplemented in curl with Secure Transport.
-
-In general, a curl build for an Apple `ARCH/SDK/DEPLOYMENT_TARGET` combination
-can be taken by providing appropriate values for `ARCH`, `SDK`, `DEPLOYMENT_TARGET`
-below and running the commands:
-
-```bash
-# Set these three according to your needs
-export ARCH=x86_64
-export SDK=macosx
-export DEPLOYMENT_TARGET=10.8
-
-export CFLAGS="-arch $ARCH -isysroot $(xcrun -sdk $SDK --show-sdk-path) -m$SDK-version-min=$DEPLOYMENT_TARGET"
-./configure --host=$ARCH-apple-darwin --prefix $(pwd)/artifacts --with-secure-transport
-make -j8
-make install
-```
-
-With CMake:
-
-```bash
-cmake . \
- -DCMAKE_OSX_ARCHITECTURES=x86_64 \
- -DCMAKE_OSX_DEPLOYMENT_TARGET=10.8 \
- -DCMAKE_OSX_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)"
-```
-
-The above command lines build curl for macOS platform with `x86_64`
-architecture and `10.8` as deployment target.
-
-Here is an example for iOS device:
-
-```bash
-export ARCH=arm64
-export SDK=iphoneos
-export DEPLOYMENT_TARGET=11.0
-
-export CFLAGS="-arch $ARCH -isysroot $(xcrun -sdk $SDK --show-sdk-path) -m$SDK-version-min=$DEPLOYMENT_TARGET"
-./configure --host=$ARCH-apple-darwin --prefix $(pwd)/artifacts --with-secure-transport
-make -j8
-make install
-```
-
-With CMake (3.16 or upper recommended):
-
-```bash
-cmake . \
- -DCMAKE_SYSTEM_NAME=iOS \
- -DCMAKE_OSX_ARCHITECTURES=arm64 \
- -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
-```
-
-Another example for watchOS simulator for macs with Apple Silicon:
-
-```bash
-export ARCH=arm64
-export SDK=watchsimulator
-export DEPLOYMENT_TARGET=5.0
-
-export CFLAGS="-arch $ARCH -isysroot $(xcrun -sdk $SDK --show-sdk-path) -m$SDK-version-min=$DEPLOYMENT_TARGET"
-./configure --host=$ARCH-apple-darwin --prefix $(pwd)/artifacts --with-secure-transport
-make -j8
-make install
-```
-
-In all above, the built libraries and executables can be found in the
-`artifacts` folder.
-
# Android
When building curl for Android you can you CMake or curl's `configure` script.
2. TLS
2.1 IMAPS connection fails with Rustls error
- 2.3 Unable to use PKCS12 certificate with Secure Transport
- 2.4 Secure Transport does not import PKCS#12 client certificates without a password
+ 2.5 Client cert handling with Issuer DN differs between backends
2.7 Client cert (MTLS) issues with Schannel
2.11 Schannel TLS 1.2 handshake bug in old Windows versions
2.13 CURLOPT_CERTINFO results in CURLE_OUT_OF_MEMORY with Schannel
6.9 SHA-256 digest not supported in Windows SSPI builds
6.10 curl never completes Negotiate over HTTP
6.11 Negotiate on Windows fails
- 6.12 cannot use Secure Transport with Crypto Token Kit
6.13 Negotiate against Hadoop HDFS
7. FTP
https://github.com/curl/curl/issues/10457
-2.3 Unable to use PKCS12 certificate with Secure Transport
+2.5 Client cert handling with Issuer DN differs between backends
- See https://github.com/curl/curl/issues/5403
+ When the specified client certificate does not match any of the
+ server-specified DNs, the OpenSSL and GnuTLS backends behave differently.
+ The github discussion may contain a solution.
-2.4 Secure Transport does not import PKCS#12 client certificates without a password
-
- libcurl calls SecPKCS12Import with the PKCS#12 client certificate, but that
- function rejects certificates that do not have a password.
- https://github.com/curl/curl/issues/1308
+ See https://github.com/curl/curl/issues/1411
2.7 Client cert (MTLS) issues with Schannel
https://github.com/curl/curl/issues/5881
-6.12 cannot use Secure Transport with Crypto Token Kit
-
- https://github.com/curl/curl/issues/7048
-
6.13 Negotiate authentication against Hadoop HDFS
https://github.com/curl/curl/issues/8264
## Native vs file based
-If curl was built with Schannel or Secure Transport support, then curl uses
-the system native CA store for verification. All other TLS libraries use a
-file based CA store by default.
+If curl was built with Schannel support, then curl uses the system native CA
+store for verification. All other TLS libraries use a file based CA store by
+default.
## Verification
## Native CA store
-If curl was built with Schannel, Secure Transport or were instructed to use
-the native CA Store, then curl uses the certificates that are built into the
-OS. These are the same certificates that appear in the Internet Options
-control panel (under Windows) or Keychain Access application (under macOS).
-Any custom security rules for certificates are honored.
+If curl was built with Schannel or was instructed to use the native CA Store,
+then curl uses the certificates that are built into the OS. These are the same
+certificates that appear in the Internet Options control panel (under Windows)
+or Keychain Access application (under macOS). Any custom security rules for
+certificates are honored.
Schannel runs CRL checks on certificates unless peer verification is disabled.
-Secure Transport on iOS runs OCSP checks on certificates unless peer
-verification is disabled. Secure Transport on macOS runs either OCSP or CRL
-checks on certificates if those features are enabled, and this behavior can be
-adjusted in the preferences of Keychain Access.
## HTTPS proxy
invoked. Setting a name that is not a built-in alternative makes curl stay
with the default.
-SSL backend names (case-insensitive): **bearssl**, **gnutls**, **mbedtls**,
-**openssl**, **rustls**, **schannel**, **secure-transport**, **wolfssl**
+SSL backend names (case-insensitive): **gnutls**, **mbedtls**, **openssl**,
+**rustls**, **schannel**, **wolfssl**
## `HOME` <dir>
If set, this is used to find the home directory when that is needed. Like when
curl 8.11.0 added a build-time option to disable this search behavior, and
another option to restrict search to the application's directory.
-(iOS and macOS only) If curl is built against Secure Transport, then this
-option is supported for backward compatibility with other SSL engines, but it
-should not be set. If the option is not set, then curl uses the certificates
-in the system and user Keychain to verify the peer, which is the preferred
-method of verifying the peer's certificate chain.
-
-(Schannel only) This option is supported for Schannel in Windows 7 or later
-(added in 7.60.0). This option is supported for backward compatibility with
-other SSL engines; instead it is recommended to use Windows' store of root
-certificates (the default for Schannel).
+(Schannel) This option is supported for Schannel in Windows 7 or later (added
+in 7.60.0). This option is supported for backward compatibility with other SSL
+engines; instead it is recommended to use Windows' store of root certificates
+(the default for Schannel).
Set type of the provided client certificate. PEM, DER, ENG, PROV and P12 are
recognized types.
-The default type depends on the TLS backend and is usually PEM, however for
-Secure Transport and Schannel it is P12. If --cert is a pkcs11: URI then ENG
-or PROV is the default type (depending on OpenSSL version).
+The default type depends on the TLS backend and is usually PEM. For Schannel
+it is P12. If --cert is a pkcs11: URI then ENG or PROV is the default type
+(depending on OpenSSL version).
# `--cert`
Use the specified client certificate file when getting a file with HTTPS, FTPS
-or another SSL-based protocol. The certificate must be in PKCS#12 format if
-using Secure Transport, or PEM format if using any other engine. If the
+or another SSL-based protocol. The certificate must be PEM format. If the
optional password is not specified, it is queried for on the terminal. Note
that this option assumes a certificate file that is the private key and the
client certificate concatenated. See --cert and --key to specify them
a certificate located in a PKCS#11 device. A string beginning with `pkcs11:`
is interpreted as a PKCS#11 URI.
-(iOS and macOS only) If curl is built against Secure Transport, then the
-certificate string can either be the name of a certificate/private key in the
-system or user keychain, or the path to a PKCS#12-encoded certificate and
-private key. If you want to use a file from the current directory, please
-precede it with `./` prefix, in order to avoid confusion with a nickname.
-
-(Schannel only) Client certificates must be specified by a path expression to
-a certificate store. (Loading *PFX* is not supported; you can import it to a
+(Schannel) Client certificates must be specified by a path expression to a
+certificate store. (Loading *PFX* is not supported; you can import it to a
store first). You can use "\<store location\>\\<store name\>\\<thumbprint\>"
to refer to a certificate in the system certificates store, for example,
*"CurrentUser\MY\934a7ac6f8a5d579285a74fa61e19f23ddfe8d7a"*. Thumbprint is
# `--false-start`
+No TLS backend currently supports this feature.
+
Use false start during the TLS handshake. False start is a mode where a TLS
client starts sending application data before verifying the server's Finished
message, thus saving a round trip when performing a full handshake.
-
-This functionality is currently only implemented in the Secure Transport (on
-iOS 7.0 or later, or macOS 10.9 or later) backend.
option is set as `pkcs11` if none was provided and the --key-type option is
set as `ENG` or `PROV` if none was provided (depending on OpenSSL version).
-If curl is built against Secure Transport or Schannel then this option is
-ignored for TLS protocols (HTTPS, etc). Those backends expect the private key
-to be already present in the keychain or PKCS#12 file containing the
-certificate.
+If curl is built against Schannel then this option is ignored for TLS
+protocols (HTTPS, etc). That backend expects the private key to be already
+present in the keychain or PKCS#12 file containing the certificate.
PEM/DER support:
OpenSSL and GnuTLS (added in 7.39.0), wolfSSL (added in 7.43.0),
-mbedTLS (added in 7.47.0),
-Secure Transport macOS 10.7+/iOS 10+ (added in 7.54.1),
-Schannel (added in 7.58.1)
+mbedTLS (added in 7.47.0), Schannel (added in 7.58.1)
sha256 support:
OpenSSL, GnuTLS and wolfSSL (added in 7.44.0), mbedTLS (added in 7.47.0),
-Secure Transport macOS 10.7+/iOS 10+ (added in 7.54.1), Schannel
-(added in 7.58.1)
+Schannel (added in 7.58.1)
Other SSL backends not supported.
Set type of the provided client certificate when using HTTPS proxy. PEM, DER,
ENG, PROV and P12 are recognized types.
-The default type depends on the TLS backend and is usually PEM, however for
-Secure Transport and Schannel it is P12. If --proxy-cert is a pkcs11: URI then
-ENG or PROV is the default type (depending on OpenSSL version).
+The default type depends on the TLS backend and is usually PEM. For Schannel
+it is P12. If --proxy-cert is a pkcs11: URI then ENG or PROV is the default
+type (depending on OpenSSL version).
Equivalent to --cert-type but used in HTTPS proxy context.
# `--proxy-cert`
Use the specified client certificate file when communicating with an HTTPS
-proxy. The certificate must be in PKCS#12 format if using Secure Transport, or
-PEM format if using any other engine. If the optional password is not
+proxy. The certificate must be PEM format. If the optional password is not
specified, it is queried for on the terminal. Use --proxy-key to provide the
private key.
Unix domain sockets are supported for socks proxy. Set localhost for the host
part. e.g. socks5h://localhost/path/to/socket.sock
-HTTPS proxy support works with the https:// protocol prefix for OpenSSL
-and GnuTLS (added in 7.52.0). It also works for BearSSL, mbedTLS, Rustls,
-Schannel, Secure Transport and wolfSSL (added in 7.87.0).
+HTTPS proxy support works with the https:// protocol prefix for OpenSSL and
+GnuTLS (added in 7.52.0). It also works for BearSSL, mbedTLS, Rustls, Schannel
+and wolfSSL (added in 7.87.0).
Unrecognized and unsupported proxy protocols cause an error (added in 7.52.0).
Ancient curl versions ignored unknown schemes and used http:// instead.
## `certs`
Output the certificate chain with details. Supported only by the OpenSSL,
-GnuTLS, Schannel, Rustls, and Secure Transport backends. (Added in 7.88.0)
+GnuTLS, Schannel and Rustls backends. (Added in 7.88.0)
## `conn_id`
The connection identifier last used by the transfer. The connection id is
## `num_certs`
Number of server certificates received in the TLS handshake. Supported only by
-the OpenSSL, GnuTLS, Schannel, Rustls and Secure Transport backends.
-(Added in 7.88.0)
+the OpenSSL, GnuTLS, Schannel and Rustls backends. (Added in 7.88.0)
## `num_connects`
Number of new connects made in the recent transfer. (Added in 7.12.3)
TLS-backend:
- GnuTLS
- OpenSSL
- - BearSSL
- wolfSSL
- mbedTLS
Added-in: 8.12.0
TLS-backend:
- GnuTLS
- OpenSSL
- - BearSSL
- wolfSSL
- mbedTLS
Added-in: 8.12.0
# Names
-SSL backend names (case-insensitive): BearSSL, GnuTLS, mbedTLS, OpenSSL,
-Rustls, Schannel, Secure-Transport, wolfSSL
+SSL backend names (case-insensitive): GnuTLS, mbedTLS, OpenSSL, Rustls,
+Schannel, wolfSSL
The name "OpenSSL" is used for all versions of OpenSSL and its associated
forks/flavors in this function. OpenSSL, BoringSSL, LibreSSL, quictls and
-AmiSSL are all supported by libcurl, but in the eyes of
-curl_global_sslset(3) they are all just "OpenSSL". They all mostly
-provide the same API. curl_version_info(3) can return more specific info about
-the exact OpenSSL flavor and version number in use.
+AmiSSL are all supported by libcurl, but in the eyes of curl_global_sslset(3)
+they are all just "OpenSSL". They all mostly provide the same API.
+curl_version_info(3) can return more specific info about the exact OpenSSL
+flavor and version number in use.
# struct
CURLSSLBACKEND_POLARSSL = 6, /* deprecated */
CURLSSLBACKEND_WOLFSSL = 7,
CURLSSLBACKEND_SCHANNEL = 8,
- CURLSSLBACKEND_SECURETRANSPORT = 9,
+ CURLSSLBACKEND_SECURETRANSPORT = 9, /* deprecated */
CURLSSLBACKEND_AXTLS = 10, /* deprecated */
CURLSSLBACKEND_MBEDTLS = 11,
CURLSSLBACKEND_MESALINK = 12, /* deprecated */
- CURLSSLBACKEND_BEARSSL = 13,
+ CURLSSLBACKEND_BEARSSL = 13, /* deprecated */
CURLSSLBACKEND_RUSTLS = 14
} curl_sslbackend;
~~~
this variable's selection is used. Setting a name that is not a built-in
alternative makes libcurl stay with the default.
-SSL backend names (case-insensitive): BearSSL, GnuTLS, mbedTLS, OpenSSL,
-Rustls, Schannel, Secure-Transport, wolfSSL
+SSL backend names (case-insensitive): GnuTLS, mbedTLS, OpenSSL, Rustls,
+Schannel, wolfSSL
## `HOME`
- OpenSSL
- GnuTLS
- Schannel
- - Secure Transport
- rustls
Added-in: 7.19.1
---
# HISTORY
-GnuTLS support added in 7.42.0. Schannel support added in 7.50.0. Secure
-Transport support added in 7.79.0. mbedTLS support added in 8.9.0.
+GnuTLS support added in 7.42.0. Schannel support added in 7.50.0. mbedTLS
+support added in 8.9.0.
# %AVAILABILITY%
Protocol:
- TLS
TLS-backend:
- - BearSSL
- GnuTLS
- mbedTLS
- OpenSSL
- Schannel
- - Secure Transport
- wolfSSL
Added-in: 7.48.0
---
**CtxtHandle ***
-## Secure Transport
-
-**SSLContext ***
-
## wolfSSL
**SSL ***
Populate the long *bitmask* with the correct set of features to instruct
libcurl how to handle Alt-Svc for the transfers using this handle.
-libcurl only accepts Alt-Svc headers over a Secure Transport, meaning
-HTTPS. It also only completes a request to an alternative origin if that
-origin is properly hosted over HTTPS. These requirements are there to make
-sure both the source and the destination are legitimate.
+libcurl only accepts Alt-Svc headers over HTTPS. It also only completes a
+request to an alternative origin if that origin is properly hosted over HTTPS.
+These requirements are there to make sure both the source and the destination
+are legitimate.
Alternative services are only used when setting up new connections. If there
exists an existing connection to the host in the connection pool, then that is
This option is by default set to the system path where libcurl's CA
certificate bundle is assumed to be stored, as established at build time.
-(iOS and macOS) When curl uses Secure Transport this option is supported. If
-the option is not set, then curl uses the certificates in the system and user
-Keychain to verify the peer.
-
(Schannel) This option is supported for Schannel in Windows 7 or later but we
recommend not using it until Windows 8 since it works better starting then.
If the option is not set, then curl uses the certificates in the Windows'
# DEFAULT
-Built-in system specific. When curl is built with Secure Transport or
-Schannel, this option is not set by default.
+Built-in system specific. When curl is built with Schannel, this option is not
+set by default.
# %PROTOCOLS%
- CURLOPT_SSL_VERIFYHOST (3)
- CURLOPT_SSL_VERIFYPEER (3)
TLS-backend:
- - BearSSL
- OpenSSL
- mbedTLS
- rustls
- wolfSSL
- - Secure Transport
- Schannel
Added-in: 7.77.0
---
# HISTORY
-This option is supported by the BearSSL (since 7.79.0), mbedTLS (since
-7.81.0), Rustls (since 7.82.0), wolfSSL (since 8.2.0), OpenSSL, Secure
-Transport and Schannel backends.
+This option is supported by the mbedTLS (since 7.81.0), Rustls (since 7.82.0),
+wolfSSL (since 8.2.0), OpenSSL and Schannel backends.
# %AVAILABILITY%
- OpenSSL
- GnuTLS
- Schannel
- - Secure Transport
- rustls
Added-in: 7.19.1
---
# HISTORY
-Schannel support added in 7.50.0. Secure Transport support added in 7.79.0.
-mbedTLS support added in 8.9.0.
+Schannel support added in 7.50.0. mbedTLS support added in 8.9.0.
# %AVAILABILITY%
- GnuTLS
- wolfSSL
- mbedTLS
- - Secure Transport
- Schannel
Added-in: 7.39.0
---
7.47.0: mbedTLS
-7.54.1: Secure Transport on macOS 10.7+/iOS 10+
-
7.58.1: Schannel
## sha256 support
7.47.0: mbedTLS
-7.54.1: Secure Transport on macOS 10.7+/iOS 10+
-
7.58.1: Schannel
Other SSL backends not supported.
## https://
-HTTPS Proxy. (Added in 7.52.0 for OpenSSL and GnuTLS Since 7.87.0, it
-also works for BearSSL, mbedTLS, Rustls, Schannel, Secure Transport and
-wolfSSL.)
+HTTPS Proxy. (Added in 7.52.0 for OpenSSL and GnuTLS Since 7.87.0, it also
+works for mbedTLS, Rustls, Schannel and wolfSSL.)
This uses HTTP/1 by default. Setting CURLOPT_PROXYTYPE(3) to
**CURLPROXY_HTTPS2** allows libcurl to negotiate using HTTP/2 with proxy.
## CURLPROXY_HTTPS
HTTPS Proxy using HTTP/1. (Added in 7.52.0 for OpenSSL and GnuTLS. Since
-7.87.0, it also works for BearSSL, mbedTLS, Rustls, Schannel, Secure Transport
-and wolfSSL.)
+7.87.0, it also works for mbedTLS, Rustls, Schannel and wolfSSL.)
## CURLPROXY_HTTPS2
This option is by default set to the system path where libcurl's CA
certificate bundle is assumed to be stored, as established at build time.
-(iOS and macOS only) If curl is built against Secure Transport, then this
-option is supported for backward compatibility with other SSL engines, but it
-should not be set. If the option is not set, then curl uses the certificates
-in the system and user Keychain to verify the peer, which is the preferred
-method of verifying the peer's certificate chain.
-
The application does not have to keep the string around after setting this
option.
TLS-backend:
- OpenSSL
- rustls
- - Secure Transport
- Schannel
Added-in: 7.77.0
---
- GnuTLS
- mbedTLS
- Schannel
- - Secure Transport
- wolfSSL
Added-in: 7.52.0
---
Pass a pointer to a null-terminated string as parameter. The string should be
the filename of your client certificate used to connect to the HTTPS proxy.
-The default format is "P12" on Secure Transport and "PEM" on other engines,
-and can be changed with CURLOPT_PROXY_SSLCERTTYPE(3).
-
-With Secure Transport, this can also be the nickname of the certificate you
-wish to authenticate with as it is named in the security database. If you want
-to use a file from the current directory, please precede it with "./" prefix,
-in order to avoid confusion with a nickname.
+The default format "PEM", and can be changed with
+CURLOPT_PROXY_SSLCERTTYPE(3).
When using a client certificate, you most likely also need to provide a
private key with CURLOPT_PROXY_SSLKEY(3).
- GnuTLS
- mbedTLS
- Schannel
- - Secure Transport
- wolfSSL
Added-in: 7.52.0
---
Pass a pointer to a null-terminated string as parameter. The string should be
the format of your client certificate used when connecting to an HTTPS proxy.
-Supported formats are "PEM" and "DER", except with Secure Transport or
-Schannel. OpenSSL (versions 0.9.3 and later), Secure Transport (on iOS 5 or
-later, or macOS 10.7 or later) and Schannel support "P12" for PKCS#12-encoded
-files.
+Supported formats are "PEM" and "DER", except with Schannel. OpenSSL and
+Schannel support "P12" for PKCS#12-encoded files.
The application does not have to keep the string around after setting this
option.
TLS-backend:
- OpenSSL
- Schannel
- - Secure Transport
Added-in: 7.71.0
---
Pass a pointer to a curl_blob structure, which contains information (pointer
and size) about a memory block with binary data of the certificate used to
-connect to the HTTPS proxy. The format must be "P12" on Secure Transport or
-Schannel. The format must be "P12" or "PEM" on OpenSSL. The string "P12" or
-"PEM" must be specified with CURLOPT_PROXY_SSLCERTTYPE(3).
+connect to the HTTPS proxy. The format must be "P12" on Schannel. The format
+must be "P12" or "PEM" on OpenSSL. The string "P12" or "PEM" must be specified
+with CURLOPT_PROXY_SSLCERTTYPE(3).
If the blob is initialized with the flags member of struct curl_blob set to
CURL_BLOB_COPY, the application does not have to keep the buffer around after
default format is "PEM" and can be changed with
CURLOPT_PROXY_SSLKEYTYPE(3).
-(Windows, iOS and macOS) This option is ignored by Secure Transport and
-Schannel SSL backends because they expect the private key to be already
-present in the key chain or PKCS#12 file containing the certificate.
+This option is ignored by the Schannel backend because it expects the private
+key to be already present in the key chain or PKCS#12 file containing the
+certificate.
The application does not have to keep the string around after setting this
option.
- TLS
TLS-backend:
- OpenSSL
- - BearSSL
- wolfSSL
Added-in: 7.52.0
---
- TLS
TLS-backend:
- OpenSSL
- - BearSSL
- Schannel
- - Secure Transport
- wolfSSL
- mbedTLS
- rustls
# HISTORY
OpenSSL support added in 7.52.0.
-wolfSSL, Schannel, Secure Transport, and BearSSL support added in 7.87.0
+wolfSSL, Schannel support added in 7.87.0
mbedTLS support added in 8.8.0.
Rustls support added in 8.10.0.
- GnuTLS
- mbedTLS
- Schannel
- - Secure Transport
- wolfSSL
Added-in: 7.1
---
# DESCRIPTION
Pass a pointer to a null-terminated string as parameter. The string should be
-the filename of your client certificate. The default format is `P12` on Secure
-Transport and `PEM` on other engines, and can be changed with
-CURLOPT_SSLCERTTYPE(3).
+the filename of your client certificate. The default format is `PEM` but can
+be changed with CURLOPT_SSLCERTTYPE(3).
-With Secure Transport, this can also be the nickname of the certificate you
-wish to authenticate with as it is named in the security database. If you want
-to use a file from the current directory, please precede it with `./` prefix,
-in order to avoid confusion with a nickname.
-
-(Schannel only) Client certificates can be specified by a path expression to a
+(Schannel) Client certificates can be specified by a path expression to a
certificate store. (You can import *PFX* to a store first). You can use
"\<store location\>\\\<store name\>\\\<thumbprint\>" to refer to a certificate
in the system certificates store, for example,
- GnuTLS
- mbedTLS
- Schannel
- - Secure Transport
- wolfSSL
Added-in: 7.9.3
---
Pass a pointer to a null-terminated string as parameter. The string should be
the format of your certificate.
-Supported formats are "PEM" and "DER", except with Secure Transport or
-Schannel. OpenSSL (versions 0.9.3 and later), Secure Transport (on iOS 5 or
-later, or macOS 10.7 or later) and Schannel support "P12" for PKCS#12-encoded
-files. GnuTLS supports P12 starting with curl 8.11.0.
+Supported formats are "PEM" and "DER", except with Schannel. OpenSSL and
+Schannel support "P12" for PKCS#12-encoded files. GnuTLS supports P12 starting
+with curl 8.11.0.
The application does not have to keep the string around after setting this
option.
- TLS
TLS-backend:
- OpenSSL
- - Secure Transport
- Schannel
- mbedTLS
- wolfSSL
# DESCRIPTION
Pass a pointer to a curl_blob structure, which contains (pointer and size) a
-client certificate. The format must be "P12" on Secure Transport or
-Schannel. The format must be "P12" or "PEM" on OpenSSL. The format must be
-"DER" or "PEM" on mbedTLS. The format must be specified with
-CURLOPT_SSLCERTTYPE(3).
+client certificate. The format must be "P12" on Schannel. The format must be
+"P12" or "PEM" on OpenSSL. The format must be "DER" or "PEM" on mbedTLS. The
+format must be specified with CURLOPT_SSLCERTTYPE(3).
If the blob is initialized with the flags member of struct curl_blob set to
CURL_BLOB_COPY, the application does not have to keep the buffer around after
the filename of your private key. The default format is "PEM" and can be
changed with CURLOPT_SSLKEYTYPE(3).
-(Windows, iOS and macOS) This option is ignored by Secure Transport and
-Schannel SSL backends because they expect the private key to be already present
-in the key-chain or PKCS#12 file containing the certificate.
+(Windows) This option is ignored by the Schannel SSL backend because it
+expects the private key to be already present in the key-chain or PKCS#12 file
+containing the certificate.
The application does not have to keep the string around after setting this
option.
- TLS
TLS-backend:
- OpenSSL
- - BearSSL
- wolfSSL
Added-in: 7.9.3
---
- TLS
TLS-backend:
- OpenSSL
- - BearSSL
- Schannel
- - Secure Transport
- wolfSSL
- mbedTLS
- rustls
OpenSSL support added in 7.9.
wolfSSL support added in 7.53.0.
Schannel support added in 7.61.0.
-Secure Transport support added in 7.77.0.
-BearSSL support added in 7.83.0.
mbedTLS support added in 8.8.0.
Rustls support added in 8.10.0.
- OpenSSL
- wolfSSL
- mbedTLS
- - BearSSL
Added-in: 7.10.6
---
# HISTORY
-Added in 7.11.0 for OpenSSL, in 7.42.0 for wolfSSL, in 7.54.0 for mbedTLS,
-in 7.83.0 in BearSSL.
+Added in 7.11.0 for OpenSSL, in 7.42.0 for wolfSSL, in 7.54.0 for mbedTLS.
# %AVAILABILITY%
- OpenSSL
- wolfSSL
- mbedTLS
- - BearSSL
Added-in: 7.10.6
---
give a last chance to an application to modify the behavior of the SSL
initialization. The *ssl_ctx* parameter is a pointer to the SSL library's
*SSL_CTX* for OpenSSL or wolfSSL, a pointer to *mbedtls_ssl_config* for
-mbedTLS or a pointer to *br_ssl_client_context* for BearSSL. If an error is
-returned from the callback no attempt to establish a connection is made and
-the perform operation returns the callback's error code. Set the *clientp*
-argument passed in to this callback with the CURLOPT_SSL_CTX_DATA(3) option.
+mbedTLS. If an error is returned from the callback no attempt to establish a
+connection is made and the perform operation returns the callback's error
+code. Set the *clientp* argument passed in to this callback with the
+CURLOPT_SSL_CTX_DATA(3) option.
This function gets called for all new connections made to a server, during the
SSL negotiation. While *ssl_ctx* points to a newly initialized object each
Protocol:
- TLS
TLS-backend:
- - Secure Transport
+ - none
Added-in: 7.42.0
---
it should be a Subject Alternate Name kind and its type should correctly
identify the field as an IP address.
-# LIMITATIONS
-
-Secure Transport: If *verify* value is 0, then SNI is also disabled. SNI is a
-TLS extension that sends the hostname to the server. The server may use that
-information to do such things as sending back a specific certificate for the
-hostname, or forwarding the request to a specific origin server. Some
-hostnames may be inaccessible if SNI is not sent.
-
# DEFAULT
2
- `aws` - built with **aws-sigv4** support
- `AppleIDN`
- `asyn-rr` - c-ares is used for additional records only
-- `bearssl`
- `brotli`
- `c-ares` - c-ares is used for (all) name resolves
- `CharConv`
- `PSL`
- `rustls`
- `Schannel`
-- `sectransp`
- `shuffle-dns`
- `socks`
- `SPNEGO`
set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "OPENSSL_")
elseif(CURL_USE_MBEDTLS)
set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "MBEDTLS_")
- elseif(CURL_USE_BEARSSL)
- set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "BEARSSL_")
elseif(CURL_USE_WOLFSSL)
set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "WOLFSSL_")
elseif(CURL_USE_GNUTLS)
vauth/vauth.h
LIB_VTLS_CFILES = \
- vtls/bearssl.c \
vtls/cipher_suite.c \
vtls/gtls.c \
vtls/hostcheck.c \
vtls/rustls.c \
vtls/schannel.c \
vtls/schannel_verify.c \
- vtls/sectransp.c \
vtls/vtls.c \
vtls/vtls_scache.c \
vtls/vtls_spack.c \
vtls/x509asn1.c
LIB_VTLS_HFILES = \
- vtls/bearssl.h \
vtls/cipher_suite.h \
vtls/gtls.h \
vtls/hostcheck.h \
vtls/rustls.h \
vtls/schannel.h \
vtls/schannel_int.h \
- vtls/sectransp.h \
vtls/vtls.h \
vtls/vtls_int.h \
vtls/vtls_scache.h \
/* if GnuTLS is enabled */
#cmakedefine USE_GNUTLS 1
-/* if Secure Transport is enabled */
-#cmakedefine USE_SECTRANSP 1
-
/* if SSL session export support is available */
#cmakedefine USE_SSLS_EXPORT 1
/* if mbedTLS is enabled */
#cmakedefine USE_MBEDTLS 1
-/* if BearSSL is enabled */
-#cmakedefine USE_BEARSSL 1
-
/* if Rustls is enabled */
#cmakedefine USE_RUSTLS 1
#if defined(USE_CURL_NTLM_CORE) && \
(defined(USE_GNUTLS) || \
- defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || \
defined(USE_WIN32_CRYPTO))
#if defined(USE_CURL_NTLM_CORE) && \
(defined(USE_GNUTLS) || \
- defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || \
defined(USE_WIN32_CRYPTO))
3. USE_GNUTLS
4. -
5. USE_MBEDTLS
- 6. USE_SECTRANSP
- 7. USE_OS400CRYPTO
- 8. USE_WIN32_CRYPTO
+ 6. USE_OS400CRYPTO
+ 7. USE_WIN32_CRYPTO
This ensures that:
- the same SSL branch gets activated throughout this source
# include <mbedtls/des.h>
-#elif defined(USE_SECTRANSP)
-
-# include <CommonCrypto/CommonCryptor.h>
-# include <CommonCrypto/CommonDigest.h>
-
#elif defined(USE_OS400CRYPTO)
# include "cipher.mih" /* mih/cipher */
#elif defined(USE_WIN32_CRYPTO)
return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
}
-#elif defined(USE_SECTRANSP)
-
-static bool encrypt_des(const unsigned char *in, unsigned char *out,
- const unsigned char *key_56)
-{
- char key[8];
- size_t out_len;
- CCCryptorStatus err;
-
- /* Expand the 56-bit key to 64 bits */
- extend_key_56_to_64(key_56, key);
-
- /* Set the key parity to odd */
- Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
-
- /* Perform the encryption */
- err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key,
- kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out,
- 8 /* outbuflen */, &out_len);
-
- return err == kCCSuccess;
-}
-
#elif defined(USE_OS400CRYPTO)
static bool encrypt_des(const unsigned char *in, unsigned char *out,
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_SECTRANSP) \
- || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
+#elif defined(USE_MBEDTLS) || defined(USE_OS400CRYPTO) || \
+ defined(USE_WIN32_CRYPTO)
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
encrypt_des(plaintext, results + 16, keys + 14);
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_SECTRANSP) \
- || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
+#elif defined(USE_MBEDTLS) || defined(USE_OS400CRYPTO) || \
+ defined(USE_WIN32_CRYPTO)
encrypt_des(magic, lmbuffer, pw);
encrypt_des(magic, lmbuffer + 8, pw + 7);
#endif
#endif
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
- defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
- defined(USE_BEARSSL) || defined(USE_RUSTLS)
+ defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \
+ defined(USE_RUSTLS)
#define USE_SSL /* SSL support has been enabled */
#endif
/* Single point where USE_NTLM definition might be defined */
#ifndef CURL_DISABLE_NTLM
# if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
- defined(USE_GNUTLS) || defined(USE_SECTRANSP) || \
+ defined(USE_GNUTLS) || \
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
(defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
# define USE_CURL_NTLM_CORE
* * GnuTLS
* * wolfSSL
* * Schannel SSPI
- * * Secure Transport (Darwin)
* * mbedTLS
- * * BearSSL
* * Rustls
* Skip the backend if it does not support the required algorithm */
/* Set the default CA cert bundle/path detected/specified at build time.
*
- * If Schannel or Secure Transport is the selected SSL backend then these
- * locations are ignored. We allow setting CA location for Schannel and
- * Secure Transport when explicitly specified by the user via
- * CURLOPT_CAINFO / --cacert.
+ * If Schannel is the selected SSL backend then these locations are ignored.
+ * We allow setting CA location for Schannel when explicitly specified by
+ * the user via CURLOPT_CAINFO / --cacert.
*/
- if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL &&
- Curl_ssl_backend() != CURLSSLBACKEND_SECURETRANSPORT) {
+ if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
#ifdef CURL_CA_BUNDLE
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
if(result)
+++ /dev/null
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Michael Forney, <mforney@mforney.org>
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-#include "../curl_setup.h"
-
-#ifdef USE_BEARSSL
-
-#include <bearssl.h>
-
-#include "bearssl.h"
-#include "cipher_suite.h"
-#include "../urldata.h"
-#include "../sendf.h"
-#include "../curlx/inet_pton.h"
-#include "vtls.h"
-#include "vtls_int.h"
-#include "vtls_scache.h"
-#include "../connect.h"
-#include "../select.h"
-#include "../multiif.h"
-#include "../curl_printf.h"
-
-/* The last #include files should be: */
-#include "../curl_memory.h"
-#include "../memdebug.h"
-
-struct x509_context {
- const br_x509_class *vtable;
- br_x509_minimal_context minimal;
- br_x509_decoder_context decoder;
- bool verifyhost;
- bool verifypeer;
- int cert_num;
-};
-
-struct bearssl_ssl_backend_data {
- br_ssl_client_context ctx;
- struct x509_context x509;
- unsigned char buf[BR_SSL_BUFSIZE_BIDI];
- br_x509_trust_anchor *anchors;
- size_t anchors_len;
- const char *protocols[ALPN_ENTRIES_MAX];
- /* SSL client context is active */
- bool active;
- /* size of pending write, yet to be flushed */
- size_t pending_write;
- BIT(sent_shutdown);
-};
-
-struct cafile_parser {
- CURLcode err;
- bool in_cert;
- br_x509_decoder_context xc;
- /* array of trust anchors loaded from CAfile */
- br_x509_trust_anchor *anchors;
- size_t anchors_len;
- /* buffer for DN data */
- unsigned char dn[1024];
- size_t dn_len;
-};
-
-#define CAFILE_SOURCE_PATH 1
-#define CAFILE_SOURCE_BLOB 2
-struct cafile_source {
- int type;
- const char *data;
- size_t len;
-};
-
-static void append_dn(void *ctx, const void *buf, size_t len)
-{
- struct cafile_parser *ca = ctx;
-
- if(ca->err != CURLE_OK || !ca->in_cert)
- return;
- if(sizeof(ca->dn) - ca->dn_len < len) {
- ca->err = CURLE_FAILED_INIT;
- return;
- }
- memcpy(ca->dn + ca->dn_len, buf, len);
- ca->dn_len += len;
-}
-
-static void x509_push(void *ctx, const void *buf, size_t len)
-{
- struct cafile_parser *ca = ctx;
-
- if(ca->in_cert)
- br_x509_decoder_push(&ca->xc, buf, len);
-}
-
-static CURLcode load_cafile(struct cafile_source *source,
- br_x509_trust_anchor **anchors,
- size_t *anchors_len)
-{
- struct cafile_parser ca;
- br_pem_decoder_context pc;
- br_x509_trust_anchor *ta;
- size_t ta_size;
- br_x509_trust_anchor *new_anchors;
- size_t new_anchors_len;
- br_x509_pkey *pkey;
- FILE *fp = 0;
- unsigned char buf[BUFSIZ];
- const unsigned char *p = NULL;
- const char *name;
- size_t n = 0, i, pushed;
-
- DEBUGASSERT(source->type == CAFILE_SOURCE_PATH
- || source->type == CAFILE_SOURCE_BLOB);
-
- if(source->type == CAFILE_SOURCE_PATH) {
- fp = fopen(source->data, "rb");
- if(!fp)
- return CURLE_SSL_CACERT_BADFILE;
- }
-
- if(source->type == CAFILE_SOURCE_BLOB && source->len > (size_t)INT_MAX)
- return CURLE_SSL_CACERT_BADFILE;
-
- ca.err = CURLE_OK;
- ca.in_cert = FALSE;
- ca.anchors = NULL;
- ca.anchors_len = 0;
- br_pem_decoder_init(&pc);
- br_pem_decoder_setdest(&pc, x509_push, &ca);
- do {
- if(source->type == CAFILE_SOURCE_PATH) {
- n = fread(buf, 1, sizeof(buf), fp);
- if(n == 0)
- break;
- p = buf;
- }
- else if(source->type == CAFILE_SOURCE_BLOB) {
- n = source->len;
- p = (const unsigned char *) source->data;
- }
- while(n) {
- pushed = br_pem_decoder_push(&pc, p, n);
- if(ca.err)
- goto fail;
- p += pushed;
- n -= pushed;
-
- switch(br_pem_decoder_event(&pc)) {
- case 0:
- break;
- case BR_PEM_BEGIN_OBJ:
- name = br_pem_decoder_name(&pc);
- if(strcmp(name, "CERTIFICATE") && strcmp(name, "X509 CERTIFICATE"))
- break;
- br_x509_decoder_init(&ca.xc, append_dn, &ca);
- ca.in_cert = TRUE;
- ca.dn_len = 0;
- break;
- case BR_PEM_END_OBJ:
- if(!ca.in_cert)
- break;
- ca.in_cert = FALSE;
- if(br_x509_decoder_last_error(&ca.xc)) {
- ca.err = CURLE_SSL_CACERT_BADFILE;
- goto fail;
- }
- /* add trust anchor */
- if(ca.anchors_len == SIZE_MAX / sizeof(ca.anchors[0])) {
- ca.err = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
- new_anchors_len = ca.anchors_len + 1;
- new_anchors = realloc(ca.anchors,
- new_anchors_len * sizeof(ca.anchors[0]));
- if(!new_anchors) {
- ca.err = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
- ca.anchors = new_anchors;
- ca.anchors_len = new_anchors_len;
- ta = &ca.anchors[ca.anchors_len - 1];
- ta->dn.data = NULL;
- ta->flags = 0;
- if(br_x509_decoder_isCA(&ca.xc))
- ta->flags |= BR_X509_TA_CA;
- pkey = br_x509_decoder_get_pkey(&ca.xc);
- if(!pkey) {
- ca.err = CURLE_SSL_CACERT_BADFILE;
- goto fail;
- }
- ta->pkey = *pkey;
-
- /* calculate space needed for trust anchor data */
- ta_size = ca.dn_len;
- switch(pkey->key_type) {
- case BR_KEYTYPE_RSA:
- ta_size += pkey->key.rsa.nlen + pkey->key.rsa.elen;
- break;
- case BR_KEYTYPE_EC:
- ta_size += pkey->key.ec.qlen;
- break;
- default:
- ca.err = CURLE_FAILED_INIT;
- goto fail;
- }
-
- /* fill in trust anchor DN and public key data */
- ta->dn.data = malloc(ta_size);
- if(!ta->dn.data) {
- ca.err = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
- memcpy(ta->dn.data, ca.dn, ca.dn_len);
- ta->dn.len = ca.dn_len;
- switch(pkey->key_type) {
- case BR_KEYTYPE_RSA:
- ta->pkey.key.rsa.n = ta->dn.data + ta->dn.len;
- memcpy(ta->pkey.key.rsa.n, pkey->key.rsa.n, pkey->key.rsa.nlen);
- ta->pkey.key.rsa.e = ta->pkey.key.rsa.n + ta->pkey.key.rsa.nlen;
- memcpy(ta->pkey.key.rsa.e, pkey->key.rsa.e, pkey->key.rsa.elen);
- break;
- case BR_KEYTYPE_EC:
- ta->pkey.key.ec.q = ta->dn.data + ta->dn.len;
- memcpy(ta->pkey.key.ec.q, pkey->key.ec.q, pkey->key.ec.qlen);
- break;
- }
- break;
- default:
- ca.err = CURLE_SSL_CACERT_BADFILE;
- goto fail;
- }
- }
- } while(source->type != CAFILE_SOURCE_BLOB);
- if(fp && ferror(fp))
- ca.err = CURLE_READ_ERROR;
- else if(ca.in_cert)
- ca.err = CURLE_SSL_CACERT_BADFILE;
-
-fail:
- if(fp)
- fclose(fp);
- if(ca.err == CURLE_OK) {
- *anchors = ca.anchors;
- *anchors_len = ca.anchors_len;
- }
- else {
- for(i = 0; i < ca.anchors_len; ++i)
- free(ca.anchors[i].dn.data);
- free(ca.anchors);
- }
-
- return ca.err;
-}
-
-static void x509_start_chain(const br_x509_class **ctx,
- const char *server_name)
-{
- struct x509_context *x509 = (struct x509_context *)ctx;
-
- if(!x509->verifypeer) {
- x509->cert_num = 0;
- return;
- }
-
- if(!x509->verifyhost)
- server_name = NULL;
- x509->minimal.vtable->start_chain(&x509->minimal.vtable, server_name);
-}
-
-static void x509_start_cert(const br_x509_class **ctx, uint32_t length)
-{
- struct x509_context *x509 = (struct x509_context *)ctx;
-
- if(!x509->verifypeer) {
- /* Only decode the first cert in the chain to obtain the public key */
- if(x509->cert_num == 0)
- br_x509_decoder_init(&x509->decoder, NULL, NULL);
- return;
- }
-
- x509->minimal.vtable->start_cert(&x509->minimal.vtable, length);
-}
-
-static void x509_append(const br_x509_class **ctx, const unsigned char *buf,
- size_t len)
-{
- struct x509_context *x509 = (struct x509_context *)ctx;
-
- if(!x509->verifypeer) {
- if(x509->cert_num == 0)
- br_x509_decoder_push(&x509->decoder, buf, len);
- return;
- }
-
- x509->minimal.vtable->append(&x509->minimal.vtable, buf, len);
-}
-
-static void x509_end_cert(const br_x509_class **ctx)
-{
- struct x509_context *x509 = (struct x509_context *)ctx;
-
- if(!x509->verifypeer) {
- x509->cert_num++;
- return;
- }
-
- x509->minimal.vtable->end_cert(&x509->minimal.vtable);
-}
-
-static unsigned x509_end_chain(const br_x509_class **ctx)
-{
- struct x509_context *x509 = (struct x509_context *)ctx;
-
- if(!x509->verifypeer) {
- return (unsigned)br_x509_decoder_last_error(&x509->decoder);
- }
-
- return x509->minimal.vtable->end_chain(&x509->minimal.vtable);
-}
-
-static const br_x509_pkey *x509_get_pkey(const br_x509_class *const *ctx,
- unsigned *usages)
-{
- struct x509_context *x509 = (struct x509_context *)CURL_UNCONST(ctx);
-
- if(!x509->verifypeer) {
- /* Nothing in the chain is verified, just return the public key of the
- first certificate and allow its usage for both TLS_RSA_* and
- TLS_ECDHE_* */
- if(usages)
- *usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN;
- return br_x509_decoder_get_pkey(&x509->decoder);
- }
-
- return x509->minimal.vtable->get_pkey(&x509->minimal.vtable, usages);
-}
-
-static const br_x509_class x509_vtable = {
- sizeof(struct x509_context),
- x509_start_chain,
- x509_start_cert,
- x509_append,
- x509_end_cert,
- x509_end_chain,
- x509_get_pkey
-};
-
-static CURLcode
-bearssl_set_ssl_version_min_max(struct Curl_easy *data,
- br_ssl_engine_context *ssl_eng,
- struct ssl_primary_config *conn_config)
-{
- unsigned version_min, version_max;
-
- switch(conn_config->version) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_TLSv1_0:
- version_min = BR_TLS10;
- break;
- case CURL_SSLVERSION_TLSv1_1:
- version_min = BR_TLS11;
- break;
- case CURL_SSLVERSION_TLSv1_2:
- version_min = BR_TLS12;
- break;
- case CURL_SSLVERSION_TLSv1_3:
- failf(data, "BearSSL: does not support TLS 1.3");
- return CURLE_SSL_CONNECT_ERROR;
- default:
- failf(data, "BearSSL: unsupported minimum TLS version value");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- switch(conn_config->version_max) {
- case CURL_SSLVERSION_MAX_DEFAULT:
- case CURL_SSLVERSION_MAX_NONE:
- case CURL_SSLVERSION_MAX_TLSv1_3:
- case CURL_SSLVERSION_MAX_TLSv1_2:
- version_max = BR_TLS12;
- break;
- case CURL_SSLVERSION_MAX_TLSv1_1:
- version_max = BR_TLS11;
- break;
- case CURL_SSLVERSION_MAX_TLSv1_0:
- version_max = BR_TLS10;
- break;
- default:
- failf(data, "BearSSL: unsupported maximum TLS version value");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- br_ssl_engine_set_versions(ssl_eng, version_min, version_max);
-
- return CURLE_OK;
-}
-
-static const uint16_t ciphertable[] = {
- /* RFC 2246 TLS 1.0 */
- BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x000A */
-
- /* RFC 3268 TLS 1.0 AES */
- BR_TLS_RSA_WITH_AES_128_CBC_SHA, /* 0x002F */
- BR_TLS_RSA_WITH_AES_256_CBC_SHA, /* 0x0035 */
-
- /* RFC 5246 TLS 1.2 */
- BR_TLS_RSA_WITH_AES_128_CBC_SHA256, /* 0x003C */
- BR_TLS_RSA_WITH_AES_256_CBC_SHA256, /* 0x003D */
-
- /* RFC 5288 TLS 1.2 AES GCM */
- BR_TLS_RSA_WITH_AES_128_GCM_SHA256, /* 0x009C */
- BR_TLS_RSA_WITH_AES_256_GCM_SHA384, /* 0x009D */
-
- /* RFC 4492 TLS 1.0 ECC */
- BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC003 */
- BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC004 */
- BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC005 */
- BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC008 */
- BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC009 */
- BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC00A */
- BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC00D */
- BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* 0xC00E */
- BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* 0xC00F */
- BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC012 */
- BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* 0xC013 */
- BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, /* 0xC014 */
-
- /* RFC 5289 TLS 1.2 ECC HMAC SHA256/384 */
- BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC023 */
- BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC024 */
- BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC025 */
- BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC026 */
- BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, /* 0xC027 */
- BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, /* 0xC028 */
- BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, /* 0xC029 */
- BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, /* 0xC02A */
-
- /* RFC 5289 TLS 1.2 GCM */
- BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02B */
- BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02C */
- BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02D */
- BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02E */
- BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, /* 0xC02F */
- BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, /* 0xC030 */
- BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, /* 0xC031 */
- BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, /* 0xC032 */
-
-#ifdef BR_TLS_RSA_WITH_AES_128_CCM
- /* RFC 6655 TLS 1.2 CCM
- Supported since BearSSL 0.6 */
- BR_TLS_RSA_WITH_AES_128_CCM, /* 0xC09C */
- BR_TLS_RSA_WITH_AES_256_CCM, /* 0xC09D */
- BR_TLS_RSA_WITH_AES_128_CCM_8, /* 0xC0A0 */
- BR_TLS_RSA_WITH_AES_256_CCM_8, /* 0xC0A1 */
-
- /* RFC 7251 TLS 1.2 ECC CCM
- Supported since BearSSL 0.6 */
- BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, /* 0xC0AC */
- BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, /* 0xC0AD */
- BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, /* 0xC0AE */
- BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, /* 0xC0AF */
-#endif
-
- /* RFC 7905 TLS 1.2 ChaCha20-Poly1305
- Supported since BearSSL 0.2 */
- BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA8 */
- BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA9 */
-};
-
-#define NUM_OF_CIPHERS CURL_ARRAYSIZE(ciphertable)
-
-static CURLcode bearssl_set_selected_ciphers(struct Curl_easy *data,
- br_ssl_engine_context *ssl_eng,
- const char *ciphers)
-{
- uint16_t selected[NUM_OF_CIPHERS];
- size_t count = 0, i;
- const char *ptr, *end;
-
- for(ptr = ciphers; ptr[0] != '\0' && count < NUM_OF_CIPHERS; ptr = end) {
- uint16_t id = Curl_cipher_suite_walk_str(&ptr, &end);
-
- /* Check if cipher is supported */
- if(id) {
- for(i = 0; i < NUM_OF_CIPHERS && ciphertable[i] != id; i++);
- if(i == NUM_OF_CIPHERS)
- id = 0;
- }
- if(!id) {
- if(ptr[0] != '\0')
- infof(data, "BearSSL: unknown cipher in list: \"%.*s\"",
- (int) (end - ptr), ptr);
- continue;
- }
-
- /* No duplicates allowed */
- for(i = 0; i < count && selected[i] != id; i++);
- if(i < count) {
- infof(data, "BearSSL: duplicate cipher in list: \"%.*s\"",
- (int) (end - ptr), ptr);
- continue;
- }
-
- selected[count++] = id;
- }
-
- if(count == 0) {
- failf(data, "BearSSL: no supported cipher in list");
- return CURLE_SSL_CIPHER;
- }
-
- br_ssl_engine_set_suites(ssl_eng, selected, count);
- return CURLE_OK;
-}
-
-static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
- const char * const ssl_cafile =
- /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
- (ca_info_blob ? NULL : conn_config->CAfile);
- const char *hostname = connssl->peer.hostname;
- const bool verifypeer = conn_config->verifypeer;
- const bool verifyhost = conn_config->verifyhost;
- CURLcode ret;
- int session_set = 0;
-
- DEBUGASSERT(backend);
- CURL_TRC_CF(data, cf, "connect_step1");
-
- if(verifypeer) {
- if(ca_info_blob) {
- struct cafile_source source;
- source.type = CAFILE_SOURCE_BLOB;
- source.data = ca_info_blob->data;
- source.len = ca_info_blob->len;
-
- CURL_TRC_CF(data, cf, "connect_step1, load ca_info_blob");
- ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
- if(ret != CURLE_OK) {
- failf(data, "error importing CA certificate blob");
- return ret;
- }
- }
-
- if(ssl_cafile) {
- struct cafile_source source;
- source.type = CAFILE_SOURCE_PATH;
- source.data = ssl_cafile;
- source.len = 0;
-
- CURL_TRC_CF(data, cf, "connect_step1, load cafile");
- ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
- if(ret != CURLE_OK) {
- failf(data, "error setting certificate verify locations."
- " CAfile: %s", ssl_cafile);
- return ret;
- }
- }
- }
-
- /* initialize SSL context */
- br_ssl_client_init_full(&backend->ctx, &backend->x509.minimal,
- backend->anchors, backend->anchors_len);
-
- ret = bearssl_set_ssl_version_min_max(data, &backend->ctx.eng, conn_config);
- if(ret != CURLE_OK)
- return ret;
-
- br_ssl_engine_set_buffer(&backend->ctx.eng, backend->buf,
- sizeof(backend->buf), 1);
-
- if(conn_config->cipher_list) {
- /* Override the ciphers as specified. For the default cipher list see the
- BearSSL source code of br_ssl_client_init_full() */
- CURL_TRC_CF(data, cf, "connect_step1, set ciphers");
- ret = bearssl_set_selected_ciphers(data, &backend->ctx.eng,
- conn_config->cipher_list);
- if(ret)
- return ret;
- }
-
- /* initialize X.509 context */
- backend->x509.vtable = &x509_vtable;
- backend->x509.verifypeer = verifypeer;
- backend->x509.verifyhost = verifyhost;
- br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable);
-
- if(ssl_config->primary.cache_session) {
- struct Curl_ssl_session *sc_session = NULL;
-
- ret = Curl_ssl_scache_take(cf, data, connssl->peer.scache_key,
- &sc_session);
- if(!ret && sc_session && sc_session->sdata && sc_session->sdata_len) {
- const br_ssl_session_parameters *session;
- session = (const br_ssl_session_parameters *)sc_session->sdata;
- br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
- session_set = 1;
- infof(data, "BearSSL: reusing session ID");
- /* single use of sessions */
- Curl_ssl_scache_return(cf, data, connssl->peer.scache_key, sc_session);
- }
- }
-
- if(connssl->alpn) {
- struct alpn_proto_buf proto;
- size_t i;
-
- for(i = 0; i < connssl->alpn->count; ++i) {
- backend->protocols[i] = connssl->alpn->entries[i];
- }
- br_ssl_engine_set_protocol_names(&backend->ctx.eng, backend->protocols,
- connssl->alpn->count);
- Curl_alpn_to_proto_str(&proto, connssl->alpn);
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
- }
-
- if(connssl->peer.type != CURL_SSL_PEER_DNS) {
- if(verifyhost) {
- failf(data, "BearSSL: "
- "host verification of IP address is not supported");
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- hostname = NULL;
- }
- else {
- if(!connssl->peer.sni) {
- failf(data, "Failed to set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
- hostname = connssl->peer.sni;
- CURL_TRC_CF(data, cf, "connect_step1, SNI set");
- }
-
- /* give application a chance to interfere with SSL set up. */
- if(data->set.ssl.fsslctx) {
- Curl_set_in_callback(data, TRUE);
- ret = (*data->set.ssl.fsslctx)(data, &backend->ctx,
- data->set.ssl.fsslctxp);
- Curl_set_in_callback(data, FALSE);
- if(ret) {
- failf(data, "BearSSL: error signaled by ssl ctx callback");
- return ret;
- }
- }
-
- if(!br_ssl_client_reset(&backend->ctx, hostname, session_set))
- return CURLE_FAILED_INIT;
- backend->active = TRUE;
-
- connssl->connecting_state = ssl_connect_2;
-
- return CURLE_OK;
-}
-
-static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- unsigned target)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- unsigned state;
- unsigned char *buf;
- size_t len;
- ssize_t ret;
- CURLcode result;
- int err;
-
- DEBUGASSERT(backend);
-
- connssl->io_need = CURL_SSL_IO_NEED_NONE;
- for(;;) {
- state = br_ssl_engine_current_state(&backend->ctx.eng);
- if(state & BR_SSL_CLOSED) {
- err = br_ssl_engine_last_error(&backend->ctx.eng);
- switch(err) {
- case BR_ERR_OK:
- /* TLS close notify */
- if(connssl->state != ssl_connection_complete) {
- failf(data, "SSL: connection closed during handshake");
- return CURLE_SSL_CONNECT_ERROR;
- }
- return CURLE_OK;
- case BR_ERR_X509_EXPIRED:
- failf(data, "SSL: X.509 verification: "
- "certificate is expired or not yet valid");
- return CURLE_PEER_FAILED_VERIFICATION;
- case BR_ERR_X509_BAD_SERVER_NAME:
- failf(data, "SSL: X.509 verification: "
- "expected server name was not found in the chain");
- return CURLE_PEER_FAILED_VERIFICATION;
- case BR_ERR_X509_NOT_TRUSTED:
- failf(data, "SSL: X.509 verification: "
- "chain could not be linked to a trust anchor");
- return CURLE_PEER_FAILED_VERIFICATION;
- default:;
- }
- failf(data, "BearSSL: connection error 0x%04x", err);
- /* X.509 errors are documented to have the range 32..63 */
- if(err >= 32 && err < 64)
- return CURLE_PEER_FAILED_VERIFICATION;
- return CURLE_SSL_CONNECT_ERROR;
- }
- if(state & target)
- return CURLE_OK;
- if(state & BR_SSL_SENDREC) {
- buf = br_ssl_engine_sendrec_buf(&backend->ctx.eng, &len);
- ret = Curl_conn_cf_send(cf->next, data, (const char *)buf, len, FALSE,
- &result);
- CURL_TRC_CF(data, cf, "ssl_send(len=%zu) -> %zd, %d", len, ret, result);
- if(ret <= 0) {
- if(result == CURLE_AGAIN)
- connssl->io_need |= CURL_SSL_IO_NEED_SEND;
- return result;
- }
- br_ssl_engine_sendrec_ack(&backend->ctx.eng, ret);
- }
- else if(state & BR_SSL_RECVREC) {
- buf = br_ssl_engine_recvrec_buf(&backend->ctx.eng, &len);
- ret = Curl_conn_cf_recv(cf->next, data, (char *)buf, len, &result);
- CURL_TRC_CF(data, cf, "ssl_recv(len=%zu) -> %zd, %d", len, ret, result);
- if(ret == 0) {
- failf(data, "SSL: EOF without close notify");
- return CURLE_RECV_ERROR;
- }
- if(ret <= 0) {
- if(result == CURLE_AGAIN)
- connssl->io_need |= CURL_SSL_IO_NEED_RECV;
- return result;
- }
- br_ssl_engine_recvrec_ack(&backend->ctx.eng, ret);
- }
- }
-}
-
-static CURLcode bearssl_connect_step2(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- br_ssl_session_parameters session;
- char cipher_str[64];
- CURLcode ret;
-
- DEBUGASSERT(backend);
- CURL_TRC_CF(data, cf, "connect_step2");
-
- ret = bearssl_run_until(cf, data, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
- if(ret == CURLE_AGAIN)
- return CURLE_OK;
- if(ret == CURLE_OK) {
- unsigned int tver;
- int subver = 0;
-
- if(br_ssl_engine_current_state(&backend->ctx.eng) == BR_SSL_CLOSED) {
- failf(data, "SSL: connection closed during handshake");
- return CURLE_SSL_CONNECT_ERROR;
- }
- connssl->connecting_state = ssl_connect_3;
- /* Informational message */
- tver = br_ssl_engine_get_version(&backend->ctx.eng);
- switch(tver) {
- case BR_TLS12:
- subver = 2; /* 1.2 */
- break;
- case BR_TLS11:
- subver = 1; /* 1.1 */
- break;
- case BR_TLS10: /* 1.0 */
- default: /* unknown, leave it at zero */
- break;
- }
- br_ssl_engine_get_session_parameters(&backend->ctx.eng, &session);
- Curl_cipher_suite_get_str(session.cipher_suite, cipher_str,
- sizeof(cipher_str), TRUE);
- infof(data, "BearSSL: TLS v1.%d connection using %s", subver,
- cipher_str);
- }
- return ret;
-}
-
-static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- CURLcode ret;
-
- DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- DEBUGASSERT(backend);
- CURL_TRC_CF(data, cf, "connect_step3");
-
- if(connssl->alpn) {
- const char *proto;
-
- proto = br_ssl_engine_get_selected_protocol(&backend->ctx.eng);
- Curl_alpn_set_negotiated(cf, data, connssl, (const unsigned char *)proto,
- proto ? strlen(proto) : 0);
- }
-
- if(ssl_config->primary.cache_session) {
- struct Curl_ssl_session *sc_session;
- br_ssl_session_parameters *session;
-
- session = malloc(sizeof(*session));
- if(!session)
- return CURLE_OUT_OF_MEMORY;
- br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
- ret = Curl_ssl_session_create((unsigned char *)session, sizeof(*session),
- (int)session->version,
- connssl->negotiated.alpn,
- 0, 0, &sc_session);
- if(!ret) {
- ret = Curl_ssl_scache_put(cf, data, connssl->peer.scache_key,
- sc_session);
- /* took ownership of `sc_session` */
- }
- if(ret)
- return ret;
- }
-
- connssl->connecting_state = ssl_connect_done;
-
- return CURLE_OK;
-}
-
-static ssize_t bearssl_send(struct Curl_cfilter *cf, struct Curl_easy *data,
- const void *buf, size_t len, CURLcode *err)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- unsigned char *app;
- size_t applen;
-
- DEBUGASSERT(backend);
-
- for(;;) {
- *err = bearssl_run_until(cf, data, BR_SSL_SENDAPP);
- if(*err)
- return -1;
- app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen);
- if(!app) {
- failf(data, "SSL: connection closed during write");
- *err = CURLE_SEND_ERROR;
- return -1;
- }
- if(backend->pending_write) {
- applen = backend->pending_write;
- backend->pending_write = 0;
- return applen;
- }
- if(applen > len)
- applen = len;
- memcpy(app, buf, applen);
- br_ssl_engine_sendapp_ack(&backend->ctx.eng, applen);
- br_ssl_engine_flush(&backend->ctx.eng, 0);
- backend->pending_write = applen;
- }
-}
-
-static ssize_t bearssl_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
- char *buf, size_t len, CURLcode *err)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- unsigned char *app;
- size_t applen;
-
- DEBUGASSERT(backend);
-
- *err = bearssl_run_until(cf, data, BR_SSL_RECVAPP);
- if(*err != CURLE_OK)
- return -1;
- app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen);
- if(!app)
- return 0;
- if(applen > len)
- applen = len;
- memcpy(buf, app, applen);
- br_ssl_engine_recvapp_ack(&backend->ctx.eng, applen);
-
- return applen;
-}
-
-static CURLcode bearssl_connect(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool *done)
-{
- CURLcode ret;
- struct ssl_connect_data *connssl = cf->ctx;
-
- CURL_TRC_CF(data, cf, "connect()");
- /* check if the connection has already been established */
- if(ssl_connection_complete == connssl->state) {
- CURL_TRC_CF(data, cf, "connect_common, connected");
- *done = TRUE;
- return CURLE_OK;
- }
-
- *done = FALSE;
- connssl->io_need = CURL_SSL_IO_NEED_NONE;
-
- if(ssl_connect_1 == connssl->connecting_state) {
- ret = bearssl_connect_step1(cf, data);
- if(ret)
- return ret;
- }
-
- if(ssl_connect_2 == connssl->connecting_state) {
- ret = bearssl_connect_step2(cf, data);
- if(ret)
- return ret;
- }
-
- if(ssl_connect_3 == connssl->connecting_state) {
- ret = bearssl_connect_step3(cf, data);
- if(ret)
- return ret;
- }
-
- if(ssl_connect_done == connssl->connecting_state) {
- connssl->state = ssl_connection_complete;
- *done = TRUE;
- }
-
- return CURLE_OK;
-}
-
-static size_t bearssl_version(char *buffer, size_t size)
-{
- return msnprintf(buffer, size, "BearSSL");
-}
-
-static bool bearssl_data_pending(struct Curl_cfilter *cf,
- const struct Curl_easy *data)
-{
- struct ssl_connect_data *ctx = cf->ctx;
- struct bearssl_ssl_backend_data *backend;
-
- (void)data;
- DEBUGASSERT(ctx && ctx->backend);
- backend = (struct bearssl_ssl_backend_data *)ctx->backend;
- return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP;
-}
-
-static CURLcode bearssl_random(struct Curl_easy *data UNUSED_PARAM,
- unsigned char *entropy, size_t length)
-{
- static br_hmac_drbg_context ctx;
- static bool seeded = FALSE;
-
- if(!seeded) {
- br_prng_seeder seeder;
-
- br_hmac_drbg_init(&ctx, &br_sha256_vtable, NULL, 0);
- seeder = br_prng_seeder_system(NULL);
- if(!seeder || !seeder(&ctx.vtable))
- return CURLE_FAILED_INIT;
- seeded = TRUE;
- }
- br_hmac_drbg_generate(&ctx, entropy, length);
-
- return CURLE_OK;
-}
-
-static void *bearssl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
-{
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- DEBUGASSERT(backend);
- return &backend->ctx;
-}
-
-static CURLcode bearssl_shutdown(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool send_shutdown, bool *done)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- CURLcode result;
-
- DEBUGASSERT(backend);
- if(!backend->active || cf->shutdown) {
- *done = TRUE;
- return CURLE_OK;
- }
-
- *done = FALSE;
- if(!backend->sent_shutdown) {
- (void)send_shutdown; /* unknown how to suppress our close notify */
- br_ssl_engine_close(&backend->ctx.eng);
- backend->sent_shutdown = TRUE;
- }
-
- result = bearssl_run_until(cf, data, BR_SSL_CLOSED);
- if(result == CURLE_OK) {
- *done = TRUE;
- }
- else if(result == CURLE_AGAIN) {
- CURL_TRC_CF(data, cf, "shutdown EAGAIN, io_need=%x", connssl->io_need);
- result = CURLE_OK;
- }
- else
- CURL_TRC_CF(data, cf, "shutdown error: %d", result);
-
- cf->shutdown = (result || *done);
- return result;
-}
-
-static void bearssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- size_t i;
-
- (void)data;
- DEBUGASSERT(backend);
-
- backend->active = FALSE;
- if(backend->anchors) {
- for(i = 0; i < backend->anchors_len; ++i)
- free(backend->anchors[i].dn.data);
- Curl_safefree(backend->anchors);
- }
-}
-
-static CURLcode bearssl_sha256sum(const unsigned char *input,
- size_t inputlen,
- unsigned char *sha256sum,
- size_t sha256len UNUSED_PARAM)
-{
- br_sha256_context ctx;
-
- br_sha256_init(&ctx);
- br_sha256_update(&ctx, input, inputlen);
- br_sha256_out(&ctx, sha256sum);
- return CURLE_OK;
-}
-
-const struct Curl_ssl Curl_ssl_bearssl = {
- { CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */
-
- SSLSUPP_CAINFO_BLOB |
- SSLSUPP_SSL_CTX |
- SSLSUPP_HTTPS_PROXY |
- SSLSUPP_CIPHER_LIST,
-
- sizeof(struct bearssl_ssl_backend_data),
-
- NULL, /* init */
- NULL, /* cleanup */
- bearssl_version, /* version */
- bearssl_shutdown, /* shutdown */
- bearssl_data_pending, /* data_pending */
- bearssl_random, /* random */
- NULL, /* cert_status_request */
- bearssl_connect, /* connect */
- Curl_ssl_adjust_pollset, /* adjust_pollset */
- bearssl_get_internals, /* get_internals */
- bearssl_close, /* close_one */
- NULL, /* close_all */
- NULL, /* set_engine */
- NULL, /* set_engine_default */
- NULL, /* engines_list */
- NULL, /* false_start */
- bearssl_sha256sum, /* sha256sum */
- bearssl_recv, /* recv decrypted data */
- bearssl_send, /* send data to encrypt */
- NULL, /* get_channel_binding */
-};
-
-#endif /* USE_BEARSSL */
+++ /dev/null
-#ifndef HEADER_CURL_BEARSSL_H
-#define HEADER_CURL_BEARSSL_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Michael Forney, <mforney@mforney.org>
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-#include "../curl_setup.h"
-
-#ifdef USE_BEARSSL
-
-extern const struct Curl_ssl Curl_ssl_bearssl;
-
-#endif /* USE_BEARSSL */
-#endif /* HEADER_CURL_BEARSSL_H */
***************************************************************************/
#include "../curl_setup.h"
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) || defined(USE_RUSTLS)
+#if defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#include "cipher_suite.h"
#include "../curl_printf.h"
#include "../strcase.h"
"CAMELLIA128" "\0"
"CAMELLIA256" "\0"
#endif
-#if defined(USE_SECTRANSP)
- "40" "\0"
- "ADH" "\0"
- "AECDH" "\0"
- "anon" "\0"
- "DES40" "\0"
- "DH" "\0"
- "DSS" "\0"
- "EDH" "\0"
- "EXP" "\0"
- "EXPORT" "\0"
- "IDEA" "\0"
- "RC2" "\0"
- "RC4" "\0"
-#endif
;
/* Indexes of above cs_txt */
enum {
CS_TXT_IDX_CAMELLIA,
CS_TXT_IDX_CAMELLIA128,
CS_TXT_IDX_CAMELLIA256,
-#endif
-#if defined(USE_SECTRANSP)
- CS_TXT_IDX_40,
- CS_TXT_IDX_ADH,
- CS_TXT_IDX_AECDH,
- CS_TXT_IDX_anon,
- CS_TXT_IDX_DES40,
- CS_TXT_IDX_DH,
- CS_TXT_IDX_DSS,
- CS_TXT_IDX_EDH,
- CS_TXT_IDX_EXP,
- CS_TXT_IDX_EXPORT,
- CS_TXT_IDX_IDEA,
- CS_TXT_IDX_RC2,
- CS_TXT_IDX_RC4,
#endif
CS_TXT_LEN,
};
/* !checksrc! disable COMMANOSPACE all */
static const struct cs_entry cs_list [] = {
/* TLS 1.3 ciphers */
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_RUSTLS)
+#if defined(USE_MBEDTLS) || defined(USE_RUSTLS)
CS_ENTRY(0x1301, TLS,AES,128,GCM,SHA256,,,),
CS_ENTRY(0x1302, TLS,AES,256,GCM,SHA384,,,),
CS_ENTRY(0x1303, TLS,CHACHA20,POLY1305,SHA256,,,,),
CS_ENTRY(0xCCA8, ECDHE,RSA,CHACHA20,POLY1305,,,,),
CS_ENTRY(0xCCA9, TLS,ECDHE,ECDSA,WITH,CHACHA20,POLY1305,SHA256,),
CS_ENTRY(0xCCA9, ECDHE,ECDSA,CHACHA20,POLY1305,,,,),
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#if defined(USE_MBEDTLS)
CS_ENTRY(0x002F, TLS,RSA,WITH,AES,128,CBC,SHA,),
CS_ENTRY(0x002F, AES128,SHA,,,,,,),
CS_ENTRY(0x0035, TLS,RSA,WITH,AES,256,CBC,SHA,),
CS_ENTRY(0xC032, TLS,ECDH,RSA,WITH,AES,256,GCM,SHA384),
CS_ENTRY(0xC032, ECDH,RSA,AES256,GCM,SHA384,,,),
#endif
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS)
+#if defined(USE_MBEDTLS)
CS_ENTRY(0x0001, TLS,RSA,WITH,NULL,MD5,,,),
CS_ENTRY(0x0001, NULL,MD5,,,,,,),
CS_ENTRY(0x0002, TLS,RSA,WITH,NULL,SHA,,,),
CS_ENTRY(0xCCAB, TLS,PSK,WITH,CHACHA20,POLY1305,SHA256,,),
CS_ENTRY(0xCCAB, PSK,CHACHA20,POLY1305,,,,,),
#endif
-#if defined(USE_SECTRANSP) || defined(USE_BEARSSL)
- CS_ENTRY(0x000A, TLS,RSA,WITH,3DES,EDE,CBC,SHA,),
- CS_ENTRY(0x000A, DES,CBC3,SHA,,,,,),
- CS_ENTRY(0xC003, TLS,ECDH,ECDSA,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0xC003, ECDH,ECDSA,DES,CBC3,SHA,,,),
- CS_ENTRY(0xC008, TLS,ECDHE,ECDSA,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0xC008, ECDHE,ECDSA,DES,CBC3,SHA,,,),
- CS_ENTRY(0xC00D, TLS,ECDH,RSA,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0xC00D, ECDH,RSA,DES,CBC3,SHA,,,),
- CS_ENTRY(0xC012, TLS,ECDHE,RSA,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0xC012, ECDHE,RSA,DES,CBC3,SHA,,,),
-#endif
-#if defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#if defined(USE_MBEDTLS)
CS_ENTRY(0xC09C, TLS,RSA,WITH,AES,128,CCM,,),
CS_ENTRY(0xC09C, AES128,CCM,,,,,,),
CS_ENTRY(0xC09D, TLS,RSA,WITH,AES,256,CCM,,),
CS_ENTRY(0xC0AF, TLS,ECDHE,ECDSA,WITH,AES,256,CCM,8),
CS_ENTRY(0xC0AF, ECDHE,ECDSA,AES256,CCM8,,,,),
#endif
-#if defined(USE_SECTRANSP)
- /* entries marked bc are backward compatible aliases for old OpenSSL names */
- CS_ENTRY(0x0003, TLS,RSA,EXPORT,WITH,RC4,40,MD5,),
- CS_ENTRY(0x0003, EXP,RC4,MD5,,,,,),
- CS_ENTRY(0x0004, TLS,RSA,WITH,RC4,128,MD5,,),
- CS_ENTRY(0x0004, RC4,MD5,,,,,,),
- CS_ENTRY(0x0005, TLS,RSA,WITH,RC4,128,SHA,,),
- CS_ENTRY(0x0005, RC4,SHA,,,,,,),
- CS_ENTRY(0x0006, TLS,RSA,EXPORT,WITH,RC2,CBC,40,MD5),
- CS_ENTRY(0x0006, EXP,RC2,CBC,MD5,,,,),
- CS_ENTRY(0x0007, TLS,RSA,WITH,IDEA,CBC,SHA,,),
- CS_ENTRY(0x0007, IDEA,CBC,SHA,,,,,),
- CS_ENTRY(0x0008, TLS,RSA,EXPORT,WITH,DES40,CBC,SHA,),
- CS_ENTRY(0x0008, EXP,DES,CBC,SHA,,,,),
- CS_ENTRY(0x0009, TLS,RSA,WITH,DES,CBC,SHA,,),
- CS_ENTRY(0x0009, DES,CBC,SHA,,,,,),
- CS_ENTRY(0x000B, TLS,DH,DSS,EXPORT,WITH,DES40,CBC,SHA),
- CS_ENTRY(0x000B, EXP,DH,DSS,DES,CBC,SHA,,),
- CS_ENTRY(0x000C, TLS,DH,DSS,WITH,DES,CBC,SHA,),
- CS_ENTRY(0x000C, DH,DSS,DES,CBC,SHA,,,),
- CS_ENTRY(0x000D, TLS,DH,DSS,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0x000D, DH,DSS,DES,CBC3,SHA,,,),
- CS_ENTRY(0x000E, TLS,DH,RSA,EXPORT,WITH,DES40,CBC,SHA),
- CS_ENTRY(0x000E, EXP,DH,RSA,DES,CBC,SHA,,),
- CS_ENTRY(0x000F, TLS,DH,RSA,WITH,DES,CBC,SHA,),
- CS_ENTRY(0x000F, DH,RSA,DES,CBC,SHA,,,),
- CS_ENTRY(0x0010, TLS,DH,RSA,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0x0010, DH,RSA,DES,CBC3,SHA,,,),
- CS_ENTRY(0x0011, TLS,DHE,DSS,EXPORT,WITH,DES40,CBC,SHA),
- CS_ENTRY(0x0011, EXP,DHE,DSS,DES,CBC,SHA,,),
- CS_ENTRY(0x0011, EXP,EDH,DSS,DES,CBC,SHA,,), /* bc */
- CS_ENTRY(0x0012, TLS,DHE,DSS,WITH,DES,CBC,SHA,),
- CS_ENTRY(0x0012, DHE,DSS,DES,CBC,SHA,,,),
- CS_ENTRY(0x0012, EDH,DSS,DES,CBC,SHA,,,), /* bc */
- CS_ENTRY(0x0013, TLS,DHE,DSS,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0x0013, DHE,DSS,DES,CBC3,SHA,,,),
- CS_ENTRY(0x0013, EDH,DSS,DES,CBC3,SHA,,,), /* bc */
- CS_ENTRY(0x0014, TLS,DHE,RSA,EXPORT,WITH,DES40,CBC,SHA),
- CS_ENTRY(0x0014, EXP,DHE,RSA,DES,CBC,SHA,,),
- CS_ENTRY(0x0014, EXP,EDH,RSA,DES,CBC,SHA,,), /* bc */
- CS_ENTRY(0x0015, TLS,DHE,RSA,WITH,DES,CBC,SHA,),
- CS_ENTRY(0x0015, DHE,RSA,DES,CBC,SHA,,,),
- CS_ENTRY(0x0015, EDH,RSA,DES,CBC,SHA,,,), /* bc */
- CS_ENTRY(0x0016, TLS,DHE,RSA,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0x0016, DHE,RSA,DES,CBC3,SHA,,,),
- CS_ENTRY(0x0016, EDH,RSA,DES,CBC3,SHA,,,), /* bc */
- CS_ENTRY(0x0017, TLS,DH,anon,EXPORT,WITH,RC4,40,MD5),
- CS_ENTRY(0x0017, EXP,ADH,RC4,MD5,,,,),
- CS_ENTRY(0x0018, TLS,DH,anon,WITH,RC4,128,MD5,),
- CS_ENTRY(0x0018, ADH,RC4,MD5,,,,,),
- CS_ENTRY(0x0019, TLS,DH,anon,EXPORT,WITH,DES40,CBC,SHA),
- CS_ENTRY(0x0019, EXP,ADH,DES,CBC,SHA,,,),
- CS_ENTRY(0x001A, TLS,DH,anon,WITH,DES,CBC,SHA,),
- CS_ENTRY(0x001A, ADH,DES,CBC,SHA,,,,),
- CS_ENTRY(0x001B, TLS,DH,anon,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0x001B, ADH,DES,CBC3,SHA,,,,),
- CS_ENTRY(0x0030, TLS,DH,DSS,WITH,AES,128,CBC,SHA),
- CS_ENTRY(0x0030, DH,DSS,AES128,SHA,,,,),
- CS_ENTRY(0x0031, TLS,DH,RSA,WITH,AES,128,CBC,SHA),
- CS_ENTRY(0x0031, DH,RSA,AES128,SHA,,,,),
- CS_ENTRY(0x0032, TLS,DHE,DSS,WITH,AES,128,CBC,SHA),
- CS_ENTRY(0x0032, DHE,DSS,AES128,SHA,,,,),
- CS_ENTRY(0x0034, TLS,DH,anon,WITH,AES,128,CBC,SHA),
- CS_ENTRY(0x0034, ADH,AES128,SHA,,,,,),
- CS_ENTRY(0x0036, TLS,DH,DSS,WITH,AES,256,CBC,SHA),
- CS_ENTRY(0x0036, DH,DSS,AES256,SHA,,,,),
- CS_ENTRY(0x0037, TLS,DH,RSA,WITH,AES,256,CBC,SHA),
- CS_ENTRY(0x0037, DH,RSA,AES256,SHA,,,,),
- CS_ENTRY(0x0038, TLS,DHE,DSS,WITH,AES,256,CBC,SHA),
- CS_ENTRY(0x0038, DHE,DSS,AES256,SHA,,,,),
- CS_ENTRY(0x003A, TLS,DH,anon,WITH,AES,256,CBC,SHA),
- CS_ENTRY(0x003A, ADH,AES256,SHA,,,,,),
- CS_ENTRY(0x003E, TLS,DH,DSS,WITH,AES,128,CBC,SHA256),
- CS_ENTRY(0x003E, DH,DSS,AES128,SHA256,,,,),
- CS_ENTRY(0x003F, TLS,DH,RSA,WITH,AES,128,CBC,SHA256),
- CS_ENTRY(0x003F, DH,RSA,AES128,SHA256,,,,),
- CS_ENTRY(0x0040, TLS,DHE,DSS,WITH,AES,128,CBC,SHA256),
- CS_ENTRY(0x0040, DHE,DSS,AES128,SHA256,,,,),
- CS_ENTRY(0x0068, TLS,DH,DSS,WITH,AES,256,CBC,SHA256),
- CS_ENTRY(0x0068, DH,DSS,AES256,SHA256,,,,),
- CS_ENTRY(0x0069, TLS,DH,RSA,WITH,AES,256,CBC,SHA256),
- CS_ENTRY(0x0069, DH,RSA,AES256,SHA256,,,,),
- CS_ENTRY(0x006A, TLS,DHE,DSS,WITH,AES,256,CBC,SHA256),
- CS_ENTRY(0x006A, DHE,DSS,AES256,SHA256,,,,),
- CS_ENTRY(0x006C, TLS,DH,anon,WITH,AES,128,CBC,SHA256),
- CS_ENTRY(0x006C, ADH,AES128,SHA256,,,,,),
- CS_ENTRY(0x006D, TLS,DH,anon,WITH,AES,256,CBC,SHA256),
- CS_ENTRY(0x006D, ADH,AES256,SHA256,,,,,),
- CS_ENTRY(0x008A, TLS,PSK,WITH,RC4,128,SHA,,),
- CS_ENTRY(0x008A, PSK,RC4,SHA,,,,,),
- CS_ENTRY(0x008B, TLS,PSK,WITH,3DES,EDE,CBC,SHA,),
- CS_ENTRY(0x008B, PSK,3DES,EDE,CBC,SHA,,,),
- CS_ENTRY(0x008E, TLS,DHE,PSK,WITH,RC4,128,SHA,),
- CS_ENTRY(0x008E, DHE,PSK,RC4,SHA,,,,),
- CS_ENTRY(0x008F, TLS,DHE,PSK,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0x008F, DHE,PSK,3DES,EDE,CBC,SHA,,),
- CS_ENTRY(0x0092, TLS,RSA,PSK,WITH,RC4,128,SHA,),
- CS_ENTRY(0x0092, RSA,PSK,RC4,SHA,,,,),
- CS_ENTRY(0x0093, TLS,RSA,PSK,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0x0093, RSA,PSK,3DES,EDE,CBC,SHA,,),
- CS_ENTRY(0x00A0, TLS,DH,RSA,WITH,AES,128,GCM,SHA256),
- CS_ENTRY(0x00A0, DH,RSA,AES128,GCM,SHA256,,,),
- CS_ENTRY(0x00A1, TLS,DH,RSA,WITH,AES,256,GCM,SHA384),
- CS_ENTRY(0x00A1, DH,RSA,AES256,GCM,SHA384,,,),
- CS_ENTRY(0x00A2, TLS,DHE,DSS,WITH,AES,128,GCM,SHA256),
- CS_ENTRY(0x00A2, DHE,DSS,AES128,GCM,SHA256,,,),
- CS_ENTRY(0x00A3, TLS,DHE,DSS,WITH,AES,256,GCM,SHA384),
- CS_ENTRY(0x00A3, DHE,DSS,AES256,GCM,SHA384,,,),
- CS_ENTRY(0x00A4, TLS,DH,DSS,WITH,AES,128,GCM,SHA256),
- CS_ENTRY(0x00A4, DH,DSS,AES128,GCM,SHA256,,,),
- CS_ENTRY(0x00A5, TLS,DH,DSS,WITH,AES,256,GCM,SHA384),
- CS_ENTRY(0x00A5, DH,DSS,AES256,GCM,SHA384,,,),
- CS_ENTRY(0x00A6, TLS,DH,anon,WITH,AES,128,GCM,SHA256),
- CS_ENTRY(0x00A6, ADH,AES128,GCM,SHA256,,,,),
- CS_ENTRY(0x00A7, TLS,DH,anon,WITH,AES,256,GCM,SHA384),
- CS_ENTRY(0x00A7, ADH,AES256,GCM,SHA384,,,,),
- CS_ENTRY(0xC002, TLS,ECDH,ECDSA,WITH,RC4,128,SHA,),
- CS_ENTRY(0xC002, ECDH,ECDSA,RC4,SHA,,,,),
- CS_ENTRY(0xC007, TLS,ECDHE,ECDSA,WITH,RC4,128,SHA,),
- CS_ENTRY(0xC007, ECDHE,ECDSA,RC4,SHA,,,,),
- CS_ENTRY(0xC00C, TLS,ECDH,RSA,WITH,RC4,128,SHA,),
- CS_ENTRY(0xC00C, ECDH,RSA,RC4,SHA,,,,),
- CS_ENTRY(0xC011, TLS,ECDHE,RSA,WITH,RC4,128,SHA,),
- CS_ENTRY(0xC011, ECDHE,RSA,RC4,SHA,,,,),
- CS_ENTRY(0xC015, TLS,ECDH,anon,WITH,NULL,SHA,,),
- CS_ENTRY(0xC015, AECDH,NULL,SHA,,,,,),
- CS_ENTRY(0xC016, TLS,ECDH,anon,WITH,RC4,128,SHA,),
- CS_ENTRY(0xC016, AECDH,RC4,SHA,,,,,),
- CS_ENTRY(0xC017, TLS,ECDH,anon,WITH,3DES,EDE,CBC,SHA),
- CS_ENTRY(0xC017, AECDH,DES,CBC3,SHA,,,,),
- CS_ENTRY(0xC018, TLS,ECDH,anon,WITH,AES,128,CBC,SHA),
- CS_ENTRY(0xC018, AECDH,AES128,SHA,,,,,),
- CS_ENTRY(0xC019, TLS,ECDH,anon,WITH,AES,256,CBC,SHA),
- CS_ENTRY(0xC019, AECDH,AES256,SHA,,,,,),
-#endif
#if defined(USE_MBEDTLS)
/* entries marked ns are "non-standard", they are not in OpenSSL */
CS_ENTRY(0x0041, TLS,RSA,WITH,CAMELLIA,128,CBC,SHA,),
return r;
}
-#endif /* defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) || defined(USE_RUSTLS) */
+#endif /* defined(USE_MBEDTLS) || defined(USE_RUSTLS) */
#include "../curl_setup.h"
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) || defined(USE_RUSTLS)
+#if defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#include <stdint.h>
/* Lookup IANA id for cipher suite string, returns 0 if not recognized */
int Curl_cipher_suite_get_str(uint16_t id, char *buf, size_t buf_size,
bool prefer_rfc);
-#endif /* defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) || defined(USE_RUSTLS) */
+#endif /* defined(USE_MBEDTLS) || defined(USE_RUSTLS) */
#endif /* HEADER_CURL_CIPHER_SUITE_H */
+++ /dev/null
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) Nick Zitzmann, <nickzman@gmail.com>.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-/*
- * Source file for all iOS and macOS Secure Transport-specific code for the
- * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
- */
-
-#include "../curl_setup.h"
-
-#ifdef USE_SECTRANSP
-
-#include "../urldata.h" /* for the Curl_easy definition */
-#include "../curlx/base64.h"
-#include "../curlx/strparse.h"
-#include "../multiif.h"
-#include "../strcase.h"
-#include "x509asn1.h"
-#include "vtls_scache.h"
-#include "../strerror.h"
-#include "cipher_suite.h"
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunreachable-code"
-#endif /* __clang__ */
-
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Waddress"
-#endif
-
-#if defined(__GNUC__) && defined(__APPLE__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-#include <limits.h>
-
-#include <Security/Security.h>
-/* For some reason, when building for iOS, the omnibus header above does
- * not include SecureTransport.h as of iOS SDK 5.1. */
-#include <Security/SecureTransport.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <CommonCrypto/CommonDigest.h>
-
-/* The Security framework has changed greatly between iOS and different macOS
- versions, and we will try to support as many of them as we can (back to
- Leopard and iOS 5) by using macros and weak-linking.
-
- In general, you want to build this using the most recent OS SDK, since some
- features require curl to be built against the latest SDK. TLS 1.1 and 1.2
- support, for instance, require the macOS 10.8 SDK or later. TLS 1.3
- requires the macOS 10.13 or iOS 11 SDK or later. */
-#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
-#error "The Secure Transport backend requires Leopard or later."
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
-
-#define CURL_BUILD_IOS 0
-#define CURL_BUILD_IOS_7 0
-#define CURL_BUILD_IOS_9 0
-#define CURL_BUILD_IOS_11 0
-#define CURL_BUILD_IOS_13 0
-#define CURL_BUILD_MAC 1
-/* This is the maximum API level we are allowed to use when building: */
-#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
-#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
-#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
-#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
-#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
-#define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
-#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
-#define CURL_BUILD_MAC_10_15 MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
-/* These macros mean "the following code is present to allow runtime backward
- compatibility with at least this cat or earlier":
- (You set this at build-time using the compiler command line option
- "-mmacosx-version-min.") */
-#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
-#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
-#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
-#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
-#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
-
-#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
-#define CURL_BUILD_IOS 1
-#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
-#define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
-#define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
-#define CURL_BUILD_IOS_13 __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
-#define CURL_BUILD_MAC 0
-#define CURL_BUILD_MAC_10_5 0
-#define CURL_BUILD_MAC_10_6 0
-#define CURL_BUILD_MAC_10_7 0
-#define CURL_BUILD_MAC_10_8 0
-#define CURL_BUILD_MAC_10_9 0
-#define CURL_BUILD_MAC_10_11 0
-#define CURL_BUILD_MAC_10_13 0
-#define CURL_BUILD_MAC_10_15 0
-#define CURL_SUPPORT_MAC_10_5 0
-#define CURL_SUPPORT_MAC_10_6 0
-#define CURL_SUPPORT_MAC_10_7 0
-#define CURL_SUPPORT_MAC_10_8 0
-#define CURL_SUPPORT_MAC_10_9 0
-
-#else
-#error "The Secure Transport backend requires iOS or macOS."
-#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
-
-#if CURL_BUILD_MAC
-#include <sys/sysctl.h>
-#endif /* CURL_BUILD_MAC */
-
-#include "../sendf.h"
-#include "../curlx/inet_pton.h"
-#include "../connect.h"
-#include "../select.h"
-#include "vtls.h"
-#include "vtls_int.h"
-#include "sectransp.h"
-#include "../curl_printf.h"
-#include "../strdup.h"
-
-#include "../curl_memory.h"
-/* The last #include file should be: */
-#include "../memdebug.h"
-
-
-/* From MacTypes.h (which we cannot include because it is not present in
- iOS: */
-#define ioErr -36
-#define paramErr -50
-
-struct st_ssl_backend_data {
- SSLContextRef ssl_ctx;
- bool ssl_direction; /* true if writing, false if reading */
- size_t ssl_write_buffered_length;
- BIT(sent_shutdown);
-};
-
-/* Create the list of default ciphers to use by making an intersection of the
- * ciphers supported by Secure Transport and the list below, using the order
- * of the former.
- * This list is based on TLS recommendations by Mozilla, balancing between
- * security and wide compatibility: "Most ciphers that are not clearly broken
- * and dangerous to use are supported"
- */
-static const uint16_t default_ciphers[] = {
- TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x000A */
- TLS_RSA_WITH_AES_128_CBC_SHA, /* 0x002F */
- TLS_RSA_WITH_AES_256_CBC_SHA, /* 0x0035 */
-
-#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC009 */
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC00A */
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* 0xC013 */
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, /* 0xC014 */
-#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
-
-#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- TLS_RSA_WITH_AES_128_CBC_SHA256, /* 0x003C */
- TLS_RSA_WITH_AES_256_CBC_SHA256, /* 0x003D */
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, /* 0x0067 */
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, /* 0x006B */
- TLS_RSA_WITH_AES_128_GCM_SHA256, /* 0x009C */
- TLS_RSA_WITH_AES_256_GCM_SHA384, /* 0x009D */
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, /* 0x009E */
- TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, /* 0x009F */
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC023 */
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC024 */
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, /* 0xC027 */
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, /* 0xC028 */
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02B */
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02C */
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, /* 0xC02F */
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, /* 0xC030 */
-#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
-
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA8 */
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA9 */
-
- /* TLSv1.3 is not supported by Secure Transport, but there is also other
- * code referencing TLSv1.3, like: kTLSProtocol13 ? */
- TLS_AES_128_GCM_SHA256, /* 0x1301 */
- TLS_AES_256_GCM_SHA384, /* 0x1302 */
- TLS_CHACHA20_POLY1305_SHA256, /* 0x1303 */
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
-};
-
-/* pinned public key support tests */
-
-/* version 1 supports macOS 10.12+ and iOS 10+ */
-#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
- (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
-#define SECTRANSP_PINNEDPUBKEY_V1 1
-#endif
-
-/* version 2 supports macOS 10.7+ */
-#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
-#define SECTRANSP_PINNEDPUBKEY_V2 1
-#endif
-
-#if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2)
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define SECTRANSP_PINNEDPUBKEY 1
-#endif /* SECTRANSP_PINNEDPUBKEY */
-
-#ifdef SECTRANSP_PINNEDPUBKEY
-/* both new and old APIs return rsa keys missing the spki header (not DER) */
-static const unsigned char rsa4096SpkiHeader[] = {
- 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
- 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00};
-
-static const unsigned char rsa2048SpkiHeader[] = {
- 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
- 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
-#ifdef SECTRANSP_PINNEDPUBKEY_V1
-/* the *new* version does not return DER encoded ecdsa certs like the old... */
-static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
- 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
- 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
- 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
- 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
- 0x42, 0x00};
-
-static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
- 0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
- 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
- 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
- 0x00, 0x22, 0x03, 0x62, 0x00};
-#endif /* SECTRANSP_PINNEDPUBKEY_V1 */
-#endif /* SECTRANSP_PINNEDPUBKEY */
-
-static OSStatus sectransp_bio_cf_in_read(SSLConnectionRef connection,
- void *buf,
- size_t *dataLength) /* IN/OUT */
-{
- const struct Curl_cfilter *cf = (const struct Curl_cfilter *)connection;
- struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nread;
- CURLcode result;
- OSStatus rtn = noErr;
-
- DEBUGASSERT(data);
- nread = Curl_conn_cf_recv(cf->next, data, buf, *dataLength, &result);
- CURL_TRC_CF(data, cf, "bio_read(len=%zu) -> %zd, result=%d",
- *dataLength, nread, result);
- if(nread < 0) {
- switch(result) {
- case CURLE_OK:
- case CURLE_AGAIN:
- rtn = errSSLWouldBlock;
- backend->ssl_direction = FALSE;
- break;
- default:
- rtn = ioErr;
- break;
- }
- nread = 0;
- }
- else if(nread == 0) {
- rtn = errSSLClosedGraceful;
- }
- else if((size_t)nread < *dataLength) {
- rtn = errSSLWouldBlock;
- }
- *dataLength = nread;
- return rtn;
-}
-
-static OSStatus sectransp_bio_cf_out_write(SSLConnectionRef connection,
- const void *buf,
- size_t *dataLength) /* IN/OUT */
-{
- const struct Curl_cfilter *cf = (const struct Curl_cfilter *)connection;
- struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nwritten;
- CURLcode result;
- OSStatus rtn = noErr;
-
- DEBUGASSERT(data);
- nwritten = Curl_conn_cf_send(cf->next, data, buf, *dataLength, FALSE,
- &result);
- CURL_TRC_CF(data, cf, "bio_send(len=%zu) -> %zd, result=%d",
- *dataLength, nwritten, result);
- if(nwritten <= 0) {
- if(result == CURLE_AGAIN) {
- rtn = errSSLWouldBlock;
- backend->ssl_direction = TRUE;
- }
- else {
- rtn = ioErr;
- }
- nwritten = 0;
- }
- else if((size_t)nwritten < *dataLength) {
- rtn = errSSLWouldBlock;
- }
- *dataLength = nwritten;
- return rtn;
-}
-
-#if CURL_BUILD_MAC
-CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
-{
- int mib[2];
- size_t os_version_len;
- char buf[256];
-
- /* Get the Darwin kernel version from the kernel using sysctl(): */
- mib[0] = CTL_KERN;
- mib[1] = KERN_OSRELEASE;
- if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1)
- return;
- if(os_version_len < sizeof(buf)) {
- if(sysctl(mib, 2, buf, &os_version_len, NULL, 0) != -1) {
- const char *os = buf;
- curl_off_t fnum;
- curl_off_t snum;
- /* Parse the version: */
- if(!curlx_str_number(&os, &fnum, INT_MAX) &&
- !curlx_str_single(&os, '.') &&
- !curlx_str_number(&os, &snum, INT_MAX)) {
- *major = (int)fnum;
- *minor = (int)snum;
- }
- }
- }
-}
-#endif /* CURL_BUILD_MAC */
-
-/* Apple provides a myriad of ways of getting information about a certificate
- into a string. Some are not available under iOS or newer cats. Here's a
- unified function for getting a string describing the certificate that ought
- to work in all cats starting with Leopard. */
-CF_INLINE CFStringRef getsubject(SecCertificateRef cert)
-{
- CFStringRef server_cert_summary = CFSTR("(null)");
-
-#if CURL_BUILD_IOS
- /* iOS: There is only one way to do this. */
- server_cert_summary = SecCertificateCopySubjectSummary(cert);
-#else
-#if CURL_BUILD_MAC_10_7
- /* Lion & later: Get the long description if we can. */
- if(&SecCertificateCopyLongDescription)
- server_cert_summary =
- SecCertificateCopyLongDescription(NULL, cert, NULL);
- else
-#endif /* CURL_BUILD_MAC_10_7 */
-#if CURL_BUILD_MAC_10_6
- /* Snow Leopard: Get the certificate summary. */
- if(&SecCertificateCopySubjectSummary)
- server_cert_summary = SecCertificateCopySubjectSummary(cert);
- else
-#endif /* CURL_BUILD_MAC_10_6 */
- /* Leopard is as far back as we go... */
- (void)SecCertificateCopyCommonName(cert, &server_cert_summary);
-#endif /* CURL_BUILD_IOS */
- return server_cert_summary;
-}
-
-static CURLcode CopyCertSubject(struct Curl_easy *data,
- SecCertificateRef cert, char **certp)
-{
- CFStringRef c = getsubject(cert);
- CURLcode result = CURLE_OK;
- const char *direct;
- char *cbuf = NULL;
- *certp = NULL;
-
- if(!c) {
- failf(data, "SSL: invalid CA certificate subject");
- return CURLE_PEER_FAILED_VERIFICATION;
- }
-
- /* If the subject is already available as UTF-8 encoded (ie 'direct') then
- use that, else convert it. */
- direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8);
- if(direct) {
- *certp = strdup(direct);
- if(!*certp) {
- failf(data, "SSL: out of memory");
- result = CURLE_OUT_OF_MEMORY;
- }
- }
- else {
- size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
- cbuf = calloc(1, cbuf_size);
- if(cbuf) {
- if(!CFStringGetCString(c, cbuf, (CFIndex)cbuf_size,
- kCFStringEncodingUTF8)) {
- failf(data, "SSL: invalid CA certificate subject");
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- else
- /* pass back the buffer */
- *certp = cbuf;
- }
- else {
- failf(data, "SSL: could not allocate %zu bytes of memory", cbuf_size);
- result = CURLE_OUT_OF_MEMORY;
- }
- }
- if(result)
- free(cbuf);
- CFRelease(c);
- return result;
-}
-
-#if CURL_SUPPORT_MAC_10_6
-/* The SecKeychainSearch API was deprecated in Lion, and using it will raise
- deprecation warnings, so let's not compile this unless it is necessary: */
-static OSStatus CopyIdentityWithLabelOldSchool(char *label,
- SecIdentityRef *out_c_a_k)
-{
- OSStatus status = errSecItemNotFound;
- SecKeychainAttributeList attr_list;
- SecKeychainAttribute attr;
- SecKeychainSearchRef search = NULL;
- SecCertificateRef cert = NULL;
-
- /* Set up the attribute list: */
- attr_list.count = 1L;
- attr_list.attr = &attr;
-
- /* Set up our lone search criterion: */
- attr.tag = kSecLabelItemAttr;
- attr.data = label;
- attr.length = (UInt32)strlen(label);
-
- /* Start searching: */
- status = SecKeychainSearchCreateFromAttributes(NULL,
- kSecCertificateItemClass,
- &attr_list,
- &search);
- if(status == noErr) {
- status = SecKeychainSearchCopyNext(search,
- (SecKeychainItemRef *)&cert);
- if(status == noErr && cert) {
- /* If we found a certificate, does it have a private key? */
- status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
- CFRelease(cert);
- }
- }
-
- if(search)
- CFRelease(search);
- return status;
-}
-#endif /* CURL_SUPPORT_MAC_10_6 */
-
-static OSStatus CopyIdentityWithLabel(char *label,
- SecIdentityRef *out_cert_and_key)
-{
- OSStatus status = errSecItemNotFound;
-
-#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
- CFArrayRef keys_list;
- CFIndex keys_list_count;
- CFIndex i;
-
- /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
- kSecClassIdentity was introduced in Lion. If both exist, let's use them
- to find the certificate. */
- if(&SecItemCopyMatching && kSecClassIdentity) {
- CFTypeRef keys[5];
- CFTypeRef values[5];
- CFDictionaryRef query_dict;
- CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
- kCFStringEncodingUTF8);
-
- /* Set up our search criteria and expected results: */
- values[0] = kSecClassIdentity; /* we want a certificate and a key */
- keys[0] = kSecClass;
- values[1] = kCFBooleanTrue; /* we want a reference */
- keys[1] = kSecReturnRef;
- values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
- * label matching below worked correctly */
- keys[2] = kSecMatchLimit;
- /* identity searches need a SecPolicyRef in order to work */
- values[3] = SecPolicyCreateSSL(FALSE, NULL);
- keys[3] = kSecMatchPolicy;
- /* match the name of the certificate (does not work in macOS 10.12.1) */
- values[4] = label_cf;
- keys[4] = kSecAttrLabel;
- query_dict = CFDictionaryCreate(NULL, (const void **)keys,
- (const void **)values, 5L,
- &kCFCopyStringDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFRelease(values[3]);
-
- /* Do we have a match? */
- status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
-
- /* Because kSecAttrLabel matching does not work with kSecClassIdentity,
- * we need to find the correct identity ourselves */
- if(status == noErr) {
- keys_list_count = CFArrayGetCount(keys_list);
- *out_cert_and_key = NULL;
- status = 1;
- for(i = 0; i < keys_list_count; i++) {
- OSStatus err = noErr;
- SecCertificateRef cert = NULL;
- const void *item = CFArrayGetValueAtIndex(keys_list, i);
- SecIdentityRef identity = (SecIdentityRef)CURL_UNCONST(item);
- err = SecIdentityCopyCertificate(identity, &cert);
- if(err == noErr) {
- CFStringRef common_name = NULL;
- OSStatus copy_status = noErr;
-#if CURL_BUILD_IOS
- common_name = SecCertificateCopySubjectSummary(cert);
-#elif CURL_BUILD_MAC_10_7
- copy_status = SecCertificateCopyCommonName(cert, &common_name);
-#endif
- if(copy_status == noErr &&
- CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
- CFRelease(cert);
- CFRelease(common_name);
- CFRetain(identity);
- *out_cert_and_key = identity;
- status = noErr;
- break;
- }
- if(common_name)
- CFRelease(common_name);
- }
- CFRelease(cert);
- }
- }
-
- if(keys_list)
- CFRelease(keys_list);
- CFRelease(query_dict);
- CFRelease(label_cf);
- }
- else {
-#if CURL_SUPPORT_MAC_10_6
- /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
- status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
-#endif /* CURL_SUPPORT_MAC_10_6 */
- }
-#elif CURL_SUPPORT_MAC_10_6
- /* For developers building on older cats, we have no choice but to fall back
- to SecKeychainSearch. */
- status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
-#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
- return status;
-}
-
-static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
- const struct curl_blob *blob,
- const char *cPassword,
- SecIdentityRef *out_cert_and_key)
-{
- OSStatus status = errSecItemNotFound;
- CFURLRef pkcs_url = NULL;
- CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
- cPassword, kCFStringEncodingUTF8) : NULL;
- CFDataRef pkcs_data = NULL;
-
- /* We can import P12 files on iOS or macOS 10.7 or later: */
- /* These constants are documented as having first appeared in 10.6 but they
- raise linker errors when used on that cat for some reason. */
-#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
- bool resource_imported;
-
- if(blob) {
- pkcs_data = CFDataCreate(kCFAllocatorDefault,
- (const unsigned char *)blob->data,
- (CFIndex)blob->len);
- status = (pkcs_data != NULL) ? errSecSuccess : errSecAllocate;
- resource_imported = (pkcs_data != NULL);
- }
- else {
- pkcs_url =
- CFURLCreateFromFileSystemRepresentation(NULL,
- (const UInt8 *)cPath,
- (CFIndex)strlen(cPath), FALSE);
- resource_imported =
- CFURLCreateDataAndPropertiesFromResource(NULL,
- pkcs_url, &pkcs_data,
- NULL, NULL, &status);
- }
-
- if(resource_imported) {
- CFArrayRef items = NULL;
-
- /* On iOS SecPKCS12Import will never add the client certificate to the
- * Keychain.
- *
- * It gives us back a SecIdentityRef that we can use directly. */
-#if CURL_BUILD_IOS
- const void *cKeys[] = {kSecImportExportPassphrase};
- const void *cValues[] = {password};
- CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
- password ? 1L : 0L, NULL, NULL);
-
- if(options) {
- status = SecPKCS12Import(pkcs_data, options, &items);
- CFRelease(options);
- }
-
-
- /* On macOS SecPKCS12Import will always add the client certificate to
- * the Keychain.
- *
- * As this does not match iOS, and apps may not want to see their client
- * certificate saved in the user's keychain, we use SecItemImport
- * with a NULL keychain to avoid importing it.
- *
- * This returns a SecCertificateRef from which we can construct a
- * SecIdentityRef.
- */
-#elif CURL_BUILD_MAC_10_7
- SecItemImportExportKeyParameters keyParams;
- SecExternalFormat inputFormat = kSecFormatPKCS12;
- SecExternalItemType inputType = kSecItemTypeCertificate;
-
- memset(&keyParams, 0x00, sizeof(keyParams));
- keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
- keyParams.passphrase = password;
-
- status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType,
- 0, &keyParams, NULL, &items);
-#endif
-
-
- /* Extract the SecIdentityRef */
- if(status == errSecSuccess && items && CFArrayGetCount(items)) {
- CFIndex i, count;
- count = CFArrayGetCount(items);
-
- for(i = 0; i < count; i++) {
- const CFTypeRef item = CFArrayGetValueAtIndex(items, i);
- CFTypeID itemID = CFGetTypeID(item);
-
- if(itemID == CFDictionaryGetTypeID()) {
- const CFTypeRef identity = CFDictionaryGetValue(
- (CFDictionaryRef)item,
- kSecImportItemIdentity);
- CFRetain(identity);
- *out_cert_and_key = (SecIdentityRef)CURL_UNCONST(identity);
- break;
- }
-#if CURL_BUILD_MAC_10_7
- else if(itemID == SecCertificateGetTypeID()) {
- status = SecIdentityCreateWithCertificate(NULL,
- (SecCertificateRef)CURL_UNCONST(item),
- out_cert_and_key);
- break;
- }
-#endif
- }
- }
-
- if(items)
- CFRelease(items);
- CFRelease(pkcs_data);
- }
-#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
- if(password)
- CFRelease(password);
- if(pkcs_url)
- CFRelease(pkcs_url);
- return status;
-}
-
-/* This code was borrowed from nss.c, with some modifications:
- * Determine whether the nickname passed in is a filename that needs to
- * be loaded as a PEM or a nickname.
- *
- * returns 1 for a file
- * returns 0 for not a file
- */
-CF_INLINE bool is_file(const char *filename)
-{
- struct_stat st;
-
- if(!filename)
- return FALSE;
-
- if(stat(filename, &st) == 0)
- return S_ISREG(st.st_mode);
- return FALSE;
-}
-
-static CURLcode
-sectransp_set_ssl_version_min_max(struct Curl_easy *data,
- struct st_ssl_backend_data *backend,
- struct ssl_primary_config *conn_config)
-{
-#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- OSStatus err;
- SSLProtocol ver_min;
- SSLProtocol ver_max;
-
-#if CURL_SUPPORT_MAC_10_7
- if(!&SSLSetProtocolVersionMax)
- goto legacy;
-#endif
-
- switch(conn_config->version) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_TLSv1_0:
- ver_min = kTLSProtocol1;
- break;
- case CURL_SSLVERSION_TLSv1_1:
- ver_min = kTLSProtocol11;
- break;
- case CURL_SSLVERSION_TLSv1_2:
- ver_min = kTLSProtocol12;
- break;
- case CURL_SSLVERSION_TLSv1_3:
- default:
- failf(data, "SSL: unsupported minimum TLS version value");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- switch(conn_config->version_max) {
- case CURL_SSLVERSION_MAX_DEFAULT:
- case CURL_SSLVERSION_MAX_NONE:
- case CURL_SSLVERSION_MAX_TLSv1_3:
- case CURL_SSLVERSION_MAX_TLSv1_2:
- ver_max = kTLSProtocol12;
- break;
- case CURL_SSLVERSION_MAX_TLSv1_1:
- ver_max = kTLSProtocol11;
- break;
- case CURL_SSLVERSION_MAX_TLSv1_0:
- ver_max = kTLSProtocol1;
- break;
- default:
- failf(data, "SSL: unsupported maximum TLS version value");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- err = SSLSetProtocolVersionMin(backend->ssl_ctx, ver_min);
- if(err != noErr) {
- failf(data, "SSL: failed to set minimum TLS version");
- return CURLE_SSL_CONNECT_ERROR;
- }
- err = SSLSetProtocolVersionMax(backend->ssl_ctx, ver_max);
- if(err != noErr) {
- failf(data, "SSL: failed to set maximum TLS version");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- return CURLE_OK;
-#endif
-#if CURL_SUPPORT_MAC_10_7
- goto legacy;
-legacy:
- switch(conn_config->version) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_TLSv1_0:
- break;
- default:
- failf(data, "SSL: unsupported minimum TLS version value");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- /* only TLS 1.0 is supported, disable SSL 3.0 and SSL 2.0 */
- SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, FALSE);
- SSLSetProtocolVersionEnabled(backend->ssl_ctx, kTLSProtocol1, TRUE);
-
- return CURLE_OK;
-#endif
-}
-
-static int sectransp_cipher_suite_get_str(uint16_t id, char *buf,
- size_t buf_size, bool prefer_rfc)
-{
- /* are these fortezza suites even supported ? */
- if(id == SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA)
- msnprintf(buf, buf_size, "%s", "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA");
- else if(id == SSL_FORTEZZA_DMS_WITH_NULL_SHA)
- msnprintf(buf, buf_size, "%s", "SSL_FORTEZZA_DMS_WITH_NULL_SHA");
- /* can TLS_EMPTY_RENEGOTIATION_INFO_SCSV even be set ? */
- else if(id == TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
- msnprintf(buf, buf_size, "%s", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
- /* do we still need to support these SSL2-only ciphers ? */
- else if(id == SSL_RSA_WITH_RC2_CBC_MD5)
- msnprintf(buf, buf_size, "%s", "SSL_RSA_WITH_RC2_CBC_MD5");
- else if(id == SSL_RSA_WITH_IDEA_CBC_MD5)
- msnprintf(buf, buf_size, "%s", "SSL_RSA_WITH_IDEA_CBC_MD5");
- else if(id == SSL_RSA_WITH_DES_CBC_MD5)
- msnprintf(buf, buf_size, "%s", "SSL_RSA_WITH_DES_CBC_MD5");
- else if(id == SSL_RSA_WITH_3DES_EDE_CBC_MD5)
- msnprintf(buf, buf_size, "%s", "SSL_RSA_WITH_3DES_EDE_CBC_MD5");
- else
- return Curl_cipher_suite_get_str(id, buf, buf_size, prefer_rfc);
- return 0;
-}
-
-static uint16_t sectransp_cipher_suite_walk_str(const char **str,
- const char **end)
-{
- uint16_t id = Curl_cipher_suite_walk_str(str, end);
- size_t len = *end - *str;
-
- if(!id) {
- /* are these fortezza suites even supported ? */
- if(strncasecompare("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA", *str, len))
- id = SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA;
- else if(strncasecompare("SSL_FORTEZZA_DMS_WITH_NULL_SHA", *str, len))
- id = SSL_FORTEZZA_DMS_WITH_NULL_SHA;
- /* can TLS_EMPTY_RENEGOTIATION_INFO_SCSV even be set ? */
- else if(strncasecompare("TLS_EMPTY_RENEGOTIATION_INFO_SCSV", *str, len))
- id = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
- /* do we still need to support these SSL2-only ciphers ? */
- else if(strncasecompare("SSL_RSA_WITH_RC2_CBC_MD5", *str, len))
- id = SSL_RSA_WITH_RC2_CBC_MD5;
- else if(strncasecompare("SSL_RSA_WITH_IDEA_CBC_MD5", *str, len))
- id = SSL_RSA_WITH_IDEA_CBC_MD5;
- else if(strncasecompare("SSL_RSA_WITH_DES_CBC_MD5", *str, len))
- id = SSL_RSA_WITH_DES_CBC_MD5;
- else if(strncasecompare("SSL_RSA_WITH_3DES_EDE_CBC_MD5", *str, len))
- id = SSL_RSA_WITH_3DES_EDE_CBC_MD5;
- }
- return id;
-}
-
-/* allocated memory must be freed */
-static SSLCipherSuite * sectransp_get_supported_ciphers(SSLContextRef ssl_ctx,
- size_t *len)
-{
- SSLCipherSuite *ciphers = NULL;
- OSStatus err = noErr;
- *len = 0;
-
- err = SSLGetNumberSupportedCiphers(ssl_ctx, len);
- if(err != noErr)
- goto failed;
-
- ciphers = malloc(*len * sizeof(SSLCipherSuite));
- if(!ciphers)
- goto failed;
-
- err = SSLGetSupportedCiphers(ssl_ctx, ciphers, len);
- if(err != noErr)
- goto failed;
-
-#if CURL_BUILD_MAC
- {
- int maj = 0, min = 0;
- GetDarwinVersionNumber(&maj, &min);
- /* There is a known bug in early versions of Mountain Lion where ST's ECC
- ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
- Work around the problem here by disabling those ciphers if we are
- running in an affected version of macOS. */
- if(maj == 12 && min <= 3) {
- size_t i = 0, j = 0;
- for(; i < *len; i++) {
- if(ciphers[i] >= 0xC001 && ciphers[i] <= 0xC032)
- continue;
- ciphers[j++] = ciphers[i];
- }
- *len = j;
- }
- }
-#endif
-
- return ciphers;
-failed:
- *len = 0;
- Curl_safefree(ciphers);
- return NULL;
-}
-
-static CURLcode sectransp_set_default_ciphers(struct Curl_easy *data,
- SSLContextRef ssl_ctx)
-{
- CURLcode ret = CURLE_SSL_CIPHER;
- size_t count = 0, i, j;
- OSStatus err;
- size_t supported_len;
- SSLCipherSuite *ciphers = NULL;
-
- ciphers = sectransp_get_supported_ciphers(ssl_ctx, &supported_len);
- if(!ciphers) {
- failf(data, "SSL: Failed to get supported ciphers");
- goto failed;
- }
-
- /* Intersect the ciphers supported by Secure Transport with the default
- * ciphers, using the order of the former. */
- for(i = 0; i < supported_len; i++) {
- for(j = 0; j < CURL_ARRAYSIZE(default_ciphers); j++) {
- if(default_ciphers[j] == ciphers[i]) {
- ciphers[count++] = ciphers[i];
- break;
- }
- }
- }
-
- if(count == 0) {
- failf(data, "SSL: no supported default ciphers");
- goto failed;
- }
-
- err = SSLSetEnabledCiphers(ssl_ctx, ciphers, count);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
- goto failed;
- }
-
- ret = CURLE_OK;
-failed:
- Curl_safefree(ciphers);
- return ret;
-}
-
-static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
- SSLContextRef ssl_ctx,
- const char *ciphers)
-{
- CURLcode ret = CURLE_SSL_CIPHER;
- size_t count = 0, i;
- const char *ptr, *end;
- OSStatus err;
- size_t supported_len;
- SSLCipherSuite *supported = NULL;
- SSLCipherSuite *selected = NULL;
-
- supported = sectransp_get_supported_ciphers(ssl_ctx, &supported_len);
- if(!supported) {
- failf(data, "SSL: Failed to get supported ciphers");
- goto failed;
- }
-
- selected = malloc(supported_len * sizeof(SSLCipherSuite));
- if(!selected) {
- failf(data, "SSL: Failed to allocate memory");
- goto failed;
- }
-
- for(ptr = ciphers; ptr[0] != '\0' && count < supported_len; ptr = end) {
- uint16_t id = sectransp_cipher_suite_walk_str(&ptr, &end);
-
- /* Check if cipher is supported */
- if(id) {
- for(i = 0; i < supported_len && supported[i] != id; i++);
- if(i == supported_len)
- id = 0;
- }
- if(!id) {
- if(ptr[0] != '\0')
- infof(data, "SSL: unknown cipher in list: \"%.*s\"", (int) (end - ptr),
- ptr);
- continue;
- }
-
- /* No duplicates allowed (so selected cannot overflow) */
- for(i = 0; i < count && selected[i] != id; i++);
- if(i < count) {
- infof(data, "SSL: duplicate cipher in list: \"%.*s\"", (int) (end - ptr),
- ptr);
- continue;
- }
-
- selected[count++] = id;
- }
-
- if(count == 0) {
- failf(data, "SSL: no supported cipher in list");
- goto failed;
- }
-
- err = SSLSetEnabledCiphers(ssl_ctx, selected, count);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
- goto failed;
- }
-
- ret = CURLE_OK;
-failed:
- Curl_safefree(supported);
- Curl_safefree(selected);
- return ret;
-}
-
-static void sectransp_session_free(void *sessionid)
-{
- /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
- cached session ID inside the Security framework. There is a private
- function that does this, but I do not want to have to explain to you why I
- got your application rejected from the App Store due to the use of a
- private API, so the best we can do is free up our own char array that we
- created way back in sectransp_connect_step1... */
- Curl_safefree(sessionid);
-}
-
-static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- const struct curl_blob *ssl_cablob = conn_config->ca_info_blob;
- const char * const ssl_cafile =
- /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
- (ssl_cablob ? NULL : conn_config->CAfile);
- const bool verifypeer = conn_config->verifypeer;
- char * const ssl_cert = ssl_config->primary.clientcert;
- const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
- char *ciphers;
- OSStatus err = noErr;
- CURLcode result;
-#if CURL_BUILD_MAC
- int darwinver_maj = 0, darwinver_min = 0;
-
- DEBUGASSERT(backend);
-
- CURL_TRC_CF(data, cf, "connect_step1");
- GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
-#endif /* CURL_BUILD_MAC */
-
-#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(&SSLCreateContext) { /* use the newer API if available */
- if(backend->ssl_ctx)
- CFRelease(backend->ssl_ctx);
- backend->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
- if(!backend->ssl_ctx) {
- failf(data, "SSL: could not create a context");
- return CURLE_OUT_OF_MEMORY;
- }
- }
- else {
- /* The old ST API does not exist under iOS, so do not compile it: */
-#if CURL_SUPPORT_MAC_10_8
- if(backend->ssl_ctx)
- (void)SSLDisposeContext(backend->ssl_ctx);
- err = SSLNewContext(FALSE, &(backend->ssl_ctx));
- if(err != noErr) {
- failf(data, "SSL: could not create a context: OSStatus %d", err);
- return CURLE_OUT_OF_MEMORY;
- }
-#endif /* CURL_SUPPORT_MAC_10_8 */
- }
-#else
- if(backend->ssl_ctx)
- (void)SSLDisposeContext(backend->ssl_ctx);
- err = SSLNewContext(FALSE, &(backend->ssl_ctx));
- if(err != noErr) {
- failf(data, "SSL: could not create a context: OSStatus %d", err);
- return CURLE_OUT_OF_MEMORY;
- }
-#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- backend->ssl_write_buffered_length = 0UL; /* reset buffered write length */
-
- result = sectransp_set_ssl_version_min_max(data, backend, conn_config);
- if(result != CURLE_OK)
- return result;
-
- if(connssl->alpn) {
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
-#ifdef HAVE_BUILTIN_AVAILABLE
- if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
-#else
- if(&SSLSetALPNProtocols && &SSLCopyALPNProtocols) {
-#endif
- struct alpn_proto_buf proto;
- size_t i;
- CFStringRef cstr;
- CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
- &kCFTypeArrayCallBacks);
- for(i = 0; i < connssl->alpn->count; ++i) {
- cstr = CFStringCreateWithCString(NULL, connssl->alpn->entries[i],
- kCFStringEncodingUTF8);
- if(!cstr)
- return CURLE_OUT_OF_MEMORY;
- CFArrayAppendValue(alpnArr, cstr);
- CFRelease(cstr);
- }
- err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
- if(err != noErr)
- infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d",
- err);
- CFRelease(alpnArr);
- Curl_alpn_to_proto_str(&proto, connssl->alpn);
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
- }
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
- }
-
- if(ssl_config->key) {
- infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
- "Transport. The private key must be in the Keychain.");
- }
-
- if(ssl_cert || ssl_cert_blob) {
- bool is_cert_data = ssl_cert_blob != NULL;
- bool is_cert_file = (!is_cert_data) && is_file(ssl_cert);
- SecIdentityRef cert_and_key = NULL;
-
- /* User wants to authenticate with a client cert. Look for it. Assume that
- the user wants to use an identity loaded from the Keychain. If not, try
- it as a file on disk */
-
- if(!is_cert_data)
- err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
- else
- err = !noErr;
- if((err != noErr) && (is_cert_file || is_cert_data)) {
- if(!ssl_config->cert_type)
- infof(data, "SSL: Certificate type not set, assuming "
- "PKCS#12 format.");
- else if(!strcasecompare(ssl_config->cert_type, "P12")) {
- failf(data, "SSL: The Security framework only supports "
- "loading identities that are in PKCS#12 format.");
- return CURLE_SSL_CERTPROBLEM;
- }
-
- err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob,
- ssl_config->key_passwd,
- &cert_and_key);
- }
-
- if(err == noErr && cert_and_key) {
- SecCertificateRef cert = NULL;
- CFTypeRef certs_c[1];
- CFArrayRef certs;
-
- /* If we found one, print it out: */
- err = SecIdentityCopyCertificate(cert_and_key, &cert);
- if(err == noErr) {
- char *certp;
- result = CopyCertSubject(data, cert, &certp);
- if(!result) {
- infof(data, "Client certificate: %s", certp);
- free(certp);
- }
-
- CFRelease(cert);
- if(result == CURLE_PEER_FAILED_VERIFICATION)
- return CURLE_SSL_CERTPROBLEM;
- if(result)
- return result;
- }
- certs_c[0] = cert_and_key;
- certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
- &kCFTypeArrayCallBacks);
- err = SSLSetCertificate(backend->ssl_ctx, certs);
- if(certs)
- CFRelease(certs);
- if(err != noErr) {
- failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
- return CURLE_SSL_CERTPROBLEM;
- }
- CFRelease(cert_and_key);
- }
- else {
- const char *cert_showfilename_error =
- is_cert_data ? "(memory blob)" : ssl_cert;
-
- switch(err) {
- case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
- failf(data, "SSL: Incorrect password for the certificate \"%s\" "
- "and its private key.", cert_showfilename_error);
- break;
- case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
- failf(data, "SSL: Couldn't make sense of the data in the "
- "certificate \"%s\" and its private key.",
- cert_showfilename_error);
- break;
- case -25260: /* errSecPassphraseRequired */
- failf(data, "SSL The certificate \"%s\" requires a password.",
- cert_showfilename_error);
- break;
- case errSecItemNotFound:
- failf(data, "SSL: cannot find the certificate \"%s\" and its private "
- "key in the Keychain.", cert_showfilename_error);
- break;
- default:
- failf(data, "SSL: cannot load the certificate \"%s\" and its private "
- "key: OSStatus %d", cert_showfilename_error, err);
- break;
- }
- return CURLE_SSL_CERTPROBLEM;
- }
- }
-
- /* SSL always tries to verify the peer, this only says whether it should
- * fail to connect if the verification fails, or if it should continue
- * anyway. In the latter case the result of the verification is checked with
- * SSL_get_verify_result() below. */
-#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
- /* Snow Leopard introduced the SSLSetSessionOption() function, but due to
- a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
- works, it does not work as expected under Snow Leopard, Lion or
- Mountain Lion.
- So we need to call SSLSetEnableCertVerify() on those older cats in order
- to disable certificate validation if the user turned that off.
- (Secure Transport always validates the certificate chain by default.)
- Note:
- Darwin 11.x.x is Lion (10.7)
- Darwin 12.x.x is Mountain Lion (10.8)
- Darwin 13.x.x is Mavericks (10.9)
- Darwin 14.x.x is Yosemite (10.10)
- Darwin 15.x.x is El Capitan (10.11)
- */
-#if CURL_BUILD_MAC
- if(&SSLSetSessionOption && darwinver_maj >= 13) {
-#else
- if(&SSLSetSessionOption) {
-#endif /* CURL_BUILD_MAC */
- bool break_on_auth = !conn_config->verifypeer ||
- ssl_cafile || ssl_cablob;
- err = SSLSetSessionOption(backend->ssl_ctx,
- kSSLSessionOptionBreakOnServerAuth,
- break_on_auth);
- if(err != noErr) {
- failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
- else {
-#if CURL_SUPPORT_MAC_10_8
- err = SSLSetEnableCertVerify(backend->ssl_ctx,
- conn_config->verifypeer ? true : FALSE);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
-#endif /* CURL_SUPPORT_MAC_10_8 */
- }
-#else
- err = SSLSetEnableCertVerify(backend->ssl_ctx,
- conn_config->verifypeer ? true : FALSE);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
-#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
-
- if((ssl_cafile || ssl_cablob) && verifypeer) {
- bool is_cert_data = ssl_cablob != NULL;
- bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile);
-
- if(!(is_cert_file || is_cert_data)) {
- failf(data, "SSL: cannot load CA certificate file %s",
- ssl_cafile ? ssl_cafile : "(blob memory)");
- return CURLE_SSL_CACERT_BADFILE;
- }
- }
-
- /* Configure hostname check. SNI is used if available.
- * Both hostname check and SNI require SSLSetPeerDomainName().
- * Also: the verifyhost setting influences SNI usage */
- if(conn_config->verifyhost) {
- char *server = connssl->peer.sni ?
- connssl->peer.sni : connssl->peer.hostname;
- err = SSLSetPeerDomainName(backend->ssl_ctx, server, strlen(server));
-
- if(err != noErr) {
- failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
- err);
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- if(connssl->peer.type != CURL_SSL_PEER_DNS) {
- infof(data, "WARNING: using IP address, SNI is being disabled by "
- "the OS.");
- }
- }
- else {
- infof(data, "WARNING: disabling hostname validation also disables SNI.");
- }
-
- ciphers = conn_config->cipher_list;
- if(ciphers) {
- result = sectransp_set_selected_ciphers(data, backend->ssl_ctx, ciphers);
- }
- else {
- result = sectransp_set_default_ciphers(data, backend->ssl_ctx);
- }
- if(result != CURLE_OK) {
- failf(data, "SSL: Unable to set ciphers for SSL/TLS handshake. "
- "Error code: %d", (int)result);
- return CURLE_SSL_CIPHER;
- }
-
-#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
- /* We want to enable 1/n-1 when using a CBC cipher unless the user
- specifically does not want us doing that: */
- if(&SSLSetSessionOption) {
- SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
- !ssl_config->enable_beast);
- SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart,
- ssl_config->falsestart); /* false start support */
- }
-#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
-
- /* Check if there is a cached ID we can/should use here! */
- if(ssl_config->primary.cache_session) {
- char *ssl_sessionid;
- size_t ssl_sessionid_len;
-
- Curl_ssl_scache_lock(data);
- ssl_sessionid = Curl_ssl_scache_get_obj(cf, data,
- connssl->peer.scache_key);
- if(ssl_sessionid) {
- /* we got a session id, use it! */
- err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid,
- strlen(ssl_sessionid));
- Curl_ssl_scache_unlock(data);
- if(err != noErr) {
- failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- else
- infof(data, "SSL reusing session ID");
- }
- /* If there is not one, then let's make one up! This has to be done prior
- to starting the handshake. */
- else {
- ssl_sessionid =
- aprintf("%s:%d:%d:%s:%d",
- ssl_cafile ? ssl_cafile : "(blob memory)",
- verifypeer, conn_config->verifyhost, connssl->peer.hostname,
- connssl->peer.port);
- ssl_sessionid_len = strlen(ssl_sessionid);
-
- err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
- if(err != noErr) {
- Curl_ssl_scache_unlock(data);
- failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- /* This is all a bit weird, as we have not handshaked yet.
- * I hope this backend will go away soon. */
- result = Curl_ssl_scache_add_obj(cf, data, connssl->peer.scache_key,
- (void *)ssl_sessionid,
- sectransp_session_free);
- Curl_ssl_scache_unlock(data);
- if(result)
- return result;
- }
- }
-
- err = SSLSetIOFuncs(backend->ssl_ctx,
- sectransp_bio_cf_in_read,
- sectransp_bio_cf_out_write);
- if(err != noErr) {
- failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- err = SSLSetConnection(backend->ssl_ctx, cf);
- if(err != noErr) {
- failf(data, "SSL: SSLSetConnection() failed: %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- connssl->connecting_state = ssl_connect_2;
- return CURLE_OK;
-}
-
-static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
-{
- char *sep_start, *sep_end, *cert_start, *cert_end;
- size_t i, j, err;
- size_t len;
- char *b64;
-
- /* Jump through the separators at the beginning of the certificate. */
- sep_start = strstr(in, "-----");
- if(!sep_start)
- return 0;
- cert_start = strstr(sep_start + 1, "-----");
- if(!cert_start)
- return -1;
-
- cert_start += 5;
-
- /* Find separator after the end of the certificate. */
- cert_end = strstr(cert_start, "-----");
- if(!cert_end)
- return -1;
-
- sep_end = strstr(cert_end + 1, "-----");
- if(!sep_end)
- return -1;
- sep_end += 5;
-
- len = cert_end - cert_start;
- b64 = malloc(len + 1);
- if(!b64)
- return -1;
-
- /* Create base64 string without linefeeds. */
- for(i = 0, j = 0; i < len; i++) {
- if(cert_start[i] != '\r' && cert_start[i] != '\n')
- b64[j++] = cert_start[i];
- }
- b64[j] = '\0';
-
- err = curlx_base64_decode((const char *)b64, out, outlen);
- free(b64);
- if(err) {
- free(*out);
- return -1;
- }
-
- return sep_end - in;
-}
-
-#define MAX_CERTS_SIZE (50*1024*1024) /* arbitrary - to catch mistakes */
-
-static int read_cert(const char *file, unsigned char **out, size_t *outlen)
-{
- int fd;
- ssize_t n;
- unsigned char buf[512];
- struct dynbuf certs;
-
- curlx_dyn_init(&certs, MAX_CERTS_SIZE);
-
- fd = open(file, 0);
- if(fd < 0)
- return -1;
-
- for(;;) {
- n = read(fd, buf, sizeof(buf));
- if(!n)
- break;
- if(n < 0) {
- close(fd);
- curlx_dyn_free(&certs);
- return -1;
- }
- if(curlx_dyn_addn(&certs, buf, n)) {
- close(fd);
- return -1;
- }
- }
- close(fd);
-
- *out = curlx_dyn_uptr(&certs);
- *outlen = curlx_dyn_len(&certs);
-
- return 0;
-}
-
-static CURLcode append_cert_to_array(struct Curl_easy *data,
- const unsigned char *buf, size_t buflen,
- CFMutableArrayRef array)
-{
- char *certp;
- CURLcode result;
- SecCertificateRef cacert;
- CFDataRef certdata;
-
- certdata = CFDataCreate(kCFAllocatorDefault, buf, (CFIndex)buflen);
- if(!certdata) {
- failf(data, "SSL: failed to allocate array for CA certificate");
- return CURLE_OUT_OF_MEMORY;
- }
-
- cacert = SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
- CFRelease(certdata);
- if(!cacert) {
- failf(data, "SSL: failed to create SecCertificate from CA certificate");
- return CURLE_SSL_CACERT_BADFILE;
- }
-
- /* Check if cacert is valid. */
- result = CopyCertSubject(data, cacert, &certp);
- switch(result) {
- case CURLE_OK:
- break;
- case CURLE_PEER_FAILED_VERIFICATION:
- CFRelease(cacert);
- return CURLE_SSL_CACERT_BADFILE;
- case CURLE_OUT_OF_MEMORY:
- default:
- CFRelease(cacert);
- return result;
- }
- free(certp);
-
- CFArrayAppendValue(array, cacert);
- CFRelease(cacert);
-
- return CURLE_OK;
-}
-
-static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const unsigned char *certbuf, size_t buflen,
- SSLContextRef ctx)
-{
- int n = 0;
- CURLcode rc;
- long res;
- unsigned char *der;
- size_t derlen, offset = 0;
- OSStatus ret;
- SecTrustResultType trust_eval;
- CFMutableArrayRef array = NULL;
- SecTrustRef trust = NULL;
- CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
- (void)cf;
- /*
- * Certbuf now contains the contents of the certificate file, which can be
- * - a single DER certificate,
- * - a single PEM certificate or
- * - a bunch of PEM certificates (certificate bundle).
- *
- * Go through certbuf, and convert any PEM certificate in it into DER
- * format.
- */
- array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
- if(!array) {
- failf(data, "SSL: out of memory creating CA certificate array");
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- while(offset < buflen) {
- n++;
-
- /*
- * Check if the certificate is in PEM format, and convert it to DER. If
- * this fails, we assume the certificate is in DER format.
- */
- res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
- if(res < 0) {
- failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
- n, offset);
- result = CURLE_SSL_CACERT_BADFILE;
- goto out;
- }
- offset += res;
-
- if(res == 0 && offset == 0) {
- /* This is not a PEM file, probably a certificate in DER format. */
- rc = append_cert_to_array(data, certbuf, buflen, array);
- if(rc != CURLE_OK) {
- CURL_TRC_CF(data, cf, "append_cert for CA failed");
- result = rc;
- goto out;
- }
- break;
- }
- else if(res == 0) {
- /* No more certificates in the bundle. */
- break;
- }
-
- rc = append_cert_to_array(data, der, derlen, array);
- free(der);
- if(rc != CURLE_OK) {
- CURL_TRC_CF(data, cf, "append_cert for CA failed");
- result = rc;
- goto out;
- }
- }
-
- ret = SSLCopyPeerTrust(ctx, &trust);
- if(!trust) {
- failf(data, "SSL: error getting certificate chain");
- goto out;
- }
- else if(ret != noErr) {
- failf(data, "SSLCopyPeerTrust() returned error %d", ret);
- goto out;
- }
-
- CURL_TRC_CF(data, cf, "setting %d trust anchors", n);
- ret = SecTrustSetAnchorCertificates(trust, array);
- if(ret != noErr) {
- failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
- goto out;
- }
- ret = SecTrustSetAnchorCertificatesOnly(trust, TRUE);
- if(ret != noErr) {
- failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
- goto out;
- }
-
- trust_eval = 0;
- ret = SecTrustEvaluate(trust, &trust_eval);
- if(ret != noErr) {
- failf(data, "SecTrustEvaluate() returned error %d", ret);
- goto out;
- }
-
- switch(trust_eval) {
- case kSecTrustResultUnspecified:
- /* what does this really mean? */
- CURL_TRC_CF(data, cf, "trust result: Unspecified");
- result = CURLE_OK;
- goto out;
- case kSecTrustResultProceed:
- CURL_TRC_CF(data, cf, "trust result: Proceed");
- result = CURLE_OK;
- goto out;
-
- case kSecTrustResultRecoverableTrustFailure:
- failf(data, "SSL: peer not verified: RecoverableTrustFailure");
- goto out;
- case kSecTrustResultDeny:
- failf(data, "SSL: peer not verified: Deny");
- goto out;
- default:
- failf(data, "SSL: perr not verified: result=%d", trust_eval);
- goto out;
- }
-
-out:
- if(trust)
- CFRelease(trust);
- if(array)
- CFRelease(array);
- return result;
-}
-
-static CURLcode verify_cert(struct Curl_cfilter *cf,
- struct Curl_easy *data, const char *cafile,
- const struct curl_blob *ca_info_blob,
- SSLContextRef ctx)
-{
- CURLcode result;
- unsigned char *certbuf;
- size_t buflen;
- bool free_certbuf = FALSE;
-
- if(ca_info_blob) {
- CURL_TRC_CF(data, cf, "verify_peer, CA from config blob");
- certbuf = ca_info_blob->data;
- buflen = ca_info_blob->len;
- }
- else if(cafile) {
- CURL_TRC_CF(data, cf, "verify_peer, CA from file '%s'", cafile);
- if(read_cert(cafile, &certbuf, &buflen) < 0) {
- failf(data, "SSL: failed to read or invalid CA certificate");
- return CURLE_SSL_CACERT_BADFILE;
- }
- free_certbuf = TRUE;
- }
- else
- return CURLE_SSL_CACERT_BADFILE;
-
- result = verify_cert_buf(cf, data, certbuf, buflen, ctx);
- if(free_certbuf)
- free(certbuf);
- return result;
-}
-
-
-#ifdef SECTRANSP_PINNEDPUBKEY
-static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
- SSLContextRef ctx,
- const char *pinnedpubkey)
-{ /* Scratch */
- size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
- const unsigned char *pubkey = NULL;
- unsigned char *realpubkey = NULL;
- const unsigned char *spkiHeader = NULL;
- CFDataRef publicKeyBits = NULL;
-
- /* Result is returned to caller */
- CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-
- /* if a path was not specified, do not pin */
- if(!pinnedpubkey)
- return CURLE_OK;
-
-
- if(!ctx)
- return result;
-
- do {
- SecTrustRef trust;
- OSStatus ret;
- SecKeyRef keyRef;
-
- ret = SSLCopyPeerTrust(ctx, &trust);
- if(ret != noErr || !trust)
- break;
-
- keyRef = SecTrustCopyPublicKey(trust);
- CFRelease(trust);
- if(!keyRef)
- break;
-
-#ifdef SECTRANSP_PINNEDPUBKEY_V1
-
- publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
- CFRelease(keyRef);
- if(!publicKeyBits)
- break;
-
-#elif SECTRANSP_PINNEDPUBKEY_V2
-
- {
- OSStatus success;
- success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
- &publicKeyBits);
- CFRelease(keyRef);
- if(success != errSecSuccess || !publicKeyBits)
- break;
- }
-
-#endif /* SECTRANSP_PINNEDPUBKEY_V2 */
-
- pubkeylen = (size_t)CFDataGetLength(publicKeyBits);
- pubkey = (const unsigned char *)CFDataGetBytePtr(publicKeyBits);
-
- switch(pubkeylen) {
- case 526:
- /* 4096 bit RSA pubkeylen == 526 */
- spkiHeader = rsa4096SpkiHeader;
- break;
- case 270:
- /* 2048 bit RSA pubkeylen == 270 */
- spkiHeader = rsa2048SpkiHeader;
- break;
-#ifdef SECTRANSP_PINNEDPUBKEY_V1
- case 65:
- /* ecDSA secp256r1 pubkeylen == 65 */
- spkiHeader = ecDsaSecp256r1SpkiHeader;
- spkiHeaderLength = 26;
- break;
- case 97:
- /* ecDSA secp384r1 pubkeylen == 97 */
- spkiHeader = ecDsaSecp384r1SpkiHeader;
- spkiHeaderLength = 23;
- break;
- default:
- infof(data, "SSL: unhandled public key length: %zu", pubkeylen);
-#elif SECTRANSP_PINNEDPUBKEY_V2
- default:
- /* ecDSA secp256r1 pubkeylen == 91 header already included?
- * ecDSA secp384r1 header already included too
- * we assume rest of algorithms do same, so do nothing
- */
- result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
- pubkeylen);
-#endif /* SECTRANSP_PINNEDPUBKEY_V2 */
- continue; /* break from loop */
- }
-
- realpubkeylen = pubkeylen + spkiHeaderLength;
- realpubkey = malloc(realpubkeylen);
- if(!realpubkey)
- break;
-
- memcpy(realpubkey, spkiHeader, spkiHeaderLength);
- memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
-
- result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
- realpubkeylen);
-
- } while(0);
-
- Curl_safefree(realpubkey);
- if(publicKeyBits)
- CFRelease(publicKeyBits);
-
- return result;
-}
-#endif /* SECTRANSP_PINNEDPUBKEY */
-
-static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- OSStatus err;
- SSLCipherSuite cipher;
- SSLProtocol protocol = 0;
-
- DEBUGASSERT(ssl_connect_2 == connssl->connecting_state);
- DEBUGASSERT(backend);
- CURL_TRC_CF(data, cf, "connect_step2");
-
- /* Here goes nothing: */
-check_handshake:
- connssl->io_need = CURL_SSL_IO_NEED_NONE;
- err = SSLHandshake(backend->ssl_ctx);
-
- if(err != noErr) {
- switch(err) {
- case errSSLWouldBlock: /* they are not done with us yet */
- connssl->io_need = backend->ssl_direction ?
- CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
- return CURLE_OK;
-
- /* The below is errSSLServerAuthCompleted; it is not defined in
- Leopard's headers */
- case -9841:
- if((conn_config->CAfile || conn_config->ca_info_blob) &&
- conn_config->verifypeer) {
- CURLcode result = verify_cert(cf, data, conn_config->CAfile,
- conn_config->ca_info_blob,
- backend->ssl_ctx);
- if(result)
- return result;
- }
- /* the documentation says we need to call SSLHandshake() again */
- goto check_handshake;
-
- /* Problem with encrypt / decrypt */
- case errSSLPeerDecodeError:
- failf(data, "Decode failed");
- break;
- case errSSLDecryptionFail:
- case errSSLPeerDecryptionFail:
- failf(data, "Decryption failed");
- break;
- case errSSLPeerDecryptError:
- failf(data, "A decryption error occurred");
- break;
- case errSSLBadCipherSuite:
- failf(data, "A bad SSL cipher suite was encountered");
- break;
- case errSSLCrypto:
- failf(data, "An underlying cryptographic error was encountered");
- break;
-#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
- case errSSLWeakPeerEphemeralDHKey:
- failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
- break;
-#endif
-
- /* Problem with the message record validation */
- case errSSLBadRecordMac:
- case errSSLPeerBadRecordMac:
- failf(data, "A record with a bad message authentication code (MAC) "
- "was encountered");
- break;
- case errSSLRecordOverflow:
- case errSSLPeerRecordOverflow:
- failf(data, "A record overflow occurred");
- break;
-
- /* Problem with zlib decompression */
- case errSSLPeerDecompressFail:
- failf(data, "Decompression failed");
- break;
-
- /* Problem with access */
- case errSSLPeerAccessDenied:
- failf(data, "Access was denied");
- break;
- case errSSLPeerInsufficientSecurity:
- failf(data, "There is insufficient security for this operation");
- break;
-
- /* These are all certificate problems with the server: */
- case errSSLXCertChainInvalid:
- failf(data, "SSL certificate problem: Invalid certificate chain");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLUnknownRootCert:
- failf(data, "SSL certificate problem: Untrusted root certificate");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLNoRootCert:
- failf(data, "SSL certificate problem: No root certificate");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLCertNotYetValid:
- failf(data, "SSL certificate problem: The certificate chain had a "
- "certificate that is not yet valid");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLCertExpired:
- case errSSLPeerCertExpired:
- failf(data, "SSL certificate problem: Certificate chain had an "
- "expired certificate");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLBadCert:
- case errSSLPeerBadCert:
- failf(data, "SSL certificate problem: Couldn't understand the server "
- "certificate format");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLPeerUnsupportedCert:
- failf(data, "SSL certificate problem: An unsupported certificate "
- "format was encountered");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLPeerCertRevoked:
- failf(data, "SSL certificate problem: The certificate was revoked");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLPeerCertUnknown:
- failf(data, "SSL certificate problem: The certificate is unknown");
- return CURLE_PEER_FAILED_VERIFICATION;
-
- /* These are all certificate problems with the client: */
- case errSecAuthFailed:
- failf(data, "SSL authentication failed");
- break;
- case errSSLPeerHandshakeFail:
- failf(data, "SSL peer handshake failed, the server most likely "
- "requires a client certificate to connect");
- break;
- case errSSLPeerUnknownCA:
- failf(data, "SSL server rejected the client certificate due to "
- "the certificate being signed by an unknown certificate "
- "authority");
- break;
-
- /* This error is raised if the server's cert did not match the server's
- hostname: */
- case errSSLHostNameMismatch:
- failf(data, "SSL certificate peer verification failed, the "
- "certificate did not match \"%s\"\n", connssl->peer.dispname);
- return CURLE_PEER_FAILED_VERIFICATION;
-
- /* Problem with SSL / TLS negotiation */
- case errSSLNegotiation:
- failf(data, "Could not negotiate an SSL cipher suite with the server");
- break;
- case errSSLBadConfiguration:
- failf(data, "A configuration error occurred");
- break;
- case errSSLProtocol:
- failf(data, "SSL protocol error");
- break;
- case errSSLPeerProtocolVersion:
- failf(data, "A bad protocol version was encountered");
- break;
- case errSSLPeerNoRenegotiation:
- failf(data, "No renegotiation is allowed");
- break;
-
- /* Generic handshake errors: */
- case errSSLConnectionRefused:
- failf(data, "Server dropped the connection during the SSL handshake");
- break;
- case errSSLClosedAbort:
- failf(data, "Server aborted the SSL handshake");
- break;
- case errSSLClosedGraceful:
- failf(data, "The connection closed gracefully");
- break;
- case errSSLClosedNoNotify:
- failf(data, "The server closed the session with no notification");
- break;
- /* Sometimes paramErr happens with buggy ciphers: */
- case paramErr:
- case errSSLInternal:
- case errSSLPeerInternalError:
- failf(data, "Internal SSL engine error encountered during the "
- "SSL handshake");
- break;
- case errSSLFatalAlert:
- failf(data, "Fatal SSL engine error encountered during the SSL "
- "handshake");
- break;
- /* Unclassified error */
- case errSSLBufferOverflow:
- failf(data, "An insufficient buffer was provided");
- break;
- case errSSLIllegalParam:
- failf(data, "An illegal parameter was encountered");
- break;
- case errSSLModuleAttach:
- failf(data, "Module attach failure");
- break;
- case errSSLSessionNotFound:
- failf(data, "An attempt to restore an unknown session failed");
- break;
- case errSSLPeerExportRestriction:
- failf(data, "An export restriction occurred");
- break;
- case errSSLPeerUserCancelled:
- failf(data, "The user canceled the operation");
- break;
- case errSSLPeerUnexpectedMsg:
- failf(data, "Peer rejected unexpected message");
- break;
-#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
- /* Treating non-fatal error as fatal like before */
- case errSSLClientHelloReceived:
- failf(data, "A non-fatal result for providing a server name "
- "indication");
- break;
-#endif
-
- /* Error codes defined in the enum but should never be returned.
- We list them here just in case. */
-#if CURL_BUILD_MAC_10_6
- /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
- case errSSLClientCertRequested:
- failf(data, "Server requested a client certificate during the "
- "handshake");
- return CURLE_SSL_CLIENTCERT;
-#endif
-#if CURL_BUILD_MAC_10_9
- /* Alias for errSSLLast, end of error range */
- case errSSLUnexpectedRecord:
- failf(data, "Unexpected (skipped) record in DTLS");
- break;
-#endif
- default:
- /* May also return codes listed in Security Framework Result Codes */
- failf(data, "Unknown SSL protocol error in connection to %s:%d",
- connssl->peer.hostname, err);
- break;
- }
- return CURLE_SSL_CONNECT_ERROR;
- }
- else {
- char cipher_str[64];
- /* we have been connected fine, we are not waiting for anything else. */
- connssl->connecting_state = ssl_connect_3;
-
-#ifdef SECTRANSP_PINNEDPUBKEY
- if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
- CURLcode result =
- pkp_pin_peer_pubkey(data, backend->ssl_ctx,
- data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
- if(result) {
- failf(data, "SSL: public key does not match pinned public key");
- return result;
- }
- }
-#endif /* SECTRANSP_PINNEDPUBKEY */
-
- /* Informational message */
- (void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher);
- (void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol);
-
- sectransp_cipher_suite_get_str((uint16_t) cipher, cipher_str,
- sizeof(cipher_str), TRUE);
- switch(protocol) {
- case kSSLProtocol2:
- infof(data, "SSL 2.0 connection using %s", cipher_str);
- break;
- case kSSLProtocol3:
- infof(data, "SSL 3.0 connection using %s", cipher_str);
- break;
- case kTLSProtocol1:
- infof(data, "TLS 1.0 connection using %s", cipher_str);
- break;
-#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- case kTLSProtocol11:
- infof(data, "TLS 1.1 connection using %s", cipher_str);
- break;
- case kTLSProtocol12:
- infof(data, "TLS 1.2 connection using %s", cipher_str);
- break;
-#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
- case kTLSProtocol13:
- infof(data, "TLS 1.3 connection using %s", cipher_str);
- break;
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
- default:
- infof(data, "Unknown protocol connection");
- break;
- }
-
- if(connssl->alpn) {
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
-#ifdef HAVE_BUILTIN_AVAILABLE
- if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
-#else
- if(&SSLSetALPNProtocols && &SSLCopyALPNProtocols) {
-#endif
- CFArrayRef alpnArr = NULL;
- CFStringRef chosenProtocol = NULL;
- err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr);
-
- if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
- chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
-
-#ifdef USE_HTTP2
- if(chosenProtocol &&
- !CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
- cf->conn->alpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(chosenProtocol &&
- !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
- cf->conn->alpn = CURL_HTTP_VERSION_1_1;
- }
- else
- infof(data, VTLS_INFOF_NO_ALPN);
-
- /* chosenProtocol is a reference to the string within alpnArr
- and does not need to be freed separately */
- if(alpnArr)
- CFRelease(alpnArr);
- }
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
- }
-
- return CURLE_OK;
- }
-}
-
-static CURLcode
-add_cert_to_certinfo(struct Curl_easy *data,
- const SecCertificateRef server_cert,
- int idx)
-{
- CURLcode result = CURLE_OK;
- const char *beg;
- const char *end;
- CFDataRef cert_data = SecCertificateCopyData(server_cert);
-
- if(!cert_data)
- return CURLE_PEER_FAILED_VERIFICATION;
-
- beg = (const char *)CFDataGetBytePtr(cert_data);
- end = beg + CFDataGetLength(cert_data);
- result = Curl_extract_certinfo(data, idx, beg, end);
- CFRelease(cert_data);
- return result;
-}
-
-static CURLcode
-collect_server_cert_single(struct Curl_cfilter *cf, struct Curl_easy *data,
- const SecCertificateRef server_cert,
- CFIndex idx)
-{
- CURLcode result = CURLE_OK;
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- if(data->set.verbose) {
- char *certp;
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s", certp);
- free(certp);
- }
- }
-#endif
- if(ssl_config->certinfo)
- result = add_cert_to_certinfo(data, server_cert, (int)idx);
- return result;
-}
-
-/* This should be called during step3 of the connection at the earliest */
-static CURLcode collect_server_cert(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- const bool show_verbose_server_cert = data->set.verbose;
-#else
- const bool show_verbose_server_cert = FALSE;
-#endif
- struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- CURLcode result = ssl_config->certinfo ?
- CURLE_PEER_FAILED_VERIFICATION : CURLE_OK;
- struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- CFArrayRef server_certs = NULL;
- SecCertificateRef server_cert;
- OSStatus err;
- CFIndex i, count;
- SecTrustRef trust = NULL;
-
- DEBUGASSERT(backend);
-
- if(!show_verbose_server_cert && !ssl_config->certinfo)
- return CURLE_OK;
-
- if(!backend->ssl_ctx)
- return result;
-
-#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
-#if CURL_BUILD_IOS
-#pragma unused(server_certs)
- err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
- /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
- a null trust, so be on guard for that: */
- if(err == noErr && trust) {
- count = SecTrustGetCertificateCount(trust);
- if(ssl_config->certinfo)
- result = Curl_ssl_init_certinfo(data, (int)count);
- for(i = 0L ; !result && (i < count) ; i++) {
- server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = collect_server_cert_single(cf, data, server_cert, i);
- }
- CFRelease(trust);
- }
-#else
- /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion.
- The function SecTrustGetCertificateAtIndex() is officially present
- in Lion, but it is unfortunately also present in Snow Leopard as
- private API and does not work as expected. So we have to look for
- a different symbol to make sure this code is only executed under
- Lion or later. */
- if(&SecTrustCopyPublicKey) {
-#pragma unused(server_certs)
- err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
- /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
- a null trust, so be on guard for that: */
- if(err == noErr && trust) {
- count = SecTrustGetCertificateCount(trust);
- if(ssl_config->certinfo)
- result = Curl_ssl_init_certinfo(data, (int)count);
- for(i = 0L ; !result && (i < count) ; i++) {
- server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = collect_server_cert_single(cf, data, server_cert, i);
- }
- CFRelease(trust);
- }
- }
- else {
-#if CURL_SUPPORT_MAC_10_8
- err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
- /* Just in case SSLCopyPeerCertificates() returns null too... */
- if(err == noErr && server_certs) {
- count = CFArrayGetCount(server_certs);
- if(ssl_config->certinfo)
- result = Curl_ssl_init_certinfo(data, (int)count);
- for(i = 0L ; !result && (i < count) ; i++) {
- const void *item = CFArrayGetValueAtIndex(server_certs, i);
- server_cert = (SecCertificateRef)CURL_UNCONST(item);
- result = collect_server_cert_single(cf, data, server_cert, i);
- }
- CFRelease(server_certs);
- }
-#endif /* CURL_SUPPORT_MAC_10_8 */
- }
-#endif /* CURL_BUILD_IOS */
-#else
-#pragma unused(trust)
- err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
- if(err == noErr) {
- count = CFArrayGetCount(server_certs);
- if(ssl_config->certinfo)
- result = Curl_ssl_init_certinfo(data, (int)count);
- for(i = 0L ; !result && (i < count) ; i++) {
- const void *item = CFArrayGetValueAtIndex(server_certs, i);
- server_cert = (SecCertificateRef)CURL_UNCONST(item);
- result = collect_server_cert_single(cf, data, server_cert, i);
- }
- CFRelease(server_certs);
- }
-#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
- return result;
-}
-
-static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- CURLcode result;
-
- CURL_TRC_CF(data, cf, "connect_step3");
- /* There is no step 3!
- * Well, okay, let's collect server certificates, and if verbose mode is on,
- * let's print the details of the server certificates. */
- result = collect_server_cert(cf, data);
- if(result)
- return result;
-
- connssl->connecting_state = ssl_connect_done;
- return CURLE_OK;
-}
-
-static CURLcode sectransp_connect(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool *done)
-{
- CURLcode result;
- struct ssl_connect_data *connssl = cf->ctx;
-
- /* check if the connection has already been established */
- if(ssl_connection_complete == connssl->state) {
- *done = TRUE;
- return CURLE_OK;
- }
-
- *done = FALSE;
- connssl->io_need = CURL_SSL_IO_NEED_NONE;
-
- if(ssl_connect_1 == connssl->connecting_state) {
- result = sectransp_connect_step1(cf, data);
- if(result)
- return result;
- }
-
- if(ssl_connect_2 == connssl->connecting_state) {
- result = sectransp_connect_step2(cf, data);
- if(result)
- return result;
- }
-
- if(ssl_connect_3 == connssl->connecting_state) {
- result = sectransp_connect_step3(cf, data);
- if(result)
- return result;
- }
-
- if(ssl_connect_done == connssl->connecting_state) {
- CURL_TRC_CF(data, cf, "connected");
- connssl->state = ssl_connection_complete;
- *done = TRUE;
- }
-
- return CURLE_OK;
-}
-
-static ssize_t sectransp_recv(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- char *buf,
- size_t buffersize,
- CURLcode *curlcode);
-
-static CURLcode sectransp_shutdown(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- bool send_shutdown, bool *done)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- CURLcode result = CURLE_OK;
- ssize_t nread = 0;
- char buf[1024];
- size_t i;
-
- DEBUGASSERT(backend);
- if(!backend->ssl_ctx || cf->shutdown) {
- *done = TRUE;
- goto out;
- }
-
- connssl->io_need = CURL_SSL_IO_NEED_NONE;
- *done = FALSE;
-
- if(send_shutdown && !backend->sent_shutdown) {
- OSStatus err;
-
- CURL_TRC_CF(data, cf, "shutdown, send close notify");
- err = SSLClose(backend->ssl_ctx);
- switch(err) {
- case noErr:
- backend->sent_shutdown = TRUE;
- break;
- case errSSLWouldBlock:
- connssl->io_need = CURL_SSL_IO_NEED_SEND;
- result = CURLE_OK;
- goto out;
- default:
- CURL_TRC_CF(data, cf, "shutdown, error: %d", (int)err);
- result = CURLE_SEND_ERROR;
- goto out;
- }
- }
-
- for(i = 0; i < 10; ++i) {
- if(!backend->sent_shutdown) {
- nread = sectransp_recv(cf, data, buf, (int)sizeof(buf), &result);
- }
- else {
- /* We would like to read the close notify from the server using
- * Secure Transport, however SSLRead() no longer works after we
- * sent the notify from our side. So, we just read from the
- * underlying filter and hope it will end. */
- nread = Curl_conn_cf_recv(cf->next, data, buf, sizeof(buf), &result);
- }
- CURL_TRC_CF(data, cf, "shutdown read -> %zd, %d", nread, result);
- if(nread <= 0)
- break;
- }
-
- if(nread > 0) {
- /* still data coming in? */
- connssl->io_need = CURL_SSL_IO_NEED_RECV;
- }
- else if(nread == 0) {
- /* We got the close notify alert and are done. */
- CURL_TRC_CF(data, cf, "shutdown done");
- *done = TRUE;
- }
- else if(result == CURLE_AGAIN) {
- connssl->io_need = CURL_SSL_IO_NEED_RECV;
- result = CURLE_OK;
- }
- else {
- DEBUGASSERT(result);
- CURL_TRC_CF(data, cf, "shutdown, error: %d", result);
- }
-
-out:
- cf->shutdown = (result || *done);
- return result;
-}
-
-static void sectransp_close(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
-
- (void) data;
-
- DEBUGASSERT(backend);
-
- if(backend->ssl_ctx) {
- CURL_TRC_CF(data, cf, "close");
-#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(&SSLCreateContext)
- CFRelease(backend->ssl_ctx);
-#if CURL_SUPPORT_MAC_10_8
- else
- (void)SSLDisposeContext(backend->ssl_ctx);
-#endif /* CURL_SUPPORT_MAC_10_8 */
-#else
- (void)SSLDisposeContext(backend->ssl_ctx);
-#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- backend->ssl_ctx = NULL;
- }
-}
-
-static size_t sectransp_version(char *buffer, size_t size)
-{
- return msnprintf(buffer, size, "SecureTransport");
-}
-
-static bool sectransp_data_pending(struct Curl_cfilter *cf,
- const struct Curl_easy *data)
-{
- const struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- OSStatus err;
- size_t buffer;
-
- (void)data;
- DEBUGASSERT(backend);
-
- if(backend->ssl_ctx) { /* SSL is in use */
- CURL_TRC_CF((struct Curl_easy *)CURL_UNCONST(data), cf, "data_pending");
- err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
- if(err == noErr)
- return buffer > 0UL;
- return FALSE;
- }
- else
- return FALSE;
-}
-
-static CURLcode sectransp_random(struct Curl_easy *data UNUSED_PARAM,
- unsigned char *entropy, size_t length)
-{
- /* arc4random_buf() is not available on cats older than Lion, so let's
- do this manually for the benefit of the older cats. */
- size_t i;
- u_int32_t random_number = 0;
-
- (void)data;
-
- for(i = 0 ; i < length ; i++) {
- if(i % sizeof(u_int32_t) == 0)
- random_number = arc4random();
- entropy[i] = random_number & 0xFF;
- random_number >>= 8;
- }
- i = random_number = 0;
- return CURLE_OK;
-}
-
-static CURLcode sectransp_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
-{
- (void)sha256len;
- assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
- (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
- return CURLE_OK;
-}
-
-static bool sectransp_false_start(void)
-{
-#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
- if(&SSLSetSessionOption)
- return TRUE;
-#endif
- return FALSE;
-}
-
-static ssize_t sectransp_send(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- size_t processed = 0UL;
- OSStatus err;
-
- DEBUGASSERT(backend);
-
- /* The SSLWrite() function works a little differently than expected. The
- fourth argument (processed) is currently documented in Apple's
- documentation as: "On return, the length, in bytes, of the data actually
- written."
-
- Now, one could interpret that as "written to the socket," but actually,
- it returns the amount of data that was written to a buffer internal to
- the SSLContextRef instead. So it is possible for SSLWrite() to return
- errSSLWouldBlock and a number of bytes "written" because those bytes were
- encrypted and written to a buffer, not to the socket.
-
- So if this happens, then we need to keep calling SSLWrite() over and
- over again with no new data until it quits returning errSSLWouldBlock. */
-
- /* Do we have buffered data to write from the last time we were called? */
- if(backend->ssl_write_buffered_length) {
- /* Write the buffered data: */
- err = SSLWrite(backend->ssl_ctx, NULL, 0UL, &processed);
- switch(err) {
- case noErr:
- /* processed is always going to be 0 because we did not write to
- the buffer, so return how much was written to the socket */
- processed = backend->ssl_write_buffered_length;
- backend->ssl_write_buffered_length = 0UL;
- break;
- case errSSLWouldBlock: /* argh, try again */
- *curlcode = CURLE_AGAIN;
- return -1L;
- default:
- failf(data, "SSLWrite() returned error %d", err);
- *curlcode = CURLE_SEND_ERROR;
- return -1L;
- }
- }
- else {
- /* We have got new data to write: */
- err = SSLWrite(backend->ssl_ctx, mem, len, &processed);
- if(err != noErr) {
- switch(err) {
- case errSSLWouldBlock:
- /* Data was buffered but not sent, we have to tell the caller
- to try sending again, and remember how much was buffered */
- backend->ssl_write_buffered_length = len;
- *curlcode = CURLE_AGAIN;
- return -1L;
- default:
- failf(data, "SSLWrite() returned error %d", err);
- *curlcode = CURLE_SEND_ERROR;
- return -1L;
- }
- }
- }
- return (ssize_t)processed;
-}
-
-static ssize_t sectransp_recv(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- char *buf,
- size_t buffersize,
- CURLcode *curlcode)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- size_t processed = 0UL;
- OSStatus err;
-
- DEBUGASSERT(backend);
-
-again:
- *curlcode = CURLE_OK;
- err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed);
-
- if(err != noErr) {
- switch(err) {
- case errSSLWouldBlock: /* return how much we read (if anything) */
- if(processed) {
- return (ssize_t)processed;
- }
- *curlcode = CURLE_AGAIN;
- return -1L;
-
- /* errSSLClosedGraceful - server gracefully shut down the SSL session
- errSSLClosedNoNotify - server hung up on us instead of sending a
- closure alert notice, read() is returning 0
- Either way, inform the caller that the server disconnected. */
- case errSSLClosedGraceful:
- case errSSLClosedNoNotify:
- *curlcode = CURLE_OK;
- return 0;
-
- /* The below is errSSLPeerAuthCompleted; it is not defined in
- Leopard's headers */
- case -9841:
- if((conn_config->CAfile || conn_config->ca_info_blob) &&
- conn_config->verifypeer) {
- CURLcode result = verify_cert(cf, data, conn_config->CAfile,
- conn_config->ca_info_blob,
- backend->ssl_ctx);
- if(result) {
- *curlcode = result;
- return -1;
- }
- }
- goto again;
- default:
- failf(data, "SSLRead() return error %d", err);
- *curlcode = CURLE_RECV_ERROR;
- return -1L;
- }
- }
- return (ssize_t)processed;
-}
-
-static void *sectransp_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
-{
- struct st_ssl_backend_data *backend =
- (struct st_ssl_backend_data *)connssl->backend;
- (void)info;
- DEBUGASSERT(backend);
- return backend->ssl_ctx;
-}
-
-const struct Curl_ssl Curl_ssl_sectransp = {
- { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
-
- SSLSUPP_CAINFO_BLOB |
- SSLSUPP_CERTINFO |
-#ifdef SECTRANSP_PINNEDPUBKEY
- SSLSUPP_PINNEDPUBKEY |
-#endif /* SECTRANSP_PINNEDPUBKEY */
- SSLSUPP_HTTPS_PROXY |
- SSLSUPP_CIPHER_LIST,
-
- sizeof(struct st_ssl_backend_data),
-
- NULL, /* init */
- NULL, /* cleanup */
- sectransp_version, /* version */
- sectransp_shutdown, /* shutdown */
- sectransp_data_pending, /* data_pending */
- sectransp_random, /* random */
- NULL, /* cert_status_request */
- sectransp_connect, /* connect */
- Curl_ssl_adjust_pollset, /* adjust_pollset */
- sectransp_get_internals, /* get_internals */
- sectransp_close, /* close_one */
- NULL, /* close_all */
- NULL, /* set_engine */
- NULL, /* set_engine_default */
- NULL, /* engines_list */
- sectransp_false_start, /* false_start */
- sectransp_sha256sum, /* sha256sum */
- sectransp_recv, /* recv decrypted data */
- sectransp_send, /* send data to encrypt */
- NULL, /* get_channel_binding */
-};
-
-#if defined(__GNUC__) && defined(__APPLE__)
-#pragma GCC diagnostic pop
-#endif
-
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-
-#endif /* USE_SECTRANSP */
+++ /dev/null
-#ifndef HEADER_CURL_SECTRANSP_H
-#define HEADER_CURL_SECTRANSP_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-#include "../curl_setup.h"
-
-#ifdef USE_SECTRANSP
-
-extern const struct Curl_ssl Curl_ssl_sectransp;
-
-#endif /* USE_SECTRANSP */
-#endif /* HEADER_CURL_SECTRANSP_H */
#include "gtls.h" /* GnuTLS versions */
#include "wolfssl.h" /* wolfSSL versions */
#include "schannel.h" /* Schannel SSPI version */
-#include "sectransp.h" /* Secure Transport (Darwin) version */
#include "mbedtls.h" /* mbedTLS versions */
-#include "bearssl.h" /* BearSSL versions */
#include "rustls.h" /* Rustls versions */
#include "../slist.h"
&Curl_ssl_rustls;
#elif defined(USE_OPENSSL)
&Curl_ssl_openssl;
-#elif defined(USE_SECTRANSP)
- &Curl_ssl_sectransp;
#elif defined(USE_SCHANNEL)
&Curl_ssl_schannel;
-#elif defined(USE_BEARSSL)
- &Curl_ssl_bearssl;
#else
#error "Missing struct Curl_ssl for selected SSL backend"
#endif
#if defined(USE_OPENSSL)
&Curl_ssl_openssl,
#endif
-#if defined(USE_SECTRANSP)
- &Curl_ssl_sectransp,
-#endif
#if defined(USE_SCHANNEL)
&Curl_ssl_schannel,
#endif
-#if defined(USE_BEARSSL)
- &Curl_ssl_bearssl,
-#endif
#if defined(USE_RUSTLS)
&Curl_ssl_rustls,
#endif
#include "../curl_setup.h"
-#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
- defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
+#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
-#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
- defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_RUSTLS)
+#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_MBEDTLS) || \
+ defined(USE_WOLFSSL) || defined(USE_RUSTLS)
#define WANT_PARSEX509 /* uses Curl_parseX509() */
#endif
-#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
- defined(USE_MBEDTLS) || defined(USE_RUSTLS)
+#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_MBEDTLS) || \
+ defined(USE_RUSTLS)
#define WANT_EXTRACT_CERTINFO /* uses Curl_extract_certinfo() */
#endif
#endif /* WANT_EXTRACT_CERTINFO */
-#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP
- or USE_MBEDTLS or USE_RUSTLS */
+#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_MBEDTLS or
+ USE_RUSTLS */
#include "../curl_setup.h"
-#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
- defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
+#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#include "../cfilters.h"
const char *beg, const char *end);
#ifdef UNITTESTS
-#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
- defined(USE_MBEDTLS) || defined(USE_RUSTLS)
+#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_MBEDTLS) || \
+ defined(USE_RUSTLS)
/* used by unit1656.c */
CURLcode Curl_x509_GTime2str(struct dynbuf *store,
#endif
#endif
-#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP
- or USE_MBEDTLS or USE_RUSTLS */
+#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_MBEDTLS or
+ USE_RUSTLS */
#endif /* HEADER_CURL_X509ASN1_H */
+++ /dev/null
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-#***************************************************************************
-
-AC_DEFUN([CURL_WITH_BEARSSL], [
-dnl ----------------------------------------------------
-dnl check for BearSSL
-dnl ----------------------------------------------------
-
-if test "x$OPT_BEARSSL" != xno; then
- _cppflags=$CPPFLAGS
- _ldflags=$LDFLAGS
- _ldflagspc=$LDFLAGSPC
- ssl_msg=
-
- if test X"$OPT_BEARSSL" != Xno; then
-
- if test "$OPT_BEARSSL" = "yes"; then
- OPT_BEARSSL=""
- fi
-
- if test -z "$OPT_BEARSSL" ; then
- dnl check for lib first without setting any new path
-
- AC_CHECK_LIB(bearssl, br_ssl_client_init_full,
- dnl libbearssl found, set the variable
- [
- AC_DEFINE(USE_BEARSSL, 1, [if BearSSL is enabled])
- BEARSSL_ENABLED=1
- USE_BEARSSL="yes"
- ssl_msg="BearSSL"
- test bearssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
- ], [], -lbearssl)
- fi
-
- addld=""
- addlib=""
- addcflags=""
- bearssllib=""
-
- if test "x$USE_BEARSSL" != "xyes"; then
- dnl add the path and test again
- addld=-L$OPT_BEARSSL/lib$libsuff
- addcflags=-I$OPT_BEARSSL/include
- bearssllib=$OPT_BEARSSL/lib$libsuff
-
- LDFLAGS="$LDFLAGS $addld"
- LDFLAGSPC="$LDFLAGSPC $addld"
- if test "$addcflags" != "-I/usr/include"; then
- CPPFLAGS="$CPPFLAGS $addcflags"
- fi
-
- AC_CHECK_LIB(bearssl, br_ssl_client_init_full,
- [
- AC_DEFINE(USE_BEARSSL, 1, [if BearSSL is enabled])
- BEARSSL_ENABLED=1
- USE_BEARSSL="yes"
- ssl_msg="BearSSL"
- test bearssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
- ],
- [
- CPPFLAGS=$_cppflags
- LDFLAGS=$_ldflags
- LDFLAGSPC=$_ldflagspc
- ], -lbearssl)
- fi
-
- if test "x$USE_BEARSSL" = "xyes"; then
- AC_MSG_NOTICE([detected BearSSL])
- check_for_ca_bundle=1
-
- LIBS="-lbearssl $LIBS"
-
- if test -n "$bearssllib"; then
- dnl when shared libs were found in a path that the run-time
- dnl linker doesn't search through, we need to add it to
- dnl CURL_LIBRARY_PATH to prevent further configure tests to fail
- dnl due to this
- if test "x$cross_compiling" != "xyes"; then
- CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$bearssllib"
- export CURL_LIBRARY_PATH
- AC_MSG_NOTICE([Added $bearssllib to CURL_LIBRARY_PATH])
- fi
- fi
- fi
-
- fi dnl BearSSL not disabled
-
- test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
-fi
-])
+++ /dev/null
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-#***************************************************************************
-
-AC_DEFUN([CURL_WITH_SECURETRANSPORT], [
-AC_MSG_CHECKING([whether to enable Secure Transport])
-if test "x$OPT_SECURETRANSPORT" != xno; then
- if test "x$OPT_SECURETRANSPORT" != "xno" &&
- (test "x$cross_compiling" != "xno" || test -d "/System/Library/Frameworks/Security.framework"); then
- AC_MSG_RESULT(yes)
- AC_DEFINE(USE_SECTRANSP, 1, [enable Secure Transport])
- ssl_msg="Secure Transport"
- test secure-transport != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
- SECURETRANSPORT_ENABLED=1
- SECURETRANSPORT_LDFLAGS='-framework CoreFoundation -framework CoreServices -framework Security'
- LDFLAGS="$LDFLAGS $SECURETRANSPORT_LDFLAGS"
- LDFLAGSPC="$LDFLAGSPC $SECURETRANSPORT_LDFLAGS"
- else
- AC_MSG_RESULT(no)
- fi
- test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
-else
- AC_MSG_RESULT(no)
-fi
-
-])
);
my %knowntls = (
- 'BearSSL' => 1,
'GnuTLS' => 1,
'mbedTLS' => 1,
'OpenSSL' => 1,
'rustls' => 1,
'Schannel' => 1,
- 'Secure Transport' => 1,
'wolfSSL' => 1,
'All' => 1,
'none' => 1,
<features>
SSL
!Schannel
-!sectransp
-!bearssl
local-http
</features>
<server>
# SSL with libraries supporting CURLOPT_CERTINFO
<features>
SSL
-!bearssl
!wolfssl
</features>
<server>
<features>
SSL
local-http
-!bearssl
!Schannel
-!sectransp
!wolfssl
</features>
<server>
<features>
SSL
!wolfssl
-!bearssl
!mbedtls
</features>
<server>
# download via https: proxy (no tunnel) using IP address
@pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
reason='curl lacks HTTPS-proxy support')
- @pytest.mark.skipif(condition=Env.curl_uses_lib('bearssl'), reason="ip address cert verification not supported")
@pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
def test_10_14_proxys_ip_addr(self, env: Env, httpd, proto):
if proto == 'h2' and not env.curl_uses_lib('nghttp2'):
exp_resumed = 'Initial' # 1.2 works in LibreSSL, but 1.3 does not, TODO
if env.curl_uses_lib('rustls-ffi'):
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 session resume not working in 3.6.0')
# use ip address for connect
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
def test_17_05_good_ip_addr(self, env: Env, proto, httpd, nghttpx):
- if env.curl_uses_lib('bearssl'):
- pytest.skip("BearSSL does not support cert verification with IP addresses")
if env.curl_uses_lib('mbedtls'):
pytest.skip("mbedTLS does use IP addresses in SNI")
if proto == 'h3' and not env.have_h3():
elif env.curl_uses_lib('schannel'): # not in CI, so untested
if ciphers12 is not None:
pytest.skip('Schannel does not support setting TLSv1.2 ciphers by name')
- elif env.curl_uses_lib('bearssl'):
- if tls_proto == 'TLSv1.3':
- pytest.skip('BearSSL does not support TLSv1.3')
- tls_proto = 'TLSv1.2'
elif env.curl_uses_lib('mbedtls') and not env.curl_lib_version_at_least('mbedtls', '3.6.0'):
if tls_proto == 'TLSv1.3':
pytest.skip('mbedTLS < 3.6.0 does not support TLSv1.3')
- elif env.curl_uses_lib('sectransp'): # not in CI, so untested
- if tls_proto == 'TLSv1.3':
- pytest.skip('Secure Transport does not support TLSv1.3')
- tls_proto = 'TLSv1.2'
# test
extra_args = ['--tls13-ciphers', ':'.join(ciphers13)] if ciphers13 else []
extra_args += ['--ciphers', ':'.join(ciphers12)] if ciphers12 else []
curl = CurlClient(env=env, run_env=run_env)
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/sslinfo'
# SSL backend specifics
- if env.curl_uses_lib('bearssl'):
- supported = ['TLSv1', 'TLSv1.1', 'TLSv1.2', None]
- elif env.curl_uses_lib('sectransp'): # not in CI, so untested
- supported = ['TLSv1', 'TLSv1.1', 'TLSv1.2', None]
- elif env.curl_uses_lib('gnutls'):
+ if env.curl_uses_lib('gnutls'):
supported = ['TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3']
elif env.curl_uses_lib('quiche'):
supported = ['TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3']
pytest.skip('Libressl resumption does not work inTLSv1.3')
if env.curl_uses_lib('rustls-ffi'):
pytest.skip('rustsls does not expose sessions')
- if env.curl_uses_lib('bearssl'):
- pytest.skip('BearSSL does not support TLSv1.3')
if env.curl_uses_lib('mbedtls') and \
not env.curl_lib_version_at_least('mbedtls', '3.6.0'):
pytest.skip('mbedtls TLSv1.3 session resume not working before 3.6.0')
$feature{"wolfssl"} = 1;
$feature{"SSLpinning"} = 1;
}
- elsif ($libcurl =~ /\sbearssl\b/i) {
- $feature{"bearssl"} = 1;
- }
- elsif ($libcurl =~ /\ssecuretransport\b/i) {
- $feature{"sectransp"} = 1;
- $feature{"SSLpinning"} = 1;
- }
elsif ($libcurl =~ /\s(BoringSSL|AWS-LC)\b/i) {
# OpenSSL compatible API
$feature{"OpenSSL"} = 1;
{
}
-#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
+#if defined(USE_GNUTLS) || defined(USE_SCHANNEL)
/* cert captured from gdb when connecting to curl.se on October 26
2018 */
}
-#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
- defined(USE_MBEDTLS)
+#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_MBEDTLS)
struct test_spec {
const char *input;
{
}
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) || defined(USE_RUSTLS)
+#if defined(USE_MBEDTLS) || defined(USE_RUSTLS)
struct test_cs_entry {
uint16_t id;
const char *openssl;
};
static const struct test_cs_entry test_cs_list[] = {
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_RUSTLS)
+#if defined(USE_MBEDTLS) || defined(USE_RUSTLS)
{ 0x1301, "TLS_AES_128_GCM_SHA256",
NULL },
{ 0x1302, "TLS_AES_256_GCM_SHA384",
"ECDHE-RSA-CHACHA20-POLY1305" },
{ 0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"ECDHE-ECDSA-CHACHA20-POLY1305" },
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#if defined(USE_MBEDTLS)
{ 0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA",
"AES128-SHA" },
{ 0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA",
{ 0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
"ECDH-RSA-AES256-GCM-SHA384" },
#endif
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS)
+#if defined(USE_MBEDTLS)
{ 0x0001, "TLS_RSA_WITH_NULL_MD5",
"NULL-MD5" },
{ 0x0002, "TLS_RSA_WITH_NULL_SHA",
{ 0xCCAB, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",
"PSK-CHACHA20-POLY1305" },
#endif
-#if defined(USE_SECTRANSP) || defined(USE_BEARSSL)
- { 0x000A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
- "DES-CBC3-SHA" },
- { 0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
- "ECDH-ECDSA-DES-CBC3-SHA" },
- { 0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
- "ECDHE-ECDSA-DES-CBC3-SHA" },
- { 0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
- "ECDH-RSA-DES-CBC3-SHA" },
- { 0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
- "ECDHE-RSA-DES-CBC3-SHA" },
-#endif
-#if defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#if defined(USE_MBEDTLS)
{ 0xC09C, "TLS_RSA_WITH_AES_128_CCM",
"AES128-CCM" },
{ 0xC09D, "TLS_RSA_WITH_AES_256_CCM",
{ 0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",
"ECDHE-ECDSA-AES256-CCM8" },
#endif
-#if defined(USE_SECTRANSP)
- { 0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5",
- "EXP-RC4-MD5" },
- { 0x0004, "TLS_RSA_WITH_RC4_128_MD5",
- "RC4-MD5" },
- { 0x0005, "TLS_RSA_WITH_RC4_128_SHA",
- "RC4-SHA" },
- { 0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5",
- "EXP-RC2-CBC-MD5" },
- { 0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA",
- "IDEA-CBC-SHA" },
- { 0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA",
- "EXP-DES-CBC-SHA" },
- { 0x0009, "TLS_RSA_WITH_DES_CBC_SHA",
- "DES-CBC-SHA" },
- { 0x000B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",
- "EXP-DH-DSS-DES-CBC-SHA" },
- { 0x000C, "TLS_DH_DSS_WITH_DES_CBC_SHA",
- "DH-DSS-DES-CBC-SHA" },
- { 0x000D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA",
- "DH-DSS-DES-CBC3-SHA" },
- { 0x000E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",
- "EXP-DH-RSA-DES-CBC-SHA" },
- { 0x000F, "TLS_DH_RSA_WITH_DES_CBC_SHA",
- "DH-RSA-DES-CBC-SHA" },
- { 0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA",
- "DH-RSA-DES-CBC3-SHA" },
- { 0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
- "EXP-DHE-DSS-DES-CBC-SHA" },
- { 0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA",
- "DHE-DSS-DES-CBC-SHA" },
- { 0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
- "DHE-DSS-DES-CBC3-SHA" },
- { 0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
- "EXP-DHE-RSA-DES-CBC-SHA" },
- { 0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA",
- "DHE-RSA-DES-CBC-SHA" },
- { 0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
- "DHE-RSA-DES-CBC3-SHA" },
- { 0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5",
- "EXP-ADH-RC4-MD5" },
- { 0x0018, "TLS_DH_anon_WITH_RC4_128_MD5",
- "ADH-RC4-MD5" },
- { 0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
- "EXP-ADH-DES-CBC-SHA" },
- { 0x001A, "TLS_DH_anon_WITH_DES_CBC_SHA",
- "ADH-DES-CBC-SHA" },
- { 0x001B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA",
- "ADH-DES-CBC3-SHA" },
- { 0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA",
- "DH-DSS-AES128-SHA" },
- { 0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA",
- "DH-RSA-AES128-SHA" },
- { 0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
- "DHE-DSS-AES128-SHA" },
- { 0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA",
- "ADH-AES128-SHA" },
- { 0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA",
- "DH-DSS-AES256-SHA" },
- { 0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA",
- "DH-RSA-AES256-SHA" },
- { 0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
- "DHE-DSS-AES256-SHA" },
- { 0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA",
- "ADH-AES256-SHA" },
- { 0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256",
- "DH-DSS-AES128-SHA256" },
- { 0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256",
- "DH-RSA-AES128-SHA256" },
- { 0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
- "DHE-DSS-AES128-SHA256" },
- { 0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256",
- "DH-DSS-AES256-SHA256" },
- { 0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256",
- "DH-RSA-AES256-SHA256" },
- { 0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
- "DHE-DSS-AES256-SHA256" },
- { 0x006C, "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
- "ADH-AES128-SHA256" },
- { 0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
- "ADH-AES256-SHA256" },
- { 0x008A, "TLS_PSK_WITH_RC4_128_SHA",
- "PSK-RC4-SHA" },
- { 0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA",
- "PSK-3DES-EDE-CBC-SHA" },
- { 0x008E, "TLS_DHE_PSK_WITH_RC4_128_SHA",
- "DHE-PSK-RC4-SHA" },
- { 0x008F, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",
- "DHE-PSK-3DES-EDE-CBC-SHA" },
- { 0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA",
- "RSA-PSK-RC4-SHA" },
- { 0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",
- "RSA-PSK-3DES-EDE-CBC-SHA" },
- { 0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256",
- "DH-RSA-AES128-GCM-SHA256" },
- { 0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384",
- "DH-RSA-AES256-GCM-SHA384" },
- { 0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
- "DHE-DSS-AES128-GCM-SHA256" },
- { 0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
- "DHE-DSS-AES256-GCM-SHA384" },
- { 0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256",
- "DH-DSS-AES128-GCM-SHA256" },
- { 0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384",
- "DH-DSS-AES256-GCM-SHA384" },
- { 0x00A6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
- "ADH-AES128-GCM-SHA256" },
- { 0x00A7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
- "ADH-AES256-GCM-SHA384" },
- { 0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
- "ECDH-ECDSA-RC4-SHA" },
- { 0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
- "ECDHE-ECDSA-RC4-SHA" },
- { 0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA",
- "ECDH-RSA-RC4-SHA" },
- { 0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
- "ECDHE-RSA-RC4-SHA" },
- { 0xC015, "TLS_ECDH_anon_WITH_NULL_SHA",
- "AECDH-NULL-SHA" },
- { 0xC016, "TLS_ECDH_anon_WITH_RC4_128_SHA",
- "AECDH-RC4-SHA" },
- { 0xC017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
- "AECDH-DES-CBC3-SHA" },
- { 0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
- "AECDH-AES128-SHA" },
- { 0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
- "AECDH-AES256-SHA" },
- /* Backward compatible aliases (EDH vs DHE) */
- { 0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
- "EXP-EDH-DSS-DES-CBC-SHA" },
- { 0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA",
- "EDH-DSS-DES-CBC-SHA" },
- { 0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
- "EDH-DSS-DES-CBC3-SHA" },
- { 0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
- "EXP-EDH-RSA-DES-CBC-SHA" },
- { 0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA",
- "EDH-RSA-DES-CBC-SHA" },
- { 0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
- "EDH-RSA-DES-CBC3-SHA" },
-#endif
#if defined(USE_MBEDTLS)
/* entries marked ns are non-"standard", they are not in OpenSSL */
{ 0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
const char *str;
};
static const struct test_str_entry test_str_list[] = {
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_RUSTLS)
+#if defined(USE_MBEDTLS) || defined(USE_RUSTLS)
{ 0x1301, "TLS_AES_128_GCM_SHA256"},
{ 0x1302, "TLS_AES_256_GCM_SHA384"},
{ 0x1303, "TLS_CHACHA20_POLY1305_SHA256"},
{ 0xC030, "ECDHE-RSA-AES256-GCM-SHA384"},
{ 0xCCA9, "ECDHE-ECDSA-CHACHA20-POLY1305"},
{ 0xCCA8, "ECDHE-RSA-CHACHA20-POLY1305"},
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS)
+#if defined(USE_MBEDTLS)
{ 0x009E, "DHE-RSA-AES128-GCM-SHA256"},
{ 0x009F, "DHE-RSA-AES256-GCM-SHA384"},
#else
#else
{ 0x0000, "DHE-RSA-CHACHA20-POLY1305"},
#endif
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#if defined(USE_MBEDTLS)
{ 0xC023, "ECDHE-ECDSA-AES128-SHA256" },
{ 0xC027, "ECDHE-RSA-AES128-SHA256" },
{ 0xC009, "ECDHE-ECDSA-AES128-SHA" },
{ 0x0000, "ECDHE-ECDSA-AES256-SHA" },
{ 0x0000, "ECDHE-RSA-AES256-SHA" },
#endif
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS)
+#if defined(USE_MBEDTLS)
{ 0x0067, "DHE-RSA-AES128-SHA256" },
{ 0x006B, "DHE-RSA-AES256-SHA256" },
#else
{ 0x0000, "DHE-RSA-AES128-SHA256" },
{ 0x0000, "DHE-RSA-AES256-SHA256" },
#endif
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#if defined(USE_MBEDTLS)
{ 0x009C, "AES128-GCM-SHA256" },
{ 0x009D, "AES256-GCM-SHA384" },
{ 0x003C, "AES128-SHA256" },
{ 0x0000, "AES128-SHA" },
{ 0x0000, "AES256-SHA" },
#endif
-#if defined(USE_SECTRANSP) || defined(USE_BEARSSL)
- { 0x000A, "DES-CBC3-SHA" },
-#else
{ 0x0000, "DES-CBC3-SHA" },
-#endif
{ 0x0000, "GIBBERISH" },
{ 0x0000, "" },
};
}
UNITTEST_STOP
-#else /* defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) */
+#else /* defined(USE_MBEDTLS) */
UNITTEST_START
UNITTEST_STOP
-#endif /* defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) || defined(USE_RUSTLS) */
+#endif /* defined(USE_MBEDTLS) || defined(USE_RUSTLS) */